3 * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
4 * All rights reserved. See COPYRIGHT.
9 #endif /* HAVE_CONFIG_H */
17 #include <sys/types.h>
18 #include <sys/socket.h>
20 #include <sys/types.h>
23 #include <atalk/logger.h>
24 #include <atalk/util.h>
26 #include <atalk/dsi.h>
27 #include <atalk/server_child.h>
30 * Start a DSI session, fork an afpd process
32 * @param childp (w) after fork: parent return pointer to child, child returns NULL
33 * @returns 0 on sucess, any other value denotes failure
35 int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_child_t **childp)
41 if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
42 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
46 if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
47 LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
51 switch (pid = dsi->proto_open(dsi)) { /* in libatalk/dsi/dsi_tcp.c */
53 /* if we fail, just return. it might work later */
54 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
57 case 0: /* child. mostly handled below. */
61 /* using SIGKILL is hokey, but the child might not have
62 * re-established its signal handler for SIGTERM yet. */
64 if ((child = server_child_add(serv_children, pid, ipc_fds[0])) == NULL) {
65 LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
67 dsi->header.dsi_flags = DSIFL_REPLY;
68 dsi->header.dsi_data.dsi_code = DSIERR_SERVBUSY;
70 dsi->header.dsi_data.dsi_code = DSIERR_OK;
73 dsi->proto_close(dsi);
78 /* child: check number of open connections. this is one off the
80 if ((serv_children->servch_count >= serv_children->servch_nsessions) &&
81 (dsi->header.dsi_command == DSIFUNC_OPEN)) {
82 LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
83 dsi->header.dsi_flags = DSIFL_REPLY;
84 dsi->header.dsi_data.dsi_code = DSIERR_TOOMANY;
89 /* get rid of some stuff */
90 dsi->AFPobj->ipc_fd = ipc_fds[1];
92 close(dsi->serversock);
94 server_child_free(serv_children);
96 switch (dsi->header.dsi_command) {
97 case DSIFUNC_STAT: /* send off status and return */
99 /* OpenTransport 1.1.2 bug workaround:
101 * OT code doesn't currently handle close sockets well. urk.
102 * the workaround: wait for the client to close its
103 * side. timeouts prevent indefinite resource use.
106 static struct timeval timeout = {120, 0};
112 FD_SET(dsi->socket, &readfds);
114 select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
119 case DSIFUNC_OPEN: /* setup session */
120 /* set up the tickle timer */
121 dsi->timer.it_interval.tv_sec = dsi->timer.it_value.tv_sec = tickleval;
122 dsi->timer.it_interval.tv_usec = dsi->timer.it_value.tv_usec = 0;
123 dsi_opensession(dsi);
127 default: /* just close */
128 LOG(log_info, logtype_dsi, "DSIUnknown %d", dsi->header.dsi_command);
129 dsi->proto_close(dsi);