]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/afp_asp.c
31aa8a753db1fadd6af549eb83fc4270f0074712
[netatalk.git] / etc / afpd / afp_asp.c
1 /*
2  * $Id: afp_asp.c,v 1.21 2003-08-29 23:35:34 bfernhomberg 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 __inline__ void afp_authprint_remove(AFPObj *);
51
52 static __inline__ void afp_asp_close(AFPObj *obj)
53 {
54     ASP asp = obj->handle;
55
56     if (obj->options.authprintdir) afp_authprint_remove(obj);
57
58     if (obj->logout)
59         (*obj->logout)();
60
61     LOG(log_info, logtype_afpd, "%.2fKB read, %.2fKB written",
62         asp->read_count / 1024.0, asp->write_count / 1024.0);
63     asp_close( asp );
64     close_vols();
65 }
66
67 /* removes the authprint trailing when appropriate */
68 static __inline__ 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 static void afp_asp_die(const int sig)
127 {
128     ASP asp = child->handle;
129
130     asp_attention(asp, AFPATTN_SHUTDOWN);
131     if ( asp_shutdown( asp ) < 0 ) {
132         LOG(log_error, logtype_afpd, "afp_die: asp_shutdown: %s", strerror(errno) );
133     }
134
135     afp_asp_close(child);
136     if (sig == SIGTERM || sig == SIGALRM)
137         exit( 0 );
138     else
139         exit(sig);
140 }
141
142 static void afp_asp_timedown()
143 {
144     struct sigaction    sv;
145     struct itimerval    it;
146
147     /* shutdown and don't reconnect. server going down in 5 minutes. */
148     asp_attention(child->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
149                   AFPATTN_TIME(5));
150
151     it.it_interval.tv_sec = 0;
152     it.it_interval.tv_usec = 0;
153     it.it_value.tv_sec = 300;
154     it.it_value.tv_usec = 0;
155     if ( setitimer( ITIMER_REAL, &it, 0 ) < 0 ) {
156         LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) );
157         afp_asp_die(1);
158     }
159
160     memset(&sv, 0, sizeof(sv));
161     sv.sa_handler = afp_asp_die;
162     sigemptyset( &sv.sa_mask );
163     sv.sa_flags = SA_RESTART;
164     if ( sigaction( SIGALRM, &sv, 0 ) < 0 ) {
165         LOG(log_error, logtype_afpd, "afp_timedown: sigaction: %s", strerror(errno) );
166         afp_asp_die(1);
167     }
168
169     /* ignore SIGHUP */
170     sv.sa_handler = SIG_IGN;
171     sigemptyset( &sv.sa_mask );
172     sv.sa_flags = SA_RESTART;
173     if ( sigaction( SIGHUP, &sv, 0 ) < 0 ) {
174         LOG(log_error, logtype_afpd, "afp_timedown: sigaction SIGHUP: %s", strerror(errno) );
175         afp_asp_die(1);
176     }
177 }
178
179 /* ---------------------- */
180 #ifdef SERVERTEXT
181 static void afp_asp_getmesg (int sig)
182 {
183     readmessage();
184     asp_attention(child->handle, AFPATTN_MESG | AFPATTN_TIME(5));
185 }
186 #endif /* SERVERTEXT */
187
188
189 void afp_over_asp(AFPObj *obj)
190 {
191     ASP asp;
192     struct sigaction  action;
193     int         func, ccnt = 0, reply = 0;
194
195     obj->exit = afp_asp_die;
196     obj->reply = (int (*)()) asp_cmdreply;
197     obj->attention = (int (*)(void *, AFPUserBytes)) asp_attention;
198     child = obj;
199     asp = (ASP) obj->handle;
200
201     /* install signal handlers */
202     memset(&action, 0, sizeof(action));
203     action.sa_handler = afp_asp_timedown;
204     sigemptyset( &action.sa_mask );
205     action.sa_flags = SA_RESTART;
206     if ( sigaction( SIGHUP, &action, 0 ) < 0 ) {
207         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
208         afp_asp_die(1);
209     }
210
211     action.sa_handler = afp_asp_die;
212     sigemptyset( &action.sa_mask );
213     action.sa_flags = SA_RESTART;
214     if ( sigaction( SIGTERM, &action, 0 ) < 0 ) {
215         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
216         afp_asp_die(1);
217     }
218
219 #ifdef SERVERTEXT
220     /* Added for server message support */
221     action.sa_handler = afp_asp_getmesg;
222     sigemptyset( &action.sa_mask );
223     sigaddset(&action.sa_mask, SIGUSR2);
224     action.sa_flags = SA_RESTART;
225     if ( sigaction( SIGUSR2, &action, 0) < 0 ) {
226         LOG(log_error, logtype_afpd, "afp_over_asp: sigaction: %s", strerror(errno) );
227         afp_asp_die(1);
228     }
229 #endif /* SERVERTEXT */
230
231
232     LOG(log_info, logtype_afpd, "session from %u.%u:%u on %u.%u:%u",
233         ntohs( asp->asp_sat.sat_addr.s_net ),
234         asp->asp_sat.sat_addr.s_node, asp->asp_sat.sat_port,
235         ntohs( atp_sockaddr( asp->asp_atp )->sat_addr.s_net ),
236         atp_sockaddr( asp->asp_atp )->sat_addr.s_node,
237         atp_sockaddr( asp->asp_atp )->sat_port );
238
239     while ((reply = asp_getrequest(asp))) {
240         switch (reply) {
241         case ASPFUNC_CLOSE :
242             afp_asp_close(obj);
243             LOG(log_info, logtype_afpd, "done" );
244
245             if ( obj->options.flags & OPTION_DEBUG ) {
246                 printf( "done\n" );
247             }
248             return;
249             break;
250
251         case ASPFUNC_CMD :
252 #ifdef AFS
253             if ( writtenfork ) {
254                 if ( flushfork( writtenfork ) < 0 ) {
255                     LOG(log_error, logtype_afpd, "main flushfork: %s",
256                                                 strerror(errno));
257                 }
258                 writtenfork = NULL;
259             }
260 #endif /* AFS */
261             func = (u_char) asp->commands[0];
262             if ( obj->options.flags & OPTION_DEBUG ) {
263                 printf("command: %d (%s)\n", func, AfpNum2name(func));
264                 bprint( asp->commands, asp->cmdlen );
265             }
266             if ( afp_switch[ func ] != NULL ) {
267                 /*
268                  * The function called from afp_switch is expected to
269                  * read its parameters out of buf, put its
270                  * results in replybuf (updating rbuflen), and
271                  * return an error code.
272                 */
273                 asp->datalen = ASP_DATASIZ;
274                 reply = (*afp_switch[ func ])(obj,
275                                               asp->commands, asp->cmdlen,
276                                               asp->data, &asp->datalen);
277 #ifdef FORCE_UIDGID
278                 /* bring everything back to old euid, egid */
279                 if (obj->force_uid)
280                     restore_uidgid ( &obj->uidgid );
281 #endif /* FORCE_UIDGID */
282             } else {
283                 LOG(log_error, logtype_afpd, "bad function %X", func );
284                 asp->datalen = 0;
285                 reply = AFPERR_NOOP;
286             }
287             if ( obj->options.flags & OPTION_DEBUG ) {
288                 printf( "reply: %d, %d\n", reply, ccnt++ );
289                 bprint( asp->data, asp->datalen );
290             }
291
292             if ( asp_cmdreply( asp, reply ) < 0 ) {
293                 LOG(log_error, logtype_afpd, "asp_cmdreply: %s", strerror(errno) );
294                 afp_asp_die(1);
295             }
296             break;
297
298         case ASPFUNC_WRITE :
299             func = (u_char) asp->commands[0];
300             if ( obj->options.flags & OPTION_DEBUG ) {
301                 printf( "(write) command: %d\n", func );
302                 bprint( asp->commands, asp->cmdlen );
303             }
304             if ( afp_switch[ func ] != NULL ) {
305                 asp->datalen = ASP_DATASIZ;
306                 reply = (*afp_switch[ func ])(obj,
307                                               asp->commands, asp->cmdlen,
308                                               asp->data, &asp->datalen);
309 #ifdef FORCE_UIDGID
310                 /* bring everything back to old euid, egid */
311                 if (obj->force_uid)
312                     restore_uidgid ( &obj->uidgid );
313 #endif /* FORCE_UIDGID */
314             } else {
315                 LOG(log_error, logtype_afpd, "(write) bad function %X", func );
316                 asp->datalen = 0;
317                 reply = AFPERR_NOOP;
318             }
319             if ( obj->options.flags & OPTION_DEBUG ) {
320                 printf( "(write) reply code: %d, %d\n", reply, ccnt++ );
321                 bprint( asp->data, asp->datalen );
322             }
323             if ( asp_wrtreply( asp, reply ) < 0 ) {
324                 LOG(log_error, logtype_afpd, "asp_wrtreply: %s", strerror(errno) );
325                 afp_asp_die(1);
326             }
327             break;
328         default:
329             /*
330                * Bad asp packet.  Probably should have asp filter them,
331                * since they are typically things like out-of-order packet.
332                */
333             LOG(log_info, logtype_afpd, "main: asp_getrequest: %d", reply );
334             break;
335         }
336
337         if ( obj->options.flags & OPTION_DEBUG ) {
338 #ifdef notdef
339             pdesc( stdout );
340 #endif /* notdef */
341             of_pforkdesc( stdout );
342             fflush( stdout );
343         }
344     }
345 }
346
347 #endif