Hi,

I've made the patch for rresvport_af(3) and rcmd_af(3) which makes possible to use more connections for rsh/rshd. I've also reviewed freebsd src tree and I think these changes in libc do not break any existing applications.
Can anybody look at the patch?

--
Andrey Zonov

Index: libexec/rshd/rshd.c
===================================================================
--- libexec/rshd/rshd.c (revision 215508)
+++ libexec/rshd/rshd.c (working copy)
@@ -278,11 +278,6 @@
        (void) alarm(0);
        if (port != 0) {
                int lport = IPPORT_RESERVED - 1;
-               s = rresvport_af(&lport, af);
-               if (s < 0) {
-                       syslog(LOG_ERR, "can't get stderr port: %m");
-                       exit(1);
-               }
                if (port >= IPPORT_RESERVED ||
                    port < IPPORT_RESERVED/2) {
                        syslog(LOG_NOTICE|LOG_AUTH,
@@ -291,10 +286,31 @@
                            port);
                        exit(1);
                }
-               *((in_port_t *)&fromp->sa_data) = htons(port);
-               if (connect(s, fromp, fromp->sa_len) < 0) {
-                       syslog(LOG_INFO, "connect second port %d: %m", port);
-                       exit(1);
+               for ( ;; ) {
+                       s = rresvport_af(&lport, af);
+                       if (s < 0) {
+                               if (errno == EADDRINUSE ||
+                                   errno == EADDRNOTAVAIL) {
+                                       lport--;
+                                       continue;
+                               }
+                               if (errno == EAGAIN)
+                                       syslog(LOG_ERR, "socket: all ports in 
use");
+                               else
+                                       syslog(LOG_ERR, "can't get stderr port: 
%m");
+                               exit(1);
+                       }
+                       *((in_port_t *)&fromp->sa_data) = htons(port);
+                       if (connect(s, fromp, fromp->sa_len) < 0) {
+                               if (errno == EADDRINUSE) {
+                                       lport--;
+                                       close(s);
+                                       continue;
+                               }
+                               syslog(LOG_INFO, "connect second port %d: %m", 
port);
+                               exit(1);
+                       }
+                       break;
                }
        }
 
@@ -535,11 +551,11 @@
        char c;
 
        do {
+               if (cnt-- == 0)
+                       rshd_errx(1, "%s too long", error);
                if (read(STDIN_FILENO, &c, 1) != 1)
                        exit(1);
                *buf++ = c;
-               if (--cnt == 0)
-                       rshd_errx(1, "%s too long", error);
        } while (c != 0);
 }
 
Index: lib/libc/net/rcmd.c
===================================================================
--- lib/libc/net/rcmd.c (revision 215508)
+++ lib/libc/net/rcmd.c (working copy)
@@ -152,6 +152,11 @@
        for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
                s = rresvport_af(&lport, ai->ai_family);
                if (s < 0) {
+                       if (errno == EADDRINUSE ||
+                           errno == EADDRNOTAVAIL) {
+                               lport--;
+                               continue;
+                       }
                        if (errno != EAGAIN && ai->ai_next) {
                                ai = ai->ai_next;
                                continue;
@@ -212,17 +217,34 @@
                        fprintf(stderr, "Trying %s...\n", paddr);
                }
        }
-       lport--;
+       lport = IPPORT_RESERVED - 1;
        if (fd2p == 0) {
                _write(s, "", 1);
                lport = 0;
        } else {
-               int s2 = rresvport_af(&lport, ai->ai_family), s3;
+               int s2, s3;
                socklen_t len = ai->ai_addrlen;
                int nfds;
 
-               if (s2 < 0)
-                       goto bad;
+               for ( ;; ) {
+                       s2 = rresvport_af(&lport, ai->ai_family);
+                       if (s2 < 0) {
+                               if (errno == EADDRINUSE ||
+                                   errno == EADDRNOTAVAIL) {
+                                       lport--;
+                                       continue;
+                               }
+                               if (errno == EAGAIN)
+                                       (void)fprintf(stderr,
+                                           "rcmd: socket2: All ports in 
use\n");
+                               else
+                                       (void)fprintf(stderr, "rcmd: socket2: 
%s\n",
+                                           strerror(errno));
+                               goto bad;
+                       }
+                       break;
+               }
+
                _listen(s2, 1);
                (void)snprintf(num, sizeof(num), "%d", lport);
                if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
@@ -366,6 +388,27 @@
                return (-1);
        }
 #endif
+       if (*alport && *alport < IPPORT_RESERVED - 1) {
+               if (*alport < IPPORT_RESERVED / 2) {
+                       (void)_close(s);
+                       errno = EAGAIN;
+                       return (-1);
+               }
+               int reuse = 1;
+               if (_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, 
sizeof(reuse)) < 0) {
+                       (void)_close(s);
+                       return (-1);
+               }
+
+               *sport = htons((u_short)*alport);
+               if (_bind(s, (struct sockaddr *)&ss, ((struct sockaddr 
*)&ss)->sa_len) < 0) {
+                       (void)_close(s);
+                       return (-1);
+               }
+               *alport = (int)ntohs(*sport);
+               return (s);
+       }
+
        *sport = 0;
        if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
                (void)_close(s);
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to