]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_asp.c
remove gcc warnings and cleanup inline mess
[netatalk.git] / etc / afpd / afp_asp.c
1 /*
2  * $Id: afp_asp.c,v 1.18.6.6.2.2 2008-11-25 15:16:31 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 extern struct oforks    *writtenfork;
47
48 static AFPObj *child;
49
50 static void afp_authprint_remove(AFPObj *);
51
52 static void afp_asp_close(AFPObj *obj)
53 {
54     ASP asp = obj->handle;
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(stat(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()
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, 0 ) < 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, 0 ) < 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, 0 ) < 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()
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     obj->exit = afp_asp_die;
217     obj->reply = (int (*)()) asp_cmdreply;
218     obj->attention = (int (*)(void *, AFPUserBytes)) asp_attention;
219     child = obj;
220     asp = (ASP) obj->handle;
221
222     /* install signal handlers 
223      * With ASP tickle handler is done in the parent process
224     */
225     memset(&action, 0, sizeof(action));
226
227     /* install SIGHUP */
228     action.sa_handler = afp_asp_reload; 
229     sigemptyset( &action.sa_mask );
230     sigaddset(&action.sa_mask, SIGTERM);
231     sigaddset(&action.sa_mask, SIGUSR1);
232 #ifdef SERVERTEXT
233     sigaddset(&action.sa_mask, SIGUSR2);
234 #endif    
235     action.sa_flags = SA_RESTART;
236     if ( sigaction( SIGHUP, &action, 0 ) < 0 ) {
237         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
238         afp_asp_die(EXITERR_SYS);
239     }
240
241     /*  install SIGTERM */
242     action.sa_handler = afp_asp_die;
243     sigemptyset( &action.sa_mask );
244     sigaddset(&action.sa_mask, SIGHUP);
245     sigaddset(&action.sa_mask, SIGUSR1);
246 #ifdef SERVERTEXT
247     sigaddset(&action.sa_mask, SIGUSR2);
248 #endif    
249     action.sa_flags = SA_RESTART;
250     if ( sigaction( SIGTERM, &action, 0 ) < 0 ) {
251         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
252         afp_asp_die(EXITERR_SYS);
253     }
254
255 #ifdef SERVERTEXT
256     /* Added for server message support */
257     action.sa_handler = afp_asp_getmesg;
258     sigemptyset( &action.sa_mask );
259     sigaddset(&action.sa_mask, SIGTERM);
260     sigaddset(&action.sa_mask, SIGUSR1);
261     sigaddset(&action.sa_mask, SIGHUP);
262     action.sa_flags = SA_RESTART;
263     if ( sigaction( SIGUSR2, &action, 0) < 0 ) {
264         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
265         afp_asp_die(EXITERR_SYS);
266     }
267 #endif /* SERVERTEXT */
268
269     /*  SIGUSR1 - set down in 5 minutes  */
270     action.sa_handler = afp_asp_timedown; 
271     sigemptyset( &action.sa_mask );
272     sigaddset(&action.sa_mask, SIGHUP);
273     sigaddset(&action.sa_mask, SIGTERM);
274 #ifdef SERVERTEXT
275     sigaddset(&action.sa_mask, SIGUSR2);
276 #endif    
277     action.sa_flags = SA_RESTART;
278     if ( sigaction( SIGUSR1, &action, 0 ) < 0 ) {
279         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
280         afp_asp_die(EXITERR_SYS);
281     }
282
283     LOG(log_info, logtype_afpd, "session from %u.%u:%u on %u.%u:%u",
284         ntohs( asp->asp_sat.sat_addr.s_net ),
285         asp->asp_sat.sat_addr.s_node, asp->asp_sat.sat_port,
286         ntohs( atp_sockaddr( asp->asp_atp )->sat_addr.s_net ),
287         atp_sockaddr( asp->asp_atp )->sat_addr.s_node,
288         atp_sockaddr( asp->asp_atp )->sat_port );
289
290     while ((reply = asp_getrequest(asp))) {
291         if (reload_request) {
292             reload_request = 0;
293             load_volumes(child);
294         }
295         switch (reply) {
296         case ASPFUNC_CLOSE :
297             afp_asp_close(obj);
298             LOG(log_info, logtype_afpd, "done" );
299
300 #ifdef DEBUG1
301             if ( obj->options.flags & OPTION_DEBUG ) {
302                 printf( "done\n" );
303             }
304 #endif
305             return;
306             break;
307
308         case ASPFUNC_CMD :
309 #ifdef AFS
310             if ( writtenfork ) {
311                 if ( flushfork( writtenfork ) < 0 ) {
312                     LOG(log_error, logtype_afpd, "main flushfork: %s",
313                                                 strerror(errno));
314                 }
315                 writtenfork = NULL;
316             }
317 #endif /* AFS */
318             func = (u_char) asp->commands[0];
319 #ifdef DEBUG1
320             if ( obj->options.flags & OPTION_DEBUG ) {
321                 printf("command: %d (%s)\n", func, AfpNum2name(func));
322                 bprint( asp->commands, asp->cmdlen );
323             }
324 #endif            
325             if ( afp_switch[ func ] != NULL ) {
326                 /*
327                  * The function called from afp_switch is expected to
328                  * read its parameters out of buf, put its
329                  * results in replybuf (updating rbuflen), and
330                  * return an error code.
331                 */
332                 asp->datalen = ASP_DATASIZ;
333                 reply = (*afp_switch[ func ])(obj,
334                                               asp->commands, asp->cmdlen,
335                                               asp->data, &asp->datalen);
336 #ifdef FORCE_UIDGID
337                 /* bring everything back to old euid, egid */
338                 if (obj->force_uid)
339                     restore_uidgid ( &obj->uidgid );
340 #endif /* FORCE_UIDGID */
341             } else {
342                 LOG(log_error, logtype_afpd, "bad function %X", func );
343                 asp->datalen = 0;
344                 reply = AFPERR_NOOP;
345             }
346 #ifdef DEBUG1
347             if ( obj->options.flags & OPTION_DEBUG ) {
348                 printf( "reply: %d, %d\n", reply, ccnt++ );
349                 bprint( asp->data, asp->datalen );
350             }
351 #endif
352             if ( asp_cmdreply( asp, reply ) < 0 ) {
353                 LOG(log_error, logtype_afpd, "asp_cmdreply: %s", strerror(errno) );
354                 afp_asp_die(EXITERR_CLNT);
355             }
356             break;
357
358         case ASPFUNC_WRITE :
359             func = (u_char) asp->commands[0];
360 #ifdef DEBUG1
361             if ( obj->options.flags & OPTION_DEBUG ) {
362                 printf( "(write) command: %d\n", func );
363                 bprint( asp->commands, asp->cmdlen );
364             }
365 #endif
366             if ( afp_switch[ func ] != NULL ) {
367                 asp->datalen = ASP_DATASIZ;
368                 reply = (*afp_switch[ func ])(obj,
369                                               asp->commands, asp->cmdlen,
370                                               asp->data, &asp->datalen);
371 #ifdef FORCE_UIDGID
372                 /* bring everything back to old euid, egid */
373                 if (obj->force_uid)
374                     restore_uidgid ( &obj->uidgid );
375 #endif /* FORCE_UIDGID */
376             } else {
377                 LOG(log_error, logtype_afpd, "(write) bad function %X", func );
378                 asp->datalen = 0;
379                 reply = AFPERR_NOOP;
380             }
381 #ifdef DEBUG1
382             if ( obj->options.flags & OPTION_DEBUG ) {
383                 printf( "(write) reply code: %d, %d\n", reply, ccnt++ );
384                 bprint( asp->data, asp->datalen );
385             }
386 #endif
387             if ( asp_wrtreply( asp, reply ) < 0 ) {
388                 LOG(log_error, logtype_afpd, "asp_wrtreply: %s", strerror(errno) );
389                 afp_asp_die(EXITERR_CLNT);
390             }
391             break;
392         default:
393             /*
394                * Bad asp packet.  Probably should have asp filter them,
395                * since they are typically things like out-of-order packet.
396                */
397             LOG(log_info, logtype_afpd, "main: asp_getrequest: %d", reply );
398             break;
399         }
400 #ifdef DEBUG1
401         if ( obj->options.flags & OPTION_DEBUG ) {
402 #ifdef notdef
403             pdesc( stdout );
404 #endif /* notdef */
405             of_pforkdesc( stdout );
406             fflush( stdout );
407         }
408 #endif
409     }
410 }
411
412 #endif