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