cli_setup_creds new arguments added.
[samba.git] / source3 / smbd / connection.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    connection claim routines
5    Copyright (C) Andrew Tridgell 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
25 extern fstring remote_machine;
26
27 extern int DEBUGLEVEL;
28
29 /****************************************************************************
30 simple routines to do connection counting
31 ****************************************************************************/
32 BOOL yield_connection(connection_struct *conn,char *name,int max_connections)
33 {
34         struct connect_record crec;
35         pstring fname;
36         int fd;
37         int mypid = getpid();
38         int i;
39
40         DEBUG(3,("Yielding connection to %s\n",name));
41
42         if (max_connections <= 0)
43                 return(True);
44
45         bzero(&crec,sizeof(crec));
46
47         pstrcpy(fname,lp_lockdir());
48         trim_string(fname,"","/");
49
50         pstrcat(fname,"/");
51         pstrcat(fname,name);
52         pstrcat(fname,".LCK");
53
54         fd = sys_open(fname,O_RDWR,0);
55         if (fd == -1) {
56                 DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
57                 return(False);
58         }
59
60         if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
61                 DEBUG(0,("ERROR: can't get lock on %s\n", fname));
62                 return False;
63         }
64
65         /* find the right spot */
66         for (i=0;i<max_connections;i++) {
67                 if (read(fd, &crec,sizeof(crec)) != sizeof(crec)) {
68                         DEBUG(2,("Entry not found in lock file %s\n",fname));
69                         if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
70                                 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
71                         }
72                         close(fd);
73                         return(False);
74                 }
75                 if (crec.pid == mypid && crec.cnum == conn->cnum)
76                         break;
77         }
78
79         if (crec.pid != mypid || crec.cnum != conn->cnum) {
80                 if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
81                         DEBUG(0,("ERROR: can't release lock on %s\n", fname));
82                 }
83                 close(fd);
84                 DEBUG(2,("Entry not found in lock file %s\n",fname));
85                 return(False);
86         }
87
88         bzero((void *)&crec,sizeof(crec));
89   
90         /* remove our mark */
91         if (sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
92             write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
93                 DEBUG(2,("Couldn't update lock file %s (%s)\n",fname,strerror(errno)));
94                 if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
95                         DEBUG(0,("ERROR: can't release lock on %s\n", fname));
96                 }
97                 close(fd);
98                 return(False);
99         }
100
101         if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
102                 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
103         }
104
105         DEBUG(3,("Yield successful\n"));
106
107         close(fd);
108         return(True);
109 }
110
111
112 /****************************************************************************
113 simple routines to do connection counting
114 ****************************************************************************/
115 BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
116 {
117         extern int Client;
118         struct connect_record crec;
119         pstring fname;
120         int fd=-1;
121         int i,foundi= -1;
122         int total_recs;
123         
124         if (max_connections <= 0)
125                 return(True);
126         
127         DEBUG(5,("trying claim %s %s %d\n",lp_lockdir(),name,max_connections));
128         
129         pstrcpy(fname,lp_lockdir());
130         trim_string(fname,"","/");
131         
132         if (!directory_exist(fname,NULL))
133                 mkdir(fname,0755);
134         
135         pstrcat(fname,"/");
136         pstrcat(fname,name);
137         pstrcat(fname,".LCK");
138         
139         if (!file_exist(fname,NULL)) {
140                 fd = sys_open(fname,O_RDWR|O_CREAT|O_EXCL, 0644);
141         }
142
143         if (fd == -1) {
144                 fd = sys_open(fname,O_RDWR,0);
145         }
146         
147         if (fd == -1) {
148                 DEBUG(1,("couldn't open lock file %s\n",fname));
149                 return(False);
150         }
151
152         if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_WRLCK)==False) {
153                 DEBUG(0,("ERROR: can't get lock on %s\n", fname));
154                 return False;
155         }
156
157         total_recs = file_size(fname) / sizeof(crec);
158                         
159         /* find a free spot */
160         for (i=0;i<max_connections;i++) {
161                 if (i>=total_recs || 
162                     sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec) ||
163                     read(fd,&crec,sizeof(crec)) != sizeof(crec)) {
164                         if (foundi < 0) foundi = i;
165                         break;
166                 }
167                 
168                 if (Clear && crec.pid && !process_exists(crec.pid)) {
169                         if(sys_lseek(fd,i*sizeof(crec),SEEK_SET) != i*sizeof(crec)) {
170               DEBUG(0,("claim_connection: ERROR: sys_lseek failed to seek \
171 to %d\n", i*sizeof(crec) ));
172               continue;
173             }
174                         bzero((void *)&crec,sizeof(crec));
175                         write(fd, &crec,sizeof(crec));
176                         if (foundi < 0) foundi = i;
177                         continue;
178                 }
179                 if (foundi < 0 && (!crec.pid || !process_exists(crec.pid))) {
180                         foundi=i;
181                         if (!Clear) break;
182                 }
183         }  
184         
185         if (foundi < 0) {
186                 DEBUG(3,("no free locks in %s\n",fname));
187                 if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
188                         DEBUG(0,("ERROR: can't release lock on %s\n", fname));
189                 }
190                 close(fd);
191                 return(False);
192         }      
193         
194         /* fill in the crec */
195         bzero((void *)&crec,sizeof(crec));
196         crec.magic = 0x280267;
197         crec.pid = getpid();
198         if (conn) {
199                 crec.cnum = conn->cnum;
200                 crec.uid = conn->uid;
201                 crec.gid = conn->gid;
202                 StrnCpy(crec.name,
203                         lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
204         } else {
205                 crec.cnum = -1;
206         }
207         crec.start = time(NULL);
208         
209         StrnCpy(crec.machine,remote_machine,sizeof(crec.machine)-1);
210         StrnCpy(crec.addr,client_addr(Client),sizeof(crec.addr)-1);
211         
212         /* make our mark */
213         if (sys_lseek(fd,foundi*sizeof(crec),SEEK_SET) != foundi*sizeof(crec) ||
214             write(fd, &crec,sizeof(crec)) != sizeof(crec)) {
215                 if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
216                         DEBUG(0,("ERROR: can't release lock on %s\n", fname));
217                 }
218                 close(fd);
219                 return(False);
220         }
221
222         if (fcntl_lock(fd,SMB_F_SETLKW,0,1,F_UNLCK)==False) {
223                 DEBUG(0,("ERROR: can't release lock on %s\n", fname));
224         }
225         
226         close(fd);
227         return(True);
228 }