smbd: Remove sconn->using_smb2
[samba.git] / source3 / smbd / smb2_oplock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    oplock processing
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 1998 - 2001
6    Copyright (C) Volker Lendecke 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #define DBGC_CLASS DBGC_LOCKING
23 #include "includes.h"
24 #include "lib/util/server_id.h"
25 #include "locking/share_mode_lock.h"
26 #include "smbd/smbd.h"
27 #include "smbd/globals.h"
28 #include "messages.h"
29 #include "locking/leases_db.h"
30 #include "../librpc/gen_ndr/ndr_open_files.h"
31
32 /*
33  * helper function used by the kernel oplock backends to post the break message
34  */
35 void break_kernel_oplock(struct messaging_context *msg_ctx, files_struct *fsp)
36 {
37         uint8_t msg[MSG_SMB_KERNEL_BREAK_SIZE];
38
39         /* Put the kernel break info into the message. */
40         push_file_id_24((char *)msg, &fsp->file_id);
41         SIVAL(msg, 24, fh_get_gen_id(fsp->fh));
42
43         /* Don't need to be root here as we're only ever
44            sending to ourselves. */
45
46         messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
47                            MSG_SMB_KERNEL_BREAK,
48                            msg, MSG_SMB_KERNEL_BREAK_SIZE);
49 }
50
51 /****************************************************************************
52  Attempt to set an oplock on a file. Succeeds if kernel oplocks are
53  disabled (just sets flags).
54 ****************************************************************************/
55
56 NTSTATUS set_file_oplock(files_struct *fsp)
57 {
58         struct smbd_server_connection *sconn = fsp->conn->sconn;
59         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
60         bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
61                         (koplocks != NULL);
62         struct file_id_buf buf;
63
64         smb_vfs_assert_allowed();
65
66         if (fsp->oplock_type == LEVEL_II_OPLOCK && use_kernel) {
67                 DEBUG(10, ("Refusing level2 oplock, kernel oplocks "
68                            "don't support them\n"));
69                 return NT_STATUS_NOT_SUPPORTED;
70         }
71
72         if ((fsp->oplock_type != NO_OPLOCK) &&
73             use_kernel &&
74             !koplocks->ops->set_oplock(koplocks, fsp, fsp->oplock_type))
75         {
76                 return map_nt_error_from_unix(errno);
77         }
78
79         fsp->sent_oplock_break = NO_BREAK_SENT;
80         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
81                 sconn->oplocks.level_II_open++;
82         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
83                 sconn->oplocks.exclusive_open++;
84         }
85
86         DBG_INFO("granted oplock on file %s, %s/%"PRIu64", "
87                  "tv_sec = %x, tv_usec = %x\n",
88                  fsp_str_dbg(fsp),
89                  file_id_str_buf(fsp->file_id, &buf),
90                  fh_get_gen_id(fsp->fh),
91                  (int)fsp->open_time.tv_sec,
92                  (int)fsp->open_time.tv_usec);
93
94         return NT_STATUS_OK;
95 }
96
97 static void release_fsp_kernel_oplock(files_struct *fsp)
98 {
99         struct smbd_server_connection *sconn = fsp->conn->sconn;
100         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
101         bool use_kernel;
102
103         smb_vfs_assert_allowed();
104
105         if (koplocks == NULL) {
106                 return;
107         }
108         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn));
109         if (!use_kernel) {
110                 return;
111         }
112         if (fsp->oplock_type == NO_OPLOCK) {
113                 return;
114         }
115         if (fsp->oplock_type == LEASE_OPLOCK) {
116                 /*
117                  * For leases we don't touch kernel oplocks at all
118                  */
119                 return;
120         }
121
122         koplocks->ops->release_oplock(koplocks, fsp, NO_OPLOCK);
123 }
124
125 /****************************************************************************
126  Attempt to release an oplock on a file. Decrements oplock count.
127 ****************************************************************************/
128
129 void release_file_oplock(files_struct *fsp)
130 {
131         struct smbd_server_connection *sconn = fsp->conn->sconn;
132
133         release_fsp_kernel_oplock(fsp);
134
135         if (fsp->oplock_type == LEVEL_II_OPLOCK) {
136                 sconn->oplocks.level_II_open--;
137         } else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
138                 sconn->oplocks.exclusive_open--;
139         }
140
141         SMB_ASSERT(sconn->oplocks.exclusive_open>=0);
142         SMB_ASSERT(sconn->oplocks.level_II_open>=0);
143
144         fsp->oplock_type = NO_OPLOCK;
145         fsp->sent_oplock_break = NO_BREAK_SENT;
146
147         TALLOC_FREE(fsp->oplock_timeout);
148 }
149
150 /****************************************************************************
151  Attempt to downgrade an oplock on a file. Doesn't decrement oplock count.
152 ****************************************************************************/
153
154 static void downgrade_file_oplock(files_struct *fsp)
155 {
156         struct smbd_server_connection *sconn = fsp->conn->sconn;
157         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
158         bool use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
159                         (koplocks != NULL);
160
161         smb_vfs_assert_allowed();
162
163         if (!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
164                 DEBUG(0, ("trying to downgrade an already-downgraded oplock!\n"));
165                 return;
166         }
167
168         if (use_kernel) {
169                 koplocks->ops->release_oplock(koplocks, fsp, LEVEL_II_OPLOCK);
170         }
171         fsp->oplock_type = LEVEL_II_OPLOCK;
172         sconn->oplocks.exclusive_open--;
173         sconn->oplocks.level_II_open++;
174         fsp->sent_oplock_break = NO_BREAK_SENT;
175
176         TALLOC_FREE(fsp->oplock_timeout);
177 }
178
179 uint32_t get_lease_type(struct share_mode_entry *e, struct file_id id)
180 {
181         struct GUID_txt_buf guid_strbuf;
182         struct file_id_buf file_id_strbuf;
183         NTSTATUS status;
184         uint32_t current_state;
185
186         if (e->op_type != LEASE_OPLOCK) {
187                 return map_oplock_to_lease_type(e->op_type);
188         }
189
190         status = leases_db_get(&e->client_guid,
191                                &e->lease_key,
192                                &id,
193                                &current_state,
194                                NULL,    /* breaking */
195                                NULL,    /* breaking_to_requested */
196                                NULL,    /* breaking_to_required */
197                                NULL,    /* lease_version */
198                                NULL);   /* epoch */
199         if (NT_STATUS_IS_OK(status)) {
200                 return current_state;
201         }
202
203         if (share_entry_stale_pid(e)) {
204                 return 0;
205         }
206         DBG_ERR("leases_db_get for client_guid [%s] "
207                 "lease_key [%"PRIu64"/%"PRIu64"] "
208                 "file_id [%s] failed: %s\n",
209                 GUID_buf_string(&e->client_guid, &guid_strbuf),
210                 e->lease_key.data[0],
211                 e->lease_key.data[1],
212                 file_id_str_buf(id, &file_id_strbuf),
213                 nt_errstr(status));
214         smb_panic("leases_db_get() failed");
215 }
216
217 /****************************************************************************
218  Remove a file oplock. Copes with level II and exclusive.
219  Locks then unlocks the share mode lock. Client can decide to go directly
220  to none even if a "break-to-level II" was sent.
221 ****************************************************************************/
222
223 bool remove_oplock(files_struct *fsp)
224 {
225         bool ret;
226         struct share_mode_lock *lck;
227
228         DBG_DEBUG("remove_oplock called for %s\n", fsp_str_dbg(fsp));
229
230         /* Remove the oplock flag from the sharemode. */
231         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
232         if (lck == NULL) {
233                 DBG_ERR("failed to lock share entry for "
234                          "file %s\n", fsp_str_dbg(fsp));
235                 return false;
236         }
237
238         ret = remove_share_oplock(lck, fsp);
239         if (!ret) {
240                 struct file_id_buf buf;
241
242                 DBG_ERR("failed to remove share oplock for "
243                         "file %s, %s, %s\n",
244                         fsp_str_dbg(fsp), fsp_fnum_dbg(fsp),
245                         file_id_str_buf(fsp->file_id, &buf));
246         }
247         release_file_oplock(fsp);
248
249         TALLOC_FREE(lck);
250         return ret;
251 }
252
253 /*
254  * Deal with a reply when a break-to-level II was sent.
255  */
256 bool downgrade_oplock(files_struct *fsp)
257 {
258         bool ret;
259         struct share_mode_lock *lck;
260
261         DEBUG(10, ("downgrade_oplock called for %s\n",
262                    fsp_str_dbg(fsp)));
263
264         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
265         if (lck == NULL) {
266                 DEBUG(0,("downgrade_oplock: failed to lock share entry for "
267                          "file %s\n", fsp_str_dbg(fsp)));
268                 return False;
269         }
270         ret = downgrade_share_oplock(lck, fsp);
271         if (!ret) {
272                 struct file_id_buf idbuf;
273                 DBG_ERR("failed to downgrade share oplock "
274                         "for file %s, %s, file_id %s\n",
275                         fsp_str_dbg(fsp),
276                         fsp_fnum_dbg(fsp),
277                         file_id_str_buf(fsp->file_id, &idbuf));
278         }
279         downgrade_file_oplock(fsp);
280
281         TALLOC_FREE(lck);
282         return ret;
283 }
284
285 static void lease_timeout_handler(struct tevent_context *ctx,
286                                   struct tevent_timer *te,
287                                   struct timeval now,
288                                   void *private_data)
289 {
290         struct fsp_lease *lease =
291                 talloc_get_type_abort(private_data,
292                 struct fsp_lease);
293         struct files_struct *fsp;
294         struct share_mode_lock *lck;
295         uint16_t old_epoch = lease->lease.lease_epoch;
296
297         fsp = file_find_one_fsp_from_lease_key(lease->sconn,
298                                                &lease->lease.lease_key);
299         if (fsp == NULL) {
300                 /* race? */
301                 TALLOC_FREE(lease->timeout);
302                 return;
303         }
304
305         /*
306          * Paranoia check: There can only be one fsp_lease per lease
307          * key
308          */
309         SMB_ASSERT(fsp->lease == lease);
310
311         lck = get_existing_share_mode_lock(
312                         talloc_tos(), fsp->file_id);
313         if (lck == NULL) {
314                 /* race? */
315                 TALLOC_FREE(lease->timeout);
316                 return;
317         }
318
319         fsp_lease_update(fsp);
320
321         if (lease->lease.lease_epoch != old_epoch) {
322                 /*
323                  * If the epoch changed we need to wait for
324                  * the next timeout to happen.
325                  */
326                 DEBUG(10, ("lease break timeout race (epoch) for file %s - ignoring\n",
327                            fsp_str_dbg(fsp)));
328                 TALLOC_FREE(lck);
329                 return;
330         }
331
332         if (!(lease->lease.lease_flags & SMB2_LEASE_FLAG_BREAK_IN_PROGRESS)) {
333                 /*
334                  * If the epoch changed we need to wait for
335                  * the next timeout to happen.
336                  */
337                 DEBUG(10, ("lease break timeout race (flags) for file %s - ignoring\n",
338                            fsp_str_dbg(fsp)));
339                 TALLOC_FREE(lck);
340                 return;
341         }
342
343         DEBUG(1, ("lease break timed out for file %s -- replying anyway\n",
344                   fsp_str_dbg(fsp)));
345         (void)downgrade_lease(lease->sconn->client,
346                         1,
347                         &fsp->file_id,
348                         &lease->lease.lease_key,
349                         SMB2_LEASE_NONE);
350
351         TALLOC_FREE(lck);
352 }
353
354 bool fsp_lease_update(struct files_struct *fsp)
355 {
356         const struct GUID *client_guid = fsp_client_guid(fsp);
357         struct fsp_lease *lease = fsp->lease;
358         uint32_t current_state;
359         bool breaking;
360         uint16_t lease_version, epoch;
361         NTSTATUS status;
362
363         status = leases_db_get(client_guid,
364                                &lease->lease.lease_key,
365                                &fsp->file_id,
366                                &current_state,
367                                &breaking,
368                                NULL, /* breaking_to_requested */
369                                NULL, /* breaking_to_required */
370                                &lease_version,
371                                &epoch);
372         if (!NT_STATUS_IS_OK(status)) {
373                 DBG_WARNING("Could not find lease entry: %s\n",
374                             nt_errstr(status));
375                 TALLOC_FREE(lease->timeout);
376                 lease->lease.lease_state = SMB2_LEASE_NONE;
377                 lease->lease.lease_epoch += 1;
378                 lease->lease.lease_flags = 0;
379                 return false;
380         }
381
382         DEBUG(10,("%s: refresh lease state\n", __func__));
383
384         /* Ensure we're in sync with current lease state. */
385         if (lease->lease.lease_epoch != epoch) {
386                 DEBUG(10,("%s: cancel outdated timeout\n", __func__));
387                 TALLOC_FREE(lease->timeout);
388         }
389         lease->lease.lease_epoch = epoch;
390         lease->lease.lease_state = current_state;
391
392         if (breaking) {
393                 lease->lease.lease_flags |= SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
394
395                 if (lease->timeout == NULL) {
396                         struct timeval t = timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0);
397
398                         DEBUG(10,("%s: setup timeout handler\n", __func__));
399
400                         lease->timeout = tevent_add_timer(lease->sconn->ev_ctx,
401                                                           lease, t,
402                                                           lease_timeout_handler,
403                                                           lease);
404                         if (lease->timeout == NULL) {
405                                 DEBUG(0, ("%s: Could not add lease timeout handler\n",
406                                           __func__));
407                         }
408                 }
409         } else {
410                 lease->lease.lease_flags &= ~SMB2_LEASE_FLAG_BREAK_IN_PROGRESS;
411                 TALLOC_FREE(lease->timeout);
412         }
413
414         return true;
415 }
416
417 struct downgrade_lease_additional_state {
418         struct tevent_immediate *im;
419         struct smbXsrv_client *client;
420         uint32_t break_flags;
421         struct smb2_lease_key lease_key;
422         uint32_t break_from;
423         uint32_t break_to;
424         uint16_t new_epoch;
425 };
426
427 static void downgrade_lease_additional_trigger(struct tevent_context *ev,
428                                                struct tevent_immediate *im,
429                                                void *private_data)
430 {
431         struct downgrade_lease_additional_state *state =
432                 talloc_get_type_abort(private_data,
433                 struct downgrade_lease_additional_state);
434         NTSTATUS status;
435
436         status = smbd_smb2_send_lease_break(state->client,
437                                             state->new_epoch,
438                                             state->break_flags,
439                                             &state->lease_key,
440                                             state->break_from,
441                                             state->break_to);
442         if (!NT_STATUS_IS_OK(status)) {
443                 smbd_server_disconnect_client(state->client,
444                                               nt_errstr(status));
445         }
446         TALLOC_FREE(state);
447 }
448
449 struct fsps_lease_update_state {
450         const struct file_id *id;
451         const struct smb2_lease_key *key;
452 };
453
454 static struct files_struct *fsps_lease_update_fn(
455         struct files_struct *fsp, void *private_data)
456 {
457         struct fsps_lease_update_state *state =
458                 (struct fsps_lease_update_state *)private_data;
459
460         if (fsp->oplock_type != LEASE_OPLOCK) {
461                 return NULL;
462         }
463         if (!smb2_lease_key_equal(&fsp->lease->lease.lease_key, state->key)) {
464                 return NULL;
465         }
466         if (!file_id_equal(&fsp->file_id, state->id)) {
467                 return NULL;
468         }
469
470         fsp_lease_update(fsp);
471
472         return NULL;
473 }
474
475 static void fsps_lease_update(struct smbd_server_connection *sconn,
476                               const struct file_id *id,
477                               const struct smb2_lease_key *key)
478 {
479         struct fsps_lease_update_state state = { .id = id, .key = key };
480         files_forall(sconn, fsps_lease_update_fn, &state);
481 }
482
483 NTSTATUS downgrade_lease(struct smbXsrv_client *client,
484                          uint32_t num_file_ids,
485                          const struct file_id *ids,
486                          const struct smb2_lease_key *key,
487                          uint32_t lease_state)
488 {
489         struct smbd_server_connection *sconn = client->sconn;
490         const struct GUID *client_guid = NULL;
491         struct share_mode_lock *lck;
492         const struct file_id id = ids[0];
493         uint32_t current_state, breaking_to_requested, breaking_to_required;
494         bool breaking;
495         uint16_t lease_version, epoch;
496         NTSTATUS status;
497         uint32_t i;
498         struct file_id_buf idbuf;
499
500         DBG_DEBUG("Downgrading %s to %"PRIu32"\n",
501                   file_id_str_buf(id, &idbuf),
502                   lease_state);
503
504         lck = get_existing_share_mode_lock(talloc_tos(), id);
505         if (lck == NULL) {
506                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
507         }
508
509         client_guid = &sconn->client->global->client_guid;
510
511         status = leases_db_get(client_guid,
512                                key,
513                                &id,
514                                &current_state,
515                                &breaking,
516                                &breaking_to_requested,
517                                &breaking_to_required,
518                                &lease_version,
519                                &epoch);
520         if (!NT_STATUS_IS_OK(status)) {
521                 DBG_WARNING("leases_db_get returned %s\n",
522                             nt_errstr(status));
523                 TALLOC_FREE(lck);
524                 return status;
525         }
526
527         if (!breaking) {
528                 DBG_WARNING("Attempt to break from %"PRIu32" to %"PRIu32" - "
529                             "but we're not in breaking state\n",
530                             current_state, lease_state);
531                 TALLOC_FREE(lck);
532                 return NT_STATUS_UNSUCCESSFUL;
533         }
534
535         /*
536          * Can't upgrade anything: breaking_to_requested (and current_state)
537          * must be a strict bitwise superset of new_lease_state
538          */
539         if ((lease_state & breaking_to_requested) != lease_state) {
540                 DBG_WARNING("Attempt to upgrade from %"PRIu32" to %"PRIu32" "
541                             "- expected %"PRIu32"\n",
542                             current_state, lease_state,
543                             breaking_to_requested);
544                 TALLOC_FREE(lck);
545                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
546         }
547
548         if (current_state != lease_state) {
549                 current_state = lease_state;
550         }
551
552         status = NT_STATUS_OK;
553
554         if ((lease_state & ~breaking_to_required) != 0) {
555                 struct downgrade_lease_additional_state *state;
556
557                 DBG_INFO("lease state %"PRIu32" not fully broken from "
558                          "%"PRIu32" to %"PRIu32"\n",
559                          lease_state,
560                          current_state,
561                          breaking_to_required);
562
563                 breaking_to_requested = breaking_to_required;
564
565                 if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
566                         /*
567                          * Here we break in steps, as windows does
568                          * see the breaking3 and v2_breaking3 tests.
569                          */
570                         breaking_to_requested |= SMB2_LEASE_READ;
571                 }
572
573                 state = talloc_zero(client,
574                                     struct downgrade_lease_additional_state);
575                 if (state == NULL) {
576                         TALLOC_FREE(lck);
577                         return NT_STATUS_NO_MEMORY;
578                 }
579
580                 state->im = tevent_create_immediate(state);
581                 if (state->im == NULL) {
582                         TALLOC_FREE(state);
583                         TALLOC_FREE(lck);
584                         return NT_STATUS_NO_MEMORY;
585                 }
586
587                 state->client = client;
588                 state->lease_key = *key;
589                 state->break_from = current_state;
590                 state->break_to = breaking_to_requested;
591                 if (lease_version > 1) {
592                         state->new_epoch = epoch;
593                 }
594
595                 if (current_state & (SMB2_LEASE_WRITE|SMB2_LEASE_HANDLE)) {
596                         state->break_flags =
597                                 SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED;
598                 } else {
599                         /*
600                          * This is an async break without
601                          * SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED
602                          *
603                          * we need to store NONE state in the
604                          * database.
605                          */
606                         current_state = 0;
607                         breaking_to_requested = 0;
608                         breaking_to_required = 0;
609                         breaking = false;
610
611                         {
612                                 NTSTATUS set_status;
613
614                                 set_status = leases_db_set(
615                                         &sconn->client->global->client_guid,
616                                         key,
617                                         current_state,
618                                         breaking,
619                                         breaking_to_requested,
620                                         breaking_to_required,
621                                         lease_version,
622                                         epoch);
623
624                                 if (!NT_STATUS_IS_OK(set_status)) {
625                                         DBG_DEBUG("leases_db_set failed: %s\n",
626                                                   nt_errstr(set_status));
627                                         return set_status;
628                                 }
629                         }
630                 }
631
632                 tevent_schedule_immediate(state->im,
633                                           client->raw_ev_ctx,
634                                           downgrade_lease_additional_trigger,
635                                           state);
636
637                 status = NT_STATUS_OPLOCK_BREAK_IN_PROGRESS;
638         } else {
639                 DBG_DEBUG("breaking from %"PRIu32" to %"PRIu32" - "
640                           "expected %"PRIu32"\n",
641                           current_state,
642                           lease_state,
643                           breaking_to_requested);
644
645                 breaking_to_requested = 0;
646                 breaking_to_required = 0;
647                 breaking = false;
648         }
649
650         {
651                 NTSTATUS set_status;
652
653                 set_status = leases_db_set(
654                         client_guid,
655                         key,
656                         current_state,
657                         breaking,
658                         breaking_to_requested,
659                         breaking_to_required,
660                         lease_version,
661                         epoch);
662
663                 if (!NT_STATUS_IS_OK(set_status)) {
664                         DBG_DEBUG("leases_db_set failed: %s\n",
665                                   nt_errstr(set_status));
666                         TALLOC_FREE(lck);
667                         return set_status;
668                 }
669         }
670
671         DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
672                   file_id_str_buf(id, &idbuf),
673                   lease_state,
674                   nt_errstr(status));
675
676         share_mode_wakeup_waiters(id);
677
678         fsps_lease_update(sconn, &id, key);
679
680         TALLOC_FREE(lck);
681
682         DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
683                   file_id_str_buf(id, &idbuf),
684                   lease_state,
685                   nt_errstr(status));
686
687         /*
688          * Dynamic share case. Ensure other opens are copies.
689          * This will only be breaking to NONE.
690          */
691
692         for (i = 1; i < num_file_ids; i++) {
693                 lck = get_existing_share_mode_lock(talloc_tos(), ids[i]);
694                 if (lck == NULL) {
695                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
696                 }
697
698                 fsps_lease_update(sconn, &ids[i], key);
699
700                 DBG_DEBUG("Downgrading %s to %"PRIu32" => %s\n",
701                           file_id_str_buf(ids[i], &idbuf),
702                           lease_state,
703                           nt_errstr(status));
704
705                 TALLOC_FREE(lck);
706         }
707
708         return status;
709 }
710
711 #define SMB1_BREAK_MESSAGE_LENGTH (smb_size + 8*2)
712
713 /****************************************************************************
714  Function to do the waiting before sending a local break.
715 ****************************************************************************/
716
717 static void wait_before_sending_break(void)
718 {
719         long wait_time = (long)lp_oplock_break_wait_time();
720
721         if (wait_time) {
722                 smb_msleep(wait_time);
723         }
724 }
725
726 /****************************************************************************
727  Ensure that we have a valid oplock.
728 ****************************************************************************/
729
730 static files_struct *initial_break_processing(
731         struct smbd_server_connection *sconn, struct file_id id,
732         unsigned long file_id)
733 {
734         files_struct *fsp = NULL;
735         struct file_id_buf idbuf;
736
737         DBG_NOTICE("called for %s/%u\n"
738                    "Current oplocks_open (exclusive = %d, levelII = %d)\n",
739                    file_id_str_buf(id, &idbuf),
740                    (int)file_id,
741                    sconn->oplocks.exclusive_open,
742                    sconn->oplocks.level_II_open);
743
744         /*
745          * We need to search the file open table for the
746          * entry containing this dev and inode, and ensure
747          * we have an oplock on it.
748          */
749
750         fsp = file_find_dif(sconn, id, file_id);
751
752         if(fsp == NULL) {
753                 /* The file could have been closed in the meantime - return success. */
754                 DBG_NOTICE("cannot find open file "
755                            "with file_id %s gen_id = %lu, allowing break to "
756                            "succeed.\n",
757                            file_id_str_buf(id, &idbuf),
758                            file_id);
759                 return NULL;
760         }
761
762         /* Ensure we have an oplock on the file */
763
764         /*
765          * There is a potential race condition in that an oplock could
766          * have been broken due to another udp request, and yet there are
767          * still oplock break messages being sent in the udp message
768          * queue for this file. So return true if we don't have an oplock,
769          * as we may have just freed it.
770          */
771
772         if(fsp->oplock_type == NO_OPLOCK) {
773                 DBG_NOTICE("file %s (file_id = %s gen_id = %"PRIu64") "
774                            "has no oplock. "
775                            "Allowing break to succeed regardless.\n",
776                            fsp_str_dbg(fsp),
777                            file_id_str_buf(id, &idbuf),
778                            fh_get_gen_id(fsp->fh));
779                 return NULL;
780         }
781
782         return fsp;
783 }
784
785 static void oplock_timeout_handler(struct tevent_context *ctx,
786                                    struct tevent_timer *te,
787                                    struct timeval now,
788                                    void *private_data)
789 {
790         files_struct *fsp = (files_struct *)private_data;
791
792         SMB_ASSERT(fsp->sent_oplock_break != NO_BREAK_SENT);
793
794         /* Remove the timed event handler. */
795         TALLOC_FREE(fsp->oplock_timeout);
796         DEBUG(0, ("Oplock break failed for file %s -- replying anyway\n",
797                   fsp_str_dbg(fsp)));
798         remove_oplock(fsp);
799 }
800
801 /*******************************************************************
802  Add a timeout handler waiting for the client reply.
803 *******************************************************************/
804
805 static void add_oplock_timeout_handler(files_struct *fsp)
806 {
807         if (fsp->oplock_timeout != NULL) {
808                 DEBUG(0, ("Logic problem -- have an oplock event hanging "
809                           "around\n"));
810         }
811
812         fsp->oplock_timeout =
813                 tevent_add_timer(fsp->conn->sconn->ev_ctx, fsp,
814                                  timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
815                                  oplock_timeout_handler, fsp);
816
817         if (fsp->oplock_timeout == NULL) {
818                 DEBUG(0, ("Could not add oplock timeout handler\n"));
819         }
820 }
821
822 /*******************************************************************
823  This handles the generic oplock break message from another smbd.
824 *******************************************************************/
825
826 static void process_oplock_break_message(struct messaging_context *msg_ctx,
827                                          void *private_data,
828                                          uint32_t msg_type,
829                                          struct server_id src,
830                                          DATA_BLOB *data)
831 {
832         struct oplock_break_message *msg = NULL;
833         enum ndr_err_code ndr_err;
834         files_struct *fsp;
835         bool use_kernel;
836         struct smbd_server_connection *sconn =
837                 talloc_get_type_abort(private_data,
838                 struct smbd_server_connection);
839         struct server_id self = messaging_server_id(sconn->msg_ctx);
840         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
841         uint16_t break_from;
842         uint16_t break_to;
843         bool break_needed = true;
844
845         smb_vfs_assert_allowed();
846
847         msg = talloc(talloc_tos(), struct oplock_break_message);
848         if (msg == NULL) {
849                 DBG_WARNING("talloc failed\n");
850                 return;
851         }
852
853         ndr_err = ndr_pull_struct_blob_all(
854                 data,
855                 msg,
856                 msg,
857                 (ndr_pull_flags_fn_t)ndr_pull_oplock_break_message);
858         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
859                 DBG_DEBUG("ndr_pull_oplock_break_message failed: %s\n",
860                           ndr_errstr(ndr_err));
861                 TALLOC_FREE(msg);
862                 return;
863         }
864         if (DEBUGLEVEL >= 10) {
865                 struct server_id_buf buf;
866                 DBG_DEBUG("Got break message from %s\n",
867                           server_id_str_buf(src, &buf));
868                 NDR_PRINT_DEBUG(oplock_break_message, msg);
869         }
870
871         break_to = msg->break_to;
872         fsp = initial_break_processing(sconn, msg->id, msg->share_file_id);
873
874         TALLOC_FREE(msg);
875
876         if (fsp == NULL) {
877                 /* We hit a race here. Break messages are sent, and before we
878                  * get to process this message, we have closed the file. */
879                 DEBUG(3, ("Did not find fsp\n"));
880                 return;
881         }
882
883         break_from = fsp_lease_type(fsp);
884
885         if (fsp->oplock_type != LEASE_OPLOCK) {
886                 if (fsp->sent_oplock_break != NO_BREAK_SENT) {
887                         /*
888                          * Nothing to do anymore
889                          */
890                         DEBUG(10, ("fsp->sent_oplock_break = %d\n",
891                                    fsp->sent_oplock_break));
892                         return;
893                 }
894         }
895
896         if (!(global_client_caps & CAP_LEVEL_II_OPLOCKS)) {
897                 DEBUG(10, ("client_caps without level2 oplocks\n"));
898                 break_to &= ~SMB2_LEASE_READ;
899         }
900
901         use_kernel = lp_kernel_oplocks(SNUM(fsp->conn)) &&
902                         (koplocks != NULL);
903         if (use_kernel) {
904                 DEBUG(10, ("Kernel oplocks don't allow level2\n"));
905                 break_to &= ~SMB2_LEASE_READ;
906         }
907
908         if (!lp_level2_oplocks(SNUM(fsp->conn))) {
909                 DEBUG(10, ("no level2 oplocks by config\n"));
910                 break_to &= ~SMB2_LEASE_READ;
911         }
912
913         if (fsp->oplock_type == LEASE_OPLOCK) {
914                 const struct GUID *client_guid = fsp_client_guid(fsp);
915                 struct share_mode_lock *lck;
916                 uint32_t current_state;
917                 uint32_t breaking_to_requested, breaking_to_required;
918                 bool breaking;
919                 uint16_t lease_version, epoch;
920                 NTSTATUS status;
921
922                 lck = get_existing_share_mode_lock(
923                         talloc_tos(), fsp->file_id);
924                 if (lck == NULL) {
925                         /*
926                          * We hit a race here. Break messages are sent, and
927                          * before we get to process this message, we have closed
928                          * the file.
929                          */
930                         DEBUG(3, ("Did not find share_mode\n"));
931                         return;
932                 }
933
934                 status = leases_db_get(client_guid,
935                                        &fsp->lease->lease.lease_key,
936                                        &fsp->file_id,
937                                        &current_state,
938                                        &breaking,
939                                        &breaking_to_requested,
940                                        &breaking_to_required,
941                                        &lease_version,
942                                        &epoch);
943                 if (!NT_STATUS_IS_OK(status)) {
944                         DBG_WARNING("leases_db_get returned %s\n",
945                                     nt_errstr(status));
946                         TALLOC_FREE(lck);
947                         return;
948                 }
949
950                 break_from = current_state;
951                 break_to &= current_state;
952
953                 if (breaking) {
954                         break_to &= breaking_to_required;
955                         if (breaking_to_required != break_to) {
956                                 /*
957                                  * Note we don't increment the epoch
958                                  * here, which might be a bug in
959                                  * Windows too...
960                                  */
961                                 breaking_to_required = break_to;
962                         }
963                         break_needed = false;
964                 } else if (current_state == break_to) {
965                         break_needed = false;
966                 } else if (current_state == SMB2_LEASE_READ) {
967                         current_state = SMB2_LEASE_NONE;
968                         /* Need to increment the epoch */
969                         epoch += 1;
970                 } else {
971                         breaking = true;
972                         breaking_to_required = break_to;
973                         breaking_to_requested = break_to;
974                         /* Need to increment the epoch */
975                         epoch += 1;
976                 }
977
978                 {
979                         NTSTATUS set_status;
980
981                         set_status = leases_db_set(
982                                 client_guid,
983                                 &fsp->lease->lease.lease_key,
984                                 current_state,
985                                 breaking,
986                                 breaking_to_requested,
987                                 breaking_to_required,
988                                 lease_version,
989                                 epoch);
990
991                         if (!NT_STATUS_IS_OK(set_status)) {
992                                 DBG_DEBUG("leases_db_set failed: %s\n",
993                                           nt_errstr(set_status));
994                                 return;
995                         }
996                 }
997
998                 /* Ensure we're in sync with current lease state. */
999                 fsp_lease_update(fsp);
1000
1001                 TALLOC_FREE(lck);
1002         }
1003
1004         if (!break_needed) {
1005                 DEBUG(10,("%s: skip break\n", __func__));
1006                 return;
1007         }
1008
1009         if (break_from == SMB2_LEASE_NONE) {
1010                 struct file_id_buf idbuf;
1011                 DBG_NOTICE("Already downgraded oplock to none on %s: %s\n",
1012                            file_id_str_buf(fsp->file_id, &idbuf),
1013                            fsp_str_dbg(fsp));
1014                 return;
1015         }
1016
1017         DEBUG(10, ("break_from=%u, break_to=%u\n",
1018                    (unsigned)break_from, (unsigned)break_to));
1019
1020         if (break_from == break_to) {
1021                 struct file_id_buf idbuf;
1022                 DBG_NOTICE("Already downgraded oplock to %u on %s: %s\n",
1023                            (unsigned)break_to,
1024                            file_id_str_buf(fsp->file_id, &idbuf),
1025                            fsp_str_dbg(fsp));
1026                 return;
1027         }
1028
1029         /* Need to wait before sending a break
1030            message if we sent ourselves this message. */
1031         if (server_id_equal(&self, &src)) {
1032                 wait_before_sending_break();
1033         }
1034
1035 #if defined(WITH_SMB1SERVER)
1036         if (conn_using_smb2(sconn)) {
1037 #endif
1038                 send_break_message_smb2(fsp, break_from, break_to);
1039 #if defined(WITH_SMB1SERVER)
1040         } else {
1041                 send_break_message_smb1(fsp, (break_to & SMB2_LEASE_READ) ?
1042                                         OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
1043         }
1044 #endif
1045
1046         if ((break_from == SMB2_LEASE_READ) &&
1047             (break_to == SMB2_LEASE_NONE)) {
1048                 /*
1049                  * This is an async break without a reply and thus no timeout
1050                  *
1051                  * leases are handled above.
1052                  */
1053                 if (fsp->oplock_type != LEASE_OPLOCK) {
1054                         remove_oplock(fsp);
1055                 }
1056                 return;
1057         }
1058         if (fsp->oplock_type == LEASE_OPLOCK) {
1059                 return;
1060         }
1061
1062         fsp->sent_oplock_break = (break_to & SMB2_LEASE_READ) ?
1063                 LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
1064
1065         add_oplock_timeout_handler(fsp);
1066 }
1067
1068 /*******************************************************************
1069  This handles the kernel oplock break message.
1070 *******************************************************************/
1071
1072 static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
1073                                         void *private_data,
1074                                         uint32_t msg_type,
1075                                         struct server_id src,
1076                                         DATA_BLOB *data)
1077 {
1078         struct file_id id;
1079         struct file_id_buf idbuf;
1080         unsigned long file_id;
1081         files_struct *fsp;
1082         struct smbd_server_connection *sconn =
1083                 talloc_get_type_abort(private_data,
1084                 struct smbd_server_connection);
1085         struct server_id_buf tmp;
1086
1087         if (data->data == NULL) {
1088                 DEBUG(0, ("Got NULL buffer\n"));
1089                 return;
1090         }
1091
1092         if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
1093                 DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
1094                 return;
1095         }
1096
1097         /* Pull the data from the message. */
1098         pull_file_id_24((char *)data->data, &id);
1099         file_id = (unsigned long)IVAL(data->data, 24);
1100
1101         DBG_DEBUG("Got kernel oplock break message from pid %s: %s/%u\n",
1102                   server_id_str_buf(src, &tmp),
1103                   file_id_str_buf(id, &idbuf),
1104                   (unsigned int)file_id);
1105
1106         fsp = initial_break_processing(sconn, id, file_id);
1107
1108         if (fsp == NULL) {
1109                 DEBUG(3, ("Got a kernel oplock break message for a file "
1110                           "I don't know about\n"));
1111                 return;
1112         }
1113
1114         if (fsp->sent_oplock_break != NO_BREAK_SENT) {
1115                 /* This is ok, kernel oplocks come in completely async */
1116                 DEBUG(3, ("Got a kernel oplock request while waiting for a "
1117                           "break reply\n"));
1118                 return;
1119         }
1120
1121 #if defined(WITH_SMB1SERVER)
1122         if (conn_using_smb2(sconn)) {
1123 #endif
1124                 send_break_message_smb2(fsp, 0, OPLOCKLEVEL_NONE);
1125 #if defined(WITH_SMB1SERVER)
1126         } else {
1127                 send_break_message_smb1(fsp, OPLOCKLEVEL_NONE);
1128         }
1129 #endif
1130
1131         fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
1132
1133         add_oplock_timeout_handler(fsp);
1134 }
1135
1136 static void send_break_to_none(struct messaging_context *msg_ctx,
1137                                const struct file_id *id,
1138                                const struct share_mode_entry *e)
1139 {
1140         NTSTATUS status;
1141         status = send_break_message(msg_ctx, id, e, OPLOCK_NONE);
1142         if (!NT_STATUS_IS_OK(status)) {
1143                 DBG_DEBUG("send_break_message failed: %s\n",
1144                           nt_errstr(status));
1145         }
1146 }
1147 struct break_to_none_state {
1148         struct smbd_server_connection *sconn;
1149         struct file_id id;
1150         struct smb2_lease_key lease_key;
1151         struct GUID client_guid;
1152         size_t num_read_leases;
1153         uint32_t total_lease_types;
1154 };
1155
1156 static bool do_break_lease_to_none(struct share_mode_entry *e,
1157                                    void *private_data)
1158 {
1159         struct break_to_none_state *state = private_data;
1160         uint32_t current_state = 0;
1161         bool our_own;
1162         NTSTATUS status;
1163
1164         DBG_DEBUG("lease_key=%"PRIu64"/%"PRIu64"\n",
1165                   e->lease_key.data[0],
1166                   e->lease_key.data[1]);
1167
1168         status = leases_db_get(&e->client_guid,
1169                                &e->lease_key,
1170                                &state->id,
1171                                &current_state,
1172                                NULL, /* breaking */
1173                                NULL, /* breaking_to_requested */
1174                                NULL, /* breaking_to_required */
1175                                NULL, /* lease_version */
1176                                NULL); /* epoch */
1177         if (!NT_STATUS_IS_OK(status)) {
1178                 DBG_WARNING("leases_db_get failed: %s\n",
1179                             nt_errstr(status));
1180                 return false;
1181         }
1182
1183         state->total_lease_types |= current_state;
1184
1185         if ((current_state & SMB2_LEASE_READ) == 0) {
1186                 return false;
1187         }
1188
1189         state->num_read_leases += 1;
1190
1191         our_own = smb2_lease_equal(&state->client_guid,
1192                                    &state->lease_key,
1193                                    &e->client_guid,
1194                                    &e->lease_key);
1195         if (our_own) {
1196                 DEBUG(10, ("Don't break our own lease\n"));
1197                 return false;
1198         }
1199
1200         DBG_DEBUG("Breaking %"PRIu64"/%"PRIu64" to none\n",
1201                   e->lease_key.data[0],
1202                   e->lease_key.data[1]);
1203
1204         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1205
1206         return false;
1207 }
1208
1209 static bool do_break_oplock_to_none(struct share_mode_entry *e,
1210                                     bool *modified,
1211                                     void *private_data)
1212 {
1213         struct break_to_none_state *state = private_data;
1214
1215         if (e->op_type == LEASE_OPLOCK) {
1216                 /*
1217                  * Already being taken care of
1218                  */
1219                 return false;
1220         }
1221
1222         /*
1223          * As there could have been multiple writes waiting at the
1224          * lock_share_entry gate we may not be the first to
1225          * enter. Hence the state of the op_types in the share mode
1226          * entries may be partly NO_OPLOCK and partly LEVEL_II
1227          * oplock. It will do no harm to re-send break messages to
1228          * those smbd's that are still waiting their turn to remove
1229          * their LEVEL_II state, and also no harm to ignore existing
1230          * NO_OPLOCK states. JRA.
1231          */
1232
1233         DBG_DEBUG("e->op_type == %d\n", e->op_type);
1234
1235         state->total_lease_types |= map_oplock_to_lease_type(e->op_type);
1236
1237         if (e->op_type == NO_OPLOCK) {
1238                 return false;
1239         }
1240
1241         state->num_read_leases += 1;
1242
1243         /* Paranoia .... */
1244         SMB_ASSERT(!EXCLUSIVE_OPLOCK_TYPE(e->op_type));
1245
1246         send_break_to_none(state->sconn->msg_ctx, &state->id, e);
1247
1248         return false;
1249 }
1250
1251 /****************************************************************************
1252  This function is called on any file modification or lock request. If a file
1253  is level 2 oplocked then it must tell all other level 2 holders to break to
1254  none.
1255 ****************************************************************************/
1256
1257 static void contend_level2_oplocks_begin_default(files_struct *fsp,
1258                                               enum level2_contention_type type)
1259 {
1260         struct break_to_none_state state = {
1261                 .sconn = fsp->conn->sconn, .id = fsp->file_id,
1262         };
1263         struct share_mode_lock *lck = NULL;
1264         uint32_t fsp_lease = fsp_lease_type(fsp);
1265         bool ok, has_read_lease;
1266
1267         /*
1268          * If this file is level II oplocked then we need
1269          * to grab the shared memory lock and inform all
1270          * other files with a level II lock that they need
1271          * to flush their read caches. We keep the lock over
1272          * the shared memory area whilst doing this.
1273          */
1274
1275         if (fsp_lease & SMB2_LEASE_WRITE) {
1276                 /*
1277                  * There can't be any level2 oplocks, we're alone.
1278                  */
1279                 return;
1280         }
1281
1282         has_read_lease = file_has_read_lease(fsp);
1283         if (!has_read_lease) {
1284                 DEBUG(10, ("No read oplocks around\n"));
1285                 return;
1286         }
1287
1288         if (fsp->oplock_type == LEASE_OPLOCK) {
1289                 state.client_guid = *fsp_client_guid(fsp);
1290                 state.lease_key = fsp->lease->lease.lease_key;
1291                 DEBUG(10, ("Breaking through lease key %"PRIu64"/%"PRIu64"\n",
1292                            state.lease_key.data[0],
1293                            state.lease_key.data[1]));
1294         }
1295
1296         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
1297         if (lck == NULL) {
1298                 struct file_id_buf idbuf;
1299                 DBG_WARNING("failed to lock share mode entry for file %s.\n",
1300                             file_id_str_buf(state.id, &idbuf));
1301                 return;
1302         }
1303
1304         /*
1305          * Walk leases and oplocks separately: We have to send one break per
1306          * lease. If we have multiple share_mode_entry having a common lease,
1307          * we would break the lease twice if we don't walk the leases list
1308          * separately.
1309          */
1310
1311         ok = share_mode_forall_leases(lck, do_break_lease_to_none, &state);
1312         if (!ok) {
1313                 DBG_WARNING("share_mode_forall_leases failed\n");
1314         }
1315
1316         ok = share_mode_forall_entries(lck, do_break_oplock_to_none, &state);
1317         if (!ok) {
1318                 DBG_WARNING("share_mode_forall_entries failed\n");
1319         }
1320
1321         {
1322                 /*
1323                  * Lazy update here. It might be that all leases
1324                  * have gone in the meantime.
1325                  */
1326                 uint32_t acc, sh, ls;
1327                 share_mode_flags_get(lck, &acc, &sh, &ls);
1328                 ls = state.total_lease_types;
1329                 share_mode_flags_set(lck, acc, sh, ls, NULL);
1330         }
1331
1332         TALLOC_FREE(lck);
1333 }
1334
1335 void smbd_contend_level2_oplocks_begin(files_struct *fsp,
1336                                   enum level2_contention_type type)
1337 {
1338         contend_level2_oplocks_begin_default(fsp, type);
1339 }
1340
1341 void smbd_contend_level2_oplocks_end(files_struct *fsp,
1342                                 enum level2_contention_type type)
1343 {
1344         return;
1345 }
1346
1347 /****************************************************************************
1348  Linearize a share mode entry struct to an internal oplock break message.
1349 ****************************************************************************/
1350
1351 void share_mode_entry_to_message(char *msg, const struct file_id *id,
1352                                  const struct share_mode_entry *e)
1353 {
1354         SIVAL(msg,OP_BREAK_MSG_PID_OFFSET,(uint32_t)e->pid.pid);
1355         SBVAL(msg,OP_BREAK_MSG_MID_OFFSET,e->op_mid);
1356         SSVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET,e->op_type);
1357         SIVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET,e->access_mask);
1358         SIVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET,e->share_access);
1359         SIVAL(msg,OP_BREAK_MSG_PRIV_OFFSET,e->private_options);
1360         SIVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET,(uint32_t)e->time.tv_sec);
1361         SIVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET,(uint32_t)e->time.tv_usec);
1362         /*
1363          * "id" used to be part of share_mode_entry, thus the strange
1364          * place to put this. Feel free to move somewhere else :-)
1365          */
1366         push_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1367         SIVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET,e->share_file_id);
1368         SIVAL(msg,OP_BREAK_MSG_UID_OFFSET,e->uid);
1369         SSVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET,e->flags);
1370         SIVAL(msg,OP_BREAK_MSG_NAME_HASH_OFFSET,e->name_hash);
1371         SIVAL(msg,OP_BREAK_MSG_VNN_OFFSET,e->pid.vnn);
1372 }
1373
1374 /****************************************************************************
1375  De-linearize an internal oplock break message to a share mode entry struct.
1376 ****************************************************************************/
1377
1378 void message_to_share_mode_entry(struct file_id *id,
1379                                  struct share_mode_entry *e,
1380                                  const char *msg)
1381 {
1382         e->pid = (struct server_id){
1383                 .pid = (pid_t)IVAL(msg, OP_BREAK_MSG_PID_OFFSET),
1384                 .vnn = IVAL(msg, OP_BREAK_MSG_VNN_OFFSET),
1385         };
1386         e->op_mid = BVAL(msg,OP_BREAK_MSG_MID_OFFSET);
1387         e->op_type = SVAL(msg,OP_BREAK_MSG_OP_TYPE_OFFSET);
1388         e->access_mask = IVAL(msg,OP_BREAK_MSG_ACCESS_MASK_OFFSET);
1389         e->share_access = IVAL(msg,OP_BREAK_MSG_SHARE_ACCESS_OFFSET);
1390         e->private_options = IVAL(msg,OP_BREAK_MSG_PRIV_OFFSET);
1391         e->time.tv_sec = (time_t)IVAL(msg,OP_BREAK_MSG_TIME_SEC_OFFSET);
1392         e->time.tv_usec = (int)IVAL(msg,OP_BREAK_MSG_TIME_USEC_OFFSET);
1393         /*
1394          * "id" used to be part of share_mode_entry, thus the strange
1395          * place to put this. Feel free to move somewhere else :-)
1396          */
1397         pull_file_id_24(msg+OP_BREAK_MSG_DEV_OFFSET, id);
1398         e->share_file_id = (unsigned long)IVAL(msg,OP_BREAK_MSG_FILE_ID_OFFSET);
1399         e->uid = (uint32_t)IVAL(msg,OP_BREAK_MSG_UID_OFFSET);
1400         e->flags = (uint16_t)SVAL(msg,OP_BREAK_MSG_FLAGS_OFFSET);
1401         e->name_hash = IVAL(msg, OP_BREAK_MSG_NAME_HASH_OFFSET);
1402 }
1403
1404 /****************************************************************************
1405  Setup oplocks for this process.
1406 ****************************************************************************/
1407
1408 bool init_oplocks(struct smbd_server_connection *sconn)
1409 {
1410         DEBUG(3,("init_oplocks: initializing messages.\n"));
1411
1412         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_BREAK_REQUEST,
1413                            process_oplock_break_message);
1414         messaging_register(sconn->msg_ctx, sconn, MSG_SMB_KERNEL_BREAK,
1415                            process_kernel_oplock_break);
1416         return true;
1417 }
1418
1419 void init_kernel_oplocks(struct smbd_server_connection *sconn)
1420 {
1421         struct kernel_oplocks *koplocks = sconn->oplocks.kernel_ops;
1422
1423         /* only initialize once */
1424         if (koplocks == NULL) {
1425 #ifdef HAVE_KERNEL_OPLOCKS_LINUX
1426                 koplocks = linux_init_kernel_oplocks(sconn);
1427 #endif
1428                 sconn->oplocks.kernel_ops = koplocks;
1429         }
1430 }