]> arthur.barton.de Git - netatalk.git/blob - libatalk/pap/pap_slinit.c
Added checking for USE_CRACKLIB
[netatalk.git] / libatalk / pap / pap_slinit.c
1 /*
2  * Copyright (c) 1990,1996 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <syslog.h>
9 #include <errno.h>
10 #include <sys/signal.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <sys/uio.h>
14 #include <sys/wait.h>
15 #include <sys/socket.h>
16 #include <sys/param.h>
17 #include <netatalk/at.h>
18 #include <atalk/compat.h>
19 #include <atalk/atp.h>
20 #include <atalk/pap.h>
21
22 #include <atalk/server_child.h>
23 #include "pap_child.h"
24
25 static PAP server_pap;
26 static struct server_child *children = NULL;
27 static struct pap_child    **pap_ac = NULL;
28
29 /* send tickles and check tickle status of connections */
30 static void tickle_handler()
31 {
32   int sid;
33   
34   /* check status */
35   for (sid = 0; sid < children->nsessions; sid++) {
36     if (pap_ac[sid] == NULL || pap_ac[sid]->ac_state == ACSTATE_DEAD) 
37       continue;
38     
39     if (++pap_ac[sid]->ac_state >= ACSTATE_BAD) {
40       /* kill. if already dead, just continue */
41       if (kill( pap_ac[ sid ]->ac_pid, SIGTERM) == 0)
42         syslog( LOG_INFO, "pap_alrm: %d timed out",
43                 pap_ac[ sid ]->ac_pid );
44
45       pap_ac[ sid ]->ac_state = ACSTATE_DEAD;
46       continue;
47     }
48
49     /* send off a tickle */
50     pap_tickle(server_pap, sid, &pap_ac[sid]->ac_sat);
51   }
52 }
53
54 static void child_cleanup(const pid_t pid)
55 {
56   int i;
57
58   for (i = 0; i < children->nsessions; i++)
59     if (pap_ac[i] && (pap_ac[i]->ac_pid == pid)) {
60       pap_ac[i]->ac_state = ACSTATE_DEAD;
61       break;
62     }
63 }
64
65
66 /* kill children */
67 void pap_kill(int sig)
68 {
69   if (children) 
70     server_child_kill(children, CHILD_PAPFORK, sig);
71 }
72
73
74 /*
75  * This call handles open, tickle, and getstatus requests. On a
76  * successful open, it forks a child process. 
77  * It returns an PAP to the child and parent and NULL if there is
78  * an error.
79  */
80 PAP pap_slinit(PAP pap, server_child *server_children, 
81                const int tickleval)
82 {
83     struct sigaction action;
84     struct itimerval timer;
85     struct sockaddr_at  sat;
86     struct atp_block    atpb;
87     ATP                 atp;
88     struct iovec        iov[ 8 ];
89     pid_t               pid;
90     int                 i, sid;
91     u_short             paperr;
92
93     if (!pap->inited) {
94       if (!(children = server_children))
95         return NULL;
96
97       if ((pap_ac = (struct pap_child **) 
98            calloc(server_children->nsessions, sizeof(struct pap_child *)))
99            == NULL)
100         return NULL;
101
102       server_pap = pap;
103
104       /* install cleanup pointer */
105       server_child_setup(children, CHILD_PAPFORK, child_cleanup);
106
107       /* install tickle handler */
108       action.sa_handler = tickle_handler;
109       sigemptyset(&action.sa_mask);
110       action.sa_flags = SA_RESTART;
111
112       timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
113       timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
114       if ((setitimer(ITIMER_REAL, &timer, NULL) < 0) ||
115           (sigaction(SIGALRM, &action, NULL) < 0)) {
116         exit(1);
117       }
118
119       pap->inited = 1;
120     }
121                     
122     memset( &sat, 0, sizeof( struct sockaddr_at ));
123 #ifdef BSD4_4
124     sat.sat_len = sizeof( struct sockaddr_at );
125 #endif BSD4_4
126     sat.sat_family = AF_APPLETALK;
127     sat.sat_addr.s_net = ATADDR_ANYNET;
128     sat.sat_addr.s_node = ATADDR_ANYNODE;
129     sat.sat_port = ATADDR_ANYPORT;
130     atpb.atp_saddr = &sat;
131     atpb.atp_rreqdata = pap->cmdbuf;
132     atpb.atp_rreqdlen = sizeof( pap->cmdbuf );
133     while ( atp_rreq( pap->pap_atp, &atpb ) < 0 ) {
134       if ( errno == EINTR || errno == EAGAIN ) {
135         continue;
136       }
137       return( NULL );
138     }
139     
140     switch ( pap->cmdbuf[ 0 ] ) {
141     case PAPFUNC_TICKLE:
142       sid = pap->cmdbuf[1];
143       if ((pap_ac[sid] != NULL) && (pap_ac[sid]->ac_state != ACSTATE_DEAD))
144         pap_ac[sid]->ac_state = ACSTATE_OK;
145       break;
146
147     case PAPFUNC_STAT:
148 #ifdef EBUG
149       printf( "pap stat\n" );
150 #endif EBUG
151       if ( pap->pap_slen > 0 ) {
152         pap->cmdbuf[0] = 0;
153         bcopy( pap->pap_status, pap->cmdbuf + 4, pap->pap_slen );
154         iov[ 0 ].iov_base = pap->cmdbuf;
155         iov[ 0 ].iov_len = 4 + pap->pap_slen;
156         atpb.atp_sresiov = iov;
157         atpb.atp_sresiovcnt = 1;
158         atp_sresp( pap->pap_atp, &atpb );
159       }
160       break;
161
162     case PAPFUNC_OPEN :
163       if (children->count < children->nsessions) {
164
165         /* find a slot */
166         for (sid = 0; sid < children->nsessions; sid++) {
167           if (pap_ac[sid] == NULL)
168             break;
169
170           if (pap_ac[sid]->ac_state == ACSTATE_DEAD) {
171             free(pap_ac[sid]);
172             pap_ac[sid] = NULL;
173             break;
174           }
175         }
176
177         if ((atp = atp_open(0)) == NULL) 
178           return NULL;
179
180         switch (pid = fork()) {
181         case 0 : /* child */
182           signal(SIGTERM, SIG_DFL);
183           signal(SIGHUP, SIG_DFL);
184           /* free/close some things */
185           for (i = 0; i < children->nsessions; i++ ) {
186             if ( pap_ac[i] != NULL )
187               free( pap_ac[i] );
188           }
189           free(pap_ac);
190           
191           server_child_free(children);
192           children = NULL;
193           atp_close(pap->pap_atp);
194
195           pap->child = 1;
196           pap->pap_atp = atp;
197           pap->pap_sat = sat;
198           pap->pap_wss = pap->cmdbuf[1];
199           pap->pap_seq = 0;
200           pap->pap_sid = sid;
201           pap->pap_flags = PAPFL_SSS;
202           return pap;
203           
204         case -1 : /* error */
205           pap->cmdbuf[ 0 ] = 0;
206           pap->cmdbuf[ 1 ] = 0;
207           paperr = PAPERR_SERVBUSY;
208           break;
209           
210         default : /* parent process */
211           switch (server_child_add(children, CHILD_PAPFORK, pid)) {
212           case 0: /* added child */
213             if (pap_ac[sid] = (struct pap_child *) 
214                 malloc(sizeof(struct pap_child))) {
215               pap_ac[sid]->ac_pid = pid;
216               pap_ac[sid]->ac_state = ACSTATE_OK;
217               pap_ac[sid]->ac_sat = sat;
218               pap_ac[sid]->ac_sat.sat_port = pap->cmdbuf[1];
219               
220               pap->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
221               pap->cmdbuf[1] = sid;
222               paperr = PAPERR_OK;
223               break;
224             } /* fall through if malloc fails */
225           case -1: /* bad error */
226             kill(pid, SIGQUIT); 
227             break;
228           default: /* non-fatal error */
229             break;
230           }
231           atp_close(atp);
232           break;
233         }
234         
235       } else {
236         pap->cmdbuf[0] = pap->cmdbuf[1] = 0;
237         paperr = PAPERR_SERVBUSY;
238       }
239
240       bcopy( &paperr, pap->cmdbuf + 2, sizeof( u_short ));
241       iov[ 0 ].iov_base = pap->cmdbuf;
242       iov[ 0 ].iov_len = 4;
243       atpb.atp_sresiov = iov;
244       atpb.atp_sresiovcnt = 1;
245       atp_sresp( pap->pap_atp, &atpb );
246       break;
247
248     default:
249       syslog(LOG_INFO, "PAPUnknown %d", pap->cmdbuf[0]);
250       break;
251     }
252
253     return pap;
254 }