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.)
This commit is contained in:
parent
06ffae8586
commit
469bed11ef
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
.Xr bind 2 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr rresvport 3 ,
|
||||
.Xr rresvport_af 3
|
||||
|
@ -55,95 +55,89 @@ bindresvport(sd, sin)
|
||||
int sd;
|
||||
struct sockaddr_in *sin;
|
||||
{
|
||||
struct sockaddr_in myaddr;
|
||||
int sinlen = sizeof(struct sockaddr_in);
|
||||
return bindresvport_sa(sd, (struct sockaddr *)sin);
|
||||
}
|
||||
|
||||
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) {
|
||||
/*
|
||||
* Bind a socket to a privileged port for whatever protocol.
|
||||
*/
|
||||
int
|
||||
bindresvport_sa(sd, sa)
|
||||
int sd;
|
||||
struct sockaddr *sa;
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
sa->sa_family = af;
|
||||
sa->sa_len = salen;
|
||||
|
||||
if (port == 0) {
|
||||
int oldlen = sizeof(old);
|
||||
error = getsockopt(sd, level, optname, &old, &oldlen);
|
||||
if (error < 0)
|
||||
return(error);
|
||||
|
||||
error = setsockopt(sd, level, optname, &on, sizeof(on));
|
||||
error = getsockopt(sd, proto, portrange, &old, &oldlen);
|
||||
if (error < 0)
|
||||
return(error);
|
||||
return (error);
|
||||
|
||||
error = setsockopt(sd, proto, portrange, &portlow,
|
||||
sizeof(portlow));
|
||||
if (error < 0)
|
||||
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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user