From 02397303fbdc85cccd6656b831afb17be9f661e9 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Mon, 19 Jun 2006 23:37:09 +0000 Subject: [PATCH] Pass in the correct value for the first argument of select (one larger than the largest file number in the select set) rather than some multiple of sizeof some struct. The latter is large enough accidentally work, but breaks on AIX. Map IPv4-mapped IPv6 addresses back to IPv4 in krshd for the purposes of connecting back to the remote system on AIX, since on AIX getnameinfo returns such addresses but connect won't accept them. Ticket: 3122 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@18166 dc483132-0cff-0310-8789-dd5450dbe970 --- src/appl/bsd/krlogin.c | 2 +- src/appl/bsd/krlogind.c | 2 +- src/appl/bsd/krsh.c | 4 ++-- src/appl/bsd/krshd.c | 26 +++++++++++++++++++++++++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/appl/bsd/krlogin.c b/src/appl/bsd/krlogin.c index a1e63a645..05913f607 100644 --- a/src/appl/bsd/krlogin.c +++ b/src/appl/bsd/krlogin.c @@ -1101,7 +1101,7 @@ static void writer() for (;;) { FD_ZERO(&waitread); FD_SET(0, &waitread); - n = select(8*sizeof(waitread), &waitread, 0, 0, 0, 0); + n = select(1, &waitread, 0, 0, 0, 0); if (n < 0 && errno == EINTR) continue; if (n > 0) diff --git a/src/appl/bsd/krlogind.c b/src/appl/bsd/krlogind.c index 02bed8e37..8387f18db 100644 --- a/src/appl/bsd/krlogind.c +++ b/src/appl/bsd/krlogind.c @@ -1045,7 +1045,7 @@ void protocol(f, p) } } - if (select(8*sizeof(ibits), &ibits, &obits, &ebits, 0) < 0) { + if (select(((p > f) ? p : f) + 1, &ibits, &obits, &ebits, 0) < 0) { if (errno == EINTR) continue; fatalperror(f, "select"); diff --git a/src/appl/bsd/krsh.c b/src/appl/bsd/krsh.c index 08b68fef1..155223fab 100644 --- a/src/appl/bsd/krsh.c +++ b/src/appl/bsd/krsh.c @@ -512,7 +512,7 @@ main(argc, argv0) rewrite: FD_ZERO(&rembits); FD_SET(rem, &rembits); - if (select(8*sizeof(rembits), 0, &rembits, 0, 0) < 0) { + if (select(rem + 1, 0, &rembits, 0, 0) < 0) { if (errno != EINTR) { perror("select"); exit(1); @@ -550,7 +550,7 @@ main(argc, argv0) FD_SET(rem, &readfrom); do { ready = readfrom; - if (select(8*sizeof(ready), &ready, 0, 0, 0) < 0) { + if (select(((rfd2 > rem) ? rfd2 : rem) + 1, &ready, 0, 0, 0) < 0) { if (errno != EINTR) { perror("select"); exit(1); diff --git a/src/appl/bsd/krshd.c b/src/appl/bsd/krshd.c index 808adf5d5..02ab13235 100644 --- a/src/appl/bsd/krshd.c +++ b/src/appl/bsd/krshd.c @@ -440,6 +440,22 @@ int main(argc, argv) fd = 0; } +/* + * AIX passes an IPv4-mapped IPv6 address back from getpeername, but if + * that address is later used in connect(), it returns an error. Convert + * IPv4-mapped IPv6 addresses to simple IPv4 addresses on AIX (but don't + * do this everywhere since it isn't always the right thing to do, just + * the least wrong on AIX). + */ +#if defined(_AIX) && defined(KRB5_USE_INET6) + if (((struct sockaddr*)&from)->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa2sin6(&from)->sin6_addr)) { + sa2sin(&from)->sin_len = sizeof(struct sockaddr_in); + sa2sin(&from)->sin_family = AF_INET; + sa2sin(&from)->sin_port = sa2sin6(&from)->sin6_port; + memmove(&(sa2sin(&from)->sin_addr.s_addr), &(sa2sin6(&from)->sin6_addr.u6_addr.u6_addr8[12]), 4); + } +#endif + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof (on)) < 0) syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); @@ -1198,6 +1214,7 @@ void doit(f, fromp) goto signout_please; } if (pid) { + int maxfd; #ifdef POSIX_SIGNALS sa.sa_handler = cleanup; (void)sigaction(SIGINT, &sa, (struct sigaction *)0); @@ -1231,11 +1248,18 @@ void doit(f, fromp) FD_ZERO(&readfrom); FD_SET(f, &readfrom); + maxfd = f; if(port) { FD_SET(s, &readfrom); + if (s > maxfd) + maxfd = s; FD_SET(pv[0], &readfrom); + if (pv[0] > maxfd) + maxfd = pv[0]; } FD_SET(pw[0], &readfrom); + if (pw[0] > maxfd) + maxfd = pw[0]; /* read from f, write to px[1] -- child stdin */ /* read from s, signal child */ @@ -1244,7 +1268,7 @@ void doit(f, fromp) do { ready = readfrom; - if (select(8*sizeof(ready), &ready, (fd_set *)0, + if (select(maxfd + 1, &ready, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) { if (errno == EINTR) { continue; -- 2.26.2