Remove contrib/netbsd-tests/fs/nfs/nfsservice/rpcbind
This should have been pruned in r305358 MFC after: 3 days Sponsored by: Dell EMC Isilon
This commit is contained in:
parent
bc035217de
commit
962bf8e3c1
@ -1,231 +0,0 @@
|
||||
/* $NetBSD: check_bound.c,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)check_bound.c 1.15 93/07/05 SMI" */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* check_bound.c
|
||||
* Checks to see whether the program is still bound to the
|
||||
* claimed address and returns the univeral merged address
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <stdio.h>
|
||||
#include <netconfig.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include "rpcbind.h"
|
||||
|
||||
struct fdlist {
|
||||
int fd;
|
||||
struct netconfig *nconf;
|
||||
struct fdlist *next;
|
||||
int check_binding;
|
||||
};
|
||||
|
||||
static struct fdlist *fdhead; /* Link list of the check fd's */
|
||||
static struct fdlist *fdtail;
|
||||
static const char emptystring[] = "";
|
||||
|
||||
static bool_t check_bound(struct fdlist *, const char *uaddr);
|
||||
|
||||
/*
|
||||
* Returns 1 if the given address is bound for the given addr & transport
|
||||
* For all error cases, we assume that the address is bound
|
||||
* Returns 0 for success.
|
||||
*/
|
||||
static bool_t
|
||||
check_bound(struct fdlist *fdl, const char *uaddr)
|
||||
{
|
||||
int fd;
|
||||
struct netbuf *na;
|
||||
int ans;
|
||||
|
||||
if (fdl->check_binding == FALSE)
|
||||
return (TRUE);
|
||||
|
||||
na = uaddr2taddr(fdl->nconf, uaddr);
|
||||
if (!na)
|
||||
return (TRUE); /* punt, should never happen */
|
||||
|
||||
fd = __rpc_nconf2fd(fdl->nconf);
|
||||
if (fd < 0) {
|
||||
free(na);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
ans = bind(fd, (struct sockaddr *)na->buf, na->len);
|
||||
|
||||
rump_sys_close(fd);
|
||||
free(na);
|
||||
|
||||
return (ans == 0 ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
int
|
||||
add_bndlist(struct netconfig *nconf, struct netbuf *baddr)
|
||||
{
|
||||
struct fdlist *fdl;
|
||||
struct netconfig *newnconf;
|
||||
|
||||
newnconf = getnetconfigent(nconf->nc_netid);
|
||||
if (newnconf == NULL)
|
||||
return (-1);
|
||||
fdl = (struct fdlist *)malloc((u_int)sizeof (struct fdlist));
|
||||
if (fdl == NULL) {
|
||||
freenetconfigent(newnconf);
|
||||
syslog(LOG_ERR, "no memory!");
|
||||
return (-1);
|
||||
}
|
||||
fdl->nconf = newnconf;
|
||||
fdl->next = NULL;
|
||||
if (fdhead == NULL) {
|
||||
fdhead = fdl;
|
||||
fdtail = fdl;
|
||||
} else {
|
||||
fdtail->next = fdl;
|
||||
fdtail = fdl;
|
||||
}
|
||||
/* XXX no bound checking for now */
|
||||
fdl->check_binding = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool_t
|
||||
is_bound(const char *netid, const char *uaddr)
|
||||
{
|
||||
struct fdlist *fdl;
|
||||
|
||||
for (fdl = fdhead; fdl; fdl = fdl->next)
|
||||
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
|
||||
break;
|
||||
if (fdl == NULL)
|
||||
return (TRUE);
|
||||
return (check_bound(fdl, uaddr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns NULL if there was some system error.
|
||||
* Returns "" if the address was not bound, i.e the server crashed.
|
||||
* Returns the merged address otherwise.
|
||||
*/
|
||||
char *
|
||||
mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
|
||||
{
|
||||
struct fdlist *fdl;
|
||||
char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
|
||||
|
||||
for (fdl = fdhead; fdl; fdl = fdl->next)
|
||||
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
|
||||
break;
|
||||
if (fdl == NULL)
|
||||
return (NULL);
|
||||
if (check_bound(fdl, uaddr) == FALSE)
|
||||
/* that server died */
|
||||
return strdup(emptystring);
|
||||
/*
|
||||
* If saddr is not NULL, the remote client may have included the
|
||||
* address by which it contacted us. Use that for the "client" uaddr,
|
||||
* otherwise use the info from the SVCXPRT.
|
||||
*/
|
||||
if (saddr != NULL) {
|
||||
c_uaddr = saddr;
|
||||
} else {
|
||||
c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
|
||||
if (c_uaddr == NULL) {
|
||||
syslog(LOG_ERR, "taddr2uaddr failed for %s",
|
||||
fdl->nconf->nc_netid);
|
||||
return (NULL);
|
||||
}
|
||||
allocated_uaddr = c_uaddr;
|
||||
}
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
if (saddr == NULL) {
|
||||
fprintf(stderr, "mergeaddr: client uaddr = %s\n",
|
||||
c_uaddr);
|
||||
} else {
|
||||
fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
|
||||
c_uaddr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s_uaddr = uaddr;
|
||||
/*
|
||||
* This is all we should need for IP 4 and 6
|
||||
*/
|
||||
m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
|
||||
uaddr, m_uaddr);
|
||||
#endif
|
||||
if (allocated_uaddr != NULL)
|
||||
free(allocated_uaddr);
|
||||
return (m_uaddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a netconf structure from its internal list. This
|
||||
* structure should not be freed.
|
||||
*/
|
||||
struct netconfig *
|
||||
rpcbind_get_conf(const char *netid)
|
||||
{
|
||||
struct fdlist *fdl;
|
||||
|
||||
for (fdl = fdhead; fdl; fdl = fdl->next)
|
||||
if (strcmp(fdl->nconf->nc_netid, netid) == 0)
|
||||
break;
|
||||
if (fdl == NULL)
|
||||
return (NULL);
|
||||
return (fdl->nconf);
|
||||
}
|
@ -1,366 +0,0 @@
|
||||
/* $NetBSD: pmap_svc.c,v 1.2 2013/10/19 17:45:00 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_svc.c
|
||||
* The server procedure for the version 2 portmapper.
|
||||
* All the portmapper related interface from the portmap side.
|
||||
*/
|
||||
|
||||
#ifdef PORTMAP
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/rpcb_prot.h>
|
||||
#ifdef RPCBIND_DEBUG
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#include "rpcbind.h"
|
||||
|
||||
static struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t, rpcprot_t);
|
||||
static bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long);
|
||||
static bool_t pmapproc_getport(struct svc_req *, SVCXPRT *);
|
||||
static bool_t pmapproc_dump(struct svc_req *, SVCXPRT *);
|
||||
|
||||
/*
|
||||
* Called for all the version 2 inquiries.
|
||||
*/
|
||||
void
|
||||
pmap_service(struct svc_req *rqstp, SVCXPRT *xprt)
|
||||
{
|
||||
rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc);
|
||||
switch (rqstp->rq_proc) {
|
||||
case PMAPPROC_NULL:
|
||||
/*
|
||||
* Null proc call
|
||||
*/
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "PMAPPROC_NULL\n");
|
||||
#endif
|
||||
check_access(xprt, rqstp->rq_proc, NULL, PMAPVERS);
|
||||
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) &&
|
||||
debugging) {
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_SET:
|
||||
/*
|
||||
* Set a program, version to port mapping
|
||||
*/
|
||||
pmapproc_change(rqstp, xprt, rqstp->rq_proc);
|
||||
break;
|
||||
|
||||
case PMAPPROC_UNSET:
|
||||
/*
|
||||
* Remove a program, version to port mapping.
|
||||
*/
|
||||
pmapproc_change(rqstp, xprt, rqstp->rq_proc);
|
||||
break;
|
||||
|
||||
case PMAPPROC_GETPORT:
|
||||
/*
|
||||
* Lookup the mapping for a program, version and return its
|
||||
* port number.
|
||||
*/
|
||||
pmapproc_getport(rqstp, xprt);
|
||||
break;
|
||||
|
||||
case PMAPPROC_DUMP:
|
||||
/*
|
||||
* Return the current set of mapped program, version
|
||||
*/
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "PMAPPROC_DUMP\n");
|
||||
#endif
|
||||
pmapproc_dump(rqstp, xprt);
|
||||
break;
|
||||
|
||||
case PMAPPROC_CALLIT:
|
||||
/*
|
||||
* Calls a procedure on the local machine. If the requested
|
||||
* procedure is not registered this procedure does not return
|
||||
* error information!!
|
||||
* This procedure is only supported on rpc/udp and calls via
|
||||
* rpc/udp. It passes null authentication parameters.
|
||||
*/
|
||||
rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS);
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc(xprt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the item with the given program, version number. If that version
|
||||
* number is not found, it returns the item with that program number, so that
|
||||
* the port number is now returned to the caller. The caller when makes a
|
||||
* call to this program, version number, the call will fail and it will
|
||||
* return with PROGVERS_MISMATCH. The user can then determine the highest
|
||||
* and the lowest version number for this program using clnt_geterr() and
|
||||
* use those program version numbers.
|
||||
*/
|
||||
static struct pmaplist *
|
||||
find_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
|
||||
{
|
||||
register struct pmaplist *hit = NULL;
|
||||
register struct pmaplist *pml;
|
||||
|
||||
for (pml = list_pml; pml != NULL; pml = pml->pml_next) {
|
||||
if ((pml->pml_map.pm_prog != prog) ||
|
||||
(pml->pml_map.pm_prot != prot))
|
||||
continue;
|
||||
hit = pml;
|
||||
if (pml->pml_map.pm_vers == vers)
|
||||
break;
|
||||
}
|
||||
return (hit);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
pmapproc_change(struct svc_req *rqstp, SVCXPRT *xprt, unsigned long op)
|
||||
{
|
||||
struct pmap reg;
|
||||
RPCB rpcbreg;
|
||||
long ans;
|
||||
struct sockcred *sc;
|
||||
char uidbuf[32];
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "%s request for (%lu, %lu) : ",
|
||||
op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET",
|
||||
reg.pm_prog, reg.pm_vers);
|
||||
#endif
|
||||
|
||||
if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
|
||||
svcerr_decode(xprt);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!check_access(xprt, op, ®, PMAPVERS)) {
|
||||
svcerr_weakauth(xprt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
(void)svc_getcaller(xprt);
|
||||
sc = __svc_getcallercreds(xprt);
|
||||
|
||||
/*
|
||||
* Can't use getpwnam here. We might end up calling ourselves
|
||||
* and looping.
|
||||
*/
|
||||
if (sc == NULL)
|
||||
rpcbreg.r_owner = __UNCONST(rpcbind_unknown);
|
||||
else if (sc->sc_uid == 0)
|
||||
rpcbreg.r_owner = __UNCONST(rpcbind_superuser);
|
||||
else {
|
||||
/* r_owner will be strdup-ed later */
|
||||
snprintf(uidbuf, sizeof uidbuf, "%d", sc->sc_uid);
|
||||
rpcbreg.r_owner = uidbuf;
|
||||
}
|
||||
|
||||
rpcbreg.r_prog = reg.pm_prog;
|
||||
rpcbreg.r_vers = reg.pm_vers;
|
||||
|
||||
if (op == PMAPPROC_SET) {
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d",
|
||||
(int)((reg.pm_port >> 8) & 0xff),
|
||||
(int)(reg.pm_port & 0xff));
|
||||
rpcbreg.r_addr = buf;
|
||||
if (reg.pm_prot == IPPROTO_UDP) {
|
||||
rpcbreg.r_netid = __UNCONST(udptrans);
|
||||
} else if (reg.pm_prot == IPPROTO_TCP) {
|
||||
rpcbreg.r_netid = __UNCONST(tcptrans);
|
||||
} else {
|
||||
ans = FALSE;
|
||||
goto done_change;
|
||||
}
|
||||
ans = map_set(&rpcbreg, rpcbreg.r_owner);
|
||||
} else if (op == PMAPPROC_UNSET) {
|
||||
bool_t ans1, ans2;
|
||||
|
||||
rpcbreg.r_addr = NULL;
|
||||
rpcbreg.r_netid = __UNCONST(tcptrans);
|
||||
ans1 = map_unset(&rpcbreg, rpcbreg.r_owner);
|
||||
rpcbreg.r_netid = __UNCONST(udptrans);
|
||||
ans2 = map_unset(&rpcbreg, rpcbreg.r_owner);
|
||||
ans = ans1 || ans2;
|
||||
} else {
|
||||
ans = FALSE;
|
||||
}
|
||||
done_change:
|
||||
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) &&
|
||||
debugging) {
|
||||
fprintf(stderr, "portmap: svc_sendreply\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "%s\n", ans == TRUE ? "succeeded" : "failed");
|
||||
#endif
|
||||
if (op == PMAPPROC_SET)
|
||||
rpcbs_set(RPCBVERS_2_STAT, ans);
|
||||
else
|
||||
rpcbs_unset(RPCBVERS_2_STAT, ans);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
pmapproc_getport(struct svc_req *rqstp, SVCXPRT *xprt)
|
||||
{
|
||||
struct pmap reg;
|
||||
long lport;
|
||||
int port = 0;
|
||||
struct pmaplist *fnd;
|
||||
#ifdef RPCBIND_DEBUG
|
||||
char *uaddr;
|
||||
#endif
|
||||
|
||||
if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
|
||||
svcerr_decode(xprt);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!check_access(xprt, PMAPPROC_GETPORT, ®, PMAPVERS)) {
|
||||
svcerr_weakauth(xprt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid),
|
||||
svc_getrpccaller(xprt));
|
||||
fprintf(stderr, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :",
|
||||
reg.pm_prog, reg.pm_vers,
|
||||
reg.pm_prot == IPPROTO_UDP ? "udp" : "tcp", uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot);
|
||||
if (fnd) {
|
||||
char serveuaddr[32];
|
||||
int h1, h2, h3, h4, p1, p2;
|
||||
const char *netid, *ua;
|
||||
|
||||
if (reg.pm_prot == IPPROTO_UDP) {
|
||||
ua = udp_uaddr;
|
||||
netid = udptrans;
|
||||
} else {
|
||||
ua = tcp_uaddr; /* To get the len */
|
||||
netid = tcptrans;
|
||||
}
|
||||
if (ua == NULL) {
|
||||
goto sendreply;
|
||||
}
|
||||
if (sscanf(ua, "%d.%d.%d.%d.%d.%d", &h1, &h2, &h3,
|
||||
&h4, &p1, &p2) == 6) {
|
||||
p1 = (fnd->pml_map.pm_port >> 8) & 0xff;
|
||||
p2 = (fnd->pml_map.pm_port) & 0xff;
|
||||
snprintf(serveuaddr, sizeof(serveuaddr),
|
||||
"%d.%d.%d.%d.%d.%d", h1, h2, h3, h4, p1, p2);
|
||||
if (is_bound(netid, serveuaddr)) {
|
||||
port = fnd->pml_map.pm_port;
|
||||
} else { /* this service is dead; delete it */
|
||||
delete_prog(reg.pm_prog);
|
||||
}
|
||||
}
|
||||
}
|
||||
sendreply:
|
||||
lport = port;
|
||||
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) &&
|
||||
debugging) {
|
||||
(void) fprintf(stderr, "portmap: svc_sendreply\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "port = %d\n", port);
|
||||
#endif
|
||||
rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers,
|
||||
reg.pm_prot == IPPROTO_UDP ? udptrans : tcptrans,
|
||||
port ? udptrans : "");
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
pmapproc_dump(struct svc_req *rqstp, SVCXPRT *xprt)
|
||||
{
|
||||
if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) {
|
||||
svcerr_decode(xprt);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!check_access(xprt, PMAPPROC_DUMP, NULL, PMAPVERS)) {
|
||||
svcerr_weakauth(xprt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr,
|
||||
(caddr_t)&list_pml)) && debugging) {
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "portmap: svc_sendreply\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
#endif /* PORTMAP */
|
@ -1,206 +0,0 @@
|
||||
/* $NetBSD: rpcb_stat.c,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/* #pragma ident "@(#)rpcb_stat.c 1.7 94/04/25 SMI" */
|
||||
|
||||
/*
|
||||
* rpcb_stat.c
|
||||
* Allows for gathering of statistics
|
||||
*
|
||||
* Copyright (c) 1990 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <netconfig.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpcb_prot.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef PORTMAP
|
||||
#include <rpc/pmap_prot.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "rpcbind.h"
|
||||
|
||||
static rpcb_stat_byvers inf;
|
||||
|
||||
void
|
||||
rpcbs_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
rpcbs_procinfo(rpcvers_t rtype, rpcproc_t proc)
|
||||
{
|
||||
switch (rtype + 2) {
|
||||
#ifdef PORTMAP
|
||||
case PMAPVERS: /* version 2 */
|
||||
if (proc > rpcb_highproc_2)
|
||||
return;
|
||||
break;
|
||||
#endif
|
||||
case RPCBVERS: /* version 3 */
|
||||
if (proc > rpcb_highproc_3)
|
||||
return;
|
||||
break;
|
||||
case RPCBVERS4: /* version 4 */
|
||||
if (proc > rpcb_highproc_4)
|
||||
return;
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
inf[rtype].info[proc]++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
rpcbs_set(rpcvers_t rtype, bool_t success)
|
||||
{
|
||||
if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
|
||||
return;
|
||||
inf[rtype].setinfo++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
rpcbs_unset(rpcvers_t rtype, bool_t success)
|
||||
{
|
||||
if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
|
||||
return;
|
||||
inf[rtype].unsetinfo++;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers,
|
||||
const char *netid, const char *uaddr)
|
||||
{
|
||||
rpcbs_addrlist *al;
|
||||
struct netconfig *nconf;
|
||||
|
||||
if (rtype >= RPCBVERS_STAT)
|
||||
return;
|
||||
for (al = inf[rtype].addrinfo; al; al = al->next) {
|
||||
|
||||
if(al->netid == NULL)
|
||||
return;
|
||||
if ((al->prog == prog) && (al->vers == vers) &&
|
||||
(strcmp(al->netid, netid) == 0)) {
|
||||
if ((uaddr == NULL) || (uaddr[0] == 0))
|
||||
al->failure++;
|
||||
else
|
||||
al->success++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
nconf = rpcbind_get_conf(netid);
|
||||
if (nconf == NULL) {
|
||||
return;
|
||||
}
|
||||
al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist));
|
||||
if (al == NULL) {
|
||||
return;
|
||||
}
|
||||
al->prog = prog;
|
||||
al->vers = vers;
|
||||
al->netid = nconf->nc_netid;
|
||||
if ((uaddr == NULL) || (uaddr[0] == 0)) {
|
||||
al->failure = 1;
|
||||
al->success = 0;
|
||||
} else {
|
||||
al->failure = 0;
|
||||
al->success = 1;
|
||||
}
|
||||
al->next = inf[rtype].addrinfo;
|
||||
inf[rtype].addrinfo = al;
|
||||
}
|
||||
|
||||
void
|
||||
rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog,
|
||||
rpcvers_t vers, rpcproc_t proc, char *netid, rpcblist_ptr rbl)
|
||||
{
|
||||
rpcbs_rmtcalllist *rl;
|
||||
struct netconfig *nconf;
|
||||
|
||||
if (rtype >= RPCBVERS_STAT)
|
||||
return;
|
||||
for (rl = inf[rtype].rmtinfo; rl; rl = rl->next) {
|
||||
|
||||
if(rl->netid == NULL)
|
||||
return;
|
||||
|
||||
if ((rl->prog == prog) && (rl->vers == vers) &&
|
||||
(rl->proc == proc) &&
|
||||
(strcmp(rl->netid, netid) == 0)) {
|
||||
if ((rbl == NULL) ||
|
||||
(rbl->rpcb_map.r_vers != vers))
|
||||
rl->failure++;
|
||||
else
|
||||
rl->success++;
|
||||
if (rpcbproc == RPCBPROC_INDIRECT)
|
||||
rl->indirect++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
nconf = rpcbind_get_conf(netid);
|
||||
if (nconf == NULL) {
|
||||
return;
|
||||
}
|
||||
rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist));
|
||||
if (rl == NULL) {
|
||||
return;
|
||||
}
|
||||
rl->prog = prog;
|
||||
rl->vers = vers;
|
||||
rl->proc = proc;
|
||||
rl->netid = nconf->nc_netid;
|
||||
if ((rbl == NULL) ||
|
||||
(rbl->rpcb_map.r_vers != vers)) {
|
||||
rl->failure = 1;
|
||||
rl->success = 0;
|
||||
} else {
|
||||
rl->failure = 0;
|
||||
rl->success = 1;
|
||||
}
|
||||
rl->indirect = 1;
|
||||
rl->next = inf[rtype].rmtinfo;
|
||||
inf[rtype].rmtinfo = rl;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
void *
|
||||
rpcbproc_getstat(void *arg, struct svc_req *req, SVCXPRT *xprt,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
return (void *)&inf;
|
||||
}
|
@ -1,232 +0,0 @@
|
||||
/* $NetBSD: rpcb_svc.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpcb_svc.c 1.16 93/07/05 SMI" */
|
||||
|
||||
/*
|
||||
* rpcb_svc.c
|
||||
* The server procedure for the version 3 rpcbind (TLI).
|
||||
*
|
||||
* It maintains a separate list of all the registered services with the
|
||||
* version 3 of rpcbind.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpcb_prot.h>
|
||||
#include <netconfig.h>
|
||||
#include <syslog.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rpcbind.h"
|
||||
|
||||
static void *rpcbproc_getaddr_3_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
static void *rpcbproc_dump_3_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
|
||||
/*
|
||||
* Called by svc_getreqset. There is a separate server handle for
|
||||
* every transport that it waits on.
|
||||
*/
|
||||
void
|
||||
rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
|
||||
{
|
||||
union {
|
||||
RPCB rpcbproc_set_3_arg;
|
||||
RPCB rpcbproc_unset_3_arg;
|
||||
RPCB rpcbproc_getaddr_3_local_arg;
|
||||
struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
|
||||
char *rpcbproc_uaddr2taddr_3_arg;
|
||||
struct netbuf rpcbproc_taddr2uaddr_3_arg;
|
||||
} argument;
|
||||
char *result;
|
||||
xdrproc_t xdr_argument, xdr_result;
|
||||
void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
|
||||
|
||||
rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
|
||||
|
||||
switch (rqstp->rq_proc) {
|
||||
case NULLPROC:
|
||||
/*
|
||||
* Null proc call
|
||||
*/
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_NULL\n");
|
||||
#endif
|
||||
/* This call just logs, no actual checks */
|
||||
check_access(transp, rqstp->rq_proc, NULL, RPCBVERS);
|
||||
(void) svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
|
||||
return;
|
||||
|
||||
case RPCBPROC_SET:
|
||||
xdr_argument = (xdrproc_t )xdr_rpcb;
|
||||
xdr_result = (xdrproc_t )xdr_bool;
|
||||
local = rpcbproc_set_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_UNSET:
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_bool;
|
||||
local = rpcbproc_unset_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_GETADDR:
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_wrapstring;
|
||||
local = rpcbproc_getaddr_3_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_DUMP:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_DUMP\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_void;
|
||||
xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
|
||||
local = rpcbproc_dump_3_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_CALLIT:
|
||||
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
|
||||
return;
|
||||
|
||||
case RPCBPROC_GETTIME:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_GETTIME\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_void;
|
||||
xdr_result = (xdrproc_t)xdr_u_long;
|
||||
local = rpcbproc_gettime_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_UADDR2TADDR:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_wrapstring;
|
||||
xdr_result = (xdrproc_t)xdr_netbuf;
|
||||
local = rpcbproc_uaddr2taddr_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_TADDR2UADDR:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_netbuf;
|
||||
xdr_result = (xdrproc_t)xdr_wrapstring;
|
||||
local = rpcbproc_taddr2uaddr_com;
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc(transp);
|
||||
return;
|
||||
}
|
||||
(void) memset((char *)&argument, 0, sizeof (argument));
|
||||
if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
|
||||
(char *) &argument)) {
|
||||
svcerr_decode(transp);
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "rpcbind: could not decode\n");
|
||||
return;
|
||||
}
|
||||
if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS)) {
|
||||
svcerr_weakauth(transp);
|
||||
goto done;
|
||||
}
|
||||
result = (*local)(&argument, rqstp, transp, RPCBVERS);
|
||||
if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
|
||||
result)) {
|
||||
svcerr_systemerr(transp);
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
|
||||
&argument)) {
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "unable to free arguments\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the mapping for a program, version and return its
|
||||
* address. Assuming that the caller wants the address of the
|
||||
* server running on the transport on which the request came.
|
||||
*
|
||||
* We also try to resolve the universal address in terms of
|
||||
* address of the caller.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_getaddr_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
RPCB *regp = (RPCB *)arg;
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
char *uaddr;
|
||||
|
||||
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
|
||||
svc_getrpccaller(transp));
|
||||
fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
|
||||
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
|
||||
regp->r_netid, uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
|
||||
RPCB_ALLVERS));
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_dump_3_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
return ((void *)&list_rbl);
|
||||
}
|
@ -1,455 +0,0 @@
|
||||
/* $NetBSD: rpcb_svc_4.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpcb_svc_4.c 1.8 93/07/05 SMI" */
|
||||
|
||||
/*
|
||||
* rpcb_svc_4.c
|
||||
* The server procedure for the version 4 rpcbind.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <netconfig.h>
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "rpcbind.h"
|
||||
|
||||
static void *rpcbproc_getaddr_4_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
static void *rpcbproc_getversaddr_4_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
static void *rpcbproc_getaddrlist_4_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
static void free_rpcb_entry_list(rpcb_entry_list_ptr *);
|
||||
static void *rpcbproc_dump_4_local(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
|
||||
/*
|
||||
* Called by svc_getreqset. There is a separate server handle for
|
||||
* every transport that it waits on.
|
||||
*/
|
||||
void
|
||||
rpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp)
|
||||
{
|
||||
union {
|
||||
rpcb rpcbproc_set_4_arg;
|
||||
rpcb rpcbproc_unset_4_arg;
|
||||
rpcb rpcbproc_getaddr_4_local_arg;
|
||||
char *rpcbproc_uaddr2taddr_4_arg;
|
||||
struct netbuf rpcbproc_taddr2uaddr_4_arg;
|
||||
} argument;
|
||||
char *result;
|
||||
xdrproc_t xdr_argument, xdr_result;
|
||||
void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
|
||||
|
||||
rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc);
|
||||
|
||||
switch (rqstp->rq_proc) {
|
||||
case NULLPROC:
|
||||
/*
|
||||
* Null proc call
|
||||
*/
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_NULL\n");
|
||||
#endif
|
||||
check_access(transp, rqstp->rq_proc, NULL, RPCBVERS4);
|
||||
(void) svc_sendreply(transp, (xdrproc_t) xdr_void, NULL);
|
||||
return;
|
||||
|
||||
case RPCBPROC_SET:
|
||||
/*
|
||||
* Check to see whether the message came from
|
||||
* loopback transports (for security reasons)
|
||||
*/
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_bool;
|
||||
local = rpcbproc_set_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_UNSET:
|
||||
/*
|
||||
* Check to see whether the message came from
|
||||
* loopback transports (for security reasons)
|
||||
*/
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_bool;
|
||||
local = rpcbproc_unset_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_GETADDR:
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_wrapstring;
|
||||
local = rpcbproc_getaddr_4_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_GETVERSADDR:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_GETVERSADDR\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_wrapstring;
|
||||
local = rpcbproc_getversaddr_4_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_DUMP:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_DUMP\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_void;
|
||||
xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
|
||||
local = rpcbproc_dump_4_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_INDIRECT:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_INDIRECT\n");
|
||||
#endif
|
||||
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
|
||||
return;
|
||||
|
||||
/* case RPCBPROC_CALLIT: */
|
||||
case RPCBPROC_BCAST:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_BCAST\n");
|
||||
#endif
|
||||
rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
|
||||
return;
|
||||
|
||||
case RPCBPROC_GETTIME:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_GETTIME\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_void;
|
||||
xdr_result = (xdrproc_t)xdr_u_long;
|
||||
local = rpcbproc_gettime_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_UADDR2TADDR:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_wrapstring;
|
||||
xdr_result = (xdrproc_t)xdr_netbuf;
|
||||
local = rpcbproc_uaddr2taddr_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_TADDR2UADDR:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_netbuf;
|
||||
xdr_result = (xdrproc_t)xdr_wrapstring;
|
||||
local = rpcbproc_taddr2uaddr_com;
|
||||
break;
|
||||
|
||||
case RPCBPROC_GETADDRLIST:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_GETADDRLIST\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_rpcb;
|
||||
xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr;
|
||||
local = rpcbproc_getaddrlist_4_local;
|
||||
break;
|
||||
|
||||
case RPCBPROC_GETSTAT:
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "RPCBPROC_GETSTAT\n");
|
||||
#endif
|
||||
xdr_argument = (xdrproc_t)xdr_void;
|
||||
xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers;
|
||||
local = rpcbproc_getstat;
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc(transp);
|
||||
return;
|
||||
}
|
||||
memset((char *)&argument, 0, sizeof (argument));
|
||||
if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
|
||||
(char *)&argument)) {
|
||||
svcerr_decode(transp);
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "rpcbind: could not decode\n");
|
||||
return;
|
||||
}
|
||||
if (!check_access(transp, rqstp->rq_proc, &argument, RPCBVERS4)) {
|
||||
svcerr_weakauth(transp);
|
||||
goto done;
|
||||
}
|
||||
result = (*local)(&argument, rqstp, transp, RPCBVERS4);
|
||||
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result,
|
||||
result)) {
|
||||
svcerr_systemerr(transp);
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (!svc_freeargs(transp, (xdrproc_t) xdr_argument,
|
||||
(char *)&argument)) {
|
||||
if (debugging) {
|
||||
(void) fprintf(stderr, "unable to free arguments\n");
|
||||
if (doabort) {
|
||||
rpcbind_abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the mapping for a program, version and return its
|
||||
* address. Assuming that the caller wants the address of the
|
||||
* server running on the transport on which the request came.
|
||||
* Even if a service with a different version number is available,
|
||||
* it will return that address. The client should check with an
|
||||
* clnt_call to verify whether the service is the one that is desired.
|
||||
* We also try to resolve the universal address in terms of
|
||||
* address of the caller.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_getaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
|
||||
rpcvers_t rpcbversnum)
|
||||
{
|
||||
RPCB *regp = (RPCB *)arg;
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
char *uaddr;
|
||||
|
||||
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
|
||||
svc_getrpccaller(transp));
|
||||
fprintf(stderr, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
|
||||
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
|
||||
regp->r_netid, uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
|
||||
RPCB_ALLVERS));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the mapping for a program, version and return its
|
||||
* address. Assuming that the caller wants the address of the
|
||||
* server running on the transport on which the request came.
|
||||
*
|
||||
* We also try to resolve the universal address in terms of
|
||||
* address of the caller.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_getversaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
RPCB *regp = (RPCB *)arg;
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
char *uaddr;
|
||||
|
||||
uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
|
||||
svc_getrpccaller(transp));
|
||||
fprintf(stderr, "RPCB_GETVERSADDR rqst for (%lu, %lu, %s)"
|
||||
" from %s : ",
|
||||
(unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
|
||||
regp->r_netid, uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
|
||||
RPCB_ONEVERS));
|
||||
}
|
||||
|
||||
/*
|
||||
* Lookup the mapping for a program, version and return the
|
||||
* addresses for all transports in the current transport family.
|
||||
* We return a merged address.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
RPCB *regp = (RPCB *)arg;
|
||||
static rpcb_entry_list_ptr rlist;
|
||||
register rpcblist_ptr rbl;
|
||||
rpcb_entry_list_ptr rp, tail = NULL;
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
rpcb_entry *a;
|
||||
struct netconfig *nconf;
|
||||
struct netconfig *reg_nconf;
|
||||
char *saddr, *maddr = NULL;
|
||||
|
||||
free_rpcb_entry_list(&rlist);
|
||||
prog = regp->r_prog;
|
||||
vers = regp->r_vers;
|
||||
reg_nconf = rpcbind_get_conf(transp->xp_netid);
|
||||
if (reg_nconf == NULL)
|
||||
return (NULL);
|
||||
if (*(regp->r_addr) != '\0') {
|
||||
saddr = regp->r_addr;
|
||||
} else {
|
||||
saddr = NULL;
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
fprintf(stderr, "r_addr: %s r_netid: %s nc_protofmly: %s\n",
|
||||
regp->r_addr, regp->r_netid, reg_nconf->nc_protofmly);
|
||||
}
|
||||
#endif
|
||||
for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
|
||||
if ((rbl->rpcb_map.r_prog == prog) &&
|
||||
(rbl->rpcb_map.r_vers == vers)) {
|
||||
nconf = rpcbind_get_conf(rbl->rpcb_map.r_netid);
|
||||
if (nconf == NULL)
|
||||
goto fail;
|
||||
if (strcmp(nconf->nc_protofmly, reg_nconf->nc_protofmly)
|
||||
!= 0) {
|
||||
continue; /* not same proto family */
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "\tmerge with: %s\n", rbl->rpcb_map.r_addr);
|
||||
#endif
|
||||
if ((maddr = mergeaddr(transp, rbl->rpcb_map.r_netid,
|
||||
rbl->rpcb_map.r_addr, saddr)) == NULL) {
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, " FAILED\n");
|
||||
#endif
|
||||
continue;
|
||||
} else if (!maddr[0]) {
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, " SUCCEEDED, but port died - maddr: nullstring\n");
|
||||
#endif
|
||||
/* The server died. Unset this combination */
|
||||
delete_prog(regp->r_prog);
|
||||
free(maddr);
|
||||
continue;
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, " SUCCEEDED maddr: %s\n", maddr);
|
||||
#endif
|
||||
/*
|
||||
* Add it to rlist.
|
||||
*/
|
||||
rp = (rpcb_entry_list_ptr)
|
||||
malloc((u_int)sizeof (rpcb_entry_list));
|
||||
if (rp == NULL) {
|
||||
free(maddr);
|
||||
goto fail;
|
||||
}
|
||||
a = &rp->rpcb_entry_map;
|
||||
a->r_maddr = maddr;
|
||||
a->r_nc_netid = nconf->nc_netid;
|
||||
a->r_nc_semantics = nconf->nc_semantics;
|
||||
a->r_nc_protofmly = nconf->nc_protofmly;
|
||||
a->r_nc_proto = nconf->nc_proto;
|
||||
rp->rpcb_entry_next = NULL;
|
||||
if (rlist == NULL) {
|
||||
rlist = rp;
|
||||
tail = rp;
|
||||
} else if (tail) {
|
||||
tail->rpcb_entry_next = rp;
|
||||
tail = rp;
|
||||
}
|
||||
rp = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
for (rp = rlist; rp; rp = rp->rpcb_entry_next) {
|
||||
fprintf(stderr, "\t%s %s\n", rp->rpcb_entry_map.r_maddr,
|
||||
rp->rpcb_entry_map.r_nc_proto);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* XXX: getaddrlist info is also being stuffed into getaddr.
|
||||
* Perhaps wrong, but better than it not getting counted at all.
|
||||
*/
|
||||
rpcbs_getaddr(RPCBVERS4 - 2, prog, vers, transp->xp_netid, maddr);
|
||||
return (void *)&rlist;
|
||||
|
||||
fail: free_rpcb_entry_list(&rlist);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free only the allocated structure, rest is all a pointer to some
|
||||
* other data somewhere else.
|
||||
*/
|
||||
static void
|
||||
free_rpcb_entry_list(rpcb_entry_list_ptr *rlistp)
|
||||
{
|
||||
register rpcb_entry_list_ptr rbl, tmp;
|
||||
|
||||
for (rbl = *rlistp; rbl != NULL; ) {
|
||||
tmp = rbl;
|
||||
rbl = rbl->rpcb_entry_next;
|
||||
free((char *)tmp->rpcb_entry_map.r_maddr);
|
||||
free((char *)tmp);
|
||||
}
|
||||
*rlistp = NULL;
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void *
|
||||
rpcbproc_dump_4_local(void *arg, struct svc_req *req, SVCXPRT *xprt,
|
||||
rpcvers_t versnum)
|
||||
{
|
||||
return ((void *)&list_rbl);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,127 +0,0 @@
|
||||
.\" $NetBSD: rpcbind.8,v 1.1 2010/07/26 15:53:00 pooka Exp $
|
||||
.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" Copyright 1991 Sun Microsystems, Inc.
|
||||
.Dd October 19, 2008
|
||||
.Dt RPCBIND 8
|
||||
.Sh NAME
|
||||
.Nm rpcbind
|
||||
.Nd universal addresses to RPC program number mapper
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dilLs
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is a server that converts
|
||||
.Tn RPC
|
||||
program numbers into
|
||||
universal addresses.
|
||||
It must be running on the host to be able to make
|
||||
.Tn RPC
|
||||
calls
|
||||
on a server on that machine.
|
||||
.Pp
|
||||
When an
|
||||
.Tn RPC
|
||||
service is started,
|
||||
it tells
|
||||
.Nm
|
||||
the address at which it is listening,
|
||||
and the
|
||||
.Tn RPC
|
||||
program numbers it is prepared to serve.
|
||||
When a client wishes to make an
|
||||
.Tn RPC
|
||||
call to a given program number,
|
||||
it first contacts
|
||||
.Nm
|
||||
on the server machine to determine
|
||||
the address where
|
||||
.Tn RPC
|
||||
requests should be sent.
|
||||
.Pp
|
||||
.Nm
|
||||
should be started before any other RPC service.
|
||||
Normally, standard
|
||||
.Tn RPC
|
||||
servers are started by port monitors, so
|
||||
.Nm
|
||||
must be started before port monitors are invoked.
|
||||
.Pp
|
||||
When
|
||||
.Nm
|
||||
is started, it checks that certain name-to-address
|
||||
translation-calls function correctly.
|
||||
If they fail, the network configuration databases may be corrupt.
|
||||
Since
|
||||
.Tn RPC
|
||||
services cannot function correctly in this situation,
|
||||
.Nm
|
||||
reports the condition and terminates.
|
||||
.Pp
|
||||
.Nm
|
||||
can only be started by the super-user.
|
||||
.Pp
|
||||
Access control is provided by
|
||||
.Pa /etc/hosts.allow
|
||||
and
|
||||
.Pa /etc/hosts.deny ,
|
||||
as described in
|
||||
.Xr hosts_access 5
|
||||
with daemon name
|
||||
.Nm .
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d
|
||||
Run in debug mode.
|
||||
In this mode,
|
||||
.Nm
|
||||
will not fork when it starts, will print additional information
|
||||
during operation, and will abort on certain errors.
|
||||
With this option, the name-to-address translation consistency
|
||||
checks are shown in detail.
|
||||
.It Fl i
|
||||
.Dq insecure
|
||||
mode.
|
||||
Allows calls to SET and UNSET from any host.
|
||||
Normally
|
||||
.Nm
|
||||
accepts these requests only from the loopback interface for security reasons.
|
||||
This change is necessary for programs that were compiled with earlier
|
||||
versions of the rpc library and do not make those requests using the
|
||||
loopback interface.
|
||||
.It Fl l
|
||||
Turns on libwrap connection logging.
|
||||
.It Fl s
|
||||
Causes
|
||||
.Nm
|
||||
to change to the user daemon as soon as possible.
|
||||
This causes
|
||||
.Nm
|
||||
to use non-privileged ports for outgoing connections, preventing non-privileged
|
||||
clients from using
|
||||
.Nm
|
||||
to connect to services from a privileged port.
|
||||
.It Fl L
|
||||
Allow old-style local connections over the loopback interface.
|
||||
Without this flag, local connections are only allowed over a local socket,
|
||||
.Pa /var/run/rpcbind.sock
|
||||
.El
|
||||
.Sh NOTES
|
||||
All RPC servers must be restarted if
|
||||
.Nm
|
||||
is restarted.
|
||||
.Sh FILES
|
||||
.Bl -tag -width "/var/run/rpcbind.sock" -compact
|
||||
.It Pa /var/run/rpcbind.sock
|
||||
.It Pa /etc/hosts.allow
|
||||
explicit remote host access list.
|
||||
.It Pa /etc/hosts.deny
|
||||
explicit remote host denial of service list.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpcbind 3 ,
|
||||
.Xr hosts_access 5 ,
|
||||
.Xr hosts_options 5 ,
|
||||
.Xr netconfig 5 ,
|
||||
.Xr rpcinfo 8
|
@ -1,613 +0,0 @@
|
||||
/* $NetBSD: rpcbind.c,v 1.4 2013/10/19 17:45:00 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpcbind.c 1.19 94/04/25 SMI" */
|
||||
|
||||
#if 0
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rpcbind.c
|
||||
* Implements the program, version to address mapping for rpc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <rpc/rpc.h>
|
||||
#ifdef PORTMAP
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <netconfig.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <err.h>
|
||||
#include <util.h>
|
||||
#include <pwd.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "rpcbind.h"
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
/* Global variables */
|
||||
int debugging = 1; /* Tell me what's going on */
|
||||
int doabort = 0; /* When debugging, do an abort on errors */
|
||||
rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
|
||||
|
||||
#include "svc_fdset.h"
|
||||
|
||||
/* who to suid to if -s is given */
|
||||
#define RUN_AS "daemon"
|
||||
|
||||
int runasdaemon = 0;
|
||||
int insecure = 0;
|
||||
int oldstyle_local = 0;
|
||||
int verboselog = 0;
|
||||
|
||||
#ifdef WARMSTART
|
||||
/* Local Variable */
|
||||
static int warmstart = 0; /* Grab a old copy of registrations */
|
||||
#endif
|
||||
|
||||
#ifdef PORTMAP
|
||||
struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
|
||||
const char *udptrans; /* Name of UDP transport */
|
||||
const char *tcptrans; /* Name of TCP transport */
|
||||
const char *udp_uaddr; /* Universal UDP address */
|
||||
const char *tcp_uaddr; /* Universal TCP address */
|
||||
#endif
|
||||
static const char servname[] = "sunrpc";
|
||||
|
||||
const char rpcbind_superuser[] = "superuser";
|
||||
const char rpcbind_unknown[] = "unknown";
|
||||
|
||||
static int init_transport(struct netconfig *);
|
||||
static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
|
||||
struct netbuf *);
|
||||
static void terminate(int);
|
||||
#if 0
|
||||
static void parseargs(int, char *[]);
|
||||
#endif
|
||||
|
||||
int rpcbind_main(void *);
|
||||
int
|
||||
rpcbind_main(void *arg)
|
||||
{
|
||||
struct netconfig *nconf;
|
||||
void *nc_handle; /* Net config handle */
|
||||
struct rlimit rl;
|
||||
int maxrec = RPC_MAXDATASIZE;
|
||||
extern sem_t gensem;
|
||||
|
||||
#if 0
|
||||
parseargs(argc, argv);
|
||||
#endif
|
||||
|
||||
alloc_fdset();
|
||||
|
||||
getrlimit(RLIMIT_NOFILE, &rl);
|
||||
if (rl.rlim_cur < 128) {
|
||||
if (rl.rlim_max <= 128)
|
||||
rl.rlim_cur = rl.rlim_max;
|
||||
else
|
||||
rl.rlim_cur = 128;
|
||||
setrlimit(RLIMIT_NOFILE, &rl);
|
||||
}
|
||||
#if 0
|
||||
if (geteuid()) /* This command allowed only to root */
|
||||
errx(1, "Sorry. You are not superuser");
|
||||
#endif
|
||||
nc_handle = setnetconfig(); /* open netconfig file */
|
||||
if (nc_handle == NULL)
|
||||
errx(1, "could not read /etc/netconfig");
|
||||
#ifdef PORTMAP
|
||||
udptrans = "";
|
||||
tcptrans = "";
|
||||
#endif
|
||||
|
||||
nconf = getnetconfigent("local");
|
||||
if (nconf == NULL)
|
||||
errx(1, "can't find local transport");
|
||||
|
||||
rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
|
||||
|
||||
init_transport(nconf);
|
||||
|
||||
while ((nconf = getnetconfig(nc_handle))) {
|
||||
if (nconf->nc_flag & NC_VISIBLE)
|
||||
init_transport(nconf);
|
||||
}
|
||||
endnetconfig(nc_handle);
|
||||
|
||||
/* catch the usual termination signals for graceful exit */
|
||||
(void) signal(SIGCHLD, reap);
|
||||
(void) signal(SIGINT, terminate);
|
||||
(void) signal(SIGTERM, terminate);
|
||||
(void) signal(SIGQUIT, terminate);
|
||||
/* ignore others that could get sent */
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
//(void) signal(SIGHUP, SIG_IGN); used by mountd
|
||||
(void) signal(SIGUSR1, SIG_IGN);
|
||||
(void) signal(SIGUSR2, SIG_IGN);
|
||||
#ifdef WARMSTART
|
||||
if (warmstart) {
|
||||
read_warmstart();
|
||||
}
|
||||
#endif
|
||||
if (debugging) {
|
||||
printf("rpcbind debugging enabled.");
|
||||
if (doabort) {
|
||||
printf(" Will abort on errors!\n");
|
||||
} else {
|
||||
printf("\n");
|
||||
}
|
||||
} else {
|
||||
if (daemon(0, 0))
|
||||
err(1, "fork failed");
|
||||
}
|
||||
|
||||
openlog("rpcbind", 0, LOG_DAEMON);
|
||||
pidfile(NULL);
|
||||
|
||||
if (runasdaemon) {
|
||||
struct passwd *p;
|
||||
|
||||
if((p = getpwnam(RUN_AS)) == NULL) {
|
||||
syslog(LOG_ERR, "cannot get uid of daemon: %m");
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(p->pw_uid) == -1) {
|
||||
syslog(LOG_ERR, "setuid to daemon failed: %m");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
network_init();
|
||||
|
||||
sem_post(&gensem);
|
||||
my_svc_run();
|
||||
syslog(LOG_ERR, "svc_run returned unexpectedly");
|
||||
rpcbind_abort();
|
||||
/* NOTREACHED */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds the entry into the rpcbind database.
|
||||
* If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
|
||||
* Returns 0 if succeeds, else fails
|
||||
*/
|
||||
static int
|
||||
init_transport(struct netconfig *nconf)
|
||||
{
|
||||
int fd;
|
||||
struct t_bind taddr;
|
||||
struct addrinfo hints, *res = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
SVCXPRT *my_xprt;
|
||||
int aicode, status, addrlen;
|
||||
struct sockaddr *sa;
|
||||
struct sockaddr_un sun;
|
||||
const int one = 1;
|
||||
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
return 1; /* not my type */
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
int i;
|
||||
char **s;
|
||||
|
||||
(void)fprintf(stderr, "%s: %ld lookup routines :\n",
|
||||
nconf->nc_netid, nconf->nc_nlookups);
|
||||
for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
|
||||
i++, s++)
|
||||
(void)fprintf(stderr, "[%d] - %s\n", i, *s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX - using RPC library internal functions.
|
||||
*/
|
||||
if ((fd = __rpc_nconf2fd(nconf)) < 0) {
|
||||
if (errno == EAFNOSUPPORT)
|
||||
return 1;
|
||||
warn("Cannot create socket for `%s'", nconf->nc_netid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si)) {
|
||||
warnx("Cannot get information for `%s'", nconf->nc_netid);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (si.si_af == AF_INET6) {
|
||||
/*
|
||||
* We're doing host-based access checks here, so don't allow
|
||||
* v4-in-v6 to confuse things.
|
||||
*/
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one,
|
||||
sizeof one) < 0) {
|
||||
warn("Can't make socket ipv6 only");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!strcmp(nconf->nc_netid, "local")) {
|
||||
(void)memset(&sun, 0, sizeof sun);
|
||||
sun.sun_family = AF_LOCAL;
|
||||
(void)rump_sys_unlink(_PATH_RPCBINDSOCK);
|
||||
(void)strlcpy(sun.sun_path, _PATH_RPCBINDSOCK,
|
||||
sizeof(sun.sun_path));
|
||||
sun.sun_len = SUN_LEN(&sun);
|
||||
addrlen = sizeof(struct sockaddr_un);
|
||||
sa = (struct sockaddr *)&sun;
|
||||
} else {
|
||||
/* Get rpcbind's address on this transport */
|
||||
|
||||
(void)memset(&hints, 0, sizeof hints);
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
hints.ai_family = si.si_af;
|
||||
hints.ai_socktype = si.si_socktype;
|
||||
hints.ai_protocol = si.si_proto;
|
||||
if ((aicode = getaddrinfo(NULL, servname, &hints, &res)) != 0) {
|
||||
warnx("Cannot get local address for `%s' (%s)",
|
||||
nconf->nc_netid, gai_strerror(aicode));
|
||||
return 1;
|
||||
}
|
||||
addrlen = res->ai_addrlen;
|
||||
sa = (struct sockaddr *)res->ai_addr;
|
||||
}
|
||||
|
||||
if (bind(fd, sa, addrlen) < 0) {
|
||||
warn("Cannot bind `%s'", nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
#if 0
|
||||
if (sa->sa_family == AF_LOCAL)
|
||||
if (rump_sys_chmod(sun.sun_path, S_IRWXU|S_IRWXG|S_IRWXO) == -1)
|
||||
warn("Cannot chmod `%s'", sun.sun_path);
|
||||
#endif
|
||||
|
||||
/* Copy the address */
|
||||
taddr.addr.len = taddr.addr.maxlen = addrlen;
|
||||
taddr.addr.buf = malloc(addrlen);
|
||||
if (taddr.addr.buf == NULL) {
|
||||
warn("Cannot allocate memory for `%s' address",
|
||||
nconf->nc_netid);
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
(void)memcpy(taddr.addr.buf, sa, addrlen);
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
/* for debugging print out our universal address */
|
||||
char *uaddr;
|
||||
struct netbuf nb;
|
||||
|
||||
nb.buf = sa;
|
||||
nb.len = nb.maxlen = sa->sa_len;
|
||||
uaddr = taddr2uaddr(nconf, &nb);
|
||||
(void)fprintf(stderr, "rpcbind: my address is %s\n", uaddr);
|
||||
(void)free(uaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res != NULL)
|
||||
freeaddrinfo(res);
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
listen(fd, SOMAXCONN);
|
||||
|
||||
my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE,
|
||||
RPC_MAXDATASIZE);
|
||||
if (my_xprt == NULL) {
|
||||
warnx("Could not create service for `%s'", nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef PORTMAP
|
||||
/*
|
||||
* Register both the versions for tcp/ip, udp/ip and local.
|
||||
*/
|
||||
if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
|
||||
(strcmp(nconf->nc_proto, NC_TCP) == 0 ||
|
||||
strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
|
||||
strcmp(nconf->nc_netid, "local") == 0) {
|
||||
struct pmaplist *pml;
|
||||
|
||||
if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
|
||||
pmap_service, 0)) {
|
||||
warn("Could not register on `%s'", nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
pml = malloc(sizeof (struct pmaplist));
|
||||
if (pml == NULL) {
|
||||
warn("Cannot allocate memory");
|
||||
goto error;
|
||||
}
|
||||
pml->pml_map.pm_prog = PMAPPROG;
|
||||
pml->pml_map.pm_vers = PMAPVERS;
|
||||
pml->pml_map.pm_port = PMAPPORT;
|
||||
if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
|
||||
if (tcptrans[0]) {
|
||||
warnx(
|
||||
"Cannot have more than one TCP transport");
|
||||
free(pml);
|
||||
goto error;
|
||||
}
|
||||
tcptrans = strdup(nconf->nc_netid);
|
||||
if (tcptrans == NULL) {
|
||||
free(pml);
|
||||
warn("Cannot allocate memory");
|
||||
goto error;
|
||||
}
|
||||
pml->pml_map.pm_prot = IPPROTO_TCP;
|
||||
|
||||
/* Let's snarf the universal address */
|
||||
/* "h1.h2.h3.h4.p1.p2" */
|
||||
tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
|
||||
} else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
|
||||
if (udptrans[0]) {
|
||||
free(pml);
|
||||
warnx(
|
||||
"Cannot have more than one UDP transport");
|
||||
goto error;
|
||||
}
|
||||
udptrans = strdup(nconf->nc_netid);
|
||||
if (udptrans == NULL) {
|
||||
free(pml);
|
||||
warn("Cannot allocate memory");
|
||||
goto error;
|
||||
}
|
||||
pml->pml_map.pm_prot = IPPROTO_UDP;
|
||||
|
||||
/* Let's snarf the universal address */
|
||||
/* "h1.h2.h3.h4.p1.p2" */
|
||||
udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
|
||||
}
|
||||
pml->pml_next = list_pml;
|
||||
list_pml = pml;
|
||||
|
||||
/* Add version 3 information */
|
||||
pml = malloc(sizeof (struct pmaplist));
|
||||
if (pml == NULL) {
|
||||
warn("Cannot allocate memory");
|
||||
goto error;
|
||||
}
|
||||
pml->pml_map = list_pml->pml_map;
|
||||
pml->pml_map.pm_vers = RPCBVERS;
|
||||
pml->pml_next = list_pml;
|
||||
list_pml = pml;
|
||||
|
||||
/* Add version 4 information */
|
||||
pml = malloc(sizeof (struct pmaplist));
|
||||
if (pml == NULL) {
|
||||
warn("Cannot allocate memory");
|
||||
goto error;
|
||||
}
|
||||
pml->pml_map = list_pml->pml_map;
|
||||
pml->pml_map.pm_vers = RPCBVERS4;
|
||||
pml->pml_next = list_pml;
|
||||
list_pml = pml;
|
||||
|
||||
/* Also add version 2 stuff to rpcbind list */
|
||||
rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* version 3 registration */
|
||||
if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
|
||||
warn("Could not register %s version 3", nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
|
||||
|
||||
/* version 4 registration */
|
||||
if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
|
||||
warn("Could not register %s version 4", nconf->nc_netid);
|
||||
goto error;
|
||||
}
|
||||
rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
|
||||
|
||||
/* decide if bound checking works for this transport */
|
||||
status = add_bndlist(nconf, &taddr.addr);
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
if (status < 0) {
|
||||
fprintf(stderr, "Error in finding bind status for %s\n",
|
||||
nconf->nc_netid);
|
||||
} else if (status == 0) {
|
||||
fprintf(stderr, "check binding for %s\n",
|
||||
nconf->nc_netid);
|
||||
} else if (status > 0) {
|
||||
fprintf(stderr, "No check binding for %s\n",
|
||||
nconf->nc_netid);
|
||||
}
|
||||
}
|
||||
#else
|
||||
__USE(status);
|
||||
#endif
|
||||
/*
|
||||
* rmtcall only supported on CLTS transports for now.
|
||||
*/
|
||||
if (nconf->nc_semantics == NC_TPI_CLTS) {
|
||||
status = create_rmtcall_fd(nconf);
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging) {
|
||||
if (status < 0) {
|
||||
fprintf(stderr,
|
||||
"Could not create rmtcall fd for %s\n",
|
||||
nconf->nc_netid);
|
||||
} else {
|
||||
fprintf(stderr, "rmtcall fd for %s is %d\n",
|
||||
nconf->nc_netid, status);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return (0);
|
||||
error:
|
||||
(void)rump_sys_close(fd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
|
||||
struct netbuf *addr)
|
||||
{
|
||||
rpcblist_ptr rbl;
|
||||
|
||||
rbl = malloc(sizeof(rpcblist));
|
||||
if (rbl == NULL) {
|
||||
warn("Out of memory");
|
||||
return;
|
||||
}
|
||||
|
||||
rbl->rpcb_map.r_prog = prog;
|
||||
rbl->rpcb_map.r_vers = vers;
|
||||
rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
|
||||
rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
|
||||
rbl->rpcb_map.r_owner = strdup(rpcbind_superuser);
|
||||
rbl->rpcb_next = list_rbl; /* Attach to global list */
|
||||
list_rbl = rbl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Catch the signal and die
|
||||
*/
|
||||
static void
|
||||
terminate(int dummy)
|
||||
{
|
||||
#ifdef WARMSTART
|
||||
syslog(LOG_ERR,
|
||||
"rpcbind terminating on signal. Restart with \"rpcbind -w\"");
|
||||
write_warmstart(); /* Dump yourself */
|
||||
#endif
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void
|
||||
rpcbind_abort()
|
||||
{
|
||||
#ifdef WARMSTART
|
||||
write_warmstart(); /* Dump yourself */
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* get command line options */
|
||||
static void
|
||||
parseargs(int argc, char *argv[])
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "dwailLs")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
doabort = 1; /* when debugging, do an abort on */
|
||||
break; /* errors; for rpcbind developers */
|
||||
/* only! */
|
||||
case 'd':
|
||||
debugging = 1;
|
||||
break;
|
||||
case 'i':
|
||||
insecure = 1;
|
||||
break;
|
||||
case 'L':
|
||||
oldstyle_local = 1;
|
||||
break;
|
||||
case 'l':
|
||||
verboselog = 1;
|
||||
break;
|
||||
case 's':
|
||||
runasdaemon = 1;
|
||||
break;
|
||||
#ifdef WARMSTART
|
||||
case 'w':
|
||||
warmstart = 1;
|
||||
break;
|
||||
#endif
|
||||
default: /* error */
|
||||
fprintf(stderr, "usage: rpcbind [-Idwils]\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
if (doabort && !debugging) {
|
||||
fprintf(stderr,
|
||||
"-a (abort) specified without -d (debugging) -- ignored.\n");
|
||||
doabort = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
reap(int dummy)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
while (wait3(NULL, WNOHANG, NULL) > 0)
|
||||
;
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
void
|
||||
toggle_verboselog(int dummy)
|
||||
{
|
||||
verboselog = !verboselog;
|
||||
}
|
@ -1,146 +0,0 @@
|
||||
/* $NetBSD: rpcbind.h,v 1.1 2010/07/26 15:53:00 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpcbind.h 1.4 90/04/12 SMI" */
|
||||
|
||||
/*
|
||||
* rpcbind.h
|
||||
* The common header declarations
|
||||
*/
|
||||
|
||||
#ifndef rpcbind_h
|
||||
#define rpcbind_h
|
||||
|
||||
#ifdef PORTMAP
|
||||
#include <rpc/pmap_prot.h>
|
||||
#endif
|
||||
#include <rpc/rpcb_prot.h>
|
||||
|
||||
/*
|
||||
* Stuff for the rmtcall service
|
||||
*/
|
||||
struct encap_parms {
|
||||
u_int32_t arglen;
|
||||
char *args;
|
||||
};
|
||||
|
||||
struct r_rmtcall_args {
|
||||
u_int32_t rmt_prog;
|
||||
u_int32_t rmt_vers;
|
||||
u_int32_t rmt_proc;
|
||||
int rmt_localvers; /* whether to send port # or uaddr */
|
||||
char *rmt_uaddr;
|
||||
struct encap_parms rmt_args;
|
||||
};
|
||||
|
||||
extern int debugging;
|
||||
extern int doabort;
|
||||
extern int verboselog;
|
||||
extern int insecure;
|
||||
extern int oldstyle_local;
|
||||
extern rpcblist_ptr list_rbl; /* A list of version 3 & 4 rpcbind services */
|
||||
|
||||
#ifdef PORTMAP
|
||||
extern struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
|
||||
extern const char *udptrans; /* Name of UDP transport */
|
||||
extern const char *tcptrans; /* Name of TCP transport */
|
||||
extern const char *udp_uaddr; /* Universal UDP address */
|
||||
extern const char *tcp_uaddr; /* Universal TCP address */
|
||||
#endif
|
||||
|
||||
extern const char rpcbind_superuser[];
|
||||
extern const char rpcbind_unknown[];
|
||||
|
||||
int add_bndlist(struct netconfig *, struct netbuf *);
|
||||
bool_t is_bound(const char *, const char *);
|
||||
char *mergeaddr(SVCXPRT *, char *, char *, char *);
|
||||
struct netconfig *rpcbind_get_conf(const char *);
|
||||
|
||||
void rpcbs_init(void);
|
||||
void rpcbs_procinfo(rpcvers_t, rpcproc_t);
|
||||
void rpcbs_set(rpcvers_t, bool_t);
|
||||
void rpcbs_unset(rpcvers_t, bool_t);
|
||||
void rpcbs_getaddr(rpcvers_t, rpcprog_t, rpcvers_t, const char *, const char *);
|
||||
void rpcbs_rmtcall(rpcvers_t, rpcproc_t, rpcprog_t, rpcvers_t, rpcproc_t,
|
||||
char *, rpcblist_ptr);
|
||||
void *rpcbproc_getstat(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
|
||||
|
||||
void rpcb_service_3(struct svc_req *, SVCXPRT *);
|
||||
void rpcb_service_4(struct svc_req *, SVCXPRT *);
|
||||
|
||||
/* Common functions shared between versions */
|
||||
void *rpcbproc_set_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
|
||||
void *rpcbproc_unset_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
|
||||
bool_t map_set(RPCB *, char *);
|
||||
bool_t map_unset(RPCB *, const char *);
|
||||
void delete_prog(int);
|
||||
void *rpcbproc_getaddr_com(RPCB *, struct svc_req *, SVCXPRT *, rpcvers_t,
|
||||
rpcvers_t);
|
||||
void *rpcbproc_gettime_com(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
void *rpcbproc_uaddr2taddr_com(void *, struct svc_req *,
|
||||
SVCXPRT *, rpcvers_t);
|
||||
void *rpcbproc_taddr2uaddr_com(void *, struct svc_req *, SVCXPRT *,
|
||||
rpcvers_t);
|
||||
int create_rmtcall_fd(struct netconfig *);
|
||||
void rpcbproc_callit_com(struct svc_req *, SVCXPRT *, rpcvers_t,
|
||||
rpcvers_t);
|
||||
void my_svc_run(void);
|
||||
|
||||
void rpcbind_abort(void);
|
||||
void reap(int);
|
||||
void toggle_verboselog(int);
|
||||
|
||||
int check_access(SVCXPRT *, rpcproc_t, void *, int);
|
||||
int check_callit(SVCXPRT *, struct r_rmtcall_args *, int);
|
||||
void logit(int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *);
|
||||
int is_loopback(struct netbuf *);
|
||||
|
||||
#ifdef PORTMAP
|
||||
extern void pmap_service(struct svc_req *, SVCXPRT *);
|
||||
#endif
|
||||
|
||||
void write_warmstart(void);
|
||||
void read_warmstart(void);
|
||||
|
||||
char *addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
|
||||
char *netid);
|
||||
void network_init(void);
|
||||
struct sockaddr *local_sa(int);
|
||||
|
||||
/* For different getaddr semantics */
|
||||
#define RPCB_ALLVERS 0
|
||||
#define RPCB_ONEVERS 1
|
||||
|
||||
#endif /* rpcbind_h */
|
@ -1,282 +0,0 @@
|
||||
/* $NetBSD: security.c,v 1.1 2010/07/26 15:53:01 pooka Exp $ */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/rpcb_prot.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
#include <syslog.h>
|
||||
#include <netdb.h>
|
||||
|
||||
/*
|
||||
* XXX for special case checks in check_callit.
|
||||
*/
|
||||
#include <rpcsvc/mount.h>
|
||||
#include <rpcsvc/rquota.h>
|
||||
#include <rpcsvc/nfs_prot.h>
|
||||
#include <rpcsvc/yp.h>
|
||||
#include <rpcsvc/ypclnt.h>
|
||||
#include <rpcsvc/yppasswd.h>
|
||||
|
||||
#include "rpcbind.h"
|
||||
|
||||
#ifdef LIBWRAP
|
||||
# include <tcpd.h>
|
||||
#ifndef LIBWRAP_ALLOW_FACILITY
|
||||
# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
|
||||
#endif
|
||||
#ifndef LIBWRAP_ALLOW_SEVERITY
|
||||
# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
|
||||
#endif
|
||||
#ifndef LIBWRAP_DENY_FACILITY
|
||||
# define LIBWRAP_DENY_FACILITY LOG_AUTH
|
||||
#endif
|
||||
#ifndef LIBWRAP_DENY_SEVERITY
|
||||
# define LIBWRAP_DENY_SEVERITY LOG_WARNING
|
||||
#endif
|
||||
int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
|
||||
int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
|
||||
#endif
|
||||
|
||||
#ifndef PORTMAP_LOG_FACILITY
|
||||
# define PORTMAP_LOG_FACILITY LOG_AUTH
|
||||
#endif
|
||||
#ifndef PORTMAP_LOG_SEVERITY
|
||||
# define PORTMAP_LOG_SEVERITY LOG_INFO
|
||||
#endif
|
||||
int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
|
||||
|
||||
extern int verboselog;
|
||||
|
||||
int
|
||||
check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, int rpcbvers)
|
||||
{
|
||||
struct netbuf *caller = svc_getrpccaller(xprt);
|
||||
struct sockaddr *addr = (struct sockaddr *)caller->buf;
|
||||
#ifdef LIBWRAP
|
||||
struct request_info req;
|
||||
#endif
|
||||
rpcprog_t prog = 0;
|
||||
rpcb *rpcbp;
|
||||
struct pmap *pmap;
|
||||
|
||||
/*
|
||||
* The older PMAP_* equivalents have the same numbers, so
|
||||
* they are accounted for here as well.
|
||||
*/
|
||||
switch (proc) {
|
||||
case RPCBPROC_GETADDR:
|
||||
case RPCBPROC_SET:
|
||||
case RPCBPROC_UNSET:
|
||||
if (rpcbvers > PMAPVERS) {
|
||||
rpcbp = (rpcb *)args;
|
||||
prog = rpcbp->r_prog;
|
||||
} else {
|
||||
pmap = (struct pmap *)args;
|
||||
prog = pmap->pm_prog;
|
||||
}
|
||||
if (proc == RPCBPROC_GETADDR)
|
||||
break;
|
||||
if (!insecure && !is_loopback(caller)) {
|
||||
if (verboselog)
|
||||
logit(log_severity, addr, proc, prog,
|
||||
" declined (non-loopback sender)");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case RPCBPROC_CALLIT:
|
||||
case RPCBPROC_INDIRECT:
|
||||
case RPCBPROC_DUMP:
|
||||
case RPCBPROC_GETTIME:
|
||||
case RPCBPROC_UADDR2TADDR:
|
||||
case RPCBPROC_TADDR2UADDR:
|
||||
case RPCBPROC_GETVERSADDR:
|
||||
case RPCBPROC_GETADDRLIST:
|
||||
case RPCBPROC_GETSTAT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef LIBWRAP
|
||||
if (addr->sa_family == AF_LOCAL)
|
||||
return 1;
|
||||
request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
|
||||
sock_methods(&req);
|
||||
if(!hosts_access(&req)) {
|
||||
logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (verboselog)
|
||||
logit(log_severity, addr, proc, prog, "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
is_loopback(struct netbuf *nbuf)
|
||||
{
|
||||
struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
|
||||
struct sockaddr_in *sin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
if (!oldstyle_local)
|
||||
return 0;
|
||||
sin = (struct sockaddr_in *)addr;
|
||||
return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
|
||||
(ntohs(sin->sin_port) < IPPORT_RESERVED));
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
if (!oldstyle_local)
|
||||
return 0;
|
||||
sin6 = (struct sockaddr_in6 *)addr;
|
||||
return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
|
||||
(ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
|
||||
#endif
|
||||
case AF_LOCAL:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* logit - report events of interest via the syslog daemon */
|
||||
void
|
||||
logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
|
||||
const char *text)
|
||||
{
|
||||
const char *procname;
|
||||
char procbuf[32];
|
||||
char *progname;
|
||||
char progbuf[32];
|
||||
char fromname[NI_MAXHOST];
|
||||
struct rpcent *rpc;
|
||||
static const char *procmap[] = {
|
||||
/* RPCBPROC_NULL */ "null",
|
||||
/* RPCBPROC_SET */ "set",
|
||||
/* RPCBPROC_UNSET */ "unset",
|
||||
/* RPCBPROC_GETADDR */ "getport/addr",
|
||||
/* RPCBPROC_DUMP */ "dump",
|
||||
/* RPCBPROC_CALLIT */ "callit",
|
||||
/* RPCBPROC_GETTIME */ "gettime",
|
||||
/* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
|
||||
/* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
|
||||
/* RPCBPROC_GETVERSADDR */ "getversaddr",
|
||||
/* RPCBPROC_INDIRECT */ "indirect",
|
||||
/* RPCBPROC_GETADDRLIST */ "getaddrlist",
|
||||
/* RPCBPROC_GETSTAT */ "getstat"
|
||||
};
|
||||
|
||||
/*
|
||||
* Fork off a process or the portmap daemon might hang while
|
||||
* getrpcbynumber() or syslog() does its thing.
|
||||
*/
|
||||
|
||||
if (fork() == 0) {
|
||||
setproctitle("logit");
|
||||
|
||||
/* Try to map program number to name. */
|
||||
|
||||
if (prognum == 0) {
|
||||
progname = __UNCONST("");
|
||||
} else if ((rpc = getrpcbynumber((int) prognum))) {
|
||||
progname = rpc->r_name;
|
||||
} else {
|
||||
snprintf(progname = progbuf, sizeof(progbuf), "%u",
|
||||
(unsigned)prognum);
|
||||
}
|
||||
|
||||
/* Try to map procedure number to name. */
|
||||
|
||||
if (procnum >= (sizeof procmap / sizeof (char *))) {
|
||||
snprintf(procbuf, sizeof procbuf, "%u",
|
||||
(unsigned)procnum);
|
||||
procname = procbuf;
|
||||
} else
|
||||
procname = procmap[procnum];
|
||||
|
||||
/* Write syslog record. */
|
||||
|
||||
if (addr->sa_family == AF_LOCAL)
|
||||
strlcpy(fromname, "local", sizeof(fromname));
|
||||
else
|
||||
getnameinfo(addr, addr->sa_len, fromname,
|
||||
sizeof fromname, NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
syslog(severity, "connect from %s to %s(%s)%s",
|
||||
fromname, procname, progname, text);
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum)
|
||||
{
|
||||
struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
|
||||
|
||||
/*
|
||||
* Always allow calling NULLPROC
|
||||
*/
|
||||
if (args->rmt_proc == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* XXX - this special casing sucks.
|
||||
*/
|
||||
switch (args->rmt_prog) {
|
||||
case RPCBPROG:
|
||||
/*
|
||||
* Allow indirect calls to ourselves in insecure mode.
|
||||
* The is_loopback checks aren't useful then anyway.
|
||||
*/
|
||||
if (!insecure)
|
||||
goto deny;
|
||||
break;
|
||||
case MOUNTPROG:
|
||||
if (args->rmt_proc != MOUNTPROC_MNT &&
|
||||
args->rmt_proc != MOUNTPROC_UMNT)
|
||||
break;
|
||||
goto deny;
|
||||
case YPBINDPROG:
|
||||
if (args->rmt_proc != YPBINDPROC_SETDOM)
|
||||
break;
|
||||
/* FALLTHROUGH */
|
||||
case YPPASSWDPROG:
|
||||
case NFS_PROGRAM:
|
||||
case RQUOTAPROG:
|
||||
goto deny;
|
||||
case YPPROG:
|
||||
switch (args->rmt_proc) {
|
||||
case YPPROC_ALL:
|
||||
case YPPROC_MATCH:
|
||||
case YPPROC_FIRST:
|
||||
case YPPROC_NEXT:
|
||||
goto deny;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
deny:
|
||||
logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
|
||||
": indirect call not allowed");
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,401 +0,0 @@
|
||||
/* $NetBSD: util.c,v 1.2 2011/06/11 18:03:17 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Frank van der Linden.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/queue.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <poll.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <netconfig.h>
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <rump/rump.h>
|
||||
#include <rump/rump_syscalls.h>
|
||||
|
||||
#include "rpcbind.h"
|
||||
|
||||
static struct sockaddr_in *local_in4;
|
||||
#ifdef INET6
|
||||
static struct sockaddr_in6 *local_in6;
|
||||
#endif
|
||||
|
||||
static int bitmaskcmp(void *, void *, void *, int);
|
||||
#ifdef INET6
|
||||
static void in6_fillscopeid(struct sockaddr_in6 *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For all bits set in "mask", compare the corresponding bits in
|
||||
* "dst" and "src", and see if they match.
|
||||
*/
|
||||
static int
|
||||
bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
|
||||
{
|
||||
int i, j;
|
||||
u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
|
||||
u_int8_t bitmask;
|
||||
|
||||
for (i = 0; i < bytelen; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
bitmask = 1 << j;
|
||||
if (!(netmask[i] & bitmask))
|
||||
continue;
|
||||
if ((p1[i] & bitmask) != (p2[i] & bitmask))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken from ifconfig.c
|
||||
*/
|
||||
#ifdef INET6
|
||||
static void
|
||||
in6_fillscopeid(struct sockaddr_in6 *sin6)
|
||||
{
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
|
||||
sin6->sin6_scope_id =
|
||||
ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
|
||||
sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
char *
|
||||
addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
|
||||
char *netid)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifp, *bestif;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *servsin6, *sin6mask, *clntsin6, *ifsin6, *realsin6;
|
||||
struct sockaddr_in6 *newsin6;
|
||||
#endif
|
||||
struct sockaddr_in *servsin, *sinmask, *clntsin, *newsin, *ifsin;
|
||||
struct netbuf *serv_nbp, *clnt_nbp = NULL, tbuf;
|
||||
struct sockaddr *serv_sa;
|
||||
struct sockaddr *clnt_sa;
|
||||
struct sockaddr_storage ss;
|
||||
struct netconfig *nconf;
|
||||
struct sockaddr *clnt = caller->buf;
|
||||
char *ret = NULL;
|
||||
|
||||
#ifdef INET6
|
||||
servsin6 = ifsin6 = newsin6 = NULL; /* XXXGCC -Wuninitialized */
|
||||
#endif
|
||||
servsin = newsin = NULL; /* XXXGCC -Wuninitialized */
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr,
|
||||
clnt_uaddr, netid);
|
||||
#endif
|
||||
nconf = getnetconfigent(netid);
|
||||
if (nconf == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Local merge, just return a duplicate.
|
||||
*/
|
||||
if (clnt_uaddr != NULL && strncmp(clnt_uaddr, "0.0.0.0.", 8) == 0)
|
||||
return strdup(clnt_uaddr);
|
||||
|
||||
serv_nbp = uaddr2taddr(nconf, serv_uaddr);
|
||||
if (serv_nbp == NULL)
|
||||
return NULL;
|
||||
|
||||
serv_sa = (struct sockaddr *)serv_nbp->buf;
|
||||
if (clnt_uaddr != NULL) {
|
||||
clnt_nbp = uaddr2taddr(nconf, clnt_uaddr);
|
||||
if (clnt_nbp == NULL) {
|
||||
free(serv_nbp);
|
||||
return NULL;
|
||||
}
|
||||
clnt_sa = (struct sockaddr *)clnt_nbp->buf;
|
||||
if (clnt_sa->sa_family == AF_LOCAL) {
|
||||
free(serv_nbp);
|
||||
free(clnt_nbp);
|
||||
free(clnt_sa);
|
||||
return strdup(serv_uaddr);
|
||||
}
|
||||
} else {
|
||||
clnt_sa = (struct sockaddr *)
|
||||
malloc(sizeof (struct sockaddr_storage));
|
||||
memcpy(clnt_sa, clnt, clnt->sa_len);
|
||||
}
|
||||
|
||||
if (getifaddrs(&ifp) < 0) {
|
||||
free(serv_nbp);
|
||||
free(clnt_sa);
|
||||
if (clnt_nbp != NULL)
|
||||
free(clnt_nbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through all interfaces. For each interface, see if the
|
||||
* network portion of its address is equal to that of the client.
|
||||
* If so, we have found the interface that we want to use.
|
||||
*/
|
||||
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family != clnt->sa_family ||
|
||||
!(ifap->ifa_flags & IFF_UP))
|
||||
continue;
|
||||
|
||||
switch (clnt->sa_family) {
|
||||
case AF_INET:
|
||||
/*
|
||||
* realsin: address that recvfrom gave us.
|
||||
* ifsin: address of interface being examined.
|
||||
* clntsin: address that client want us to contact
|
||||
* it on
|
||||
* servsin: local address of RPC service.
|
||||
* sinmask: netmask of this interface
|
||||
* newsin: initially a copy of clntsin, eventually
|
||||
* the merged address
|
||||
*/
|
||||
servsin = (struct sockaddr_in *)serv_sa;
|
||||
clntsin = (struct sockaddr_in *)clnt_sa;
|
||||
sinmask = (struct sockaddr_in *)ifap->ifa_netmask;
|
||||
newsin = (struct sockaddr_in *)&ss;
|
||||
ifsin = (struct sockaddr_in *)ifap->ifa_addr;
|
||||
if (!bitmaskcmp(&ifsin->sin_addr, &clntsin->sin_addr,
|
||||
&sinmask->sin_addr, sizeof (struct in_addr))) {
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
/*
|
||||
* realsin6: address that recvfrom gave us.
|
||||
* ifsin6: address of interface being examined.
|
||||
* clntsin6: address that client want us to contact
|
||||
* it on
|
||||
* servsin6: local address of RPC service.
|
||||
* sin6mask: netmask of this interface
|
||||
* newsin6: initially a copy of clntsin, eventually
|
||||
* the merged address
|
||||
*
|
||||
* For v6 link local addresses, if the client contacted
|
||||
* us via a link-local address, and wants us to reply
|
||||
* to one, use the scope id to see which one.
|
||||
*/
|
||||
realsin6 = (struct sockaddr_in6 *)clnt;
|
||||
ifsin6 = (struct sockaddr_in6 *)ifap->ifa_addr;
|
||||
in6_fillscopeid(ifsin6);
|
||||
clntsin6 = (struct sockaddr_in6 *)clnt_sa;
|
||||
servsin6 = (struct sockaddr_in6 *)serv_sa;
|
||||
sin6mask = (struct sockaddr_in6 *)ifap->ifa_netmask;
|
||||
newsin6 = (struct sockaddr_in6 *)&ss;
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&ifsin6->sin6_addr) &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&realsin6->sin6_addr) &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&clntsin6->sin6_addr)) {
|
||||
if (ifsin6->sin6_scope_id !=
|
||||
realsin6->sin6_scope_id)
|
||||
continue;
|
||||
goto found;
|
||||
}
|
||||
if (!bitmaskcmp(&ifsin6->sin6_addr,
|
||||
&clntsin6->sin6_addr, &sin6mask->sin6_addr,
|
||||
sizeof (struct in6_addr)))
|
||||
goto found;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto freeit;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Didn't find anything. Get the first possibly useful interface,
|
||||
* preferring "normal" interfaces to point-to-point and loopback
|
||||
* ones.
|
||||
*/
|
||||
bestif = NULL;
|
||||
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family != clnt->sa_family ||
|
||||
!(ifap->ifa_flags & IFF_UP))
|
||||
continue;
|
||||
if (!(ifap->ifa_flags & IFF_LOOPBACK) &&
|
||||
!(ifap->ifa_flags & IFF_POINTOPOINT)) {
|
||||
bestif = ifap;
|
||||
break;
|
||||
}
|
||||
if (bestif == NULL)
|
||||
bestif = ifap;
|
||||
else if ((bestif->ifa_flags & IFF_LOOPBACK) &&
|
||||
!(ifap->ifa_flags & IFF_LOOPBACK))
|
||||
bestif = ifap;
|
||||
}
|
||||
ifap = bestif;
|
||||
found:
|
||||
switch (clnt->sa_family) {
|
||||
case AF_INET:
|
||||
memcpy(newsin, ifap->ifa_addr, clnt_sa->sa_len);
|
||||
newsin->sin_port = servsin->sin_port;
|
||||
tbuf.len = clnt_sa->sa_len;
|
||||
tbuf.maxlen = sizeof (struct sockaddr_storage);
|
||||
tbuf.buf = newsin;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
assert(newsin6);
|
||||
memcpy(newsin6, ifsin6, clnt_sa->sa_len);
|
||||
newsin6->sin6_port = servsin6->sin6_port;
|
||||
tbuf.maxlen = sizeof (struct sockaddr_storage);
|
||||
tbuf.len = clnt_sa->sa_len;
|
||||
tbuf.buf = newsin6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
goto freeit;
|
||||
}
|
||||
if (ifap != NULL)
|
||||
ret = taddr2uaddr(nconf, &tbuf);
|
||||
freeit:
|
||||
freenetconfigent(nconf);
|
||||
free(serv_sa);
|
||||
free(serv_nbp);
|
||||
if (clnt_sa != NULL)
|
||||
free(clnt_sa);
|
||||
if (clnt_nbp != NULL)
|
||||
free(clnt_nbp);
|
||||
freeifaddrs(ifp);
|
||||
|
||||
#ifdef RPCBIND_DEBUG
|
||||
if (debugging)
|
||||
fprintf(stderr, "addrmerge: returning %s\n", ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
network_init()
|
||||
{
|
||||
#ifdef INET6
|
||||
struct ifaddrs *ifap, *ifp;
|
||||
struct ipv6_mreq mreq6;
|
||||
int ifindex, s;
|
||||
#endif
|
||||
int ecode;
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
hints.ai_family = AF_INET;
|
||||
if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "can't get local ip4 address: %s\n",
|
||||
gai_strerror(ecode));
|
||||
} else {
|
||||
local_in4 = (struct sockaddr_in *)malloc(sizeof *local_in4);
|
||||
if (local_in4 == NULL) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "can't alloc local ip4 addr\n");
|
||||
}
|
||||
memcpy(local_in4, res->ai_addr, sizeof *local_in4);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
hints.ai_family = AF_INET6;
|
||||
if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "can't get local ip6 address: %s\n",
|
||||
gai_strerror(ecode));
|
||||
} else {
|
||||
local_in6 = (struct sockaddr_in6 *)malloc(sizeof *local_in6);
|
||||
if (local_in6 == NULL) {
|
||||
if (debugging)
|
||||
fprintf(stderr, "can't alloc local ip6 addr\n");
|
||||
}
|
||||
memcpy(local_in6, res->ai_addr, sizeof *local_in6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now join the RPC ipv6 multicast group on all interfaces.
|
||||
*/
|
||||
if (getifaddrs(&ifp) < 0)
|
||||
return;
|
||||
|
||||
mreq6.ipv6mr_interface = 0;
|
||||
inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, &mreq6.ipv6mr_multiaddr);
|
||||
|
||||
s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
/*
|
||||
* Loop through all interfaces. For each interface, see if the
|
||||
* network portion of its address is equal to that of the client.
|
||||
* If so, we have found the interface that we want to use.
|
||||
*/
|
||||
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family != AF_INET6 ||
|
||||
!(ifap->ifa_flags & IFF_MULTICAST))
|
||||
continue;
|
||||
ifindex = if_nametoindex(ifap->ifa_name);
|
||||
if (ifindex == mreq6.ipv6mr_interface)
|
||||
/*
|
||||
* Already did this one.
|
||||
*/
|
||||
continue;
|
||||
mreq6.ipv6mr_interface = ifindex;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
|
||||
sizeof mreq6) < 0)
|
||||
if (debugging)
|
||||
warn("setsockopt v6 multicast");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* close(s); */
|
||||
}
|
||||
|
||||
struct sockaddr *
|
||||
local_sa(int af)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return (struct sockaddr *)local_in4;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
return (struct sockaddr *)local_in6;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user