Exemple #1
0
/*
 * This implements the yp "match" function.
 */
void
ypmatch(SVCXPRT *transp, struct svc_req *rqstp)
{
	struct ypreq_key req;
	struct ypresp_val resp;
	char *fun = "ypmatch";
	DBM *fdb;

	memset(&req, 0, sizeof (req));
	memset(&resp, 0, sizeof (resp));
	resp.status = (unsigned)YP_NOKEY;

	if (!svc_getargs(transp, (xdrproc_t)xdr_ypreq_key, (char *)&req)) {
		svcerr_decode(transp);
		return;
	}

	/*
	 * sanity check the map name and to a DBM lookup
	 * also perform an access check...
	 */
	if ((fdb = ypset_current_map(req.map, req.domain,
					&resp.status)) != NULL &&
		yp_map_access(transp, &resp.status, fdb)) {

		/* Check with the DBM database */
		resp.valdat = dbm_fetch(fdb, req.keydat);
		if (resp.valdat.dptr != NULL) {
			resp.status = YP_TRUE;
			if (!silent)
				printf("%s: dbm: %40.40s\n",
					fun, resp.valdat.dptr);
			goto send_reply;
		}

		/*
		 * If we're being asked to match YP_SECURE or YP_INTERDOMAIN
		 * and we haven't found it in the dbm file, then we don't
		 * really want to waste any more time.  Specifically, we don't
		 * want to ask DNS
		 */
		if (req.keydat.dsize == 0 ||
		    req.keydat.dptr == NULL ||
		    req.keydat.dptr[0] == '\0' ||
	strncmp(req.keydat.dptr, yp_secure, req.keydat.dsize) == 0 ||
	strncmp(req.keydat.dptr, yp_interdomain, req.keydat.dsize) == 0) {
			goto send_reply;
		}

		/* Let's try the YP_MULTI_ hack... */
#ifdef MINUS_C_OPTION
		if (multiflag == TRUE && multihomed(req, &resp, transp, fdb))
			goto send_reply;
#else
		if (multihomed(req, &resp, transp, fdb))
			goto send_reply;
#endif

		/*
		 * Let's try DNS, but if client_setup_failure is set,
		 * we have tried DNS in the past and failed, there is
		 * no reason in forcing an infinite loop by turning
		 * off DNS in setup_resolv() only to turn it back on
		 * again here.
		 */
		if (!dnsforward && !client_setup_failure) {
			datum idkey, idval;
			idkey.dptr = yp_interdomain;
			idkey.dsize = yp_interdomain_sz;
			idval = dbm_fetch(fdb, idkey);
			if (idval.dptr)
				dnsforward = TRUE;
		}

		if (dnsforward) {
			if (!resolv_pid || !resolv_client) {
				setup_resolv(&dnsforward, &resolv_pid,
						&resolv_client, resolv_tp, 0);
				if (resolv_client == NULL)
					client_setup_failure = TRUE;
			}

			if (resolv_req(&dnsforward, &resolv_client,
						&resolv_pid, resolv_tp,
						rqstp->rq_xprt, &req,
						req.map) == TRUE)
				goto free_args;
		}
	}
	send_reply:

	if (!svc_sendreply(transp, (xdrproc_t)xdr_ypresp_val,
				(caddr_t)&resp)) {
		RESPOND_ERR;
	}

	free_args:

	if (!svc_freeargs(transp, (xdrproc_t)xdr_ypreq_key,
				(char *)&req)) {
		FREE_ERR;
	}
}
Exemple #2
0
/* V1 dispatch routines */
void
ypoldmatch(SVCXPRT *transp, struct svc_req *rqstp)
{
	bool dbmop_ok = TRUE;
	struct yprequest req;
	struct ypreq_key nrq;
	struct ypresponse resp;
	char *fun = "ypoldmatch";
	DBM *fdb;

	memset((void *) &req, 0, sizeof (req));
	memset((void *) &resp, 0, sizeof (resp));

	if (!svc_getargs(transp,
				(xdrproc_t)_xdr_yprequest,
				(caddr_t)&req)) {
		svcerr_decode(transp);
		return;
	}

	if (req.yp_reqtype != YPMATCH_REQTYPE) {
		resp.ypmatch_resp_status = (unsigned)YP_BADARGS;
		dbmop_ok = FALSE;
	}

	if (dbmop_ok &&
		(((fdb = ypset_current_map(req.ypmatch_req_map,
						req.ypmatch_req_domain,
						&resp.ypmatch_resp_status))
						!= NULL) &&
						yp_map_access(transp,
						&resp.ypmatch_resp_status,
						fdb))) {

		/* Check with the DBM database */
		resp.ypmatch_resp_valdat = dbm_fetch(fdb,
						req.ypmatch_req_keydat);

		if (resp.ypmatch_resp_valptr != NULL) {
			resp.ypmatch_resp_status = YP_TRUE;
			if (!silent)
				printf("%s: dbm: %s\n",
					fun, resp.ypmatch_resp_valptr);
			goto send_oldreply;
		}

		/*
		 * If we're being asked to match YP_SECURE or YP_INTERDOMAIN
		 * and we haven't found it in the dbm file, then we don't
		 * really want to waste any more time.  Specifically, we don't
		 * want to ask DNS
		 */
		if (req.ypmatch_req_keysize == 0 ||
		    req.ypmatch_req_keyptr == NULL ||
		    req.ypmatch_req_keyptr[0] == '\0' ||
		    strncmp(req.ypmatch_req_keyptr, "YP_SECURE", 9) == 0 ||
		    strncmp(req.ypmatch_req_keyptr, "YP_INTERDOMAIN", 14) == 0)

		    goto send_oldreply;

		/* Let's try the YP_MULTI_ hack... */
#ifdef MINUS_C_OPTION
		if (multiflag == TRUE && omultihomed(req, &resp, transp, fdb))
			goto send_oldreply;
#else
		if (omultihomed(req, &resp, transp, fdb))
			goto send_oldreply;
#endif

		/* Let's try DNS */
		if (!dnsforward) {
			USE_YP_INTERDOMAIN
			datum idkey, idval;
			idkey.dptr = yp_interdomain;
			idkey.dsize = yp_interdomain_sz;
			idval = dbm_fetch(fdb, idkey);
			if (idval.dptr)
				dnsforward = TRUE;
		}

		if (dnsforward) {
		    if (!resolv_pid)
			setup_resolv(&dnsforward, &resolv_pid, &resolv_client,
					resolv_tp, 0);

		    if (req.yp_reqtype == YPREQ_KEY) {
			nrq = req.yp_reqbody.yp_req_keytype;

			resolv_req(&dnsforward, &resolv_client, &resolv_pid,
					resolv_tp, rqstp->rq_xprt,
					&nrq, nrq.map);
		    }
		    return;
		}
	}

	send_oldreply:

	if (!svc_sendreply(transp,
				(xdrproc_t)_xdr_ypresponse,
				(caddr_t)&resp)) {
		RESPOND_ERR;
	}

	if (!svc_freeargs(transp,
				(xdrproc_t)_xdr_yprequest,
				(char *)&req)) {
		FREE_ERR;
	}
}
int resolv_req(bool *fwding, CLIENT **client, int *pid, char *tp,
		SVCXPRT *xprt, struct ypreq_key *req, char *map)
{
	enum clnt_stat stat;
	struct timeval tv;
	struct ypfwdreq_key4 fwd_req4;
	struct ypfwdreq_key6 fwd_req6;
	struct in6_addr in6;
	int byname, byaddr;
	int byname_v6, byaddr_v6;
#ifdef TDRPC
	struct sockaddr_in *addrp;
#else
	struct netbuf *nb;
	char *uaddr;
	char *cp;
	int i;
	sa_family_t caller_af = AF_UNSPEC;
	struct sockaddr_in *sin4;
	struct sockaddr_in6 *sin6;
#endif


	if (! *fwding)
		return (FALSE);

	byname = strcmp(map, "hosts.byname") == 0;
	byaddr = strcmp(map, "hosts.byaddr") == 0;
	byname_v6 = strcmp(map, "ipnodes.byname") == 0;
	byaddr_v6 = strcmp(map, "ipnodes.byaddr") == 0;
	if ((!byname && !byaddr && !byname_v6 && !byaddr_v6) ||
				req->keydat.dsize == 0 ||
				req->keydat.dptr[0] == '\0' ||
				!isascii(req->keydat.dptr[0]) ||
				!isgraph(req->keydat.dptr[0])) {
		/* default status is YP_NOKEY */
		return (FALSE);
	}

#ifdef TDRPC
	fwd_req4.map = map;
	fwd_req4.keydat = req->keydat;
	fwd_req4.xid = svc_getxid(xprt);
	addrp = svc_getcaller(xprt);
	fwd_req4.ip = addrp->sin_addr.s_addr;
	fwd_req4.port = addrp->sin_port;
#else
	/*
	 * In order to tell if we have an IPv4 or IPv6 caller address,
	 * we must know that nb->buf is a (sockaddr_in *) or a
	 * (sockaddr_in6 *). Hence, we might as well dispense with the
	 * conversion to uaddr and parsing of same that this section
	 * of the code previously involved itself in.
	 */
	nb = svc_getrpccaller(xprt);
	if (nb != 0)
		caller_af = ((struct sockaddr_storage *)nb->buf)->ss_family;

	if (caller_af == AF_INET6) {
		fwd_req6.map = map;
		fwd_req6.keydat = req->keydat;
		fwd_req6.xid = svc_getxid(xprt);
		sin6 = (struct sockaddr_in6 *)nb->buf;
		fwd_req6.addr = (uint32_t *)&in6;
		memcpy(fwd_req6.addr, sin6->sin6_addr.s6_addr, sizeof (in6));
		fwd_req6.port = ntohs(sin6->sin6_port);
	} else if (caller_af == AF_INET) {
		fwd_req4.map = map;
		fwd_req4.keydat = req->keydat;
		fwd_req4.xid = svc_getxid(xprt);
		sin4 = (struct sockaddr_in *)nb->buf;
		fwd_req4.ip = ntohl(sin4->sin_addr.s_addr);
		fwd_req4.port = ntohs(sin4->sin_port);
	} else {
		syslog(LOG_ERR, "unknown caller IP address family %d",
			caller_af);
		return (FALSE);
	}
#endif

	/* Restart resolver if it died. (possible overkill) */
	if (kill(*pid, 0)) {
		syslog(LOG_INFO,
		"Restarting resolv server: old one (pid %d) died.\n", *pid);
		if (*client != NULL)
			clnt_destroy (*client);
		setup_resolv(fwding, pid, client, tp, 0 /* transient p# */);
		if (!*fwding) {
			syslog(LOG_ERR,
			"can't restart resolver: ending resolv service.\n");
			return (FALSE);
		}
	}

	/* may need to up timeout */
	tv.tv_sec = 10; tv.tv_usec = 0;
	if (caller_af == AF_INET6) {
		stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6,
					(char *)&fwd_req6, xdr_void, 0, tv);
	} else {
		stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4,
					(char *)&fwd_req4, xdr_void, 0, tv);
	}
	if (stat == RPC_SUCCESS) /* expected */
		return (TRUE);

	else { /* Over kill error recovery */
		/* make one attempt to restart service before turning off */
		syslog(LOG_INFO,
			"Restarting resolv server: old one not responding.\n");

		if (!kill(*pid, 0))
			kill (*pid, SIGINT); /* cleanup old one */

		if (*client != NULL)
			clnt_destroy (*client);
		setup_resolv(fwding, pid, client, tp, 0 /* transient p# */);
		if (!*fwding) {
			syslog(LOG_ERR,
			"can't restart resolver: ending resolv service.\n");
			return (FALSE);
		}

		if (caller_af == AF_INET6) {
			stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6,
					(char *)&fwd_req6, xdr_void, 0, tv);
		} else {
			stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4,
					(char *)&fwd_req4, xdr_void, 0, tv);
		}
		if (stat == RPC_SUCCESS) /* expected */
			return (TRUE);
		else {
			/* no more restarts */
			clnt_destroy (*client);
			*fwding = FALSE; /* turn off fwd'ing */
			syslog(LOG_ERR,
		"restarted resolver not responding: ending resolv service.\n");
			return (FALSE);
		}
	}
}