2
* $Id: afp_dsi.c,v 1.24.2.4 2003/11/18 21:47:41 bfernhomberg Exp $
4
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
5
* Copyright (c) 1990,1993 Regents of The University of Michigan.
6
* All Rights Reserved. See COPYRIGHT.
8
* modified from main.c. this handles afp over tcp.
13
#endif /* HAVE_CONFIG_H */
22
#endif /* HAVE_UNISTD_H */
23
#include <sys/socket.h>
25
#ifdef HAVE_SYS_STAT_H
27
#endif /* HAVE_SYS_STAT_H */
28
#include <netinet/in.h>
29
#include <arpa/inet.h>
30
#include <atalk/logger.h>
32
#include <atalk/dsi.h>
33
#include <atalk/compat.h>
34
#include <atalk/util.h>
44
#endif /* FORCE_UIDGID */
46
extern struct oforks *writtenfork;
48
#define CHILD_DIE (1 << 0)
49
#define CHILD_RUNNING (1 << 1)
58
static __inline__ void afp_dsi_close(AFPObj *obj)
60
DSI *dsi = obj->handle;
65
/* UAM had syslog control; afpd needs to reassert itself */
66
set_processname("afpd");
67
syslog_setup(log_debug, logtype_default, logoption_ndelay | logoption_pid, logfacility_daemon);
68
LOG(log_info, logtype_afpd, "%.2fKB read, %.2fKB written",
69
dsi->read_count/1024.0, dsi->write_count/1024.0);
74
/* a little bit of code duplication. */
75
static void afp_dsi_die(int sig)
77
dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN);
78
afp_dsi_close(child.obj);
79
if (sig) /* if no signal, assume dieing because logins are disabled &
80
don't log it (maintenance mode)*/
81
LOG(log_info, logtype_afpd, "Connection terminated");
82
if (sig == SIGTERM || sig == SIGALRM) {
90
static void afp_dsi_timedown()
95
child.flags |= CHILD_DIE;
96
/* shutdown and don't reconnect. server going down in 5 minutes. */
97
setmessage("The server is going down for maintenance.");
98
dsi_attention(child.obj->handle, AFPATTN_SHUTDOWN | AFPATTN_NORECONNECT |
99
AFPATTN_MESG | AFPATTN_TIME(5));
101
it.it_interval.tv_sec = 0;
102
it.it_interval.tv_usec = 0;
103
it.it_value.tv_sec = 300;
104
it.it_value.tv_usec = 0;
106
if ( setitimer( ITIMER_REAL, &it, 0 ) < 0 ) {
107
LOG(log_error, logtype_afpd, "afp_timedown: setitimer: %s", strerror(errno) );
111
memset(&sv, 0, sizeof(sv));
112
sv.sa_handler = afp_dsi_die;
113
sigemptyset( &sv.sa_mask );
114
sigaddset(&sv.sa_mask, SIGHUP);
115
sigaddset(&sv.sa_mask, SIGTERM);
116
sv.sa_flags = SA_RESTART;
117
if ( sigaction( SIGALRM, &sv, 0 ) < 0 ) {
118
LOG(log_error, logtype_afpd, "afp_timedown: sigaction: %s", strerror(errno) );
124
static void afp_dsi_getmesg (int sig)
127
dsi_attention(child.obj->handle, AFPATTN_MESG | AFPATTN_TIME(5));
129
#endif /* SERVERTEXT */
131
static void alarm_handler()
135
/* if we're in the midst of processing something,
137
if ((child.flags & CHILD_RUNNING) || (child.tickle++ < child.obj->options.timeout)) {
138
if (!(err = pollvoltime(child.obj)))
139
err = dsi_tickle(child.obj->handle);
143
} else { /* didn't receive a tickle. close connection */
144
LOG(log_error, logtype_afpd, "afp_alarm: child timed out");
151
* Signal handler for SIGUSR1 - set the debug flag and
152
* redirect stdout to <tmpdir>/afpd-debug-<pid>.
154
void afp_set_debug (int sig)
156
char fname[MAXPATHLEN];
158
snprintf(fname, MAXPATHLEN-1, "%s/afpd-debug-%d", P_tmpdir, getpid());
159
freopen(fname, "w", stdout);
160
child.obj->options.flags |= OPTION_DEBUG;
166
/* afp over dsi. this never returns. */
167
void afp_over_dsi(AFPObj *obj)
169
DSI *dsi = (DSI *) obj->handle;
172
struct sigaction action;
174
obj->exit = afp_dsi_die;
175
obj->reply = (int (*)()) dsi_cmdreply;
176
obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
179
child.tickle = child.flags = 0;
181
/* install SIGTERM and SIGHUP */
182
memset(&action, 0, sizeof(action));
183
action.sa_handler = afp_dsi_timedown;
184
sigemptyset( &action.sa_mask );
185
sigaddset(&action.sa_mask, SIGALRM);
186
sigaddset(&action.sa_mask, SIGTERM);
188
sigaddset(&action.sa_mask, SIGUSR2);
190
action.sa_flags = SA_RESTART;
191
if ( sigaction( SIGHUP, &action, 0 ) < 0 ) {
192
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
196
action.sa_handler = afp_dsi_die;
197
sigemptyset( &action.sa_mask );
198
sigaddset(&action.sa_mask, SIGALRM);
199
sigaddset(&action.sa_mask, SIGHUP);
201
sigaddset(&action.sa_mask, SIGUSR2);
203
action.sa_flags = SA_RESTART;
204
if ( sigaction( SIGTERM, &action, 0 ) < 0 ) {
205
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
210
/* Added for server message support */
211
action.sa_handler = afp_dsi_getmesg;
212
sigemptyset( &action.sa_mask );
213
sigaddset(&action.sa_mask, SIGTERM);
214
sigaddset(&action.sa_mask, SIGALRM);
215
sigaddset(&action.sa_mask, SIGHUP);
216
action.sa_flags = SA_RESTART;
217
if ( sigaction( SIGUSR2, &action, 0) < 0 ) {
218
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
221
#endif /* SERVERTEXT */
223
/* SIGUSR1 - set "debug" flag on this process. */
224
action.sa_handler = afp_set_debug;
225
sigemptyset( &action.sa_mask );
226
sigaddset(&action.sa_mask, SIGUSR1);
227
action.sa_flags = SA_RESTART;
228
if ( sigaction( SIGUSR1, &action, 0) < 0 ) {
229
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
234
action.sa_handler = alarm_handler;
235
sigemptyset(&action.sa_mask);
236
sigaddset(&action.sa_mask, SIGHUP);
237
sigaddset(&action.sa_mask, SIGTERM);
239
sigaddset(&action.sa_mask, SIGUSR2);
241
action.sa_flags = SA_RESTART;
242
if ((sigaction(SIGALRM, &action, NULL) < 0) ||
243
(setitimer(ITIMER_REAL, &dsi->timer, NULL) < 0)) {
247
/* get stuck here until the end */
248
while ((cmd = dsi_receive(dsi))) {
251
if (cmd == DSIFUNC_TICKLE) {
252
/* so we don't get killed on the client side. */
253
if ((child.flags & CHILD_DIE))
256
} else if (!(child.flags & CHILD_DIE)) { /* reset tickle timer */
257
setitimer(ITIMER_REAL, &dsi->timer, NULL);
263
LOG(log_info, logtype_afpd, "done");
264
if (obj->options.flags & OPTION_DEBUG )
272
if ( flushfork( writtenfork ) < 0 ) {
273
LOG(log_error, logtype_afpd, "main flushfork: %s", strerror(errno) );
279
function = (u_char) dsi->commands[0];
280
if (obj->options.flags & OPTION_DEBUG ) {
281
printf("command: %d (%s)\n", function, AfpNum2name(function));
282
bprint((char *) dsi->commands, dsi->cmdlen);
285
/* send off an afp command. in a couple cases, we take advantage
286
* of the fact that we're a stream-based protocol. */
287
if (afp_switch[function]) {
288
dsi->datalen = DSI_DATASIZ;
289
child.flags |= CHILD_RUNNING;
291
err = (*afp_switch[function])(obj,
292
dsi->commands, dsi->cmdlen,
293
dsi->data, &dsi->datalen);
295
/* bring everything back to old euid, egid */
297
restore_uidgid ( &obj->uidgid );
298
#endif /* FORCE_UIDGID */
299
child.flags &= ~CHILD_RUNNING;
301
LOG(log_error, logtype_afpd, "bad function %X", function);
306
/* single shot toggle that gets set by dsi_readinit. */
312
if (obj->options.flags & OPTION_DEBUG ) {
313
printf( "reply: %d, %d\n", err, dsi->clientID);
314
bprint((char *) dsi->data, dsi->datalen);
317
if (!dsi_cmdreply(dsi, err)) {
318
LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
323
case DSIFUNC_WRITE: /* FPWrite and FPAddIcon */
324
function = (u_char) dsi->commands[0];
325
if ( obj->options.flags & OPTION_DEBUG ) {
326
printf("(write) command: %d, %d\n", function, dsi->cmdlen);
327
bprint((char *) dsi->commands, dsi->cmdlen);
330
if ( afp_switch[ function ] != NULL ) {
331
dsi->datalen = DSI_DATASIZ;
332
child.flags |= CHILD_RUNNING;
333
err = (*afp_switch[function])(obj, dsi->commands, dsi->cmdlen,
334
dsi->data, &dsi->datalen);
335
child.flags &= ~CHILD_RUNNING;
337
/* bring everything back to old euid, egid */
339
restore_uidgid ( &obj->uidgid );
340
#endif /* FORCE_UIDGID */
342
LOG(log_error, logtype_afpd, "(write) bad function %x", function);
347
if (obj->options.flags & OPTION_DEBUG ) {
348
printf( "(write) reply code: %d, %d\n", err, dsi->clientID);
349
bprint((char *) dsi->data, dsi->datalen);
352
if (!dsi_wrtreply(dsi, err)) {
353
LOG(log_error, logtype_afpd, "dsi_wrtreply: %s", strerror(errno) );
358
case DSIFUNC_ATTN: /* attention replies */
362
/* error. this usually implies a mismatch of some kind
363
* between server and client. if things are correct,
364
* we need to flush the rest of the packet if necessary. */
366
LOG(log_info, logtype_afpd,"afp_dsi: spurious command %d", cmd);
367
dsi_writeinit(dsi, dsi->data, DSI_DATASIZ);
372
if ( obj->options.flags & OPTION_DEBUG ) {
376
of_pforkdesc( stdout );