2000-01-17  Ulrich Drepper  <drepper@cygnus.com>

	* inet/rcmd.c: Implement rcmd_af, rresvport_af, ruserok_af, and
	iruserok_af.
	* inet/rexec.c: Implement rexec_af.
	Patch by Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp>.

	* resolv/netdb.h: Add declarations of rcmd_af, rexec_af, ruserok_af,
	and rresvport_af.
This commit is contained in:
Ulrich Drepper 2000-01-18 06:46:32 +00:00
parent 0482576eec
commit 2d29aba941
4 changed files with 381 additions and 186 deletions

View File

@ -1,3 +1,13 @@
2000-01-17 Ulrich Drepper <drepper@cygnus.com>
* inet/rcmd.c: Implement rcmd_af, rresvport_af, ruserok_af, and
iruserok_af.
* inet/rexec.c: Implement rexec_af.
Patch by Hideaki YOSHIFUJI <yoshfuji@ecei.tohoku.ac.jp>.
* resolv/netdb.h: Add declarations of rcmd_af, rexec_af, ruserok_af,
and rresvport_af.
2000-01-17 Jakub Jelinek <jakub@redhat.com> 2000-01-17 Jakub Jelinek <jakub@redhat.com>
* sysdeps/unix/sysv/linux/bits/ipc.h: New file. * sysdeps/unix/sysv/linux/bits/ipc.h: New file.

View File

@ -1,3 +1,31 @@
/*
* Copyright (C) 1998 WIDE Project.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* /*
* Copyright (c) 1983, 1993, 1994 * Copyright (c) 1983, 1993, 1994
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
@ -54,100 +82,124 @@ static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
int __ivaliduser __P ((FILE *, u_int32_t, const char *, const char *)); int __ivaliduser __P ((FILE *, u_int32_t, const char *, const char *));
static int __ivaliduser2 __P ((FILE *, u_int32_t, const char *, const char *, static int __validuser2_sa __P ((FILE *, struct sockaddr *, size_t,
const char *)); const char *, const char *, const char *));
static int iruserok2 (u_int32_t raddr, int superuser, const char *ruser, static int ruserok2_sa (struct sockaddr *ra, size_t ralen,
int superuser, const char *ruser,
const char *luser, const char *rhost); const char *luser, const char *rhost);
static int ruserok_sa (struct sockaddr *ra, size_t ralen,
int superuser, const char *ruser,
const char *luser);
int iruserok_af (const void *raddr, int superuser, const char *ruser,
const char *luser, sa_family_t af);
int iruserok (u_int32_t raddr, int superuser, const char *ruser, int iruserok (u_int32_t raddr, int superuser, const char *ruser,
const char *luser); const char *luser);
static char ahostbuf[NI_MAXHOST];
int int
rcmd(ahost, rport, locuser, remuser, cmd, fd2p) rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
char **ahost; char **ahost;
u_short rport; u_short rport;
const char *locuser, *remuser, *cmd; const char *locuser, *remuser, *cmd;
int *fd2p; int *fd2p;
sa_family_t af;
{ {
struct hostent hostbuf, *hp; char paddr[INET6_ADDRSTRLEN];
size_t hstbuflen; size_t hstbuflen;
char *tmphstbuf; char *tmphstbuf;
struct sockaddr_in sin, from; struct addrinfo hints, *res, *ai;
struct sockaddr_storage from;
struct pollfd pfd[2]; struct pollfd pfd[2];
int32_t oldmask; int32_t oldmask;
pid_t pid; pid_t pid;
int s, lport, timo; int s, lport, timo, error;
char c; char c;
int herr; int refused;
char num[8];
if (af != AF_INET && af != AF_INET6)
{
__set_errno (EAFNOSUPPORT);
return -1;
}
pid = __getpid(); pid = __getpid();
hstbuflen = 1024; memset(&hints, '\0', sizeof(hints));
tmphstbuf = __alloca (hstbuflen); hints.ai_flags = AI_CANONNAME;
while (__gethostbyname_r (*ahost, &hostbuf, tmphstbuf, hstbuflen, hints.ai_family = af;
&hp, &herr) != 0 hints.ai_socktype = SOCK_STREAM;
|| hp == NULL) (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
if (herr != NETDB_INTERNAL || errno != ERANGE) error = getaddrinfo(*ahost, num, &hints, &res);
{ if (error) {
__set_h_errno (herr); fprintf(stderr, "rcmd: getaddrinfo: %s\n",
herror(*ahost); gai_strerror(error));
return -1; return (-1);
}
else
{
/* Enlarge the buffer. */
hstbuflen *= 2;
tmphstbuf = __alloca (hstbuflen);
} }
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
pfd[1].events = POLLIN; pfd[1].events = POLLIN;
*ahost = hp->h_name; if (res->ai_canonname){
strncpy(ahostbuf, res->ai_canonname, sizeof(ahostbuf));
ahostbuf[sizeof(ahostbuf)-1] = '\0';
*ahost = ahostbuf;
}
else
*ahost = NULL;
ai = res;
refused = 0;
oldmask = __sigblock(sigmask(SIGURG)); oldmask = __sigblock(sigmask(SIGURG));
for (timo = 1, lport = IPPORT_RESERVED - 1;;) { for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
s = rresvport(&lport); s = rresvport_af(&lport, ai->ai_family);
if (s < 0) { if (s < 0) {
if (errno == EAGAIN) if (errno == EAGAIN)
(void)fprintf(stderr, fprintf(stderr,
_("rcmd: socket: All ports in use\n")); _("rcmd: socket: All ports in use\n"));
else else
(void)fprintf(stderr, "rcmd: socket: %m\n"); fprintf(stderr, "rcmd: socket: %m\n");
__sigsetmask(oldmask); __sigsetmask(oldmask);
freeaddrinfo(res);
return -1; return -1;
} }
__fcntl(s, F_SETOWN, pid); __fcntl(s, F_SETOWN, pid);
sin.sin_family = hp->h_addrtype; if (__connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
bcopy(hp->h_addr_list[0], &sin.sin_addr,
MIN (sizeof (sin.sin_addr), hp->h_length));
sin.sin_port = rport;
if (__connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
break; break;
(void)__close(s); (void)__close(s);
if (errno == EADDRINUSE) { if (errno == EADDRINUSE) {
lport--; lport--;
continue; continue;
} }
if (errno == ECONNREFUSED && timo <= 16) { if (errno == ECONNREFUSED)
(void)__sleep(timo); refused = 1;
timo *= 2; if (ai->ai_next != NULL) {
continue;
}
if (hp->h_addr_list[1] != NULL) {
int oerrno = errno; int oerrno = errno;
(void)fprintf(stderr, _("connect to address %s: "), getnameinfo(ai->ai_addr, ai->ai_addrlen,
inet_ntoa(sin.sin_addr)); paddr, sizeof(paddr),
NULL, 0,
NI_NUMERICHOST);
fprintf(stderr, "connect to address %s: ", paddr);
__set_errno (oerrno); __set_errno (oerrno);
perror(0); perror(0);
hp->h_addr_list++; ai = ai->ai_next;
bcopy(hp->h_addr_list[0], &sin.sin_addr, getnameinfo(ai->ai_addr, ai->ai_addrlen,
MIN (sizeof (sin.sin_addr), hp->h_length)); paddr, sizeof(paddr),
(void)fprintf(stderr, _("Trying %s...\n"), NULL, 0,
inet_ntoa(sin.sin_addr)); NI_NUMERICHOST);
fprintf(stderr, "Trying %s...\n", paddr);
continue; continue;
} }
(void)fprintf(stderr, "%s: %m\n", hp->h_name); if (refused && timo <= 16) {
(void)sleep(timo);
timo *= 2;
ai = res;
refused = 0;
continue;
}
freeaddrinfo(res);
(void)fprintf(stderr, "%s: %s\n", *ahost, strerror(errno));
__sigsetmask(oldmask); __sigsetmask(oldmask);
return -1; return -1;
} }
@ -157,8 +209,8 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
lport = 0; lport = 0;
} else { } else {
char num[8]; char num[8];
int s2 = rresvport(&lport), s3; int s2 = rresvport_af(&lport, ai->ai_family), s3;
size_t len = sizeof(from); size_t len = ai->ai_addrlen;
if (s2 < 0) if (s2 < 0)
goto bad; goto bad;
@ -184,6 +236,17 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
goto bad; goto bad;
} }
s3 = accept(s2, (struct sockaddr *)&from, &len); s3 = accept(s2, (struct sockaddr *)&from, &len);
switch (from.__ss_family) {
case AF_INET:
rport = ntohs(((struct sockaddr_in *)&from)->sin_port);
break;
case AF_INET6:
rport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
break;
default:
rport = 0;
break;
}
(void)__close(s2); (void)__close(s2);
if (s3 < 0) { if (s3 < 0) {
(void)fprintf(stderr, (void)fprintf(stderr,
@ -192,10 +255,8 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
goto bad; goto bad;
} }
*fd2p = s3; *fd2p = s3;
from.sin_port = ntohs((u_short)from.sin_port);
if (from.sin_family != AF_INET || if (rport >= IPPORT_RESERVED || rport < IPPORT_RESERVED / 2){
from.sin_port >= IPPORT_RESERVED ||
from.sin_port < IPPORT_RESERVED / 2) {
(void)fprintf(stderr, (void)fprintf(stderr,
_("socket: protocol failure in circuit setup\n")); _("socket: protocol failure in circuit setup\n"));
goto bad2; goto bad2;
@ -218,6 +279,7 @@ rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
goto bad2; goto bad2;
} }
__sigsetmask(oldmask); __sigsetmask(oldmask);
freeaddrinfo(res);
return s; return s;
bad2: bad2:
if (lport) if (lport)
@ -225,6 +287,69 @@ bad2:
bad: bad:
(void)__close(s); (void)__close(s);
__sigsetmask(oldmask); __sigsetmask(oldmask);
freeaddrinfo(res);
return -1;
}
int
rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
char **ahost;
u_short rport;
const char *locuser, *remuser, *cmd;
int *fd2p;
{
return rcmd_af (ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
}
int
rresvport_af(alport, family)
int *alport;
sa_family_t family;
{
struct sockaddr_storage ss;
int s;
size_t len;
uint16_t *sport, i;
switch(family){
case AF_INET:
len = sizeof(struct sockaddr_in);
sport = &((struct sockaddr_in *)&ss)->sin_port;
break;
case AF_INET6:
len = sizeof(struct sockaddr_in6);
sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
break;
default:
__set_errno (EAFNOSUPPORT);
return -1;
}
s = socket(family, SOCK_STREAM, 0);
if (s < 0)
return -1;
memset (&ss, '\0', sizeof(ss));
#ifdef SALEN
ss.__ss_len = len;
#endif
ss.__ss_family = family;
for (;;) {
*sport = htons(i);
if (bind(s, (struct sockaddr *)&ss, len) >= 0){
*alport = i;
return s;
}
if (errno != EADDRINUSE) {
(void)__close(s);
return -1;
}
(*alport)--;
if (*alport == IPPORT_RESERVED/2)
break;
}
(void)__close(s);
__set_errno (EAGAIN);
return -1; return -1;
} }
@ -232,67 +357,43 @@ int
rresvport(alport) rresvport(alport)
int *alport; int *alport;
{ {
struct sockaddr_in sin; return rresvport_af(alport, AF_INET);
int s;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
s = __socket(AF_INET, SOCK_STREAM, 0);
if (s < 0)
return -1;
for (;;) {
sin.sin_port = htons((u_short)*alport);
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
return s;
if (errno != EADDRINUSE) {
(void)__close(s);
return -1;
}
(*alport)--;
if (*alport == IPPORT_RESERVED/2) {
(void)__close(s);
__set_errno (EAGAIN); /* close */
return -1;
}
}
} }
int __check_rhosts_file = 1; int __check_rhosts_file = 1;
char *__rcmd_errstr; char *__rcmd_errstr;
int
ruserok_af(rhost, superuser, ruser, luser, af)
const char *rhost, *ruser, *luser;
int superuser;
sa_family_t af;
{
struct addrinfo hints, *res, *res0;
int gai;
int ret;
memset (&hints, '\0', sizeof(hints));
hints.ai_family = af;
gai = getaddrinfo(rhost, NULL, &hints, &res0);
if (gai)
return -1;
ret = -1;
for (res=res0; res; res=res->ai_next)
if (ruserok2_sa(res->ai_addr, res->ai_addrlen,
superuser, ruser, luser, rhost) == 0){
ret = 0;
break;
}
freeaddrinfo(res0);
return (ret);
}
int int
ruserok(rhost, superuser, ruser, luser) ruserok(rhost, superuser, ruser, luser)
const char *rhost, *ruser, *luser; const char *rhost, *ruser, *luser;
int superuser; int superuser;
{ {
struct hostent hostbuf, *hp; return ruserok_af(rhost, superuser, ruser, luser, AF_INET);
size_t buflen;
char *buffer;
u_int32_t addr;
char **ap;
int herr;
buflen = 1024;
buffer = __alloca (buflen);
while (__gethostbyname_r (rhost, &hostbuf, buffer, buflen, &hp, &herr)
!= 0
|| hp == NULL)
if (herr != NETDB_INTERNAL || errno != ERANGE)
return -1;
else
{
/* Enlarge the buffer. */
buflen *= 2;
buffer = __alloca (buflen);
}
for (ap = hp->h_addr_list; *ap; ++ap) {
bcopy(*ap, &addr, sizeof(addr));
if (iruserok2(addr, superuser, ruser, luser, rhost) == 0)
return 0;
}
return -1;
} }
/* Extremely paranoid file open function. */ /* Extremely paranoid file open function. */
@ -348,8 +449,9 @@ iruserfopen (char *file, uid_t okuser)
* Returns 0 if ok, -1 if not ok. * Returns 0 if ok, -1 if not ok.
*/ */
static int static int
iruserok2 (raddr, superuser, ruser, luser, rhost) ruserok2_sa (ra, ralen, superuser, ruser, luser, rhost)
u_int32_t raddr; struct sockaddr *ra;
size_t ralen;
int superuser; int superuser;
const char *ruser, *luser, *rhost; const char *ruser, *luser, *rhost;
{ {
@ -361,7 +463,7 @@ iruserok2 (raddr, superuser, ruser, luser, rhost)
if (hostf) if (hostf)
{ {
isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); isbad = __validuser2_sa (hostf, ra, ralen, luser, ruser, rhost);
fclose (hostf); fclose (hostf);
if (!isbad) if (!isbad)
@ -395,7 +497,7 @@ iruserok2 (raddr, superuser, ruser, luser, rhost)
if (hostf != NULL) if (hostf != NULL)
{ {
isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); isbad = __validuser2_sa (hostf, ra, ralen, luser, ruser, rhost);
fclose (hostf); fclose (hostf);
} }
@ -404,15 +506,56 @@ iruserok2 (raddr, superuser, ruser, luser, rhost)
} }
return -1; return -1;
} }
/*
* ruserok_sa() is now discussed on ipng, so
* currently disabled for external use
*/
static int ruserok_sa(ra, ralen, superuser, ruser, luser)
struct sockaddr *ra;
size_t ralen;
int superuser;
const char *ruser, *luser;
{
ruserok2_sa(ra, ralen, superuser, ruser, luser, "-");
}
/* This is the exported version. */ /* This is the exported version. */
int int
iruserok_af (raddr, superuser, ruser, luser, af)
const void *raddr;
int superuser;
const char *ruser, *luser;
sa_family_t af;
{
struct sockaddr_storage ra;
size_t ralen;
memset (&ra, '\0', sizeof(ra));
switch (af){
case AF_INET:
((struct sockaddr_in *)&ra)->sin_family = AF_INET;
memcpy (&(((struct sockaddr_in *)&ra)->sin_addr), raddr,
sizeof(struct in_addr));
ralen = sizeof(struct sockaddr_in);
break;
case AF_INET6:
((struct sockaddr_in6 *)&ra)->sin6_family = AF_INET6;
memcpy (&(((struct sockaddr_in6 *)&ra)->sin6_addr), raddr,
sizeof(struct in6_addr));
ralen = sizeof(struct sockaddr_in6);
break;
default:
return 0;
}
return ruserok_sa ((struct sockaddr *)&ra, ralen, superuser, ruser, luser);
}
int
iruserok (raddr, superuser, ruser, luser) iruserok (raddr, superuser, ruser, luser)
u_int32_t raddr; u_int32_t raddr;
int superuser; int superuser;
const char *ruser, *luser; const char *ruser, *luser;
{ {
return iruserok2 (raddr, superuser, ruser, luser, "-"); return iruserok_af (&raddr, superuser, ruser, luser, AF_INET);
} }
/* /*
@ -432,26 +575,31 @@ __ivaliduser(hostf, raddr, luser, ruser)
u_int32_t raddr; u_int32_t raddr;
const char *luser, *ruser; const char *luser, *ruser;
{ {
return __ivaliduser2(hostf, raddr, luser, ruser, "-"); struct sockaddr_in ra;
memset(&ra, '\0', sizeof(ra));
ra.sin_family = AF_INET;
ra.sin_addr.s_addr = raddr;
return __validuser2_sa(hostf, (struct sockaddr *)&ra, sizeof(ra),
luser, ruser, "-");
} }
/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ /* Returns 1 on positive match, 0 on no match, -1 on negative match. */
static int static int
internal_function internal_function
__icheckhost (raddr, lhost, rhost) __checkhost_sa (ra, ralen, lhost, rhost)
u_int32_t raddr; struct sockaddr *ra;
size_t ralen;
char *lhost; char *lhost;
const char *rhost; const char *rhost;
{ {
struct hostent hostbuf, *hp; struct addrinfo hints, *res0, *res;
size_t buflen;
char *buffer;
int herr; int herr;
int save_errno; int save_errno;
u_int32_t laddr; char raddr[INET6_ADDRSTRLEN];
int match;
int negate=1; /* Multiply return with this to get -1 instead of 1 */ int negate=1; /* Multiply return with this to get -1 instead of 1 */
char **pp, *user; char *user;
/* Check nis netgroup. */ /* Check nis netgroup. */
if (strncmp ("+@", lhost, 2) == 0) if (strncmp ("+@", lhost, 2) == 0)
@ -469,34 +617,28 @@ __icheckhost (raddr, lhost, rhost)
} }
/* Try for raw ip address first. */ /* Try for raw ip address first. */
if (isdigit (*lhost) && (long) (laddr = inet_addr (lhost)) != -1) /* XXX */
return negate * (! (raddr ^ laddr)); if (getnameinfo(ra, ralen,
raddr, sizeof(raddr), NULL, 0,
NI_NUMERICHOST) == 0)
return negate * (strcmp(raddr, lhost) == 0);
/* Better be a hostname. */ /* Better be a hostname. */
buflen = 1024; match = 0;
buffer = __alloca (buflen); memset(&hints, '\0', sizeof(hints));
save_errno = errno; hints.ai_family = ra->sa_family;
while (__gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) if (getaddrinfo(lhost, NULL, &hints, &res0) == 0){
!= 0)
if (herr != NETDB_INTERNAL || errno != ERANGE)
return (0);
else {
/* Enlarge the buffer. */
buflen *= 2;
buffer = __alloca (buflen);
__set_errno (0);
}
__set_errno (save_errno);
if (hp == NULL)
return 0;
/* Spin through ip addresses. */ /* Spin through ip addresses. */
for (pp = hp->h_addr_list; *pp; ++pp) for (res=res0; res; res->ai_next){
if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) if (res->ai_family == ra->sa_family &&
return negate; !memcmp(res->ai_addr, ra, res->ai_addrlen)){
match = 1;
/* No match. */ break;
return (0); }
}
freeaddrinfo(res0);
}
return (negate * match);
} }
/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ /* Returns 1 on positive match, 0 on no match, -1 on negative match. */
@ -548,9 +690,10 @@ __isempty(p)
* Returns 0 if positive match, -1 if _not_ ok. * Returns 0 if positive match, -1 if _not_ ok.
*/ */
static int static int
__ivaliduser2(hostf, raddr, luser, ruser, rhost) __validuser2_sa(hostf, ra, ralen, luser, ruser, rhost)
FILE *hostf; FILE *hostf;
u_int32_t raddr; struct sockaddr *ra;
size_t ralen;
const char *luser, *ruser, *rhost; const char *luser, *ruser, *rhost;
{ {
register const char *user; register const char *user;
@ -598,7 +741,7 @@ __ivaliduser2(hostf, raddr, luser, ruser, rhost)
/* buf -> host(?) ; user -> username(?) */ /* buf -> host(?) ; user -> username(?) */
/* First check host part */ /* First check host part */
hcheck = __icheckhost (raddr, buf, rhost); hcheck = __checkhost_sa (ra, ralen, buf, rhost);
if (hcheck < 0) if (hcheck < 0)
break; break;

View File

@ -44,62 +44,62 @@ static char sccsid[] = "@(#)rexec.c 8.1 (Berkeley) 6/4/93";
#include <unistd.h> #include <unistd.h>
int rexecoptions; int rexecoptions;
char ahostbuf[NI_MAXHOST];
int int
rexec(ahost, rport, name, pass, cmd, fd2p) rexec_af(ahost, rport, name, pass, cmd, fd2p, af)
char **ahost; char **ahost;
int rport; int rport;
const char *name, *pass, *cmd; const char *name, *pass, *cmd;
int *fd2p; int *fd2p;
sa_family_t af;
{ {
struct sockaddr_in sin, sin2, from; struct sockaddr_storage sa2, from;
struct hostent hostbuf, *hp; struct addrinfo hints, *res0;
const char *orig_name = name; const char *orig_name = name;
const char *orig_pass = pass; const char *orig_pass = pass;
size_t hstbuflen;
char *hsttmpbuf;
u_short port; u_short port;
int s, timo = 1, s3; int s, timo = 1, s3;
char c; char c;
int herr; int herr;
int gai, ok;
char servbuff[NI_MAXSERV];
hstbuflen = 1024; snprintf(servbuff, sizeof(servbuff), "%d", rport);
hsttmpbuf = __alloca (hstbuflen); servbuff[sizeof(servbuff) - 1] = '\0';
while (__gethostbyname_r (*ahost, &hostbuf, hsttmpbuf, hstbuflen,
&hp, &herr) != 0 memset(&hints, 0, sizeof(hints));
|| hp == NULL) hints.ai_family = af;
if (herr != NETDB_INTERNAL || errno != ERANGE) hints.ai_socktype = SOCK_STREAM;
{ hints.ai_flags = AI_CANONNAME;
__set_h_errno (herr); if (gai = getaddrinfo(*ahost, servbuff, &hints, &res0)){
herror(*ahost); /* XXX: set errno? */
return -1; return -1;
} }
else
{
/* Enlarge the buffer. */
hstbuflen *= 2;
hsttmpbuf = __alloca (hstbuflen);
}
*ahost = hp->h_name; if (res0->ai_canonname){
ruserpass(hp->h_name, &name, &pass); strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf));
ahostbuf[sizeof(ahostbuf)-1] = '\0';
*ahost = ahostbuf;
}
else{
*ahost = NULL;
}
ruserpass(res0->ai_canonname, &name, &pass);
retry: retry:
s = __socket(AF_INET, SOCK_STREAM, 0); s = __socket(res0->ai_family, res0->ai_socktype, 0);
if (s < 0) { if (s < 0) {
perror("rexec: socket"); perror("rexec: socket");
return (-1); return (-1);
} }
sin.sin_family = hp->h_addrtype; if (__connect(s, res0->ai_addr, res0->ai_addrlen) < 0) {
sin.sin_port = rport;
bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
if (__connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
if (errno == ECONNREFUSED && timo <= 16) { if (errno == ECONNREFUSED && timo <= 16) {
(void) __close(s); (void) __close(s);
__sleep(timo); __sleep(timo);
timo *= 2; timo *= 2;
goto retry; goto retry;
} }
perror(hp->h_name); perror(res0->ai_canonname);
return (-1); return (-1);
} }
if (fd2p == 0) { if (fd2p == 0) {
@ -107,22 +107,26 @@ retry:
port = 0; port = 0;
} else { } else {
char num[32]; char num[32];
int s2, sin2len; int s2, sa2len;
s2 = __socket(AF_INET, SOCK_STREAM, 0); s2 = __socket(res0->ai_family, res0->ai_socktype, 0);
if (s2 < 0) { if (s2 < 0) {
(void) __close(s); (void) __close(s);
return (-1); return (-1);
} }
listen(s2, 1); listen(s2, 1);
sin2len = sizeof (sin2); sa2len = sizeof (sa2);
if (getsockname(s2, (struct sockaddr *)&sin2, &sin2len) < 0 || if (getsockname(s2, (struct sockaddr *)&sa2, &sa2len) < 0 ||
sin2len != sizeof (sin2)) { sa2len != __libc_sa_len(sa2.__ss_family)) {
perror("getsockname"); perror("getsockname");
(void) __close(s2); (void) __close(s2);
goto bad; goto bad;
} }
port = ntohs((u_short)sin2.sin_port); port = 0;
if (!getnameinfo((struct sockaddr *)&sa2, sa2len,
NULL, 0, servbuff, sizeof(servbuff),
NI_NUMERICSERV))
port = atoi(servbuff);
(void) sprintf(num, "%u", port); (void) sprintf(num, "%u", port);
(void) __write(s, num, strlen(num)+1); (void) __write(s, num, strlen(num)+1);
{ int len = sizeof (from); { int len = sizeof (from);
@ -160,10 +164,22 @@ retry:
} }
goto bad; goto bad;
} }
freeaddrinfo(res0);
return (s); return (s);
bad: bad:
if (port) if (port)
(void) __close(*fd2p); (void) __close(*fd2p);
(void) __close(s); (void) __close(s);
freeaddrinfo(res0);
return (-1); return (-1);
} }
int
rexec(ahost, rport, name, pass, cmd, fd2p)
char **ahost;
int rport;
const char *name, *pass, *cmd;
int *fd2p;
{
return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. /* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it The GNU C Library is free software; you can redistribute it
@ -368,6 +368,14 @@ extern int rcmd (char **__restrict __ahost, unsigned short int __rport,
__const char *__restrict __cmd, int *__restrict __fd2p) __const char *__restrict __cmd, int *__restrict __fd2p)
__THROW; __THROW;
/* This is the equivalent function where the protocol can be selected
and which therefore can be used for IPv6. */
extern int rcmd_af (char **__restrict __ahost, unsigned short int __rport,
__const char *__restrict __locuser,
__const char *__restrict __remuser,
__const char *__restrict __cmd, int *__restrict __fd2p,
sa_family_t __af) __THROW;
/* Call `rexecd' at port RPORT on remote machine *AHOST to execute /* Call `rexecd' at port RPORT on remote machine *AHOST to execute
CMD. The process runs at the remote machine using the ID of user CMD. The process runs at the remote machine using the ID of user
NAME whose cleartext password is PASSWD. In *FD2P the descriptor NAME whose cleartext password is PASSWD. In *FD2P the descriptor
@ -379,15 +387,33 @@ extern int rexec (char **__restrict __ahost, int __rport,
__const char *__restrict __cmd, int *__restrict __fd2p) __const char *__restrict __cmd, int *__restrict __fd2p)
__THROW; __THROW;
/* This is the equivalent function where the protocol can be selected
and which therefore can be used for IPv6. */
extern int rexec_af (char **__restrict __ahost, int __rport,
__const char *__restrict __name,
__const char *__restrict __pass,
__const char *__restrict __cmd, int *__restrict __fd2p,
sa_family_t __af) __THROW;
/* Check whether user REMUSER on system RHOST is allowed to login as LOCUSER. /* Check whether user REMUSER on system RHOST is allowed to login as LOCUSER.
If SUSER is not zero the user tries to become superuser. Return 0 if If SUSER is not zero the user tries to become superuser. Return 0 if
it is possible. */ it is possible. */
extern int ruserok (__const char *__rhost, int __suser, extern int ruserok (__const char *__rhost, int __suser,
__const char *__remuser, __const char *__locuser) __THROW; __const char *__remuser, __const char *__locuser) __THROW;
/* This is the equivalent function where the protocol can be selected
and which therefore can be used for IPv6. */
extern int ruserok_af (__const char *__rhost, int __suser,
__const char *__remuser, __const char *__locuser,
sa_family_t __af) __THROW;
/* Try to allocate reserved port, returning a descriptor for a socket opened /* Try to allocate reserved port, returning a descriptor for a socket opened
at this port or -1 if unsuccessful. The search for an available port at this port or -1 if unsuccessful. The search for an available port
will start at ALPORT and continues with lower numbers. */ will start at ALPORT and continues with lower numbers. */
extern int rresvport_af (int *__alport, sa_family_t __af) __THROW;
/* This is the equivalent function where the protocol can be selected
and which therefore can be used for IPv6. */
extern int rresvport (int *__alport) __THROW; extern int rresvport (int *__alport) __THROW;
#endif #endif