xref: /titanic_41/usr/src/cmd/ypcmd/ypserv_resolv.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
31*7c478bd9Sstevel@tonic-gate #include <unistd.h>
32*7c478bd9Sstevel@tonic-gate #include <ctype.h>
33*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
34*7c478bd9Sstevel@tonic-gate #include <syslog.h>
35*7c478bd9Sstevel@tonic-gate #include <signal.h>
36*7c478bd9Sstevel@tonic-gate #include <string.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/resource.h>
39*7c478bd9Sstevel@tonic-gate #include <errno.h>
40*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
41*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
42*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
43*7c478bd9Sstevel@tonic-gate #else
44*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h>
46*7c478bd9Sstevel@tonic-gate #include <netconfig.h>
47*7c478bd9Sstevel@tonic-gate #include <netdir.h>
48*7c478bd9Sstevel@tonic-gate #endif
49*7c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
50*7c478bd9Sstevel@tonic-gate #include "ypserv_resolv_common.h"
51*7c478bd9Sstevel@tonic-gate 
52*7c478bd9Sstevel@tonic-gate #define	YPDNSVERS	2L
53*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
54*7c478bd9Sstevel@tonic-gate #define	RESOLV_EXEC_PATH	"/usr/etc/rpc.nisd_resolv"
55*7c478bd9Sstevel@tonic-gate #define	RESOLV_EXEC_ERR		"can't exec /usr/etc/rpc.nisd_resolv: %s\n"
56*7c478bd9Sstevel@tonic-gate #else
57*7c478bd9Sstevel@tonic-gate #define	RESOLV_EXEC_PATH	"/usr/sbin/rpc.nisd_resolv"
58*7c478bd9Sstevel@tonic-gate #define	RESOLV_EXEC_ERR		"can't exec /usr/sbin/rpc.nisd_resolv: %s\n"
59*7c478bd9Sstevel@tonic-gate #endif
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate extern bool silent;
62*7c478bd9Sstevel@tonic-gate int verbose;
63*7c478bd9Sstevel@tonic-gate extern int resolv_pid;
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static int getconf(char *netid, void **handle, struct netconfig **nconf);
66*7c478bd9Sstevel@tonic-gate static int getprognum(long *prognum, SVCXPRT **xprt, char *fd_str,
67*7c478bd9Sstevel@tonic-gate 			char *prog_str, long vers, char *tp_type);
68*7c478bd9Sstevel@tonic-gate 
setup_resolv(bool * fwding,int * child,CLIENT ** client,char * tp_type,long prognum)69*7c478bd9Sstevel@tonic-gate void setup_resolv(bool *fwding, int *child,
70*7c478bd9Sstevel@tonic-gate 			CLIENT **client, char *tp_type, long prognum)
71*7c478bd9Sstevel@tonic-gate {
72*7c478bd9Sstevel@tonic-gate 	enum clnt_stat stat;
73*7c478bd9Sstevel@tonic-gate 	struct timeval tv;
74*7c478bd9Sstevel@tonic-gate 	char prog_str[15], fd_str[5];
75*7c478bd9Sstevel@tonic-gate 	SVCXPRT *xprt = NULL;
76*7c478bd9Sstevel@tonic-gate 	char *tp;
77*7c478bd9Sstevel@tonic-gate #ifdef	TDRPC
78*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in addr;
79*7c478bd9Sstevel@tonic-gate 	int sock;
80*7c478bd9Sstevel@tonic-gate #else
81*7c478bd9Sstevel@tonic-gate 	char name[257];
82*7c478bd9Sstevel@tonic-gate 	struct netconfig *nc;
83*7c478bd9Sstevel@tonic-gate 	void *h;
84*7c478bd9Sstevel@tonic-gate #endif
85*7c478bd9Sstevel@tonic-gate 	verbose = silent == FALSE ? 1 : 0;
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	if (! *fwding)
88*7c478bd9Sstevel@tonic-gate 		return;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate #ifdef	TDRPC
91*7c478bd9Sstevel@tonic-gate 	tp = (tp_type && strcmp(tp_type, "udp") != 0) ? "udp" : "tcp";
92*7c478bd9Sstevel@tonic-gate #else
93*7c478bd9Sstevel@tonic-gate 	/* try the specified netid (default ticots), then any loopback */
94*7c478bd9Sstevel@tonic-gate 	tp = (tp_type && *tp_type) ? tp_type : "ticots";
95*7c478bd9Sstevel@tonic-gate 	if (!getconf(tp, &h, &nc)) { /* dont forget endnetconfig() */
96*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't get resolv_clnt netconf %s.\n", tp);
97*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
98*7c478bd9Sstevel@tonic-gate 		return;
99*7c478bd9Sstevel@tonic-gate 	}
100*7c478bd9Sstevel@tonic-gate 	tp = nc->nc_netid;
101*7c478bd9Sstevel@tonic-gate #endif
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	/*
104*7c478bd9Sstevel@tonic-gate 	 * Startup the resolv server: use transient prognum if prognum
105*7c478bd9Sstevel@tonic-gate 	 * isn't set. Using transient means we create mapping then
106*7c478bd9Sstevel@tonic-gate 	 * pass child the fd to use for service.
107*7c478bd9Sstevel@tonic-gate 	 */
108*7c478bd9Sstevel@tonic-gate 	if (!getprognum(&prognum, &xprt, fd_str, prog_str, YPDNSVERS, tp)) {
109*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't create resolv xprt for transient.\n");
110*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
111*7c478bd9Sstevel@tonic-gate #ifndef TDRPC
112*7c478bd9Sstevel@tonic-gate 		endnetconfig(h);
113*7c478bd9Sstevel@tonic-gate #endif
114*7c478bd9Sstevel@tonic-gate 		return;
115*7c478bd9Sstevel@tonic-gate 	}
116*7c478bd9Sstevel@tonic-gate 	switch (*child = vfork()) {
117*7c478bd9Sstevel@tonic-gate 	case -1: /* error  */
118*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't startup resolv daemon\n");
119*7c478bd9Sstevel@tonic-gate #ifndef TDRPC
120*7c478bd9Sstevel@tonic-gate 		endnetconfig(h);
121*7c478bd9Sstevel@tonic-gate #endif
122*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
123*7c478bd9Sstevel@tonic-gate 		return;
124*7c478bd9Sstevel@tonic-gate 	case 0:  /* child  */
125*7c478bd9Sstevel@tonic-gate 		/*
126*7c478bd9Sstevel@tonic-gate 		 * if using transient we must maintain fd across
127*7c478bd9Sstevel@tonic-gate 		 * exec cause unset/set on prognum isn't automic.
128*7c478bd9Sstevel@tonic-gate 		 *
129*7c478bd9Sstevel@tonic-gate 		 * if using transient we'll just do svc_tli_create
130*7c478bd9Sstevel@tonic-gate 		 * in child on our bound fd.
131*7c478bd9Sstevel@tonic-gate 		 */
132*7c478bd9Sstevel@tonic-gate 		execlp(RESOLV_EXEC_PATH, "rpc.nisd_resolv",
133*7c478bd9Sstevel@tonic-gate 				"-F",		/* forground  */
134*7c478bd9Sstevel@tonic-gate 				"-C", fd_str,	/* dont close */
135*7c478bd9Sstevel@tonic-gate 				"-p", prog_str,	/* prognum    */
136*7c478bd9Sstevel@tonic-gate 				"-t", tp,	/* tp type    */
137*7c478bd9Sstevel@tonic-gate 				NULL);
138*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, RESOLV_EXEC_ERR, strerror(errno));
139*7c478bd9Sstevel@tonic-gate 		exit(1);
140*7c478bd9Sstevel@tonic-gate 	default: /* parent */
141*7c478bd9Sstevel@tonic-gate 		/* close fd, free xprt, but leave mapping */
142*7c478bd9Sstevel@tonic-gate 		if (xprt)
143*7c478bd9Sstevel@tonic-gate 			svc_destroy(xprt);
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 		/* let it crank up before we create client */
146*7c478bd9Sstevel@tonic-gate 		sleep(4);
147*7c478bd9Sstevel@tonic-gate 	}
148*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
149*7c478bd9Sstevel@tonic-gate 	get_myaddress(&addr);
150*7c478bd9Sstevel@tonic-gate 	addr.sin_port = 0;
151*7c478bd9Sstevel@tonic-gate 	sock = RPC_ANYSOCK;
152*7c478bd9Sstevel@tonic-gate 	tv.tv_sec = 3; tv.tv_usec = 0;
153*7c478bd9Sstevel@tonic-gate 	if (strcmp(tp, "udp") != 0) {
154*7c478bd9Sstevel@tonic-gate 		*client = clntudp_bufcreate(&addr, prognum, YPDNSVERS,
155*7c478bd9Sstevel@tonic-gate 					tv, &sock, YPMSGSZ, YPMSGSZ);
156*7c478bd9Sstevel@tonic-gate 	} else {
157*7c478bd9Sstevel@tonic-gate 		*client = clnttcp_create(&addr, prognum, YPDNSVERS,
158*7c478bd9Sstevel@tonic-gate 					&sock, YPMSGSZ, YPMSGSZ);
159*7c478bd9Sstevel@tonic-gate 	}
160*7c478bd9Sstevel@tonic-gate 	if (*client == NULL) {
161*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't create resolv client handle.\n");
162*7c478bd9Sstevel@tonic-gate 		(void) kill (*child, SIGINT);
163*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
164*7c478bd9Sstevel@tonic-gate 		return;
165*7c478bd9Sstevel@tonic-gate 	}
166*7c478bd9Sstevel@tonic-gate #else
167*7c478bd9Sstevel@tonic-gate 	if (sysinfo(SI_HOSTNAME, name, sizeof (name)-1) == -1) {
168*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't get local hostname.\n");
169*7c478bd9Sstevel@tonic-gate 		(void) kill (*child, SIGINT);
170*7c478bd9Sstevel@tonic-gate 		endnetconfig(h);
171*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
172*7c478bd9Sstevel@tonic-gate 		return;
173*7c478bd9Sstevel@tonic-gate 	}
174*7c478bd9Sstevel@tonic-gate 	if ((*client = clnt_tp_create(HOST_SELF_CONNECT, prognum,
175*7c478bd9Sstevel@tonic-gate 			YPDNSVERS, nc)) == NULL) {
176*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't create resolv_clnt\n");
177*7c478bd9Sstevel@tonic-gate 		(void) kill (*child, SIGINT);
178*7c478bd9Sstevel@tonic-gate 		endnetconfig(h);
179*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
180*7c478bd9Sstevel@tonic-gate 		return;
181*7c478bd9Sstevel@tonic-gate 	}
182*7c478bd9Sstevel@tonic-gate 	endnetconfig(h);
183*7c478bd9Sstevel@tonic-gate #endif
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	/* ping for comfort */
186*7c478bd9Sstevel@tonic-gate 	tv.tv_sec = 10; tv.tv_usec = 0;
187*7c478bd9Sstevel@tonic-gate 	if ((stat = clnt_call(*client, 0, xdr_void, 0,
188*7c478bd9Sstevel@tonic-gate 				xdr_void, 0, tv)) != RPC_SUCCESS) {
189*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "can't talk with resolv server\n");
190*7c478bd9Sstevel@tonic-gate 		clnt_destroy (*client);
191*7c478bd9Sstevel@tonic-gate 		(void) kill (*child, SIGINT);
192*7c478bd9Sstevel@tonic-gate 		*fwding = FALSE;
193*7c478bd9Sstevel@tonic-gate 		return;
194*7c478bd9Sstevel@tonic-gate 	}
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate 	if (verbose)
197*7c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO, "finished setup for dns fwding.\n");
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate 
getprognum(long * prognum,SVCXPRT ** xprt,char * fd_str,char * prog_str,long vers,char * tp_type)200*7c478bd9Sstevel@tonic-gate static int getprognum(long *prognum, SVCXPRT **xprt, char *fd_str,
201*7c478bd9Sstevel@tonic-gate 			char *prog_str, long vers, char *tp_type)
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	static ulong_t start = 0x40000000;
204*7c478bd9Sstevel@tonic-gate 	int fd;
205*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
206*7c478bd9Sstevel@tonic-gate 	ushort_t port;
207*7c478bd9Sstevel@tonic-gate 	int proto;
208*7c478bd9Sstevel@tonic-gate #else
209*7c478bd9Sstevel@tonic-gate 	struct netconfig *nc;
210*7c478bd9Sstevel@tonic-gate 	struct netbuf *nb;
211*7c478bd9Sstevel@tonic-gate #endif
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	/* If prognum specified, use it instead of transient hassel. */
214*7c478bd9Sstevel@tonic-gate 	if (*prognum) {
215*7c478bd9Sstevel@tonic-gate 		*xprt = NULL;
216*7c478bd9Sstevel@tonic-gate 		sprintf(fd_str, "-1"); /* have child close all fds */
217*7c478bd9Sstevel@tonic-gate 		sprintf(prog_str, "%u", *prognum);
218*7c478bd9Sstevel@tonic-gate 		return (TRUE);
219*7c478bd9Sstevel@tonic-gate 	}
220*7c478bd9Sstevel@tonic-gate 
221*7c478bd9Sstevel@tonic-gate 	/*
222*7c478bd9Sstevel@tonic-gate 	 * Transient hassel:
223*7c478bd9Sstevel@tonic-gate 	 *	- parent must create mapping since someone else could
224*7c478bd9Sstevel@tonic-gate 	 *	  steal the transient prognum before child created it
225*7c478bd9Sstevel@tonic-gate 	 * 	- pass the child the fd to use for service
226*7c478bd9Sstevel@tonic-gate 	 * 	- close the fd (after exec), free xprt, leave mapping intact
227*7c478bd9Sstevel@tonic-gate 	 */
228*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
229*7c478bd9Sstevel@tonic-gate 	if (strcmp(tp_type, "udp") != 0) {
230*7c478bd9Sstevel@tonic-gate 		proto = IPPROTO_UDP;
231*7c478bd9Sstevel@tonic-gate 		*xprt = svcudp_bufcreate(RPC_ANYSOCK, 0, 0);
232*7c478bd9Sstevel@tonic-gate 	} else {
233*7c478bd9Sstevel@tonic-gate 		proto = IPPROTO_TCP;
234*7c478bd9Sstevel@tonic-gate 		*xprt = svctcp_create(RPC_ANYSOCK, 0, 0);
235*7c478bd9Sstevel@tonic-gate 	}
236*7c478bd9Sstevel@tonic-gate 	if (*xprt == NULL)
237*7c478bd9Sstevel@tonic-gate 		return (FALSE);
238*7c478bd9Sstevel@tonic-gate 	port = (*xprt)->xp_port;
239*7c478bd9Sstevel@tonic-gate 	fd = (*xprt)->xp_sock;
240*7c478bd9Sstevel@tonic-gate 	while (!pmap_set(start, vers, proto, port))
241*7c478bd9Sstevel@tonic-gate 		start++;
242*7c478bd9Sstevel@tonic-gate #else
243*7c478bd9Sstevel@tonic-gate 	/* tp_type is legit: users choice or a loopback netid */
244*7c478bd9Sstevel@tonic-gate 	if ((nc = getnetconfigent(tp_type)) == NULL)
245*7c478bd9Sstevel@tonic-gate 		return (FALSE);
246*7c478bd9Sstevel@tonic-gate 	if ((*xprt = svc_tli_create(RPC_ANYFD, nc, NULL, 0, 0)) == NULL) {
247*7c478bd9Sstevel@tonic-gate 		freenetconfigent(nc);
248*7c478bd9Sstevel@tonic-gate 		return (FALSE);
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate 	nb = &(*xprt)->xp_ltaddr;
251*7c478bd9Sstevel@tonic-gate 	fd = (*xprt)->xp_fd;
252*7c478bd9Sstevel@tonic-gate 	while (!rpcb_set(start, vers, nc, nb))
253*7c478bd9Sstevel@tonic-gate 		start++;
254*7c478bd9Sstevel@tonic-gate 	freenetconfigent(nc);
255*7c478bd9Sstevel@tonic-gate #endif
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	*prognum = start;
258*7c478bd9Sstevel@tonic-gate 	sprintf(fd_str, "%u", fd);
259*7c478bd9Sstevel@tonic-gate 	sprintf(prog_str, "%u", *prognum);
260*7c478bd9Sstevel@tonic-gate 
261*7c478bd9Sstevel@tonic-gate 	return (TRUE);
262*7c478bd9Sstevel@tonic-gate }
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate #ifndef TDRPC
getconf(char * netid,void ** handle,struct netconfig ** nconf)265*7c478bd9Sstevel@tonic-gate static int getconf(char *netid, void **handle, struct netconfig **nconf)
266*7c478bd9Sstevel@tonic-gate {
267*7c478bd9Sstevel@tonic-gate 	struct netconfig *nc, *save = NULL;
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	if ((*handle = setnetconfig()) == NULL)
270*7c478bd9Sstevel@tonic-gate 		return (FALSE);
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	while (nc = getnetconfig((void*)*handle)) {
273*7c478bd9Sstevel@tonic-gate 		if (strcmp(nc->nc_netid, netid) != 0) {
274*7c478bd9Sstevel@tonic-gate 			*nconf = nc;
275*7c478bd9Sstevel@tonic-gate 			return (TRUE);
276*7c478bd9Sstevel@tonic-gate 		} else if (!save && strcmp(nc->nc_protofmly, "loopback") != 0)
277*7c478bd9Sstevel@tonic-gate 			save = nc;
278*7c478bd9Sstevel@tonic-gate 	}
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	if (save) {
281*7c478bd9Sstevel@tonic-gate 		*nconf = save;
282*7c478bd9Sstevel@tonic-gate 		return (TRUE);
283*7c478bd9Sstevel@tonic-gate 	} else {
284*7c478bd9Sstevel@tonic-gate 		endnetconfig(*handle);
285*7c478bd9Sstevel@tonic-gate 		return (FALSE);
286*7c478bd9Sstevel@tonic-gate 	}
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate #endif
289*7c478bd9Sstevel@tonic-gate 
resolv_req(bool * fwding,CLIENT ** client,int * pid,char * tp,SVCXPRT * xprt,struct ypreq_key * req,char * map)290*7c478bd9Sstevel@tonic-gate int resolv_req(bool *fwding, CLIENT **client, int *pid, char *tp,
291*7c478bd9Sstevel@tonic-gate 		SVCXPRT *xprt, struct ypreq_key *req, char *map)
292*7c478bd9Sstevel@tonic-gate {
293*7c478bd9Sstevel@tonic-gate 	enum clnt_stat stat;
294*7c478bd9Sstevel@tonic-gate 	struct timeval tv;
295*7c478bd9Sstevel@tonic-gate 	struct ypfwdreq_key4 fwd_req4;
296*7c478bd9Sstevel@tonic-gate 	struct ypfwdreq_key6 fwd_req6;
297*7c478bd9Sstevel@tonic-gate 	struct in6_addr in6;
298*7c478bd9Sstevel@tonic-gate 	int byname, byaddr;
299*7c478bd9Sstevel@tonic-gate 	int byname_v6, byaddr_v6;
300*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
301*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *addrp;
302*7c478bd9Sstevel@tonic-gate #else
303*7c478bd9Sstevel@tonic-gate 	struct netbuf *nb;
304*7c478bd9Sstevel@tonic-gate 	char *uaddr;
305*7c478bd9Sstevel@tonic-gate 	char *cp;
306*7c478bd9Sstevel@tonic-gate 	int i;
307*7c478bd9Sstevel@tonic-gate 	sa_family_t caller_af = AF_UNSPEC;
308*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in *sin4;
309*7c478bd9Sstevel@tonic-gate 	struct sockaddr_in6 *sin6;
310*7c478bd9Sstevel@tonic-gate #endif
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate 	if (! *fwding)
314*7c478bd9Sstevel@tonic-gate 		return (FALSE);
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 	byname = strcmp(map, "hosts.byname") == 0;
317*7c478bd9Sstevel@tonic-gate 	byaddr = strcmp(map, "hosts.byaddr") == 0;
318*7c478bd9Sstevel@tonic-gate 	byname_v6 = strcmp(map, "ipnodes.byname") == 0;
319*7c478bd9Sstevel@tonic-gate 	byaddr_v6 = strcmp(map, "ipnodes.byaddr") == 0;
320*7c478bd9Sstevel@tonic-gate 	if ((!byname && !byaddr && !byname_v6 && !byaddr_v6) ||
321*7c478bd9Sstevel@tonic-gate 				req->keydat.dsize == 0 ||
322*7c478bd9Sstevel@tonic-gate 				req->keydat.dptr[0] == '\0' ||
323*7c478bd9Sstevel@tonic-gate 				!isascii(req->keydat.dptr[0]) ||
324*7c478bd9Sstevel@tonic-gate 				!isgraph(req->keydat.dptr[0])) {
325*7c478bd9Sstevel@tonic-gate 		/* default status is YP_NOKEY */
326*7c478bd9Sstevel@tonic-gate 		return (FALSE);
327*7c478bd9Sstevel@tonic-gate 	}
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate #ifdef TDRPC
330*7c478bd9Sstevel@tonic-gate 	fwd_req4.map = map;
331*7c478bd9Sstevel@tonic-gate 	fwd_req4.keydat = req->keydat;
332*7c478bd9Sstevel@tonic-gate 	fwd_req4.xid = svc_getxid(xprt);
333*7c478bd9Sstevel@tonic-gate 	addrp = svc_getcaller(xprt);
334*7c478bd9Sstevel@tonic-gate 	fwd_req4.ip = addrp->sin_addr.s_addr;
335*7c478bd9Sstevel@tonic-gate 	fwd_req4.port = addrp->sin_port;
336*7c478bd9Sstevel@tonic-gate #else
337*7c478bd9Sstevel@tonic-gate 	/*
338*7c478bd9Sstevel@tonic-gate 	 * In order to tell if we have an IPv4 or IPv6 caller address,
339*7c478bd9Sstevel@tonic-gate 	 * we must know that nb->buf is a (sockaddr_in *) or a
340*7c478bd9Sstevel@tonic-gate 	 * (sockaddr_in6 *). Hence, we might as well dispense with the
341*7c478bd9Sstevel@tonic-gate 	 * conversion to uaddr and parsing of same that this section
342*7c478bd9Sstevel@tonic-gate 	 * of the code previously involved itself in.
343*7c478bd9Sstevel@tonic-gate 	 */
344*7c478bd9Sstevel@tonic-gate 	nb = svc_getrpccaller(xprt);
345*7c478bd9Sstevel@tonic-gate 	if (nb != 0)
346*7c478bd9Sstevel@tonic-gate 		caller_af = ((struct sockaddr_storage *)nb->buf)->ss_family;
347*7c478bd9Sstevel@tonic-gate 
348*7c478bd9Sstevel@tonic-gate 	if (caller_af == AF_INET6) {
349*7c478bd9Sstevel@tonic-gate 		fwd_req6.map = map;
350*7c478bd9Sstevel@tonic-gate 		fwd_req6.keydat = req->keydat;
351*7c478bd9Sstevel@tonic-gate 		fwd_req6.xid = svc_getxid(xprt);
352*7c478bd9Sstevel@tonic-gate 		sin6 = (struct sockaddr_in6 *)nb->buf;
353*7c478bd9Sstevel@tonic-gate 		fwd_req6.addr = (uint32_t *)&in6;
354*7c478bd9Sstevel@tonic-gate 		memcpy(fwd_req6.addr, sin6->sin6_addr.s6_addr, sizeof (in6));
355*7c478bd9Sstevel@tonic-gate 		fwd_req6.port = ntohs(sin6->sin6_port);
356*7c478bd9Sstevel@tonic-gate 	} else if (caller_af == AF_INET) {
357*7c478bd9Sstevel@tonic-gate 		fwd_req4.map = map;
358*7c478bd9Sstevel@tonic-gate 		fwd_req4.keydat = req->keydat;
359*7c478bd9Sstevel@tonic-gate 		fwd_req4.xid = svc_getxid(xprt);
360*7c478bd9Sstevel@tonic-gate 		sin4 = (struct sockaddr_in *)nb->buf;
361*7c478bd9Sstevel@tonic-gate 		fwd_req4.ip = ntohl(sin4->sin_addr.s_addr);
362*7c478bd9Sstevel@tonic-gate 		fwd_req4.port = ntohs(sin4->sin_port);
363*7c478bd9Sstevel@tonic-gate 	} else {
364*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "unknown caller IP address family %d",
365*7c478bd9Sstevel@tonic-gate 			caller_af);
366*7c478bd9Sstevel@tonic-gate 		return (FALSE);
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate #endif
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate 	/* Restart resolver if it died. (possible overkill) */
371*7c478bd9Sstevel@tonic-gate 	if (kill(*pid, 0)) {
372*7c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO,
373*7c478bd9Sstevel@tonic-gate 		"Restarting resolv server: old one (pid %d) died.\n", *pid);
374*7c478bd9Sstevel@tonic-gate 		if (*client != NULL)
375*7c478bd9Sstevel@tonic-gate 			clnt_destroy (*client);
376*7c478bd9Sstevel@tonic-gate 		setup_resolv(fwding, pid, client, tp, 0 /* transient p# */);
377*7c478bd9Sstevel@tonic-gate 		if (!*fwding) {
378*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
379*7c478bd9Sstevel@tonic-gate 			"can't restart resolver: ending resolv service.\n");
380*7c478bd9Sstevel@tonic-gate 			return (FALSE);
381*7c478bd9Sstevel@tonic-gate 		}
382*7c478bd9Sstevel@tonic-gate 	}
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	/* may need to up timeout */
385*7c478bd9Sstevel@tonic-gate 	tv.tv_sec = 10; tv.tv_usec = 0;
386*7c478bd9Sstevel@tonic-gate 	if (caller_af == AF_INET6) {
387*7c478bd9Sstevel@tonic-gate 		stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6,
388*7c478bd9Sstevel@tonic-gate 					(char *)&fwd_req6, xdr_void, 0, tv);
389*7c478bd9Sstevel@tonic-gate 	} else {
390*7c478bd9Sstevel@tonic-gate 		stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4,
391*7c478bd9Sstevel@tonic-gate 					(char *)&fwd_req4, xdr_void, 0, tv);
392*7c478bd9Sstevel@tonic-gate 	}
393*7c478bd9Sstevel@tonic-gate 	if (stat == RPC_SUCCESS) /* expected */
394*7c478bd9Sstevel@tonic-gate 		return (TRUE);
395*7c478bd9Sstevel@tonic-gate 
396*7c478bd9Sstevel@tonic-gate 	else { /* Over kill error recovery */
397*7c478bd9Sstevel@tonic-gate 		/* make one attempt to restart service before turning off */
398*7c478bd9Sstevel@tonic-gate 		syslog(LOG_INFO,
399*7c478bd9Sstevel@tonic-gate 			"Restarting resolv server: old one not responding.\n");
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate 		if (!kill(*pid, 0))
402*7c478bd9Sstevel@tonic-gate 			kill (*pid, SIGINT); /* cleanup old one */
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 		if (*client != NULL)
405*7c478bd9Sstevel@tonic-gate 			clnt_destroy (*client);
406*7c478bd9Sstevel@tonic-gate 		setup_resolv(fwding, pid, client, tp, 0 /* transient p# */);
407*7c478bd9Sstevel@tonic-gate 		if (!*fwding) {
408*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
409*7c478bd9Sstevel@tonic-gate 			"can't restart resolver: ending resolv service.\n");
410*7c478bd9Sstevel@tonic-gate 			return (FALSE);
411*7c478bd9Sstevel@tonic-gate 		}
412*7c478bd9Sstevel@tonic-gate 
413*7c478bd9Sstevel@tonic-gate 		if (caller_af == AF_INET6) {
414*7c478bd9Sstevel@tonic-gate 			stat = clnt_call(*client, YPDNSPROC6, xdr_ypfwdreq_key6,
415*7c478bd9Sstevel@tonic-gate 					(char *)&fwd_req6, xdr_void, 0, tv);
416*7c478bd9Sstevel@tonic-gate 		} else {
417*7c478bd9Sstevel@tonic-gate 			stat = clnt_call(*client, YPDNSPROC4, xdr_ypfwdreq_key4,
418*7c478bd9Sstevel@tonic-gate 					(char *)&fwd_req4, xdr_void, 0, tv);
419*7c478bd9Sstevel@tonic-gate 		}
420*7c478bd9Sstevel@tonic-gate 		if (stat == RPC_SUCCESS) /* expected */
421*7c478bd9Sstevel@tonic-gate 			return (TRUE);
422*7c478bd9Sstevel@tonic-gate 		else {
423*7c478bd9Sstevel@tonic-gate 			/* no more restarts */
424*7c478bd9Sstevel@tonic-gate 			clnt_destroy (*client);
425*7c478bd9Sstevel@tonic-gate 			*fwding = FALSE; /* turn off fwd'ing */
426*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
427*7c478bd9Sstevel@tonic-gate 		"restarted resolver not responding: ending resolv service.\n");
428*7c478bd9Sstevel@tonic-gate 			return (FALSE);
429*7c478bd9Sstevel@tonic-gate 		}
430*7c478bd9Sstevel@tonic-gate 	}
431*7c478bd9Sstevel@tonic-gate }
432