* use setsockopt(IP_PORTRANGE_LOW) instead of looping through the
address range (from freebsd). * enhance the man page to be a bit more useful.
This commit is contained in:
parent
910a3d4cc4
commit
bba0660678
|
@ -1,5 +1,5 @@
|
|||
.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
|
||||
.\" $NetBSD: bindresvport.3,v 1.3 1997/07/01 06:28:22 mikel Exp $
|
||||
.\" $NetBSD: bindresvport.3,v 1.4 1998/01/14 11:04:17 lukem Exp $
|
||||
.\"
|
||||
.Dd November 22, 1987
|
||||
.Dt BINDRESVPORT 3
|
||||
|
@ -11,7 +11,7 @@
|
|||
.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"
|
||||
.Sh DESCRIPTION
|
||||
.Fn bindresvport
|
||||
is used to bind a socket descriptor to a privileged
|
||||
|
@ -23,5 +23,60 @@ otherwise -1 is returned and
|
|||
.Va errno
|
||||
set to reflect the cause of the error.
|
||||
.Pp
|
||||
If
|
||||
.Fa sin
|
||||
is a pointer to a
|
||||
.Ft "struct sockaddr_in"
|
||||
then the appropriate fields in the structure should be defined.
|
||||
If
|
||||
.Fa sin.sin_port
|
||||
is
|
||||
.Sq 0
|
||||
then an anonymous port (in the range 600-1023) will be
|
||||
chosen, and if
|
||||
.Xr bind 2
|
||||
is successful, the
|
||||
.Fa sin.sin_port
|
||||
will be updated to contain the allocated port.
|
||||
.Pp
|
||||
If
|
||||
.Fa sin
|
||||
is the
|
||||
.Dv NULL
|
||||
pointer,
|
||||
an anonymous port will be allocated (as above).
|
||||
However, there is no way for
|
||||
.Fn bindresvport
|
||||
to return the allocated port in this case.
|
||||
.Pp
|
||||
Only root can bind to a privileged port; this call will fail for any
|
||||
other users.
|
||||
.Sh RETURN VALUES
|
||||
If the bind is successful, a 0 value is returned.
|
||||
A return value of -1 indicates an error, which is
|
||||
further specified in the global
|
||||
.Va errno .
|
||||
.Sh ERRORS
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPFNOSUPPORT
|
||||
If
|
||||
.Fa sin
|
||||
was supplied, and
|
||||
.Fa sin.sin_family
|
||||
isn't
|
||||
.Dv AF_INET .
|
||||
.El
|
||||
.Pp
|
||||
.Fn bindresvport
|
||||
may also fail and set
|
||||
.Va errno
|
||||
for any of the errors specified for the calls
|
||||
.Xr bind 2 ,
|
||||
.Xr getsockopt 2 ,
|
||||
or
|
||||
.Xr setsockopt 2 .
|
||||
.Sh SEE ALSO
|
||||
.Xr bind 2 ,
|
||||
.Xr getsockopt 2 ,
|
||||
.Xr setsockopt 2 ,
|
||||
.Xr ip 4 .
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: bindresvport.c,v 1.8 1997/07/21 14:08:21 jtc Exp $ */
|
||||
/* $NetBSD: bindresvport.c,v 1.9 1998/01/14 11:04:18 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
|
@ -35,7 +35,7 @@
|
|||
static char *sccsid = "@(#)bindresvport.c 1.8 88/02/08 SMI";
|
||||
static char *sccsid = "@(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: bindresvport.c,v 1.8 1997/07/21 14:08:21 jtc Exp $");
|
||||
__RCSID("$NetBSD: bindresvport.c,v 1.9 1998/01/14 11:04:18 lukem Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -64,36 +64,50 @@ bindresvport(sd, sin)
|
|||
int sd;
|
||||
struct sockaddr_in *sin;
|
||||
{
|
||||
int res;
|
||||
static short port;
|
||||
int res, old;
|
||||
struct sockaddr_in myaddr;
|
||||
int i;
|
||||
int sinlen = sizeof(struct sockaddr_in);
|
||||
|
||||
#define STARTPORT 600
|
||||
#define ENDPORT (IPPORT_RESERVED - 1)
|
||||
#define NPORTS (ENDPORT - STARTPORT + 1)
|
||||
|
||||
if (sin == (struct sockaddr_in *)0) {
|
||||
if (sin == NULL) {
|
||||
sin = &myaddr;
|
||||
memset(sin, 0, sizeof (*sin));
|
||||
sin->sin_len = sizeof(struct sockaddr_in);
|
||||
memset(sin, 0, sinlen);
|
||||
sin->sin_len = sinlen;
|
||||
sin->sin_family = AF_INET;
|
||||
} else if (sin->sin_family != AF_INET) {
|
||||
errno = EPFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
if (port == 0) {
|
||||
port = (getpid() % NPORTS) + STARTPORT;
|
||||
|
||||
if (sin->sin_port == 0) {
|
||||
int on, oldlen = sizeof(old);
|
||||
|
||||
res = getsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &old, &oldlen);
|
||||
if (res < 0)
|
||||
return(res);
|
||||
on = IP_PORTRANGE_LOW;
|
||||
res = setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, &on, sizeof(on));
|
||||
if (res < 0)
|
||||
return(res);
|
||||
}
|
||||
res = -1;
|
||||
errno = EADDRINUSE;
|
||||
for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
|
||||
sin->sin_port = htons(port++);
|
||||
if (port > ENDPORT) {
|
||||
port = STARTPORT;
|
||||
|
||||
res = bind(sd, (struct sockaddr *)sin, sinlen);
|
||||
|
||||
if (sin->sin_port == 0) {
|
||||
int saved_errno = errno;
|
||||
|
||||
if (res < 0) {
|
||||
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
|
||||
&old, sizeof(old)) < 0)
|
||||
errno = saved_errno;
|
||||
return (res);
|
||||
}
|
||||
|
||||
if (sin != &myaddr) { /* What did the kernel assign? */
|
||||
if (getsockname(sd, (struct sockaddr *)sin, &sinlen)
|
||||
< 0)
|
||||
errno = saved_errno;
|
||||
return (res);
|
||||
}
|
||||
res = bind(sd,
|
||||
(struct sockaddr *)sin, sizeof(struct sockaddr_in));
|
||||
}
|
||||
return (res);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue