示例#1
0
bool_t
rpcbproc_getaddr_com(rpcb *regp, char **result, ar_svc_req_t *rqstp, 
		     arpcvers_t rpcbversnum, arpcvers_t verstype)
{
	char *uaddr;
	char *saddr;
	const char *netidstr;
	rpcblist_ptr fnd;

	uaddr = NULL;
	saddr = NULL;

	if (!ar_svc_control(rqstp->rq_xprt,  AR_SVCGET_NETID, &netidstr)) {
		ar_svcflgerr_systemerr(rqstp);
		return FALSE;
	}

	fnd = find_service(regp->r_prog, regp->r_vers, netidstr);
	if (fnd && ((verstype == RPCB_ALLVERS) ||
		    (regp->r_vers == fnd->rpcb_map.r_vers))) {
		if (*(regp->r_addr) != '\0') {  /* may contain a hint about */
			saddr = regp->r_addr;   /* the interface that we    */
		}				/* should use */
		if (!(uaddr = mergeaddr(rqstp->rq_xprt, netidstr,
					fnd->rpcb_map.r_addr, saddr))) {
			/* Try whatever we have */
			uaddr = strdup(fnd->rpcb_map.r_addr);
		} else if (!uaddr[0]) {
			/*
			 * The server died.  Unset all versions of this prog.
			 */
			delete_prog(regp->r_prog);
			uaddr = strdup("");
		}
	} else {
		uaddr = strdup("");
	}

	if (!uaddr) {
		ar_svcflgerr_systemerr(rqstp);
		return FALSE;
	}

#ifdef RPCBIND_DEBUG
	if (debugging) {
		fprintf(stderr, "getaddr: %s\n", uaddr);
	}
#endif

	/* XXX: should have used some defined constant here */
	rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers,
		      netidstr, uaddr);

	*result = uaddr;
	return TRUE;
}
示例#2
0
/* ARGSUSED */
static void *
rpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp /*__unused*/,
			     SVCXPRT *transp, rpcvers_t versnum /*__unused*/)
{
	RPCB *regp = (RPCB *)arg;
	static rpcb_entry_list_ptr rlist;
	register rpcblist_ptr rbl;
	rpcb_entry_list_ptr rp, tail;
	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);
	tail = NULL;
	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);
			continue;
		}
#ifdef RPCBIND_DEBUG
		if (debugging)
			fprintf(stderr, " SUCCEEDED maddr: %s\n", maddr);
#endif
		/*
		 * Add it to rlist.
		 */
		rp = malloc(sizeof (rpcb_entry_list));
		if (rp == NULL)
			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 {
			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);
}
示例#3
0
bool_t
rpcbproc_callit_com(rpcb_rmtcallargs *a, void *result, 
		    ar_svc_req_t *rqstp, arpcvers_t versnum)
{
	rpcblist_ptr rbl;
	ar_netid_t *nconf;
	ar_svc_xprt_t *transp;
	char *uaddr, *m_uaddr = NULL, *local_uaddr = NULL;
	arpcproc_t reply_type;
	arpc_createerr_t cerr;
	struct sockaddr_storage ss;
	struct sockaddr *localsa;
	const char *netidstr;
	struct timespec tlimit;
	arpc_addr_t caller;
	arpc_addr_t tbuf;
	arpc_addr_t *na;
	char *errstr;
	struct finfo *info;
	int err;

	caller.maxlen = sizeof(ss);
	caller.len = sizeof(ss);
	caller.buf = (char *)&ss;

	reply_type = rqstp->rq_proc;
	transp = rqstp->rq_xprt;

	if (!ar_svc_control(rqstp->rq_xprt,  AR_SVCGET_NETID, &netidstr)) {
		ar_svcflgerr_systemerr(rqstp);
		return FALSE;
	}

	if (!check_callit(rqstp, a, versnum)) {
		ar_svcflgerr_weakauth(rqstp);
		return FALSE;
	}

	if (!ar_svc_control(rqstp->rq_xprt, AR_SVCGET_REMOTE_ADDR, &caller)) {
		ar_svcflgerr_systemerr(rqstp);
		return FALSE;
	}
		
#ifdef RPCBIND_DEBUG
	if (debugging) {
		uaddr = rqst2uaddr(rqstp);
		fprintf(stderr, "%s %s req for (%lu, %lu, %lu, %s) from %s : ",
			versnum == PMAPVERS ? "pmap_rmtcall" :
			versnum == RPCBVERS ? "rpcb_rmtcall" :
			versnum == RPCBVERS4 ? "rpcb_indirect" : "unknown",
			reply_type == RPCBPROC_INDIRECT ? "indirect" : 
			"callit",
			(unsigned long)a->rmt_prog, (unsigned long)a->rmt_vers,
			(unsigned long)a->rmt_proc, netidstr,
			uaddr ? uaddr : "unknown");
		if (uaddr) {
			free(uaddr);
		}
		uaddr = NULL;
	}
#endif
	rbl = find_service(a->prog, a->vers, netidstr);

	rpcbs_rmtcall(versnum - 2, reply_type, a->prog, a->vers,
		      a->proc, netidstr, rbl);

	if (rbl == (rpcblist_ptr)NULL) {
#ifdef RPCBIND_DEBUG
		if (debugging) {
			fprintf(stderr, "not found\n");
		}
#endif
		if (reply_type == RPCBPROC_INDIRECT) {
			ar_svcflgerr_noprog(rqstp);
		}
		return FALSE;
	}
	if (rbl->rpcb_map.r_vers != a->vers) {
		if (reply_type == RPCBPROC_INDIRECT) {
			arpcvers_t vers_low, vers_high;

			find_versions(a->prog, netidstr,
				      &vers_low, &vers_high);
			ar_svcflgerr_progvers(rqstp, vers_low, vers_high);
		}
		return FALSE;
	}

#ifdef RPCBIND_DEBUG
	if (debugging) {
		fprintf(stderr, "found at uaddr %s\n", rbl->rpcb_map.r_addr);
	}
#endif
	/*
	 *	Check whether this entry is valid and a server is present
	 *	Mergeaddr() returns NULL if no such entry is present, and
	 *	returns "" if the entry was present but the server is not
	 *	present (i.e., it crashed).
	 */
	if (reply_type == RPCBPROC_INDIRECT) {
		uaddr = mergeaddr(transp, netidstr, 
				  rbl->rpcb_map.r_addr, NULL);
		if (uaddr == NULL || uaddr[0] == '\0') {
			ar_svcflgerr_noprog(rqstp);
			if (uaddr != NULL) {
				free(uaddr);
			}
			uaddr = NULL;
			return FALSE;
		}
		free(uaddr);
		uaddr = NULL;
	}
	nconf = rpcbind_get_conf(netidstr);
	if (nconf == (ar_netid_t *)NULL) {
		if (reply_type == RPCBPROC_INDIRECT) {
			ar_svcflgerr_systemerr(rqstp);
			return FALSE;
		}
		if (debugging) {
			fprintf(stderr, "rpcbproc_callit_com:  "
				"rpcbind_get_conf failed\n");
		}
		return FALSE;
	}

	/* compute local_uaddr with merge (picks port from rbl, local address
	 * that most matches the request's src addr.
	 * 
	 * convert that back to uaddr
	 */

	localsa = local_sa(nconf->an_family, &tbuf.len);
	if (localsa == NULL) {
		if (debugging) {
			fprintf(stderr,
			"rpcbproc_callit_com: no local address\n");
		}
		goto error;
	}
	tbuf.maxlen = tbuf.len;
	tbuf.buf = (char *)localsa;
	local_uaddr = addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, netidstr);
	if (!local_uaddr) {
		err = ENOMEM;
		goto error;
	}

	m_uaddr = addrmerge(&caller, rbl->rpcb_map.r_addr, NULL, netidstr);
	if (!m_uaddr) {
		err = ENOMEM;
		goto error;
	}

	err = ar_uaddr2taddr(rpcbind_ioctx, netidstr, local_uaddr, &na);
	if (err != 0) {
		if (reply_type == RPCBPROC_INDIRECT) {
			ar_svcflgerr_systemerr(rqstp);
		}
		goto error;
	}

	/* allocate forward table entry */
	err = forward_register(&info);
	if (err != 0) {
		goto error;
	}

	info->clnt = NULL;
	info->cco = NULL;
	info->sco = NULL;
	info->uaddr = m_uaddr;
	m_uaddr = NULL;

	/* setup/connect clnt. ar_clnt_tli_create() */
	err = ar_clnt_tli_create(rpcbind_ioctx, netidstr, na, 
				 a->prog, a->vers, NULL, &cerr,
				 &info->clnt);
	if (err != 0) {
		if (debugging) {
			errstr = ar_astrcreateerror(&cerr);
			if (errstr) {
				fprintf(stderr, "create clnt failed: %s\n",
					errstr);
				free(errstr);
			}
		}
		goto error;
	}

	tlimit.tv_sec = MAXTIME_OFF;
	tlimit.tv_nsec = 0;
	
	/* issue async rpc through clnt ar_clnt_call_async_copy */
	err = ar_clnt_call_async_copy(info->clnt, a->proc, 
				      (axdrproc_t)&axdr_callit_rmtcallargs,
				      a, (axdrproc_t)&axdr_callit_rmtresult, 
				      sizeof(rpcb_remote_result_t),
				      &rpcb_callit_done, info,
				      &tlimit, &info->cco);
	if (err != 0) {
		goto error;
	}

	/* call is running. Mark original server call as async so we
	 * can finish it when we get the result.
	 */
	err = ar_svc_async(rqstp, &info->sco);
	if (err != 0) {
		goto error;
	}

	/* done */
	info = NULL;
	err = 0;

error:
	if (err != 0 && reply_type == RPCBPROC_INDIRECT) {
		ar_svcflgerr_systemerr(rqstp);
	}

	if (local_uaddr) {
		free(local_uaddr);
		local_uaddr = NULL;
	}
	if (m_uaddr) {
		free(m_uaddr);
		m_uaddr = NULL;
	}

	if (na) {
		if (na->buf) {
			free(na->buf);
		}
		na->buf = NULL;
		free(na);
		na = NULL;
	}
	if (info) {
		if (info->cco) {
			ar_clnt_call_cancel(info->cco);
		}
		info->cco = NULL;
		if (info->sco) {
			ar_svc_async_done(info->sco, err);
		}
		info->sco = NULL;
		if (info->clnt) {
			ar_clnt_destroy(info->clnt);
		}
		info->clnt = NULL;
		if (info->uaddr) {
			free(info->uaddr);
		}
		info->uaddr = NULL;
		info->flag &= ~FINFO_ACTIVE;
		info = NULL;
	}
		
	return FALSE;
}