]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_asp.c
remove most sparse warning 'Using plain integer as NULL pointer'
[netatalk.git] / etc / afpd / afp_asp.c
1 /*
2  * $Id: afp_asp.c,v 1.26 2009-10-14 02:24:05 didg Exp $
3  *
4  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
5  * Copyright (c) 1990,1993 Regents of The University of Michigan.
6  * All Rights Reserved.  See COPYRIGHT.
7  *
8  * modified from main.c. this handles afp over asp. 
9  */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif /* HAVE_CONFIG_H */
14
15 #ifndef NO_DDP
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <signal.h>
21 #include <atalk/logger.h>
22 #include <errno.h>
23 #ifdef HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif /* HAVE_SYS_TIME_H */
26 #ifdef HAVE_SYS_STAT_H
27 #include <sys/stat.h>
28 #endif /* HAVE_SYS_STAT_H */
29
30 #include <netatalk/endian.h>
31 #include <atalk/atp.h>
32 #include <atalk/asp.h>
33 #include <atalk/compat.h>
34 #include <atalk/util.h>
35
36 #include "globals.h"
37 #include "switch.h"
38 #include "auth.h"
39 #include "fork.h"
40
41 #ifdef FORCE_UIDGID
42 #warning UIDGID
43 #include "uid.h"
44 #endif /* FORCE_UIDGID */
45
46 static AFPObj *child;
47
48 static void afp_authprint_remove(AFPObj *);
49
50 static void afp_asp_close(AFPObj *obj)
51 {
52     ASP asp = obj->handle;
53
54     close_all_vol();
55     if (obj->options.authprintdir) afp_authprint_remove(obj);
56
57     if (obj->logout)
58         (*obj->logout)();
59
60     LOG(log_info, logtype_afpd, "%.2fKB read, %.2fKB written",
61         asp->read_count / 1024.0, asp->write_count / 1024.0);
62     asp_close( asp );
63 }
64
65 /* removes the authprint trailing when appropriate */
66 static void afp_authprint_remove(AFPObj *obj)
67 {
68     ASP asp = obj->handle;
69     char addr_filename[256];
70     char addr_filename_buff[256];
71     struct stat cap_st;
72
73     sprintf(addr_filename, "%s/net%d.%dnode%d", obj->options.authprintdir,
74                 ntohs( asp->asp_sat.sat_addr.s_net )/256,
75                 ntohs( asp->asp_sat.sat_addr.s_net )%256,
76                 asp->asp_sat.sat_addr.s_node );
77
78     memset( addr_filename_buff, 0, 256 );
79
80     if(stat(addr_filename, &cap_st) == 0) {
81         if( S_ISREG(cap_st.st_mode) ) {
82             int len;
83             int capfd = open( addr_filename, O_RDONLY );
84             if ((len = read( capfd, addr_filename_buff, 256 )) > 0) {
85                 int file_pid;
86                 char *p_filepid;
87                 close(capfd);
88                 addr_filename_buff[len] = 0;
89                 if ( (p_filepid = strrchr(addr_filename_buff, ':')) != NULL) {
90                     *p_filepid = '\0';
91                     p_filepid++;
92                     file_pid = atoi(p_filepid);
93                     if (file_pid == (int)getpid()) {
94                         if(unlink(addr_filename) == 0) {
95                             LOG(log_info, logtype_afpd, "removed %s", addr_filename);
96                         } else {
97                             LOG(log_info, logtype_afpd, "error removing %s: %s",
98                                     addr_filename, strerror(errno));
99                         }
100                     } else {
101                         LOG(log_info, logtype_afpd, "%s belongs to another pid %d",
102                              addr_filename, file_pid );
103                     }
104                 } else { /* no pid info */
105                     if (unlink(addr_filename) == 0) {
106                         LOG(log_info, logtype_afpd, "removed %s", addr_filename );
107                     } else {
108                         LOG(log_info, logtype_afpd, "error removing %s: %s",
109                                 addr_filename, strerror(errno));
110                     }
111                 }
112             } else {
113                 LOG(log_info, logtype_afpd, "couldn't read data from %s", addr_filename );
114             }
115         } else {
116             LOG(log_info, logtype_afpd, "%s is not a regular file", addr_filename );
117         }
118     } else {
119         LOG(log_info, logtype_afpd, "error stat'ing %s: %s",
120                    addr_filename, strerror(errno));
121     }
122 }
123
124 /* ------------------------
125  * SIGTERM
126 */
127 static void afp_asp_die(const int sig)
128 {
129     ASP asp = child->handle;
130
131     asp_attention(asp, AFPATTN_SHUTDOWN);
132     if ( asp_shutdown( asp ) < 0 ) {
133         LOG(log_error, logtype_afpd, "afp_die: asp_shutdown: %s", strerror(errno) );
134     }
135
136     afp_asp_close(child);
137     if (sig == SIGTERM || sig == SIGALRM)
138         exit( 0 );
139     else
140         exit(sig);
141 }
142
143 /* -----------------------------
144  * SIGUSR1
145  */
146 static void afp_asp_timedown(int sig _U_)
147 {
148     struct sigaction    sv;
149     struct itimerval    it;
150
151     /* shutdown and don't reconnect. server going down in 5 minutes. */
152     asp_attention(child->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
153                   AFPATTN_TIME(5));
154
155     it.it_interval.tv_sec = 0;
156     it.it_interval.tv_usec = 0;
157     it.it_value.tv_sec = 300;
158     it.it_value.tv_usec = 0;
159     if ( setitimer( ITIMER_REAL, &it, NULL ) < 0 ) {
160         LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) );
161         afp_asp_die(EXITERR_SYS);
162     }
163
164     memset(&sv, 0, sizeof(sv));
165     sv.sa_handler = afp_asp_die;
166     sigemptyset( &sv.sa_mask );
167     sigaddset(&sv.sa_mask, SIGHUP);
168     sigaddset(&sv.sa_mask, SIGTERM);
169     sv.sa_flags = SA_RESTART;
170     if ( sigaction( SIGALRM, &sv, NULL ) < 0 ) {
171         LOG(log_error, logtype_afpd, "afp_timedown: sigaction: %s", strerror(errno) );
172         afp_asp_die(EXITERR_SYS);
173     }
174
175     /* ignore myself */
176     sv.sa_handler = SIG_IGN;
177     sigemptyset( &sv.sa_mask );
178     sv.sa_flags = SA_RESTART;
179     if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) {
180         LOG(log_error, logtype_afpd, "afp_timedown: sigaction SIGUSR1: %s", strerror(errno) );
181         afp_asp_die(EXITERR_SYS);
182     }
183 }
184
185 /* ---------------------------------
186  * SIGHUP reload configuration file
187 */
188 extern volatile int reload_request;
189
190 static void afp_asp_reload(int sig _U_)
191 {
192     reload_request = 1;
193 }
194
195 /* ---------------------- */
196 #ifdef SERVERTEXT
197 static void afp_asp_getmesg (int sig _U_)
198 {
199     readmessage(child);
200     asp_attention(child->handle, AFPATTN_MESG | AFPATTN_TIME(5));
201 }
202 #endif /* SERVERTEXT */
203
204 /* ---------------------- */
205 void afp_over_asp(AFPObj *obj)
206 {
207     ASP asp;
208     struct sigaction  action;
209     int         func,  reply = 0;
210 #ifdef DEBUG1
211     int ccnt = 0;
212 #endif    
213
214     obj->exit = afp_asp_die;
215     obj->reply = (int (*)()) asp_cmdreply;
216     obj->attention = (int (*)(void *, AFPUserBytes)) asp_attention;
217     child = obj;
218     asp = (ASP) obj->handle;
219
220     /* install signal handlers 
221      * With ASP tickle handler is done in the parent process
222     */
223     memset(&action, 0, sizeof(action));
224
225     /* install SIGHUP */
226     action.sa_handler = afp_asp_reload; 
227     sigemptyset( &action.sa_mask );
228     sigaddset(&action.sa_mask, SIGTERM);
229     sigaddset(&action.sa_mask, SIGUSR1);
230 #ifdef SERVERTEXT
231     sigaddset(&action.sa_mask, SIGUSR2);
232 #endif    
233     action.sa_flags = SA_RESTART;
234     if ( sigaction( SIGHUP, &action, NULL ) < 0 ) {
235         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
236         afp_asp_die(EXITERR_SYS);
237     }
238
239     /*  install SIGTERM */
240     action.sa_handler = afp_asp_die;
241     sigemptyset( &action.sa_mask );
242     sigaddset(&action.sa_mask, SIGHUP);
243     sigaddset(&action.sa_mask, SIGUSR1);
244 #ifdef SERVERTEXT
245     sigaddset(&action.sa_mask, SIGUSR2);
246 #endif    
247     action.sa_flags = SA_RESTART;
248     if ( sigaction( SIGTERM, &action, NULL ) < 0 ) {
249         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
250         afp_asp_die(EXITERR_SYS);
251     }
252
253 #ifdef SERVERTEXT
254     /* Added for server message support */
255     action.sa_handler = afp_asp_getmesg;
256     sigemptyset( &action.sa_mask );
257     sigaddset(&action.sa_mask, SIGTERM);
258     sigaddset(&action.sa_mask, SIGUSR1);
259     sigaddset(&action.sa_mask, SIGHUP);
260     action.sa_flags = SA_RESTART;
261     if ( sigaction( SIGUSR2, &action, NULL) < 0 ) {
262         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
263         afp_asp_die(EXITERR_SYS);
264     }
265 #endif /* SERVERTEXT */
266
267     /*  SIGUSR1 - set down in 5 minutes  */
268     action.sa_handler = afp_asp_timedown; 
269     sigemptyset( &action.sa_mask );
270     sigaddset(&action.sa_mask, SIGHUP);
271     sigaddset(&action.sa_mask, SIGTERM);
272 #ifdef SERVERTEXT
273     sigaddset(&action.sa_mask, SIGUSR2);
274 #endif    
275     action.sa_flags = SA_RESTART;
276     if ( sigaction( SIGUSR1, &action, NULL ) < 0 ) {
277         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
278         afp_asp_die(EXITERR_SYS);
279     }
280
281     LOG(log_info, logtype_afpd, "session from %u.%u:%u on %u.%u:%u",
282         ntohs( asp->asp_sat.sat_addr.s_net ),
283         asp->asp_sat.sat_addr.s_node, asp->asp_sat.sat_port,
284         ntohs( atp_sockaddr( asp->asp_atp )->sat_addr.s_net ),
285         atp_sockaddr( asp->asp_atp )->sat_addr.s_node,
286         atp_sockaddr( asp->asp_atp )->sat_port );
287
288     while ((reply = asp_getrequest(asp))) {
289         if (reload_request) {
290             reload_request = 0;
291             load_volumes(child);
292         }
293         switch (reply) {
294         case ASPFUNC_CLOSE :
295             afp_asp_close(obj);
296             LOG(log_info, logtype_afpd, "done" );
297
298 #ifdef DEBUG1
299             if ( obj->options.flags & OPTION_DEBUG ) {
300                 printf( "done\n" );
301             }
302 #endif
303             return;
304             break;
305
306         case ASPFUNC_CMD :
307 #ifdef AFS
308             if ( writtenfork ) {
309                 if ( flushfork( writtenfork ) < 0 ) {
310                     LOG(log_error, logtype_afpd, "main flushfork: %s",
311                                                 strerror(errno));
312                 }
313                 writtenfork = NULL;
314             }
315 #endif /* AFS */
316             func = (u_char) asp->commands[0];
317 #ifdef DEBUG1
318             if ( obj->options.flags & OPTION_DEBUG ) {
319                 printf("command: %d (%s)\n", func, AfpNum2name(func));
320                 bprint( asp->commands, asp->cmdlen );
321             }
322 #endif            
323             if ( afp_switch[ func ] != NULL ) {
324                 /*
325                  * The function called from afp_switch is expected to
326                  * read its parameters out of buf, put its
327                  * results in replybuf (updating rbuflen), and
328                  * return an error code.
329                 */
330                 asp->datalen = ASP_DATASIZ;
331                 reply = (*afp_switch[ func ])(obj,
332                                               asp->commands, asp->cmdlen,
333                                               asp->data, &asp->datalen);
334 #ifdef FORCE_UIDGID
335                 /* bring everything back to old euid, egid */
336                 if (obj->force_uid)
337                     restore_uidgid ( &obj->uidgid );
338 #endif /* FORCE_UIDGID */
339             } else {
340                 LOG(log_error, logtype_afpd, "bad function %X", func );
341                 asp->datalen = 0;
342                 reply = AFPERR_NOOP;
343             }
344 #ifdef DEBUG1
345             if ( obj->options.flags & OPTION_DEBUG ) {
346                 printf( "reply: %d, %d\n", reply, ccnt++ );
347                 bprint( asp->data, asp->datalen );
348             }
349 #endif
350             if ( asp_cmdreply( asp, reply ) < 0 ) {
351                 LOG(log_error, logtype_afpd, "asp_cmdreply: %s", strerror(errno) );
352                 afp_asp_die(EXITERR_CLNT);
353             }
354             break;
355
356         case ASPFUNC_WRITE :
357             func = (u_char) asp->commands[0];
358 #ifdef DEBUG1
359             if ( obj->options.flags & OPTION_DEBUG ) {
360                 printf( "(write) command: %d\n", func );
361                 bprint( asp->commands, asp->cmdlen );
362             }
363 #endif
364             if ( afp_switch[ func ] != NULL ) {
365                 asp->datalen = ASP_DATASIZ;
366                 reply = (*afp_switch[ func ])(obj,
367                                               asp->commands, asp->cmdlen,
368                                               asp->data, &asp->datalen);
369 #ifdef FORCE_UIDGID
370                 /* bring everything back to old euid, egid */
371                 if (obj->force_uid)
372                     restore_uidgid ( &obj->uidgid );
373 #endif /* FORCE_UIDGID */
374             } else {
375                 LOG(log_error, logtype_afpd, "(write) bad function %X", func );
376                 asp->datalen = 0;
377                 reply = AFPERR_NOOP;
378             }
379 #ifdef DEBUG1
380             if ( obj->options.flags & OPTION_DEBUG ) {
381                 printf( "(write) reply code: %d, %d\n", reply, ccnt++ );
382                 bprint( asp->data, asp->datalen );
383             }
384 #endif
385             if ( asp_wrtreply( asp, reply ) < 0 ) {
386                 LOG(log_error, logtype_afpd, "asp_wrtreply: %s", strerror(errno) );
387                 afp_asp_die(EXITERR_CLNT);
388             }
389             break;
390         default:
391             /*
392                * Bad asp packet.  Probably should have asp filter them,
393                * since they are typically things like out-of-order packet.
394                */
395             LOG(log_info, logtype_afpd, "main: asp_getrequest: %d", reply );
396             break;
397         }
398 #ifdef DEBUG1
399         if ( obj->options.flags & OPTION_DEBUG ) {
400 #ifdef notdef
401             pdesc( stdout );
402 #endif /* notdef */
403             of_pforkdesc( stdout );
404             fflush( stdout );
405         }
406 #endif
407     }
408 }
409
410 #endif