2 * Copyright (c) 1990,1996 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
13 #include <sys/signal.h>
15 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <sys/param.h>
20 #include <netatalk/at.h>
21 #include <atalk/compat.h>
22 #include <atalk/atp.h>
23 #include <atalk/asp.h>
25 #include <atalk/server_child.h>
26 #include "asp_child.h"
28 static ASP server_asp;
29 static struct server_child *children = NULL;
30 static struct asp_child **asp_ac = NULL;
32 /* send tickles and check tickle status of connections
33 * thoughts on using a hashed list:
34 * + child_cleanup, finding slots
35 * - tickle_handler, freeing, tickles
36 * if setup for a large number of connections,
37 * + space: if actual connections < potential
38 * - space: actual connections ~ potential
40 static void tickle_handler()
45 for (sid = 0; sid < children->nsessions; sid++) {
46 if (asp_ac[sid] == NULL || asp_ac[sid]->ac_state == ACSTATE_DEAD)
49 if (++asp_ac[sid]->ac_state >= ACSTATE_BAD) {
50 /* kill. if already dead, just continue */
51 if (kill( asp_ac[ sid ]->ac_pid, SIGTERM) == 0)
52 syslog( LOG_INFO, "asp_alrm: %d timed out",
53 asp_ac[ sid ]->ac_pid );
55 asp_ac[ sid ]->ac_state = ACSTATE_DEAD;
59 /* send off a tickle */
60 asp_tickle(server_asp, sid, &asp_ac[sid]->ac_sat);
64 static void child_cleanup(const pid_t pid)
68 for (i = 0; i < children->nsessions; i++)
69 if (asp_ac[i] && (asp_ac[i]->ac_pid == pid)) {
70 asp_ac[i]->ac_state = ACSTATE_DEAD;
77 void asp_kill(int sig)
80 server_child_kill(children, CHILD_ASPFORK, sig);
85 * This call handles open, tickle, and getstatus requests. On a
86 * successful open, it forks a child process.
87 * It returns an ASP to the child and parent and NULL if there is
90 ASP asp_getsession(ASP asp, server_child *server_children,
93 struct sigaction action;
94 struct itimerval timer;
95 struct sockaddr_at sat;
96 struct atp_block atpb;
98 struct iovec iov[ 8 ];
104 if (!(children = server_children))
107 if ((asp_ac = (struct asp_child **)
108 calloc(server_children->nsessions, sizeof(struct asp_child *)))
114 /* install cleanup pointer */
115 server_child_setup(children, CHILD_ASPFORK, child_cleanup);
117 /* install tickle handler */
118 memset(&action, 0, sizeof(action));
119 action.sa_handler = tickle_handler;
120 sigemptyset(&action.sa_mask);
121 action.sa_flags = SA_RESTART;
123 timer.it_interval.tv_sec = timer.it_value.tv_sec = tickleval;
124 timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
125 if ((sigaction(SIGALRM, &action, NULL) < 0) ||
126 (setitimer(ITIMER_REAL, &timer, NULL) < 0)) {
134 memset( &sat, 0, sizeof( struct sockaddr_at ));
136 sat.sat_len = sizeof( struct sockaddr_at );
138 sat.sat_family = AF_APPLETALK;
139 sat.sat_addr.s_net = ATADDR_ANYNET;
140 sat.sat_addr.s_node = ATADDR_ANYNODE;
141 sat.sat_port = ATADDR_ANYPORT;
142 atpb.atp_saddr = &sat;
143 atpb.atp_rreqdata = asp->cmdbuf;
144 atpb.atp_rreqdlen = sizeof( asp->cmdbuf );
145 while ( atp_rreq( asp->asp_atp, &atpb ) < 0 ) {
146 if ( errno == EINTR || errno == EAGAIN ) {
152 switch ( asp->cmdbuf[ 0 ] ) {
154 sid = asp->cmdbuf[1];
155 if ((asp_ac[sid] != NULL) && (asp_ac[sid]->ac_state != ACSTATE_DEAD))
156 asp_ac[sid]->ac_state = ACSTATE_OK;
161 printf( "asp stat\n" );
163 if ( asp->asp_slen > 0 ) {
165 memcpy( asp->cmdbuf + 4, asp->asp_status, asp->asp_slen );
166 iov[ 0 ].iov_base = asp->cmdbuf;
167 iov[ 0 ].iov_len = 4 + asp->asp_slen;
168 atpb.atp_sresiov = iov;
169 atpb.atp_sresiovcnt = 1;
170 atp_sresp( asp->asp_atp, &atpb );
175 if (children->count < children->nsessions) {
178 for (sid = 0; sid < children->nsessions; sid++) {
179 if (asp_ac[sid] == NULL)
182 if (asp_ac[sid]->ac_state == ACSTATE_DEAD) {
189 if ((atp = atp_open(ATADDR_ANYPORT,
190 &(atp_sockaddr(asp->asp_atp)->sat_addr))) == NULL)
193 switch ((pid = fork())) {
195 signal(SIGTERM, SIG_DFL);
196 signal(SIGHUP, SIG_DFL);
197 /* free/close some things */
198 for (i = 0; i < children->nsessions; i++ ) {
199 if ( asp_ac[i] != NULL )
204 server_child_free(children);
206 atp_close(asp->asp_atp);
211 asp->asp_wss = asp->cmdbuf[1];
214 asp->asp_flags = ASPFL_SSS;
217 case -1 : /* error */
218 asp->cmdbuf[ 0 ] = 0;
219 asp->cmdbuf[ 1 ] = 0;
220 asperr = ASPERR_SERVBUSY;
223 default : /* parent process */
224 switch (server_child_add(children, CHILD_ASPFORK, pid)) {
225 case 0: /* added child */
226 if ((asp_ac[sid] = (struct asp_child *)
227 malloc(sizeof(struct asp_child)))) {
228 asp_ac[sid]->ac_pid = pid;
229 asp_ac[sid]->ac_state = ACSTATE_OK;
230 asp_ac[sid]->ac_sat = sat;
231 asp_ac[sid]->ac_sat.sat_port = asp->cmdbuf[1];
233 asp->cmdbuf[0] = atp_sockaddr(atp)->sat_port;
234 asp->cmdbuf[1] = sid;
237 } /* fall through if malloc fails */
238 case -1: /* bad error */
241 default: /* non-fatal error */
249 asp->cmdbuf[0] = asp->cmdbuf[1] = 0;
250 asperr = ASPERR_SERVBUSY;
253 memcpy( asp->cmdbuf + 2, &asperr, sizeof(asperr));
254 iov[ 0 ].iov_base = asp->cmdbuf;
255 iov[ 0 ].iov_len = 4;
256 atpb.atp_sresiov = iov;
257 atpb.atp_sresiovcnt = 1;
258 atp_sresp( asp->asp_atp, &atpb );
262 syslog(LOG_INFO, "ASPUnknown %d", asp->cmdbuf[0]);