summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>2000-01-26 09:02:42 +0000
committershin <shin@FreeBSD.org>2000-01-26 09:02:42 +0000
commiteb4463295ba6da7a5b6c1d94f38f7d52ef926c06 (patch)
treed340dd9f5ee7e86b28e10103cf6e6db099e4e4f0
parent4a29dd1cc9c6cafad16282641b92dd12b7a7ec01 (diff)
downloadFreeBSD-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.)
-rw-r--r--include/rpc/rpc.h2
-rw-r--r--lib/libc/net/rcmd.c4
-rw-r--r--lib/libc/rpc/Makefile.inc6
-rw-r--r--lib/libc/rpc/bindresvport.385
-rw-r--r--lib/libc/rpc/bindresvport.c118
5 files changed, 139 insertions, 76 deletions
diff --git a/include/rpc/rpc.h b/include/rpc/rpc.h
index ccfa30f..7fd4a7f 100644
--- a/include/rpc/rpc.h
+++ b/include/rpc/rpc.h
@@ -87,7 +87,7 @@ extern void setrpcent __P((int));
extern void endrpcent __P((void));
extern int bindresvport __P((int, struct sockaddr_in *));
-extern int bindresvport2 __P((int, struct sockaddr *, int addrlen));
+extern int bindresvport_sa __P((int, struct sockaddr *));
extern int get_myaddress __P((struct sockaddr_in *));
__END_DECLS
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);
}
OpenPOWER on IntegriCloud