move soem variables from server.c that don't belong there.
[ira/wip.git] / source3 / smbd / oplock.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    oplock processing
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 /* Oplock ipc UDP socket. */
27 int oplock_sock = -1;
28 uint16 oplock_port = 0;
29
30 /* Current number of oplocks we have outstanding. */
31 int32 global_oplocks_open = 0;
32 BOOL global_oplock_break = False;
33
34
35 extern int smb_read_error;
36
37
38 /****************************************************************************
39   open the oplock IPC socket communication
40 ****************************************************************************/
41 BOOL open_oplock_ipc(void)
42 {
43   struct sockaddr_in sock_name;
44   int len = sizeof(sock_name);
45
46   DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
47
48   /* Open a lookback UDP socket on a random port. */
49   oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK));
50   if (oplock_sock == -1)
51   {
52     DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
53 address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
54     oplock_port = 0;
55     return(False);
56   }
57
58   /* Find out the transient UDP port we have been allocated. */
59   if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0)
60   {
61     DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
62             strerror(errno)));
63     close(oplock_sock);
64     oplock_sock = -1;
65     oplock_port = 0;
66     return False;
67   }
68   oplock_port = ntohs(sock_name.sin_port);
69
70   DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n", 
71             (int)getpid(), oplock_port));
72
73   return True;
74 }
75
76 /****************************************************************************
77   process an oplock break message.
78 ****************************************************************************/
79 BOOL process_local_message(int sock, char *buffer, int buf_size)
80 {
81   int32 msg_len;
82   uint16 from_port;
83   char *msg_start;
84
85   msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
86   from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET);
87
88   msg_start = &buffer[UDP_CMD_HEADER_LEN];
89
90   DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", 
91             msg_len, from_port));
92
93   /* Switch on message command - currently OPLOCK_BREAK_CMD is the
94      only valid request. */
95
96   switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET))
97   {
98     case OPLOCK_BREAK_CMD:
99       /* Ensure that the msg length is correct. */
100       if(msg_len != OPLOCK_BREAK_MSG_LEN)
101       {
102         DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \
103 should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
104         return False;
105       }
106       {
107         uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
108         uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
109         uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
110         struct timeval tval;
111         struct sockaddr_in toaddr;
112
113         tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
114         tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
115
116         DEBUG(5,("process_local_message: oplock break request from \
117 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
118
119         /*
120          * If we have no record of any currently open oplocks,
121          * it's not an error, as a close command may have
122          * just been issued on the file that was oplocked.
123          * Just return success in this case.
124          */
125
126         if(global_oplocks_open != 0)
127         {
128           if(oplock_break(dev, inode, &tval) == False)
129           {
130             DEBUG(0,("process_local_message: oplock break failed - \
131 not returning udp message.\n"));
132             return False;
133           }
134         }
135         else
136         {
137           DEBUG(3,("process_local_message: oplock break requested with no outstanding \
138 oplocks. Returning success.\n"));
139         }
140
141         /* Send the message back after OR'ing in the 'REPLY' bit. */
142         SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
143   
144         bzero((char *)&toaddr,sizeof(toaddr));
145         toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
146         toaddr.sin_port = htons(from_port);
147         toaddr.sin_family = AF_INET;
148
149         if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
150                 (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) 
151         {
152           DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
153                     remotepid, strerror(errno)));
154           return False;
155         }
156
157         DEBUG(5,("process_local_message: oplock break reply sent to \
158 pid %d, port %d, for file dev = %x, inode = %x\n", remotepid, 
159                 from_port, dev, inode));
160
161       }
162       break;
163     /* 
164      * Keep this as a debug case - eventually we can remove it.
165      */
166     case 0x8001:
167       DEBUG(0,("process_local_message: Received unsolicited break \
168 reply - dumping info.\n"));
169
170       if(msg_len != OPLOCK_BREAK_MSG_LEN)
171       {
172         DEBUG(0,("process_local_message: ubr: incorrect length for reply \
173 (was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
174         return False;
175       }
176
177       {
178         uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
179         uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
180         uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
181
182         DEBUG(0,("process_local_message: unsolicited oplock break reply from \
183 pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
184
185        }
186        return False;
187
188     default:
189       DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
190                 (unsigned int)SVAL(msg_start,0)));
191       return False;
192   }
193   return True;
194 }
195
196 /****************************************************************************
197  Process an oplock break directly.
198 ****************************************************************************/
199 BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
200 {
201   extern struct current_user current_user;
202   extern int Client;
203   char *inbuf = NULL;
204   char *outbuf = NULL;
205   files_struct *fsp = NULL;
206   time_t start_time;
207   BOOL shutdown_server = False;
208   connection_struct *saved_conn;
209   int saved_vuid;
210   pstring saved_dir; 
211
212   if( DEBUGLVL( 3 ) )
213     {
214     dbgtext( "oplock_break: called for dev = %x, inode = %x.\n", dev, inode );
215     dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open );
216     }
217
218   /* We need to search the file open table for the
219      entry containing this dev and inode, and ensure
220      we have an oplock on it. */
221   fsp = file_find_dit(dev, inode, tval);
222
223   if(fsp == NULL)
224   {
225     /* The file could have been closed in the meantime - return success. */
226     if( DEBUGLVL( 0 ) )
227       {
228       dbgtext( "oplock_break: cannot find open file with " );
229       dbgtext( "dev = %x, inode = %x ", dev, inode);
230       dbgtext( "allowing break to succeed.\n" );
231       }
232     return True;
233   }
234
235   /* Ensure we have an oplock on the file */
236
237   /* There is a potential race condition in that an oplock could
238      have been broken due to another udp request, and yet there are
239      still oplock break messages being sent in the udp message
240      queue for this file. So return true if we don't have an oplock,
241      as we may have just freed it.
242    */
243
244   if(!fsp->granted_oplock)
245   {
246     if( DEBUGLVL( 0 ) )
247       {
248       dbgtext( "oplock_break: file %s ", fsp->fsp_name );
249       dbgtext( "(dev = %x, inode = %x) has no oplock.\n", dev, inode );
250       dbgtext( "Allowing break to succeed regardless.\n" );
251       }
252     return True;
253   }
254
255   /* mark the oplock break as sent - we don't want to send twice! */
256   if (fsp->sent_oplock_break)
257   {
258     if( DEBUGLVL( 0 ) )
259       {
260       dbgtext( "oplock_break: ERROR: oplock_break already sent for " );
261       dbgtext( "file %s ", fsp->fsp_name);
262       dbgtext( "(dev = %x, inode = %x)\n", dev, inode );
263       }
264
265     /* We have to fail the open here as we cannot send another oplock break on
266        this file whilst we are awaiting a response from the client - neither
267        can we allow another open to succeed while we are waiting for the
268        client.
269      */
270     return False;
271   }
272
273   /* Now comes the horrid part. We must send an oplock break to the client,
274      and then process incoming messages until we get a close or oplock release.
275      At this point we know we need a new inbuf/outbuf buffer pair.
276      We cannot use these staticaly as we may recurse into here due to
277      messages crossing on the wire.
278    */
279
280   if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
281   {
282     DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
283     return False;
284   }
285
286   if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
287   {
288     DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
289     free(inbuf);
290     inbuf = NULL;
291     return False;
292   }
293
294   /* Prepare the SMBlockingX message. */
295   bzero(outbuf,smb_size);
296   set_message(outbuf,8,0,True);
297
298   SCVAL(outbuf,smb_com,SMBlockingX);
299   SSVAL(outbuf,smb_tid,fsp->conn->cnum);
300   SSVAL(outbuf,smb_pid,0xFFFF);
301   SSVAL(outbuf,smb_uid,0);
302   SSVAL(outbuf,smb_mid,0xFFFF);
303   SCVAL(outbuf,smb_vwv0,0xFF);
304   SSVAL(outbuf,smb_vwv2,fsp->fnum);
305   SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
306   /* Change this when we have level II oplocks. */
307   SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE);
308  
309   send_smb(Client, outbuf);
310
311   /* Remember we just sent an oplock break on this file. */
312   fsp->sent_oplock_break = True;
313
314   /* We need this in case a readraw crosses on the wire. */
315   global_oplock_break = True;
316  
317   /* Process incoming messages. */
318
319   /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT
320      seconds we should just die.... */
321
322   start_time = time(NULL);
323
324   /*
325    * Save the information we need to re-become the
326    * user, then unbecome the user whilst we're doing this.
327    */
328   saved_conn = fsp->conn;
329   saved_vuid = current_user.vuid;
330   GetWd(saved_dir);
331   unbecome_user();
332
333   while(OPEN_FSP(fsp) && fsp->granted_oplock)
334   {
335     if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
336     {
337       /*
338        * Die if we got an error.
339        */
340
341       if (smb_read_error == READ_EOF)
342         DEBUG( 0, ( "oplock_break: end of file from client\n" ) );
343  
344       if (smb_read_error == READ_ERROR)
345         DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) );
346
347       if (smb_read_error == READ_TIMEOUT)
348         DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n",
349                      OPLOCK_BREAK_TIMEOUT ) );
350
351       DEBUGADD( 0, ( "oplock_break failed for file %s ", fsp->fsp_name ) );
352       DEBUGADD( 0, ( "(dev = %x, inode = %x).\n", dev, inode));
353       shutdown_server = True;
354       break;
355     }
356
357     /*
358      * There are certain SMB requests that we shouldn't allow
359      * to recurse. opens, renames and deletes are the obvious
360      * ones. This is handled in the switch_message() function.
361      * If global_oplock_break is set they will push the packet onto
362      * the pending smb queue and return -1 (no reply).
363      * JRA.
364      */
365
366     process_smb(inbuf, outbuf);
367
368     /*
369      * Die if we go over the time limit.
370      */
371
372     if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT)
373     {
374       if( DEBUGLVL( 0 ) )
375         {
376         dbgtext( "oplock_break: no break received from client " );
377         dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT );
378         dbgtext( "oplock_break failed for file %s ", fsp->fsp_name );
379         dbgtext( "(dev = %x, inode = %x).\n", dev, inode );
380         }
381       shutdown_server = True;
382       break;
383     }
384   }
385
386   /*
387    * Go back to being the user who requested the oplock
388    * break.
389    */
390   if(!become_user(saved_conn, saved_vuid))
391   {
392     DEBUG( 0, ( "oplock_break: unable to re-become user!" ) );
393     DEBUGADD( 0, ( "Shutting down server\n" ) );
394     close_sockets();
395     close(oplock_sock);
396     exit_server("unable to re-become user");
397   }
398   /* Including the directory. */
399   ChDir(saved_dir);
400
401   /* Free the buffers we've been using to recurse. */
402   free(inbuf);
403   free(outbuf);
404
405   /* We need this in case a readraw crossed on the wire. */
406   if(global_oplock_break)
407     global_oplock_break = False;
408
409   /*
410    * If the client did not respond we must die.
411    */
412
413   if(shutdown_server)
414   {
415     DEBUG( 0, ( "oplock_break: client failure in break - " ) );
416     DEBUGADD( 0, ( "shutting down this smbd.\n" ) );
417     close_sockets();
418     close(oplock_sock);
419     exit_server("oplock break failure");
420   }
421
422   if(OPEN_FSP(fsp))
423   {
424     /* The lockingX reply will have removed the oplock flag 
425        from the sharemode. */
426     /* Paranoia.... */
427     fsp->granted_oplock = False;
428     fsp->sent_oplock_break = False;
429     global_oplocks_open--;
430   }
431
432   /* Santity check - remove this later. JRA */
433   if(global_oplocks_open < 0)
434   {
435     DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n",
436               global_oplocks_open));
437     exit_server("oplock_break: global_oplocks_open < 0");
438   }
439
440   if( DEBUGLVL( 3 ) )
441     {
442     dbgtext( "oplock_break: returning success for " );
443     dbgtext( "dev = %x, inode = %x.\n", dev, inode );
444     dbgtext( "Current global_oplocks_open = %d\n", global_oplocks_open );
445     }
446
447   return True;
448 }
449
450 /****************************************************************************
451 Send an oplock break message to another smbd process. If the oplock is held 
452 by the local smbd then call the oplock break function directly.
453 ****************************************************************************/
454
455 BOOL request_oplock_break(share_mode_entry *share_entry, 
456                           uint32 dev, uint32 inode)
457 {
458   char op_break_msg[OPLOCK_BREAK_MSG_LEN];
459   struct sockaddr_in addr_out;
460   int pid = getpid();
461   time_t start_time;
462   int time_left;
463
464   if(pid == share_entry->pid)
465   {
466     /* We are breaking our own oplock, make sure it's us. */
467     if(share_entry->op_port != oplock_port)
468     {
469       DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
470 should be %d\n", pid, share_entry->op_port, oplock_port));
471       return False;
472     }
473
474     DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
475
476     /* Call oplock break direct. */
477     return oplock_break(dev, inode, &share_entry->time);
478   }
479
480   /* We need to send a OPLOCK_BREAK_CMD message to the
481      port in the share mode entry. */
482
483   SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
484   SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
485   SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev);
486   SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode);
487   SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
488   SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
489
490   /* set the address and port */
491   bzero((char *)&addr_out,sizeof(addr_out));
492   addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
493   addr_out.sin_port = htons( share_entry->op_port );
494   addr_out.sin_family = AF_INET;
495    
496   if( DEBUGLVL( 3 ) )
497     {
498     dbgtext( "request_oplock_break: sending a oplock break message to " );
499     dbgtext( "pid %d on port %d ", share_entry->pid, share_entry->op_port );
500     dbgtext( "for dev = %x, inode = %x\n", dev, inode );
501     }
502
503   if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
504          (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
505   {
506     if( DEBUGLVL( 0 ) )
507       {
508       dbgtext( "request_oplock_break: failed when sending a oplock " );
509       dbgtext( "break message to pid %d ", share_entry->pid );
510       dbgtext( "on port %d ", share_entry->op_port );
511       dbgtext( "for dev = %x, inode = %x.\n", dev, inode );
512       dbgtext( "Error was %s\n", strerror(errno) );
513       }
514     return False;
515   }
516
517   /*
518    * Now we must await the oplock broken message coming back
519    * from the target smbd process. Timeout if it fails to
520    * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds.
521    * While we get messages that aren't ours, loop.
522    */
523
524   start_time = time(NULL);
525   time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR;
526
527   while(time_left >= 0)
528   {
529     char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
530     int32 reply_msg_len;
531     uint16 reply_from_port;
532     char *reply_msg_start;
533
534     if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
535                time_left ? time_left * 1000 : 1) == False)
536     {
537       if(smb_read_error == READ_TIMEOUT)
538       {
539         if( DEBUGLVL( 0 ) )
540           {
541           dbgtext( "request_oplock_break: no response received to oplock " );
542           dbgtext( "break request to pid %d ", share_entry->pid );
543           dbgtext( "on port %d ", share_entry->op_port );
544           dbgtext( "for dev = %x, inode = %x\n", dev, inode );
545           }
546         /*
547          * This is a hack to make handling of failing clients more robust.
548          * If a oplock break response message is not received in the timeout
549          * period we may assume that the smbd servicing that client holding
550          * the oplock has died and the client changes were lost anyway, so
551          * we should continue to try and open the file.
552          */
553         break;
554       }
555       else
556         if( DEBUGLVL( 0 ) )
557           {
558           dbgtext( "request_oplock_break: error in response received " );
559           dbgtext( "to oplock break request to pid %d ", share_entry->pid );
560           dbgtext( "on port %d ", share_entry->op_port );
561           dbgtext( "for dev = %x, inode = %x.\n", dev, inode );
562           dbgtext( "Error was (%s).\n", strerror(errno) );
563           }
564       return False;
565     }
566
567     reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET);
568     reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET);
569
570     reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN];
571
572     if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
573     {
574       /* Ignore it. */
575       DEBUG( 0, ( "request_oplock_break: invalid message length received." ) );
576       DEBUGADD( 0, ( "  Ignoring.\n" ) );
577       continue;
578     }
579
580     /*
581      * Test to see if this is the reply we are awaiting.
582      */
583
584     if((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) &&
585        (reply_from_port == share_entry->op_port) && 
586        (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], 
587                &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
588                OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0))
589     {
590       /*
591        * This is the reply we've been waiting for.
592        */
593       break;
594     }
595     else
596     {
597       /*
598        * This is another message - probably a break request.
599        * Process it to prevent potential deadlock.
600        * Note that the code in switch_message() prevents
601        * us from recursing into here as any SMB requests
602        * we might process that would cause another oplock
603        * break request to be made will be queued.
604        * JRA.
605        */
606
607       process_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply));
608     }
609
610     time_left -= (time(NULL) - start_time);
611   }
612
613   DEBUG(3,("request_oplock_break: broke oplock.\n"));
614
615   return True;
616 }
617
618
619 /****************************************************************************
620   Attempt to break an oplock on a file (if oplocked).
621   Returns True if the file was closed as a result of
622   the oplock break, False otherwise.
623   Used as a last ditch attempt to free a space in the 
624   file table when we have run out.
625 ****************************************************************************/
626 BOOL attempt_close_oplocked_file(files_struct *fsp)
627 {
628
629   DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name));
630
631   if (fsp->open && fsp->granted_oplock && !fsp->sent_oplock_break) {
632
633     /* Try and break the oplock. */
634     file_fd_struct *fd_ptr = fsp->fd_ptr;
635     if(oplock_break( fd_ptr->dev, fd_ptr->inode, &fsp->open_time)) {
636       if(!fsp->open) /* Did the oplock break close the file ? */
637         return True;
638     }
639   }
640
641   return False;
642 }
643