Pass in the correct value for the first argument of select (one larger
authorRuss Allbery <rra@stanford.edu>
Mon, 19 Jun 2006 23:37:09 +0000 (23:37 +0000)
committerRuss Allbery <rra@stanford.edu>
Mon, 19 Jun 2006 23:37:09 +0000 (23:37 +0000)
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
src/appl/bsd/krlogind.c
src/appl/bsd/krsh.c
src/appl/bsd/krshd.c

index a1e63a64502bc9ae5fdf9e6b2dcc515e6df1a32b..05913f60750d9e8fbb5039d3360ddb2b35447d46 100644 (file)
@@ -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)
index 02bed8e370f137d5f3643d1b1d8f49f564975df0..8387f18dbfcd22063fab538dd037b964c1529875 100644 (file)
@@ -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");
index 08b68fef11863a70d8e8e4e61a978a57bc8ced0f..155223fab848ec2c5c80605ab3c3aaf07f8ee39f 100644 (file)
@@ -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);
index 808adf5d538006db9453c842cdd75b88c2f16024..02ab13235438172300284d5ae2759101c084bf2f 100644 (file)
@@ -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;