diff options
author | shin <shin@FreeBSD.org> | 2000-01-26 09:02:42 +0000 |
---|---|---|
committer | shin <shin@FreeBSD.org> | 2000-01-26 09:02:42 +0000 |
commit | eb4463295ba6da7a5b6c1d94f38f7d52ef926c06 (patch) | |
tree | d340dd9f5ee7e86b28e10103cf6e6db099e4e4f0 /lib | |
parent | 4a29dd1cc9c6cafad16282641b92dd12b7a7ec01 (diff) | |
download | FreeBSD-src-eb4463295ba6da7a5b6c1d94f38f7d52ef926c06.zip FreeBSD-src-eb4463295ba6da7a5b6c1d94f38f7d52ef926c06.tar.gz |
bindresvport related changes
-changed bindresvport2 to bindresvport_sa
-merged the man into bindresvport.3
All discussion between Jean-Luc Richier <Jean-Luc.Richier@imag.fr>,
Theo de Raadt <deraadt@cvs.openbsd.org>, itojun, is reflected to
this code. (Actually Theo de Raadt write the code simultaneously as the
discussion change.)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libc/net/rcmd.c | 4 | ||||
-rw-r--r-- | lib/libc/rpc/Makefile.inc | 6 | ||||
-rw-r--r-- | lib/libc/rpc/bindresvport.3 | 85 | ||||
-rw-r--r-- | lib/libc/rpc/bindresvport.c | 118 |
4 files changed, 138 insertions, 75 deletions
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c index 8130410..d46410a 100644 --- a/lib/libc/net/rcmd.c +++ b/lib/libc/net/rcmd.c @@ -333,8 +333,8 @@ rresvport_af(alport, family) } #endif *sport = 0; - if (bindresvport2(s, (struct sockaddr *)&ss, - ((struct sockaddr *)&ss)->sa_len) == -1) { + if (bindresvport_sa(s, (struct sockaddr *)&ss, + ((struct sockaddr *)&ss)->sa_len) == -1) { (void)_libc_close(s); return (-1); } diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc index 472cea7..1ca21c5 100644 --- a/lib/libc/rpc/Makefile.inc +++ b/lib/libc/rpc/Makefile.inc @@ -44,13 +44,13 @@ crypt.h: ${RPCDIR}/crypt.x # # MAN1+= rstat.1 -MAN3+= bindresvport.3 bindresvport2.3 des_crypt.3 getrpcent.3 getrpcport.3 \ - publickey.3 rpc.3 \ +MAN3+= bindresvport.3 des_crypt.3 getrpcent.3 getrpcport.3 publickey.3 rpc.3 \ rpc_secure.3 rtime.3 MAN5+= publickey.5 rpc.5 # MAN8+= rstat_svc.8 -MLINKS+= getrpcent.3 endrpcent.3 \ +MLINKS+= bindresvport.3 bindresvport_sa.3 \ + getrpcent.3 endrpcent.3 \ getrpcent.3 getrpcbyname.3 \ getrpcent.3 getrpcbynumber.3 \ getrpcent.3 setrpcent.3 \ diff --git a/lib/libc/rpc/bindresvport.3 b/lib/libc/rpc/bindresvport.3 index 8d1f975..d37aeff 100644 --- a/lib/libc/rpc/bindresvport.3 +++ b/lib/libc/rpc/bindresvport.3 @@ -5,30 +5,99 @@ .Dt BINDRESVPORT 3 .Os .Sh NAME -.Nm bindresvport +.Nm bindresvport , +.Nm bindresvport_sa , .Ndbind a socket to a privileged IP port .Sh SYNOPSIS .Fd #include <sys/types.h> .Fd #include <netinet/in.h> .Ft int -.Fn bindresvport "int sd" "struct sockaddr_in **sin" +.Fn bindresvport "int sd" "struct sockaddr_in *sin" +.Ft int +.Fn bindresvport_sa "int sd" "struct sockaddr *sa" .Sh DESCRIPTION .Nm Bindresvport -is used to bind a socket descriptor to a privileged +and +.Nm Bindresvport_sa +are used to bind a socket descriptor to a privileged .Tn IP port, that is, a port number in the range 0-1023. -The routine returns 0 if it is successful, -otherwise -1 is returned and -.Va errno -set to reflect the cause of the error. .Pp Only root can bind to a privileged port; this call will fail for any other users. .Pp +When +.Va sin +is not null, +.Va sin->sin_family +must be initialized to the address family of the socket, passed by +.Va sd . If the value of sin->sin_port is non-zero .Fn bindresvport will attempt to use that specific port. If it fails, it chooses another privileged port automatically. +.Pp +It is legal to pass null pointer to +.Va sin . +In this case, the caller cannot get the port number +.Fn bindresvport +has picked. +.Pp +Function prototype of +.Fn bindresvport +is biased to +.Dv AF_INET +socket. +.Fn bindresvport_sa +acts exactly the same, with more neutral function prototype. +Note that both functions behave exactly the same, and +both support +.Dv AF_INET6 +sockets as well as +.Dv AF_INET +sockets. +.Sh RETURN VALUES +.Fn bindresvport +returns 0 if it is successful, otherwise \-1 is returned and +.Va errno +set to reflect the cause of the error. +.Sh ERRORS +The +.Fn bindresvport +function fails if: +.Bl -tag -width Er +.It Bq Er EBADF +.Fa sd +is not a valid descriptor. +.It Bq Er ENOTSOCK +.Fa sd +is not a socket. +.It Bq Er EADDRNOTAVAIL +The specified address is not available from the local machine. +.It Bq Er EADDRINUSE +The specified address is already in use. +.It Bq Er EINVAL +The socket is already bound to an address, +or the socket family and the family of specified address mismatch. +.It Bq Er EACCES +The requested address is protected, and the current user +has inadequate permission to access it. +.It Bq Er EFAULT +The +.Fa name +parameter is not in a valid part of the user +address space. +.It Bq Er ENOBUFS +Insufficient resources were available in the system +to perform the operation. +.It Bq Er EPFNOSUPPORT +The protocol family has not been configured into the +system, no implementation for it exists, +or address family did not match between arguments. +.El .Sh "SEE ALSO" -.Xr bindresvport2 3
\ No newline at end of file +.Xr bind 2 , +.Xr socket 2 , +.Xr rresvport 3 , +.Xr rresvport_af 3 diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c index e8e8c15..fb43eed 100644 --- a/lib/libc/rpc/bindresvport.c +++ b/lib/libc/rpc/bindresvport.c @@ -55,95 +55,89 @@ bindresvport(sd, sin) int sd; struct sockaddr_in *sin; { - struct sockaddr_in myaddr; - int sinlen = sizeof(struct sockaddr_in); - - if (sin == (struct sockaddr_in *)0) { - sin = &myaddr; - memset(sin, 0, sinlen); - sin->sin_len = sinlen; - sin->sin_family = AF_INET; - } else if (sin->sin_family != AF_INET) { - errno = EPFNOSUPPORT; - return (-1); - } - - return (bindresvport2(sd, sin, sinlen)); + return bindresvport_sa(sd, (struct sockaddr *)sin); } +/* + * Bind a socket to a privileged port for whatever protocol. + */ int -bindresvport2(sd, sa, addrlen) +bindresvport_sa(sd, sa) int sd; struct sockaddr *sa; - socklen_t addrlen; { - int on, old, error, level, optname; - u_short port; + int old, error, af; + struct sockaddr_storage myaddr; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + int proto, portrange, portlow; + u_int16_t port; + int salen; 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; + salen = sizeof(myaddr); + sa = (struct sockaddr *)&myaddr; + + if (getsockname(sd, sa, &salen) == -1) + return -1; /* errno is correctly set */ + + af = sa->sa_family; + memset(&myaddr, 0, salen); + } else + af = sa->sa_family; + + if (af == AF_INET) { + proto = IPPROTO_IP; + portrange = IP_PORTRANGE; + portlow = IP_PORTRANGE_LOW; + sin = (struct sockaddr_in *)sa; + salen = sizeof(struct sockaddr_in); + port = sin->sin_port; + } else if (af == AF_INET6) { + proto = IPPROTO_IPV6; + portrange = IPV6_PORTRANGE; + portlow = IPV6_PORTRANGE_LOW; + sin6 = (struct sockaddr_in6 *)sa; + salen = sizeof(struct sockaddr_in6); + port = sin6->sin6_port; + } else { + errno = EPFNOSUPPORT; return (-1); } + sa->sa_family = af; + sa->sa_len = salen; if (port == 0) { int oldlen = sizeof(old); - error = getsockopt(sd, level, optname, &old, &oldlen); + + error = getsockopt(sd, proto, portrange, &old, &oldlen); if (error < 0) - return(error); + return (error); - error = setsockopt(sd, level, optname, &on, sizeof(on)); + error = setsockopt(sd, proto, portrange, &portlow, + sizeof(portlow)); if (error < 0) - return(error); + return (error); } - error = bind(sd, sa, addrlen); + error = bind(sd, sa, salen); - 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, level, optname, - &old, sizeof(old)) < 0) + if (setsockopt(sd, proto, portrange, &old, + sizeof(old)) < 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); + if (sa != (struct sockaddr *)&myaddr) { + /* Hmm, what did the kernel assign... */ + if (getsockname(sd, sa, &salen) < 0) + errno = saved_errno; + return (error); + } } return (error); } |