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