diff --git a/appl/kx/ChangeLog b/appl/kx/ChangeLog index 0f4845813..7cc0e0c06 100644 --- a/appl/kx/ChangeLog +++ b/appl/kx/ChangeLog @@ -1,3 +1,7 @@ +Sun Aug 16 18:34:30 1998 Assar Westerlund + + * implement support for Solaris's named-pipe X transport + Thu May 28 17:20:39 1998 Johan Danielsson * common.c: fix for (compiler?) bug in solaris 2.4 bind diff --git a/appl/kx/common.c b/appl/kx/common.c index 29c818153..5912cc248 100644 --- a/appl/kx/common.c +++ b/appl/kx/common.c @@ -120,18 +120,24 @@ copy_encrypted (int fd1, int fd2, des_cblock *iv, #define X_UNIX_PATH "/tmp/.X11-unix/X" #endif +#ifndef X_PIPE_PATH +#define X_PIPE_PATH "/tmp/.X11-pipe/X" +#endif + #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 #endif /* + * Allocate a unix domain socket. + * * 0 if all is OK * -1 if bind failed badly * 1 if dpy is already used */ static int -try_one (struct x_socket *s, int dpy, const char *pattern) +try_socket (struct x_socket *s, int dpy, const char *pattern) { struct sockaddr_un addr; int fd; @@ -160,29 +166,137 @@ try_one (struct x_socket *s, int dpy, const char *pattern) s->pathname = strdup (addr.sun_path); if (s->pathname == NULL) errx (1, "strdup: out of memory"); + s->flags = UNIX_SOCKET; + return 0; +} + +#ifdef MAY_HAVE_X11_PIPES +/* + * Allocate a stream (masqueraded as a named pipe) + * + * 0 if all is OK + * -1 if bind failed badly + * 1 if dpy is already used + */ + +static int +try_pipe (struct x_socket *s, int dpy, const char *pattern) +{ + char path[MAXPATHLEN]; + int ret; + int fd; + int pipefd[2]; + + snprintf (path, sizeof(path), pattern, dpy); + fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd < 0) + if (errno == EEXIST) + return 1; + else + return -1; + + close (fd); + + ret = pipe (pipefd); + if (ret < 0) + err (1, "pipe"); + + ret = ioctl (pipefd[1], I_PUSH, "connld"); + if (ret < 0) + err (1, "ioctl I_PUSH"); + + ret = fattach (pipefd[1], path); + if (ret < 0) + err (1, "fattach %s", path); + + s->fd = pipefd[0]; + close (pipefd[1]); + s->pathname = strdup (path); + if (s->pathname == NULL) + errx (1, "strdup: out of memory"); + s->flags = STREAM_PIPE; + return 0; +} +#endif /* MAY_HAVE_X11_PIPES */ + +static int +try_tcp (struct x_socket *s, int dpy) +{ + struct sockaddr_in tcpaddr; + struct in_addr local; + int one = 1; + int fd; + + memset(&local, 0, sizeof(local)); + local.s_addr = htonl(INADDR_LOOPBACK); + + fd = socket (AF_INET, SOCK_STREAM, 0); + if (fd < 0) + err (1, "socket AF_INET"); +#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) + setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, + sizeof(one)); +#endif + memset (&tcpaddr, 0, sizeof(tcpaddr)); + tcpaddr.sin_family = AF_INET; + tcpaddr.sin_addr = local; + tcpaddr.sin_port = htons(6000 + dpy); + if (bind (fd, (struct sockaddr *)&tcpaddr, + sizeof(tcpaddr)) < 0) { + close (fd); + if (errno == EADDRINUSE) + return 1; + else + return -1; + } + s->fd = fd; + s->pathname = NULL; + s->flags = TCP; return 0; } /* - * Allocate and listen on a number of local X server socket and a TCP - * socket. Return the display number. + * Allocate and listen on a number of local X server sockets, pipes, + * and a TCP socket. Return the display number. */ -static char *x_paths[] = { +static char *x_sockets[] = { X_UNIX_PATH "%u", -"/var/X/.X11-pipe/X" "%u", "/var/X/.X11-unix/X" "%u", "/usr/spool/sockets/X11/" "%u", NULL }; +static char *x_pipes[] = { +X_PIPE_PATH "%u", +"/var/X/.X11-pipe/X" "%u", +NULL +}; + +static void +try_mkdir (const char *path) +{ + char *dir; + char *p; + int oldmask; + + if((dir = strdup (path)) == NULL) + errx (1, "strdup: out of memory"); + p = strrchr (dir, '/'); + if (p) + *p = '\0'; + + oldmask = umask(0); + mkdir (dir, 01777); + chmod (dir, 01777); + umask (oldmask); + free (dir); +} + int get_xsockets (int *number, struct x_socket **sockets, int tcp_socket) { int dpy; - int oldmask; - struct in_addr local; - char *dir, *p; struct x_socket *s; int n; int i; @@ -191,20 +305,8 @@ get_xsockets (int *number, struct x_socket **sockets, int tcp_socket) if (s == NULL) errx (1, "malloc: out of memory"); - if((dir = strdup (X_UNIX_PATH)) == NULL) - errx (1, "strdup: out of memory"); - p = strrchr (dir, '/'); - if (p) - *p = '\0'; - - oldmask = umask(0); - mkdir (dir, 01777); - chmod (dir, 01777); - umask (oldmask); - free (dir); - - memset(&local, 0, sizeof(local)); - local.s_addr = htonl(INADDR_LOOPBACK); + try_mkdir (X_UNIX_PATH); + try_mkdir (X_PIPE_PATH); for(dpy = 4; dpy < 256; ++dpy) { int tcpfd; @@ -212,8 +314,8 @@ get_xsockets (int *number, struct x_socket **sockets, int tcp_socket) int tmp; n = 0; - for (path = x_paths; *path; ++path) { - tmp = try_one (&s[n], dpy, *path); + for (path = x_sockets; *path; ++path) { + tmp = try_socket (&s[n], dpy, *path); if (tmp == -1) { if (errno != ENOTDIR && errno != ENOENT) return -1; @@ -229,43 +331,46 @@ get_xsockets (int *number, struct x_socket **sockets, int tcp_socket) if (tmp == 1) continue; - if (tcp_socket) { - struct sockaddr_in tcpaddr; - int one = 1; - - tcpfd = socket (AF_INET, SOCK_STREAM, 0); - if (tcpfd < 0) - err (1, "socket AF_INET"); -#if defined(TCP_NODELAY) && defined(HAVE_SETSOCKOPT) - setsockopt (tcpfd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, - sizeof(one)); -#endif - memset (&tcpaddr, 0, sizeof(tcpaddr)); - tcpaddr.sin_family = AF_INET; - tcpaddr.sin_addr = local; - tcpaddr.sin_port = htons(6000 + dpy); - if (bind (tcpfd, (struct sockaddr *)&tcpaddr, - sizeof(tcpaddr)) < 0) { - close (tcpfd); - while(--n >= 0) { +#ifdef MAY_HAVE_X11_PIPES + for (path = x_pipes; *path; ++path) { + tmp = try_pipe (&s[n], dpy, *path); + if (tmp == -1) { + if (errno != ENOTDIR && errno != ENOENT) + return -1; + } else if (tmp == 1) { + while (--n >= 0) { close (s[n].fd); free (s[n].pathname); } - if (errno == EADDRINUSE) - continue; - else - return -1; - } - s[n].fd = tcpfd; - s[n].pathname = NULL; - ++n; + break; + } else if (tmp == 0) + ++n; + } + + if (tmp == 1) + continue; +#endif + + if (tcp_socket) { + tmp = try_tcp (&s[n], dpy); + if (tmp == -1) + return -1; + else if (tmp == 1) { + while (--n >= 0) { + close (s[n].fd); + free (s[n].pathname); + } + break; + } else if (tmp == 0) + ++n; } break; } if (dpy == 256) errx (1, "no free x-servers"); for (i = 0; i < n; ++i) - if (listen (s[i].fd, SOMAXCONN) < 0) + if (s[i].flags & LISTENP + && listen (s[i].fd, SOMAXCONN) < 0) err (1, "listen %s", s[i].pathname ? s[i].pathname : "tcp"); *number = n; *sockets = s; @@ -283,7 +388,7 @@ connect_local_xsocket (unsigned dnr) struct sockaddr_un addr; char **path; - for (path = x_paths; *path; ++path) { + for (path = x_sockets; *path; ++path) { fd = socket (AF_UNIX, SOCK_STREAM, 0); if (fd < 0) err (1, "socket AF_UNIX"); @@ -375,11 +480,12 @@ create_and_write_cookie (char *xauthfile, * Verify and remove cookies. Read and parse a X-connection from * `fd'. Check the cookie used is the same as in `cookie'. Remove the * cookie and copy the rest of it to `sock'. + * Expect cookies iff cookiesp. * Return 0 iff ok. */ int -verify_and_remove_cookies (int fd, int sock) +verify_and_remove_cookies (int fd, int sock, int cookiesp) { u_char beg[12]; int bigendianp; @@ -402,20 +508,24 @@ verify_and_remove_cookies (int fd, int sock) npad = (4 - (n % 4)) % 4; dpad = (4 - (d % 4)) % 4; protocol_name = malloc(n + npad); - if (protocol_name == NULL) + if (n + npad != 0 && protocol_name == NULL) return 1; protocol_data = malloc(d + dpad); - if (protocol_data == NULL) + if (d + dpad != 0 && protocol_data == NULL) { + free (protocol_name); goto fail; + } if (krb_net_read (fd, protocol_name, n + npad) != n + npad) goto fail; if (krb_net_read (fd, protocol_data, d + dpad) != d + dpad) goto fail; - if (strncmp (protocol_name, COOKIE_TYPE, strlen(COOKIE_TYPE)) != 0) - goto fail; - if (d != cookie_len || - memcmp (protocol_data, cookie, cookie_len) != 0) - goto fail; + if (cookiesp) { + if (strncmp (protocol_name, COOKIE_TYPE, strlen(COOKIE_TYPE)) != 0) + goto fail; + if (d != cookie_len || + memcmp (protocol_data, cookie, cookie_len) != 0) + goto fail; + } free (protocol_name); free (protocol_data); if (krb_net_write (sock, zeros, 6) != 6) @@ -433,7 +543,7 @@ fail: */ int -replace_cookie(int xserver, int fd, char *filename) +replace_cookie(int xserver, int fd, char *filename, int cookiesp) /* XXX */ { u_char beg[12]; int bigendianp; diff --git a/appl/kx/kx.c b/appl/kx/kx.c index a60152c2e..2048de333 100644 --- a/appl/kx/kx.c +++ b/appl/kx/kx.c @@ -164,7 +164,7 @@ static int passive_session (int xserver, int fd, des_cblock *iv, des_key_schedule schedule) { - if (replace_cookie (xserver, fd, XauFileName())) + if (replace_cookie (xserver, fd, XauFileName(), 1)) return 1; else return copy_encrypted (xserver, fd, iv, schedule); @@ -174,7 +174,7 @@ static int active_session (int xserver, int fd, des_cblock *iv, des_key_schedule schedule) { - if (verify_and_remove_cookies (xserver, fd)) + if (verify_and_remove_cookies (xserver, fd, 1)) return 1; else return copy_encrypted (xserver, fd, iv, schedule); diff --git a/appl/kx/kx.h b/appl/kx/kx.h index d0bbe4fbd..e6618b90e 100644 --- a/appl/kx/kx.h +++ b/appl/kx/kx.h @@ -105,6 +105,17 @@ #include #include +#ifdef HAVE_SYS_STREAM_H +#include +#endif +#ifdef HAVE_SYS_STROPTS_H +#include +#endif + +#if defined(HAVE_SYS_STROPTS_H) && defined(HAVE_FATTACH) && defined(I_PUSH) +#define MAY_HAVE_X11_PIPES +#endif + #ifdef SOCKS #include /* This doesn't belong here. */ @@ -117,16 +128,17 @@ struct hostent *gethostbyname(const char *); #include #include -int copy_encrypted (int fd1, int fd2, des_cblock *iv, - des_key_schedule schedule); - struct x_socket { char *pathname; int fd; + enum { + LISTENP = 0x80, + TCP = LISTENP | 1, + UNIX_SOCKET = LISTENP | 2, + STREAM_PIPE = 3 + } flags; }; -int get_xsockets (int *number, struct x_socket **sockets, int tcpp); - extern char x_socket[]; extern u_int32_t display_num; extern char display[]; @@ -136,13 +148,18 @@ extern int xauthfile_size; extern u_char cookie[]; extern size_t cookie_len; +int copy_encrypted (int fd1, int fd2, des_cblock *iv, + des_key_schedule schedule); + +int get_xsockets (int *number, struct x_socket **sockets, int tcpp); + int connect_local_xsocket (unsigned dnr); int create_and_write_cookie (char *xauthfile, size_t size, u_char *cookie, size_t sz); -int verify_and_remove_cookies (int fd, int sock); -int replace_cookie(int xserver, int fd, char *filename); +int verify_and_remove_cookies (int fd, int sock, int cookiesp); +int replace_cookie(int xserver, int fd, char *filename, int cookiesp); int suspicious_address (int sock, struct sockaddr_in addr); diff --git a/appl/kx/kxd.c b/appl/kx/kxd.c index 472c5b61a..e4b015edd 100644 --- a/appl/kx/kxd.c +++ b/appl/kx/kxd.c @@ -233,29 +233,29 @@ recv_conn (int sock, des_cblock *key, des_key_schedule schedule, */ static int -passive_session (int fd, int sock, des_cblock *key, +passive_session (int fd, int sock, int cookiesp, des_cblock *key, des_key_schedule schedule) { - if (verify_and_remove_cookies (fd, sock)) + if (verify_and_remove_cookies (fd, sock, cookiesp)) return 1; else return copy_encrypted (fd, sock, key, schedule); } static int -active_session (int fd, int sock, des_cblock *key, +active_session (int fd, int sock, int cookiesp, des_cblock *key, des_key_schedule schedule) { fd = connect_local_xsocket(0); - if (replace_cookie (fd, sock, xauthfile)) + if (replace_cookie (fd, sock, xauthfile, cookiesp)) return 1; else return copy_encrypted (fd, sock, key, schedule); } static int -doit_conn (int fd, int meta_sock, int flags, +doit_conn (int fd, int meta_sock, int flags, int cookiesp, des_cblock *key, des_key_schedule schedule, struct sockaddr_in *thisaddr, struct sockaddr_in *thataddr) @@ -319,9 +319,9 @@ doit_conn (int fd, int meta_sock, int flags, close (meta_sock); if (flags & PASSIVE) - return passive_session (fd, sock2, key, schedule); + return passive_session (fd, sock2, cookiesp, key, schedule); else - return active_session (fd, sock2, key, schedule); + return active_session (fd, sock2, cookiesp, key, schedule); } /* @@ -343,6 +343,232 @@ check_user_console (int fd, des_cblock *key, des_key_schedule schedule, "Permission denied"); } +/* + * Handle a passive session on `sock' + */ + +static int +doit_passive (int sock, des_cblock *key, des_key_schedule schedule, + struct sockaddr_in *me, struct sockaddr_in *him, + int flags, int tcpp) +{ + int tmp; + int len; + size_t rem; + u_char msg[1024], *p; + struct x_socket *sockets; + int nsockets; + + tmp = get_xsockets (&nsockets, &sockets, tcpp); + if (tmp < 0) { + fatal (sock, key, schedule, me, him, + "Cannot create X socket(s): %s", + strerror(errno)); + return 1; + } + display_num = tmp; + if (tcpp) + snprintf (display, display_size, "localhost:%u", display_num); + else + snprintf (display, display_size, ":%u", display_num); + if(create_and_write_cookie (xauthfile, xauthfile_size, + cookie, cookie_len)) { + cleanup(nsockets, sockets); + fatal (sock, key, schedule, me, him, + "Cookie-creation failed with: %s", + strerror(errno)); + return 1; + } + + p = msg; + rem = sizeof(msg); + *p++ = ACK; + --rem; + + len = strlen (display); + tmp = krb_put_int (len, p, rem, 4); + if (tmp < 0 || rem < len + 4) { + syslog (LOG_ERR, "doit: buffer too small"); + cleanup(nsockets, sockets); + return 1; + } + p += tmp; + rem -= tmp; + + memcpy (p, display, len); + p += len; + rem -= len; + + len = strlen (xauthfile); + tmp = krb_put_int (len, p, rem, 4); + if (tmp < 0 || rem < len + 4) { + syslog (LOG_ERR, "doit: buffer too small"); + cleanup(nsockets, sockets); + return 1; + } + p += tmp; + rem -= tmp; + + memcpy (p, xauthfile, len); + p += len; + rem -= len; + + if(write_encrypted (sock, msg, p - msg, schedule, key, + me, him) < 0) { + syslog (LOG_ERR, "write: %m"); + cleanup(nsockets, sockets); + return 1; + } + for (;;) { + pid_t child; + int fd; + fd_set fds; + int i; + int ret; + int cookiesp = TRUE; + + FD_ZERO(&fds); + FD_SET(sock, &fds); + for (i = 0; i < nsockets; ++i) + FD_SET(sockets[i].fd, &fds); + ret = select(FD_SETSIZE, &fds, NULL, NULL, NULL); + if(ret <= 0) + continue; + if(FD_ISSET(sock, &fds)){ + /* there are no processes left on the remote side + */ + cleanup(nsockets, sockets); + exit(0); + } else if(ret) { + for (i = 0; i < nsockets; ++i) { + if (FD_ISSET(sockets[i].fd, &fds)) { + if (sockets[i].flags == TCP) { + struct sockaddr_in peer; + int len = sizeof(peer); + + fd = accept (sockets[i].fd, + (struct sockaddr *)&peer, + &len); + if (fd < 0 && errno != EINTR) + syslog (LOG_ERR, "accept: %m"); + + /* XXX */ + if (fd >= 0 && suspicious_address (fd, peer)) { + close (fd); + fd = -1; + errno = EINTR; + } + } else if(sockets[i].flags == UNIX_SOCKET) { + int zero = 0; + + fd = accept (sockets[i].fd, NULL, &zero); + + if (fd < 0 && errno != EINTR) + syslog (LOG_ERR, "accept: %m"); + } else if(sockets[i].flags == STREAM_PIPE) { + /* + * this code tries to handle the + * send fd-over-pipe stuff for + * solaris + */ + + struct strrecvfd strrecvfd; + + ret = ioctl (sockets[i].fd, + I_RECVFD, &strrecvfd); + if (ret < 0 && errno != EINTR) { + syslog (LOG_ERR, "ioctl I_RECVFD: %m"); + } + + /* XXX */ + if (ret == 0) { + if (strrecvfd.uid != getuid()) { + close (strrecvfd.fd); + fd = -1; + errno = EINTR; + } else { + fd = strrecvfd.fd; + cookiesp = FALSE; + } + } + } else + abort (); + break; + } + } + } + if (fd < 0) + if (errno == EINTR) + continue; + else + return 1; + + child = fork (); + if (child < 0) { + syslog (LOG_ERR, "fork: %m"); + return 1; + } else if (child != 0) { + for (i = 0; i < nsockets; ++i) + close (sockets[i].fd); + return doit_conn (fd, sock, flags, cookiesp, + key, schedule, me, him); + } else { + close (fd); + } + } +} + +/* + * Handle an active session on `sock' + */ + +static int +doit_active (int sock, des_cblock *key, des_key_schedule schedule, + struct sockaddr_in *me, struct sockaddr_in *him, + int flags, int tcpp) +{ + u_char msg[1024], *p; + + check_user_console (sock, key, schedule, me, him); + + p = msg; + *p++ = ACK; + + if(write_encrypted (sock, msg, p - msg, schedule, key, + me, him) < 0) { + syslog (LOG_ERR, "write: %m"); + return 1; + } + for (;;) { + pid_t child; + int len; + void *ret; + + len = read_encrypted (sock, msg, sizeof(msg), &ret, + schedule, key, + him, me); + if (len < 0) { + syslog (LOG_ERR, "read: %m"); + return 1; + } + p = (u_char *)ret; + if (*p != NEW_CONN) { + syslog (LOG_ERR, "bad_message: %d", *p); + return 1; + } + + child = fork (); + if (child < 0) { + syslog (LOG_ERR, "fork: %m"); + return 1; + } else if (child == 0) { + return doit_conn (sock, sock, flags, 1, + key, schedule, me, him); + } else { + } + } +} + /* * Receive a connection on `sock' and process it. */ @@ -360,176 +586,10 @@ doit(int sock, int tcpp) flags = recv_conn (sock, &key, schedule, &me, &him); - if (flags & PASSIVE) { - int tmp; - int len; - size_t rem; - - tmp = get_xsockets (&nsockets, &sockets, tcpp); - if (tmp < 0) { - fatal (sock, &key, schedule, &me, &him, - "Cannot create X socket(s): %s", - strerror(errno)); - return 1; - } - display_num = tmp; - if (tcpp) - snprintf (display, display_size, "localhost:%u", display_num); - else - snprintf (display, display_size, ":%u", display_num); - if(create_and_write_cookie (xauthfile, xauthfile_size, - cookie, cookie_len)) { - cleanup(nsockets, sockets); - fatal (sock, &key, schedule, &me, &him, - "Cookie-creation failed with: %s", - strerror(errno)); - return 1; - } - - p = msg; - rem = sizeof(msg); - *p++ = ACK; - --rem; - - len = strlen (display); - tmp = krb_put_int (len, p, rem, 4); - if (tmp < 0 || rem < len + 4) { - syslog (LOG_ERR, "doit: buffer too small"); - cleanup(nsockets, sockets); - return 1; - } - p += tmp; - rem -= tmp; - - memcpy (p, display, len); - p += len; - rem -= len; - - len = strlen (xauthfile); - tmp = krb_put_int (len, p, rem, 4); - if (tmp < 0 || rem < len + 4) { - syslog (LOG_ERR, "doit: buffer too small"); - cleanup(nsockets, sockets); - return 1; - } - p += tmp; - rem -= tmp; - - memcpy (p, xauthfile, len); - p += len; - rem -= len; - - if(write_encrypted (sock, msg, p - msg, schedule, &key, - &me, &him) < 0) { - syslog (LOG_ERR, "write: %m"); - cleanup(nsockets, sockets); - return 1; - } - for (;;) { - pid_t child; - int fd; - fd_set fds; - int i; - int ret; - - FD_ZERO(&fds); - FD_SET(sock, &fds); - for (i = 0; i < nsockets; ++i) - FD_SET(sockets[i].fd, &fds); - ret = select(FD_SETSIZE, &fds, NULL, NULL, NULL); - if(ret <= 0) - continue; - if(FD_ISSET(sock, &fds)){ - /* there are no processes left on the remote side - */ - cleanup(nsockets, sockets); - exit(0); - } else if(ret) { - for (i = 0; i < nsockets; ++i) { - if (FD_ISSET(sockets[i].fd, &fds)) { - if (sockets[i].pathname == NULL) { - struct sockaddr_in peer; - int len = sizeof(peer); - - fd = accept (sockets[i].fd, - (struct sockaddr *)&peer, - &len); - /* XXX */ - if (fd >= 0 && suspicious_address (fd, peer)) { - close (fd); - fd = -1; - errno = EINTR; - } - } else { - int zero = 0; - - fd = accept (sockets[i].fd, NULL, &zero); - } - break; - } - } - } - if (fd < 0) - if (errno == EINTR) - continue; - else { - syslog (LOG_ERR, "accept: %m"); - return 1; - } - - child = fork (); - if (child < 0) { - syslog (LOG_ERR, "fork: %m"); - return 1; - } else if (child == 0) { - for (i = 0; i < nsockets; ++i) - close (sockets[i].fd); - return doit_conn (fd, sock, flags, - &key, schedule, &me, &him); - } else { - close (fd); - } - } - } else { - check_user_console (sock, &key, schedule, &me, &him); - - p = msg; - *p++ = ACK; - - if(write_encrypted (sock, msg, p - msg, schedule, &key, - &me, &him) < 0) { - syslog (LOG_ERR, "write: %m"); - return 1; - } - for (;;) { - pid_t child; - int len; - void *ret; - - len = read_encrypted (sock, msg, sizeof(msg), &ret, - schedule, &key, - &him, &me); - if (len < 0) { - syslog (LOG_ERR, "read: %m"); - return 1; - } - p = (u_char *)ret; - if (*p != NEW_CONN) { - syslog (LOG_ERR, "bad_message: %d", *p); - return 1; - } - - child = fork (); - if (child < 0) { - syslog (LOG_ERR, "fork: %m"); - return 1; - } else if (child == 0) { - return doit_conn (sock, sock, flags, - &key, schedule, &me, &him); - } else { - } - } - } + if (flags & PASSIVE) + return doit_passive (sock, &key, schedule, &me, &him, flags, tcpp); + else + return doit_active (sock, &key, schedule, &me, &him, flags, tcpp); } static void