diff options
author | shin <shin@FreeBSD.org> | 2000-01-13 15:09:48 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 2000-01-13 15:09:48 +0000 |
commit | 16085f42949d88bd0ba1801e6647b2c8777e30ba (patch) | |
tree | 3044ff81791eccd3209a757b144f64151f00275b /lib/libc/rpc/bindresvport.c | |
parent | 8813e718dc87a6dcf42bd2743686c7a74df222ca (diff) | |
download | FreeBSD-src-16085f42949d88bd0ba1801e6647b2c8777e30ba.zip FreeBSD-src-16085f42949d88bd0ba1801e6647b2c8777e30ba.tar.gz |
libc rcmd update for IPv6.
A new function bindresvport2(), AF independent version of bindresvport()
is also added.
Reviewed by: sumikawa
Obtained from: KAME project
Diffstat (limited to 'lib/libc/rpc/bindresvport.c')
-rw-r--r-- | lib/libc/rpc/bindresvport.c | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c index 1a62efa..e8e8c15 100644 --- a/lib/libc/rpc/bindresvport.c +++ b/lib/libc/rpc/bindresvport.c @@ -55,7 +55,6 @@ bindresvport(sd, sin) int sd; struct sockaddr_in *sin; { - int on, old, error; struct sockaddr_in myaddr; int sinlen = sizeof(struct sockaddr_in); @@ -69,39 +68,82 @@ bindresvport(sd, sin) return (-1); } - if (sin->sin_port == 0) { + return (bindresvport2(sd, sin, sinlen)); +} + +int +bindresvport2(sd, sa, addrlen) + int sd; + struct sockaddr *sa; + socklen_t addrlen; +{ + int on, old, error, level, optname; + u_short port; + + if (sa == NULL) { + errno = EINVAL; + return (-1); + } + switch (sa->sa_family) { + case AF_INET: + port = ntohs(((struct sockaddr_in *)sa)->sin_port); + level = IPPROTO_IP; + optname = IP_PORTRANGE; + on = IP_PORTRANGE_LOW; + break; +#ifdef INET6 + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); + level = IPPROTO_IPV6; + optname = IPV6_PORTRANGE; + on = IPV6_PORTRANGE_LOW; + break; +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + + if (port == 0) { int oldlen = sizeof(old); - error = getsockopt(sd, IPPROTO_IP, IP_PORTRANGE, - &old, &oldlen); + error = getsockopt(sd, level, optname, &old, &oldlen); if (error < 0) return(error); - on = IP_PORTRANGE_LOW; - error = setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, - &on, sizeof(on)); + error = setsockopt(sd, level, optname, &on, sizeof(on)); if (error < 0) return(error); } - error = bind(sd, (struct sockaddr *)sin, sinlen); + error = bind(sd, sa, addrlen); - if (sin->sin_port == 0) { + switch (sa->sa_family) { + case AF_INET: + port = ntohs(((struct sockaddr_in *)sa)->sin_port); + break; +#ifdef INET6 + case AF_INET6: + port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); + break; +#endif + default: /* shoud not match here */ + errno = EAFNOSUPPORT; + return (-1); + } + if (port == 0) { int saved_errno = errno; if (error) { - if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, + if (setsockopt(sd, level, optname, &old, sizeof(old)) < 0) errno = saved_errno; return (error); } - if (sin != &myaddr) { - /* Hmm, what did the kernel assign... */ - if (getsockname(sd, (struct sockaddr *)sin, - &sinlen) < 0) - errno = saved_errno; - return (error); - } + /* Hmm, what did the kernel assign... */ + if (getsockname(sd, (struct sockaddr *)sa, &addrlen) < 0) + errno = saved_errno; + return (error); } return (error); } |