diff options
author | peter <peter@FreeBSD.org> | 1996-05-31 04:00:21 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-05-31 04:00:21 +0000 |
commit | 3259f4bdcaa61a9bcde732df3f930ee3f278b563 (patch) | |
tree | a5bd0320906328d618f0c924406420264d68814b /lib | |
parent | b4bca346b07ffdf18d4faed43b11851e32641599 (diff) | |
download | FreeBSD-src-3259f4bdcaa61a9bcde732df3f930ee3f278b563.zip FreeBSD-src-3259f4bdcaa61a9bcde732df3f930ee3f278b563.tar.gz |
Use the setsockopt for IP_PORTRANGE to cause rresvport() to allocate a
privileged port within a single bind(), rather than looping through
attempts to bind over and over again over progressively lower ports.
This should speed up rlogin/rsh etc, and will probably cure some of the
strange rlogin hangs that have been reported in the past where rresvport()
managed to bind() to a port address that it shouldn't have.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/rcmd.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c index 405dd8e..3d6c649 100644 --- a/lib/libc/net/rcmd.c +++ b/lib/libc/net/rcmd.c @@ -222,28 +222,40 @@ rresvport(alport) int *alport; { struct sockaddr_in sin; - int s; + int s, on, len; sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; + sin.sin_port = 0; + s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) return (-1); - for (;;) { - sin.sin_port = htons((u_short)*alport); - if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) - return (s); - if (errno != EADDRINUSE) { - (void)close(s); - return (-1); - } - (*alport)--; - if (*alport == IPPORT_RESERVED/2) { + + on = IP_PORTRANGE_LOW; + if (setsockopt(s, IPPROTO_IP, IP_PORTRANGE, (char*)&on, sizeof(on)) < 0) + { + (void)close(s); + return(-1); + } + + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) { + /* attempt to find the port that we were assigned */ + len = sizeof(sin); + if (getsockname(s, (struct sockaddr *)&sin, &len) >= 0) + *alport = ntohs(sin.sin_port); + else { (void)close(s); - errno = EAGAIN; /* close */ return (-1); } + + return (s); } + if (errno == EADDRNOTAVAIL) /* no available ports? */ + errno = EAGAIN; /* "official" return for this case */ + + (void)close(s); + return (-1); } int __check_rhosts_file = 1; |