mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-27 19:37:53 +01:00
libc rcmd update for IPv6.
A new function bindresvport2(), AF independent version of bindresvport() is also added. Reviewed by: sumikawa Obtained from: KAME project
This commit is contained in:
parent
5d60ed0e69
commit
42b4f28ebd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=55918
@ -87,6 +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 get_myaddress __P((struct sockaddr_in *));
|
||||
__END_DECLS
|
||||
|
||||
|
@ -147,6 +147,7 @@ char *getusershell __P((void));
|
||||
char *getwd __P((char *)); /* obsoleted by getcwd() */
|
||||
int initgroups __P((const char *, int));
|
||||
int iruserok __P((unsigned long, int, const char *, const char *));
|
||||
int iruserok_af __P((void *, int, const char *, const char *, int));
|
||||
int issetugid __P((void));
|
||||
int lchown __P((const char *, uid_t, gid_t));
|
||||
int lockf __P((int, int, off_t));
|
||||
@ -203,6 +204,9 @@ int unwhiteout __P((const char *));
|
||||
int usleep __P((unsigned int));
|
||||
void *valloc __P((size_t)); /* obsoleted by malloc() */
|
||||
pid_t vfork __P((void));
|
||||
int rresvport_af __P((int *, int));
|
||||
int ruserok_af __P((const char *, int, const char *, const char *, int));
|
||||
int iruserok_af __P((void *, int, const char *, const char *, int));
|
||||
|
||||
extern char *suboptarg; /* getsubopt(3) external variable */
|
||||
int getsubopt __P((char **, char * const *, char **));
|
||||
|
@ -39,7 +39,10 @@
|
||||
.Nm rcmd ,
|
||||
.Nm rresvport ,
|
||||
.Nm iruserok ,
|
||||
.Nm ruserok
|
||||
.Nm ruserok ,
|
||||
.Nm rresvport_af ,
|
||||
.Nm iruserok_af ,
|
||||
.Nm ruserok_af
|
||||
.Nd routines for returning a stream to a remote command
|
||||
.Sh SYNOPSIS
|
||||
.Fd #include <unistd.h>
|
||||
@ -51,6 +54,12 @@
|
||||
.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser"
|
||||
.Ft int
|
||||
.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
|
||||
.Ft int
|
||||
.Fn rresvport_af "int *port" "int family"
|
||||
.Ft int
|
||||
.Fn iruserok_af "void *raddr" "int superuser" "const char *ruser" "const char *luser" "int af"
|
||||
.Ft int
|
||||
.Fn ruserok_af "const char *rhost" "int superuser" "const char *ruser" "const char *luser" "int af"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Fn rcmd
|
||||
@ -173,6 +182,19 @@ function is strongly preferred for security reasons.
|
||||
It requires trusting the local DNS at most, while the
|
||||
.Fn ruserok
|
||||
function requires trusting the entire DNS, which can be spoofed.
|
||||
.Pp
|
||||
Functions with ``_af'' suffix, i.e.
|
||||
.Fn rresvport_af ,
|
||||
.Fn iruserok_af and
|
||||
.Fn ruserok_af ,
|
||||
works just as same as functions without ``_af'', and is capable of
|
||||
handling both IPv6 port and IPv4 port.
|
||||
To switch address family,
|
||||
.Fa af
|
||||
argument must be filled with
|
||||
.Dv AF_INET
|
||||
or
|
||||
.Dv AF_INET6 .
|
||||
.Sh DIAGNOSTICS
|
||||
The
|
||||
.Fn rcmd
|
||||
@ -198,7 +220,18 @@ is overloaded to mean ``All network ports in use.''
|
||||
.Xr rexecd 8 ,
|
||||
.Xr rlogind 8 ,
|
||||
.Xr rshd 8
|
||||
.Pp
|
||||
W. Stevens and M. Thomas, ``Advanced Socket API for IPv6,''
|
||||
RFC2292.
|
||||
.Sh HISTORY
|
||||
These
|
||||
functions appeared in
|
||||
.Bx 4.2 .
|
||||
.Fn rresvport_af
|
||||
appeared in RFC2292, and implemented by WIDE project
|
||||
for Hydrangea IPv6 protocol stack kit.
|
||||
.Fn iruserok_af
|
||||
and
|
||||
.Fn rusreok_af
|
||||
are proposed and implemented by WIDE project
|
||||
for Hydrangea IPv6 protocol stack kit.
|
||||
|
@ -59,12 +59,19 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#endif
|
||||
|
||||
/* wrapper for KAME-special getnameinfo() */
|
||||
#ifndef NI_WITHSCOPEID
|
||||
#define NI_WITHSCOPEID 0
|
||||
#endif
|
||||
|
||||
extern int innetgr __P(( const char *, const char *, const char *, const char * ));
|
||||
|
||||
#define max(a, b) ((a > b) ? a : b)
|
||||
|
||||
int __ivaliduser __P((FILE *, u_int32_t, const char *, const char *));
|
||||
static int __icheckhost __P((u_int32_t, char *));
|
||||
static int __icheckhost __P((void *, char *, int, int));
|
||||
|
||||
char paddr[INET6_ADDRSTRLEN];
|
||||
|
||||
int
|
||||
rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
@ -73,24 +80,40 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
const char *locuser, *remuser, *cmd;
|
||||
int *fd2p;
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in sin, from;
|
||||
struct addrinfo hints, *res, *ai;
|
||||
struct sockaddr_storage from;
|
||||
fd_set reads;
|
||||
long oldmask;
|
||||
pid_t pid;
|
||||
int s, lport, timo;
|
||||
int s, aport, lport, timo, error;
|
||||
char c;
|
||||
int refused;
|
||||
char num[8];
|
||||
|
||||
pid = getpid();
|
||||
hp = gethostbyname(*ahost);
|
||||
if (hp == NULL) {
|
||||
herror(*ahost);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_protocol = 0;
|
||||
(void)snprintf(num, sizeof(num), "%d", ntohs(rport));
|
||||
error = getaddrinfo(*ahost, num, &hints, &res);
|
||||
if (error) {
|
||||
fprintf(stderr, "rcmd: getaddrinfo: %s\n",
|
||||
gai_strerror(error));
|
||||
if (error == EAI_SYSTEM)
|
||||
fprintf(stderr, "rcmd: getaddrinfo: %s\n",
|
||||
strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
*ahost = hp->h_name;
|
||||
if (res->ai_canonname)
|
||||
*ahost = res->ai_canonname;
|
||||
ai = res;
|
||||
refused = 0;
|
||||
oldmask = sigblock(sigmask(SIGURG));
|
||||
for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
|
||||
s = rresvport(&lport);
|
||||
s = rresvport_af(&lport, ai->ai_family);
|
||||
if (s < 0) {
|
||||
if (errno == EAGAIN)
|
||||
(void)fprintf(stderr,
|
||||
@ -99,40 +122,47 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
(void)fprintf(stderr, "rcmd: socket: %s\n",
|
||||
strerror(errno));
|
||||
sigsetmask(oldmask);
|
||||
freeaddrinfo(res);
|
||||
return (-1);
|
||||
}
|
||||
_libc_fcntl(s, F_SETOWN, pid);
|
||||
bzero(&sin, sizeof sin);
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = hp->h_addrtype;
|
||||
sin.sin_port = rport;
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
|
||||
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
|
||||
if (connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
|
||||
break;
|
||||
(void)_libc_close(s);
|
||||
if (errno == EADDRINUSE) {
|
||||
lport--;
|
||||
continue;
|
||||
}
|
||||
if (errno == ECONNREFUSED && timo <= 16) {
|
||||
(void)_libc_sleep(timo);
|
||||
timo *= 2;
|
||||
continue;
|
||||
}
|
||||
if (hp->h_addr_list[1] != NULL) {
|
||||
if (errno == ECONNREFUSED)
|
||||
refused = 1;
|
||||
if (ai->ai_next != NULL) {
|
||||
int oerrno = errno;
|
||||
|
||||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
paddr, sizeof(paddr),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
(void)fprintf(stderr, "connect to address %s: ",
|
||||
inet_ntoa(sin.sin_addr));
|
||||
paddr);
|
||||
errno = oerrno;
|
||||
perror(0);
|
||||
hp->h_addr_list++;
|
||||
bcopy(hp->h_addr_list[0], &sin.sin_addr, MIN(hp->h_length, sizeof sin.sin_addr));
|
||||
(void)fprintf(stderr, "Trying %s...\n",
|
||||
inet_ntoa(sin.sin_addr));
|
||||
ai = ai->ai_next;
|
||||
getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
||||
paddr, sizeof(paddr),
|
||||
NULL, 0,
|
||||
NI_NUMERICHOST|NI_WITHSCOPEID);
|
||||
fprintf(stderr, "Trying %s...\n", paddr);
|
||||
continue;
|
||||
}
|
||||
(void)fprintf(stderr, "%s: %s\n", hp->h_name, strerror(errno));
|
||||
if (refused && timo <= 16) {
|
||||
(void)_libc_sleep(timo);
|
||||
timo *= 2;
|
||||
ai = res;
|
||||
refused = 0;
|
||||
continue;
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
(void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno));
|
||||
sigsetmask(oldmask);
|
||||
return (-1);
|
||||
}
|
||||
@ -142,8 +172,8 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
|
||||
lport = 0;
|
||||
} else {
|
||||
char num[8];
|
||||
int s2 = rresvport(&lport), s3;
|
||||
int len = sizeof(from);
|
||||
int s2 = rresvport_af(&lport, ai->ai_family), s3;
|
||||
int len = ai->ai_addrlen;
|
||||
int nfds;
|
||||
|
||||
if (s2 < 0)
|
||||
@ -180,11 +210,24 @@ again:
|
||||
goto bad;
|
||||
}
|
||||
s3 = accept(s2, (struct sockaddr *)&from, &len);
|
||||
switch (from.ss_family) {
|
||||
case AF_INET:
|
||||
aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
aport = 0; /* error */
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* XXX careful for ftp bounce attacks. If discovered, shut them
|
||||
* down and check for the real auxiliary channel to connect.
|
||||
*/
|
||||
if (from.sin_family == AF_INET && from.sin_port == htons(20)) {
|
||||
if (aport == 20) {
|
||||
_libc_close(s3);
|
||||
goto again;
|
||||
}
|
||||
@ -196,10 +239,7 @@ again:
|
||||
goto bad;
|
||||
}
|
||||
*fd2p = s3;
|
||||
from.sin_port = ntohs((u_short)from.sin_port);
|
||||
if (from.sin_family != AF_INET ||
|
||||
from.sin_port >= IPPORT_RESERVED ||
|
||||
from.sin_port < IPPORT_RESERVED / 2) {
|
||||
if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
|
||||
(void)fprintf(stderr,
|
||||
"socket: protocol failure in circuit setup.\n");
|
||||
goto bad2;
|
||||
@ -222,6 +262,7 @@ again:
|
||||
goto bad2;
|
||||
}
|
||||
sigsetmask(oldmask);
|
||||
freeaddrinfo(res);
|
||||
return (s);
|
||||
bad2:
|
||||
if (lport)
|
||||
@ -229,21 +270,46 @@ bad2:
|
||||
bad:
|
||||
(void)_libc_close(s);
|
||||
sigsetmask(oldmask);
|
||||
freeaddrinfo(res);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
rresvport(alport)
|
||||
int *alport;
|
||||
rresvport(port)
|
||||
int *port;
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int s;
|
||||
return rresvport_af(port, AF_INET);
|
||||
}
|
||||
|
||||
bzero(&sin, sizeof sin);
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = INADDR_ANY;
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
int
|
||||
rresvport_af(alport, family)
|
||||
int *alport, family;
|
||||
{
|
||||
int i, s, len, err;
|
||||
struct sockaddr_storage ss;
|
||||
u_short *sport;
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = family;
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in);
|
||||
sport = &((struct sockaddr_in *)&ss)->sin_port;
|
||||
((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6);
|
||||
sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
|
||||
((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
s = socket(ss.ss_family, SOCK_STREAM, 0);
|
||||
if (s < 0)
|
||||
return (-1);
|
||||
#if 0 /* compat_exact_traditional_rresvport_semantics */
|
||||
@ -255,12 +321,13 @@ rresvport(alport)
|
||||
return (-1);
|
||||
}
|
||||
#endif
|
||||
sin.sin_port = 0;
|
||||
if (bindresvport(s, &sin) == -1) {
|
||||
*sport = 0;
|
||||
if (bindresvport2(s, (struct sockaddr *)&ss,
|
||||
((struct sockaddr *)&ss)->sa_len) == -1) {
|
||||
(void)_libc_close(s);
|
||||
return (-1);
|
||||
}
|
||||
*alport = (int)ntohs(sin.sin_port);
|
||||
*alport = (int)ntohs(*sport);
|
||||
return (s);
|
||||
}
|
||||
|
||||
@ -272,18 +339,34 @@ ruserok(rhost, superuser, ruser, luser)
|
||||
const char *rhost, *ruser, *luser;
|
||||
int superuser;
|
||||
{
|
||||
struct hostent *hp;
|
||||
u_int32_t addr;
|
||||
char **ap;
|
||||
return ruserok_af(rhost, superuser, ruser, luser, AF_INET);
|
||||
}
|
||||
|
||||
if ((hp = gethostbyname(rhost)) == NULL)
|
||||
int
|
||||
ruserok_af(rhost, superuser, ruser, luser, af)
|
||||
const char *rhost, *ruser, *luser;
|
||||
int superuser, af;
|
||||
{
|
||||
struct hostent *hp;
|
||||
union {
|
||||
struct in_addr addr_in;
|
||||
struct in6_addr addr_in6;
|
||||
} addr;
|
||||
char **ap;
|
||||
int ret, h_error;
|
||||
|
||||
if ((hp = getipnodebyname(rhost, af, AI_DEFAULT, &h_error)) == NULL)
|
||||
return (-1);
|
||||
ret = -1;
|
||||
for (ap = hp->h_addr_list; *ap; ++ap) {
|
||||
bcopy(*ap, &addr, sizeof(addr));
|
||||
if (iruserok(addr, superuser, ruser, luser) == 0)
|
||||
return (0);
|
||||
bcopy(*ap, &addr, hp->h_length);
|
||||
if (iruserok_af(&addr, superuser, ruser, luser, af) == 0) {
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
freehostent(hp);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -300,6 +383,16 @@ iruserok(raddr, superuser, ruser, luser)
|
||||
unsigned long raddr;
|
||||
int superuser;
|
||||
const char *ruser, *luser;
|
||||
{
|
||||
return iruserok_af(&raddr, superuser, ruser, luser, AF_INET);
|
||||
}
|
||||
|
||||
int
|
||||
iruserok_af(raddr, superuser, ruser, luser, af)
|
||||
void *raddr;
|
||||
int superuser;
|
||||
const char *ruser, *luser;
|
||||
int af;
|
||||
{
|
||||
register char *cp;
|
||||
struct stat sbuf;
|
||||
@ -308,12 +401,25 @@ iruserok(raddr, superuser, ruser, luser)
|
||||
uid_t uid;
|
||||
int first;
|
||||
char pbuf[MAXPATHLEN];
|
||||
int len = 0;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
len = sizeof(struct in_addr);
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
len = sizeof(struct in6_addr);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
first = 1;
|
||||
hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
|
||||
again:
|
||||
if (hostf) {
|
||||
if (__ivaliduser(hostf, (u_int32_t)raddr, luser, ruser) == 0) {
|
||||
if (__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
|
||||
== 0) {
|
||||
(void)fclose(hostf);
|
||||
return (0);
|
||||
}
|
||||
@ -375,6 +481,17 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
FILE *hostf;
|
||||
u_int32_t raddr;
|
||||
const char *luser, *ruser;
|
||||
{
|
||||
return __ivaliduser_af(hostf, &raddr, luser, ruser, AF_INET,
|
||||
sizeof(raddr));
|
||||
}
|
||||
|
||||
int
|
||||
__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
|
||||
FILE *hostf;
|
||||
void *raddr;
|
||||
const char *luser, *ruser;
|
||||
int af, len;
|
||||
{
|
||||
register char *user, *p;
|
||||
int ch;
|
||||
@ -383,6 +500,7 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
struct hostent *hp;
|
||||
/* Presumed guilty until proven innocent. */
|
||||
int userok = 0, hostok = 0;
|
||||
int h_error;
|
||||
#ifdef YP
|
||||
char *ypdomain;
|
||||
|
||||
@ -392,11 +510,11 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
#define ypdomain NULL
|
||||
#endif
|
||||
/* We need to get the damn hostname back for netgroup matching. */
|
||||
if ((hp = gethostbyaddr((char *)&raddr, sizeof(u_int32_t),
|
||||
AF_INET)) == NULL)
|
||||
if ((hp = getipnodebyaddr((char *)raddr, len, af, &h_error)) == NULL)
|
||||
return (-1);
|
||||
strncpy(hname, hp->h_name, sizeof(hname));
|
||||
hname[sizeof(hname) - 1] = '\0';
|
||||
freehostent(hp);
|
||||
|
||||
while (fgets(buf, sizeof(buf), hostf)) {
|
||||
p = buf;
|
||||
@ -438,7 +556,8 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
hostok = innetgr((char *)&buf[2],
|
||||
(char *)&hname, NULL, ypdomain);
|
||||
else /* match a host by addr */
|
||||
hostok = __icheckhost(raddr,(char *)&buf[1]);
|
||||
hostok = __icheckhost(raddr,(char *)&buf[1],
|
||||
af, len);
|
||||
break;
|
||||
case '-': /* reject '-' hosts and all their users */
|
||||
if (buf[1] == '@') {
|
||||
@ -446,12 +565,12 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
(char *)&hname, NULL, ypdomain))
|
||||
return(-1);
|
||||
} else {
|
||||
if (__icheckhost(raddr,(char *)&buf[1]))
|
||||
if (__icheckhost(raddr,(char *)&buf[1],af,len))
|
||||
return(-1);
|
||||
}
|
||||
break;
|
||||
default: /* if no '+' or '-', do a simple match */
|
||||
hostok = __icheckhost(raddr, buf);
|
||||
hostok = __icheckhost(raddr, buf, af, len);
|
||||
break;
|
||||
}
|
||||
switch(*user) {
|
||||
@ -494,27 +613,37 @@ __ivaliduser(hostf, raddr, luser, ruser)
|
||||
* Returns "true" if match, 0 if no match.
|
||||
*/
|
||||
static int
|
||||
__icheckhost(raddr, lhost)
|
||||
u_int32_t raddr;
|
||||
__icheckhost(raddr, lhost, af, len)
|
||||
void *raddr;
|
||||
register char *lhost;
|
||||
int af, len;
|
||||
{
|
||||
register struct hostent *hp;
|
||||
register u_int32_t laddr;
|
||||
char laddr[BUFSIZ]; /* xxx */
|
||||
register char **pp;
|
||||
int h_error;
|
||||
int match;
|
||||
|
||||
/* Try for raw ip address first. */
|
||||
if (isdigit((unsigned char)*lhost) && (u_int32_t)(laddr = inet_addr(lhost)) != -1)
|
||||
return (raddr == laddr);
|
||||
if (inet_pton(af, lhost, laddr) == 1) {
|
||||
if (memcmp(raddr, laddr, len) == 0)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Better be a hostname. */
|
||||
if ((hp = gethostbyname(lhost)) == NULL)
|
||||
if ((hp = getipnodebyname(lhost, af, AI_DEFAULT, &h_error)) == NULL)
|
||||
return (0);
|
||||
|
||||
/* Spin through ip addresses. */
|
||||
match = 0;
|
||||
for (pp = hp->h_addr_list; *pp; ++pp)
|
||||
if (!bcmp(&raddr, *pp, sizeof(u_int32_t)))
|
||||
return (1);
|
||||
if (!bcmp(raddr, *pp, len)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* No match. */
|
||||
return (0);
|
||||
freehostent(hp);
|
||||
return (match);
|
||||
}
|
||||
|
@ -44,7 +44,8 @@ crypt.h: ${RPCDIR}/crypt.x
|
||||
#
|
||||
|
||||
# MAN1+= rstat.1
|
||||
MAN3+= bindresvport.3 des_crypt.3 getrpcent.3 getrpcport.3 publickey.3 rpc.3 \
|
||||
MAN3+= bindresvport.3 bindresvport2.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
|
||||
|
@ -30,3 +30,5 @@ 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.
|
||||
.Sh "SEE ALSO"
|
||||
.Xr bindresvport2 3
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user