summaryrefslogtreecommitdiffstats
path: root/lib/libc/net/rcmd.c
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1996-05-31 04:00:21 +0000
committerpeter <peter@FreeBSD.org>1996-05-31 04:00:21 +0000
commit3259f4bdcaa61a9bcde732df3f930ee3f278b563 (patch)
treea5bd0320906328d618f0c924406420264d68814b /lib/libc/net/rcmd.c
parentb4bca346b07ffdf18d4faed43b11851e32641599 (diff)
downloadFreeBSD-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/libc/net/rcmd.c')
-rw-r--r--lib/libc/net/rcmd.c36
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;
OpenPOWER on IntegriCloud