コード例 #1
0
ファイル: crypt_client.c プロジェクト: hmatyschok/MeshBSD
int
_des_crypt_call(char *buf, int len, struct desparams *dparms)
{
	CLIENT *clnt;
	desresp  *result_1;
	desargs  des_crypt_1_arg;
	struct netconfig *nconf;
	void *localhandle;
	int stat;

	nconf = NULL;
	localhandle = setnetconfig();
	while ((nconf = getnetconfig(localhandle)) != NULL) {
		if (nconf->nc_protofmly != NULL &&
		     strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
			break;
	}
	if (nconf == NULL) {
		warnx("getnetconfig: %s", nc_sperror());
		endnetconfig(localhandle);
		return(DESERR_HWERROR);
	}
	clnt = clnt_tp_create(NULL, CRYPT_PROG, CRYPT_VERS, nconf);
	if (clnt == (CLIENT *) NULL) {
		endnetconfig(localhandle);
		return(DESERR_HWERROR);
	}
	endnetconfig(localhandle);

	des_crypt_1_arg.desbuf.desbuf_len = len;
	des_crypt_1_arg.desbuf.desbuf_val = buf;
	des_crypt_1_arg.des_dir = (dparms->des_dir == ENCRYPT) ? ENCRYPT_DES : DECRYPT_DES;
	des_crypt_1_arg.des_mode = (dparms->des_mode == CBC) ? CBC_DES : ECB_DES;
	bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
	bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);

	result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
	if (result_1 == (desresp *) NULL) {
		clnt_destroy(clnt);
		return(DESERR_HWERROR);
	}

	stat = result_1->stat;

	if (result_1->stat == DESERR_NONE ||
	    result_1->stat == DESERR_NOHWDEVICE) {
		bcopy(result_1->desbuf.desbuf_val, buf, len);
		bcopy(result_1->des_ivec, dparms->des_ivec, 8);
	}

	clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1);
	clnt_destroy(clnt);

	return(stat);
}
コード例 #2
0
/*
 * Determines the availability of rpc.yppasswdd.  Returns -1 for not
 * available (or unable to determine), 0 for available, 1 for available in
 * master mode.
 */
int
ypclnt_havepasswdd(ypclnt_t *ypclnt)
{
	struct netconfig *nc = NULL;
	void *localhandle = 0;
	CLIENT *clnt = NULL;
	int ret;

	/* check if rpc.yppasswdd is running */
	if (getrpcport(ypclnt->server, YPPASSWDPROG,
		YPPASSWDPROC_UPDATE, IPPROTO_UDP) == 0) {
		ypclnt_error(ypclnt, __func__, "no rpc.yppasswdd on server");
		return (-1);
	}

	/* if we're not root, use remote method */
	if (getuid() != 0)
		return (0);

	/* try to connect to rpc.yppasswdd */
	localhandle = setnetconfig();
	while ((nc = getnetconfig(localhandle)) != NULL) {
		if (nc->nc_protofmly != NULL &&
			strcmp(nc->nc_protofmly, NC_LOOPBACK) == 0)
				break;
	}
	if (nc == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "getnetconfig: %s", nc_sperror());
		ret = 0;
		goto done;
	}
	if ((clnt = clnt_tp_create(NULL, MASTER_YPPASSWDPROG,
	    MASTER_YPPASSWDVERS, nc)) == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "failed to connect to rpc.yppasswdd: %s",
		    clnt_spcreateerror(ypclnt->server));
		ret = 0;
		goto done;
	} else 
		ret = 1;

done:
	if (clnt != NULL) {
		clnt_destroy(clnt);
	}
	endnetconfig(localhandle);
	return (ret);
}
コード例 #3
0
ファイル: 1-basic.c プロジェクト: shubmit/shub-ltp
int main(int argn, char *argc[])
{
	//Program parameters : argc[1] : HostName or Host IP
	//					   argc[2] : Server Program Number
	//					   other arguments depend on test case

	//run_mode can switch into stand alone program or program launch by shell script
	//1 : stand alone, debug mode, more screen information
	//0 : launch by shell script as test case, only one printf -> result status
	int run_mode = 0;
	int test_status = 1; //Default test result set to FAILED
	int progNum = atoi(argc[2]);
	char nettype[16] = "visible";
	CLIENT *client = NULL;
	struct netconfig *nconf = NULL;

	//First, test initialization
	nconf = getnetconfigent("udp");

    if ((struct netconfig *)nconf == NULL)
    {
    	//Test failed
    	printf("1\n");
    	return 1;
    }

	//Call routine
    client = clnt_tp_create(argc[1], progNum,
                            VERSNUM, (struct netconfig *)nconf);

    if (run_mode)
    {
		printf("client : %d\n", client);
		printf("nconf : %d\n", nconf);
	}

	test_status = ((CLIENT *)client != NULL) ? 0 : 1;

	//This last printf gives the result status to the tests suite
	//normally should be 0: test has passed or 1: test has failed
	printf("%d\n", test_status);

    //clnt_destroy(client);

	return test_status;
}
コード例 #4
0
static int
yppasswd_local(ypclnt_t *ypclnt, const struct passwd *pwd)
{
	struct master_yppasswd yppwd;
	struct rpc_err rpcerr;
	struct netconfig *nc = NULL;
	void *localhandle = 0;
	CLIENT *clnt = NULL;
	int ret, *result;

	/* fill the master_yppasswd structure */
	memset(&yppwd, 0, sizeof yppwd);
	yppwd.newpw.pw_uid = pwd->pw_uid;
	yppwd.newpw.pw_gid = pwd->pw_gid;
	yppwd.newpw.pw_change = pwd->pw_change;
	yppwd.newpw.pw_expire = pwd->pw_expire;
	yppwd.newpw.pw_fields = pwd->pw_fields;
	yppwd.oldpass = strdup("");
	yppwd.domain = strdup(ypclnt->domain);
	if ((yppwd.newpw.pw_name = strdup(pwd->pw_name)) == NULL ||
	    (yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd)) == NULL ||
	    (yppwd.newpw.pw_class = strdup(pwd->pw_class)) == NULL ||
	    (yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos)) == NULL ||
	    (yppwd.newpw.pw_dir = strdup(pwd->pw_dir)) == NULL ||
	    (yppwd.newpw.pw_shell = strdup(pwd->pw_shell)) == NULL) {
		ypclnt_error(ypclnt, __func__, strerror(errno));
		ret = -1;
		goto done;
	}

	/* connect to rpc.yppasswdd */
	localhandle = setnetconfig();
	while ((nc = getnetconfig(localhandle)) != NULL) {
		if (nc->nc_protofmly != NULL &&
		    strcmp(nc->nc_protofmly, NC_LOOPBACK) == 0)
			break;
	}
	if (nc == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "getnetconfig: %s", nc_sperror());
		ret = -1;
		goto done;
	}
	if ((clnt = clnt_tp_create(NULL, MASTER_YPPASSWDPROG,
	    MASTER_YPPASSWDVERS, nc)) == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "failed to connect to rpc.yppasswdd: %s",
		    clnt_spcreateerror(ypclnt->server));
		ret = -1;
		goto done;
	}
	clnt->cl_auth = authunix_create_default();

	/* request the update */
	result = yppasswdproc_update_master_1(&yppwd, clnt);

	/* check for RPC errors */
	clnt_geterr(clnt, &rpcerr);
	if (rpcerr.re_status != RPC_SUCCESS) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed: %s",
		    clnt_sperror(clnt, ypclnt->server));
		ret = -1;
		goto done;
	}

	/* check the result of the update */
	if (result == NULL || *result != 0) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed");
		/* XXX how do we get more details? */
		ret = -1;
		goto done;
	}

	ypclnt_error(ypclnt, NULL, NULL);
	ret = 0;

 done:
	if (clnt != NULL) {
		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
	}
	endnetconfig(localhandle);
	free(yppwd.newpw.pw_name);
	if (yppwd.newpw.pw_passwd != NULL) {
		memset(yppwd.newpw.pw_passwd, 0, strlen(yppwd.newpw.pw_passwd));
		free(yppwd.newpw.pw_passwd);
	}
	free(yppwd.newpw.pw_class);
	free(yppwd.newpw.pw_gecos);
	free(yppwd.newpw.pw_dir);
	free(yppwd.newpw.pw_shell);
	if (yppwd.oldpass != NULL) {
		memset(yppwd.oldpass, 0, strlen(yppwd.oldpass));
		free(yppwd.oldpass);
	}
	return (ret);
}
コード例 #5
0
ファイル: lock_proc.c プロジェクト: 2asoft/freebsd
CLIENT *
get_client(struct sockaddr *host_addr, rpcvers_t vers)
{
	CLIENT *client;
	struct timeval retry_time, time_now;
	int error, i;
	const char *netid;
	struct netconfig *nconf;
	char host[NI_MAXHOST];
	uid_t old_euid;
	int clnt_fd;

	gettimeofday(&time_now, NULL);

	/*
	 * Search for the given client in the cache, zapping any expired
	 * entries that we happen to notice in passing.
	 */
	for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
		client = clnt_cache_ptr[i];
		if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
		    < time_now.tv_sec)) {
			/* Cache entry has expired. */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Expired CLIENT* in cache");
			clnt_cache_time[i] = 0L;
			clnt_destroy(client);
			clnt_cache_ptr[i] = NULL;
			client = NULL;
		}
		if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
		    host_addr) && clnt_cache_vers[i] == vers) {
			/* Found it! */
			if (debug_level > 3)
				syslog(LOG_DEBUG, "Found CLIENT* in cache");
			return (client);
		}
	}

	if (debug_level > 3)
		syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");

	/* Not found in cache.  Free the next entry if it is in use. */
	if (clnt_cache_ptr[clnt_cache_next_to_use]) {
		clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
		clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
	}

	/*
	 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
	 * to avoid DNS lookups.
	 */
	error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
			    NULL, 0, NI_NUMERICHOST);
	if (error != 0) {
		syslog(LOG_ERR, "unable to get name string for caller: %s",
		       gai_strerror(error));
		return NULL;
	}

#if 1
	if (host_addr->sa_family == AF_INET6)
		netid = "udp6";
	else
		netid = "udp";
#else 
	if (host_addr->sa_family == AF_INET6)
		netid = "tcp6";
	else
		netid = "tcp";
#endif
	nconf = getnetconfigent(netid);
	if (nconf == NULL) {
		syslog(LOG_ERR, "could not get netconfig info for '%s': "
				"no /etc/netconfig file?", netid);
		return NULL;
	}

	client = clnt_tp_create(host, NLM_PROG, vers, nconf);
	freenetconfigent(nconf);

	if (!client) {
		syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
		syslog(LOG_ERR, "Unable to return result to %s", host);
		return NULL;
	}

	/* Get the FD of the client, for bindresvport. */ 
	clnt_control(client, CLGET_FD, &clnt_fd);

	/* Regain root privileges, for bindresvport. */
	old_euid = geteuid();
	seteuid(0);

	/*
	 * Bind the client FD to a reserved port.
	 * Some NFS servers reject any NLM request from a non-reserved port. 
	 */ 
	bindresvport(clnt_fd, NULL);

	/* Drop root privileges again. */
	seteuid(old_euid);

	/* Success - update the cache entry */
	clnt_cache_ptr[clnt_cache_next_to_use] = client;
	memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
	    host_addr->sa_len);
	clnt_cache_vers[clnt_cache_next_to_use] = vers;
	clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
	if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
		clnt_cache_next_to_use = 0;

	/*
	 * Disable the default timeout, so we can specify our own in calls
	 * to clnt_call().  (Note that the timeout is a different concept
	 * from the retry period set in clnt_udp_create() above.)
	 */
	retry_time.tv_sec = -1;
	retry_time.tv_usec = -1;
	clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);

	if (debug_level > 3)
		syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
	return client;
}
コード例 #6
0
CLIENT *
getkwarnd_handle(void)
{
	void *localhandle;
	struct netconfig *nconf;
	struct netconfig *tpconf;
	struct timeval wait_time;
	struct utsname u;
	static char *hostname;
	static bool_t first_time = TRUE;

/*
 * Total timeout (in seconds) talking to kwarnd.
 */
#define	TOTAL_TIMEOUT	5

	if (kwarn_clnt)
		return (kwarn_clnt);
	if (!(localhandle = setnetconfig()))
		return (NULL);
	tpconf = NULL;
	if (first_time == TRUE) {
		if (uname(&u) == -1) {
			(void) endnetconfig(localhandle);
			return ((CLIENT *)NULL);
		}
		if ((hostname = strdup(u.nodename)) == (char *)NULL) {
			(void) endnetconfig(localhandle);
			return ((CLIENT *)NULL);
		}
		first_time = FALSE;
	}
	while (nconf = getnetconfig(localhandle)) {
		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
			if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
				kwarn_clnt = clnt_tp_create(hostname,
				    KWARNPROG, KWARNVERS, nconf);
				if (kwarn_clnt) {
					dprt("got COTS_ORD\n");
					break;
				}
			} else {
				tpconf = nconf;
			}
		}
	}
	if ((kwarn_clnt == NULL) && (tpconf)) {

		/* Now, try the connection-oriented loopback transport */

		kwarn_clnt = clnt_tp_create(hostname, KWARNPROG, KWARNVERS,
		    tpconf);
#ifdef DEBUG
		if (kwarn_clnt) {
			dprt("got COTS\n");
		}
#endif	/* DEBUG */
	}
	(void) endnetconfig(localhandle);

	/*
	 * This bit of code uses an as yet unimplemented argument to
	 * clnt_control(). CLSET_SVC_PRIV specifies that the underlying
	 * loopback transport should be checked to ensure it is
	 * connected to a process running as root. If so, the clnt_control()
	 * call returns TRUE. If not, it returns FALSE.
	 */

#ifdef CLSET_SVC_PRIV

	if (clnt_control(kwarn_clnt, CLSET_SVC_PRIV, NULL) != TRUE) {
		clnt_destroy(kwarn_clnt);
		kwarn_clnt = NULL;
		return (NULL);
	{
#endif
	if (kwarn_clnt == NULL)
		return (NULL);

	kwarn_clnt->cl_auth = authsys_create("", getuid(), 0, 0, NULL);
	if (kwarn_clnt->cl_auth == NULL) {
		clnt_destroy(kwarn_clnt);
		kwarn_clnt = NULL;
		return (NULL);
	}
	wait_time.tv_sec = TOTAL_TIMEOUT;
	wait_time.tv_usec = 0;
	(void) clnt_control(kwarn_clnt, CLSET_TIMEOUT, (char *)&wait_time);

	return (kwarn_clnt);
}

void
resetkwarnd_handle(void)
{
	auth_destroy(kwarn_clnt->cl_auth);
	clnt_destroy(kwarn_clnt);
	kwarn_clnt = NULL;
}
コード例 #7
0
ファイル: key_call.c プロジェクト: alexandermerritt/dragonfly
/*
 * Keep the handle cached.  This call may be made quite often.
 */
static CLIENT *
getkeyserv_handle(int vers)
{
	void *localhandle;
	struct netconfig *nconf;
	struct netconfig *tpconf;
	struct key_call_private *kcp = key_call_private_main;
	struct timeval wait_time;
	struct utsname u;
	int main_thread;
	int fd;
	static thread_key_t key_call_key;

#define	TOTAL_TIMEOUT	30	/* total timeout talking to keyserver */
#define	TOTAL_TRIES	5	/* Number of tries */

	if ((main_thread = thr_main())) {
		kcp = key_call_private_main;
	} else {
		if (key_call_key == 0) {
			mutex_lock(&tsd_lock);
			if (key_call_key == 0)
				thr_keycreate(&key_call_key, key_call_destroy);
			mutex_unlock(&tsd_lock);
		}
		kcp = (struct key_call_private *)thr_getspecific(key_call_key);
	}
	if (kcp == NULL) {
		kcp = (struct key_call_private *)malloc(sizeof (*kcp));
		if (kcp == NULL) {
			return (NULL);
		}
		if (main_thread)
			key_call_private_main = kcp;
		else
			thr_setspecific(key_call_key, (void *) kcp);
		kcp->client = NULL;
	}

	/* if pid has changed, destroy client and rebuild */
	if (kcp->client != NULL && kcp->pid != getpid()) {
		clnt_destroy(kcp->client);
		kcp->client = NULL;
	}

	if (kcp->client != NULL) {
		/* if uid has changed, build client handle again */
		if (kcp->uid != geteuid()) {
			kcp->uid = geteuid();
			auth_destroy(kcp->client->cl_auth);
			kcp->client->cl_auth =
				authsys_create("", kcp->uid, 0, 0, NULL);
			if (kcp->client->cl_auth == NULL) {
				clnt_destroy(kcp->client);
				kcp->client = NULL;
				return (NULL);
			}
		}
		/* Change the version number to the new one */
		clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
		return (kcp->client);
	}
	if (!(localhandle = setnetconfig())) {
		return (NULL);
	}
	tpconf = NULL;
	if (uname(&u) == -1)
	{
		endnetconfig(localhandle);
		return (NULL);
	}
	while ((nconf = getnetconfig(localhandle)) != NULL) {
		if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
			/*
			 * We use COTS_ORD here so that the caller can
			 * find out immediately if the server is dead.
			 */
			if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
				kcp->client = clnt_tp_create(u.nodename,
					KEY_PROG, vers, nconf);
				if (kcp->client)
					break;
			} else {
				tpconf = nconf;
			}
		}
	}
	if ((kcp->client == NULL) && (tpconf))
		/* Now, try the CLTS or COTS loopback transport */
		kcp->client = clnt_tp_create(u.nodename,
			KEY_PROG, vers, tpconf);
	endnetconfig(localhandle);

	if (kcp->client == NULL) {
		return (NULL);
	}
	kcp->uid = geteuid();
	kcp->pid = getpid();
	kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
	if (kcp->client->cl_auth == NULL) {
		clnt_destroy(kcp->client);
		kcp->client = NULL;
		return (NULL);
	}

	wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
	wait_time.tv_usec = 0;
	clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
		(char *)&wait_time);
	if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
		_fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */

	return (kcp->client);
}
コード例 #8
0
void setup_resolv(bool *fwding, int *child,
			CLIENT **client, char *tp_type, long prognum)
{
	enum clnt_stat stat;
	struct timeval tv;
	char prog_str[15], fd_str[5];
	SVCXPRT *xprt = NULL;
	char *tp;
#ifdef	TDRPC
	struct sockaddr_in addr;
	int sock;
#else
	char name[257];
	struct netconfig *nc;
	void *h;
#endif
	verbose = silent == FALSE ? 1 : 0;

	if (! *fwding)
		return;

#ifdef	TDRPC
	tp = (tp_type && strcmp(tp_type, "udp") != 0) ? "udp" : "tcp";
#else
	/* try the specified netid (default ticots), then any loopback */
	tp = (tp_type && *tp_type) ? tp_type : "ticots";
	if (!getconf(tp, &h, &nc)) { /* dont forget endnetconfig() */
		syslog(LOG_ERR, "can't get resolv_clnt netconf %s.\n", tp);
		*fwding = FALSE;
		return;
	}
	tp = nc->nc_netid;
#endif

	/*
	 * Startup the resolv server: use transient prognum if prognum
	 * isn't set. Using transient means we create mapping then
	 * pass child the fd to use for service.
	 */
	if (!getprognum(&prognum, &xprt, fd_str, prog_str, YPDNSVERS, tp)) {
		syslog(LOG_ERR, "can't create resolv xprt for transient.\n");
		*fwding = FALSE;
#ifndef TDRPC
		endnetconfig(h);
#endif
		return;
	}
	switch (*child = vfork()) {
	case -1: /* error  */
		syslog(LOG_ERR, "can't startup resolv daemon\n");
#ifndef TDRPC
		endnetconfig(h);
#endif
		*fwding = FALSE;
		return;
	case 0:  /* child  */
		/*
		 * if using transient we must maintain fd across
		 * exec cause unset/set on prognum isn't automic.
		 *
		 * if using transient we'll just do svc_tli_create
		 * in child on our bound fd.
		 */
		execlp(RESOLV_EXEC_PATH, "rpc.nisd_resolv",
				"-F",		/* forground  */
				"-C", fd_str,	/* dont close */
				"-p", prog_str,	/* prognum    */
				"-t", tp,	/* tp type    */
				NULL);
		syslog(LOG_ERR, RESOLV_EXEC_ERR, strerror(errno));
		exit(1);
	default: /* parent */
		/* close fd, free xprt, but leave mapping */
		if (xprt)
			svc_destroy(xprt);

		/* let it crank up before we create client */
		sleep(4);
	}
#ifdef TDRPC
	get_myaddress(&addr);
	addr.sin_port = 0;
	sock = RPC_ANYSOCK;
	tv.tv_sec = 3; tv.tv_usec = 0;
	if (strcmp(tp, "udp") != 0) {
		*client = clntudp_bufcreate(&addr, prognum, YPDNSVERS,
					tv, &sock, YPMSGSZ, YPMSGSZ);
	} else {
		*client = clnttcp_create(&addr, prognum, YPDNSVERS,
					&sock, YPMSGSZ, YPMSGSZ);
	}
	if (*client == NULL) {
		syslog(LOG_ERR, "can't create resolv client handle.\n");
		(void) kill (*child, SIGINT);
		*fwding = FALSE;
		return;
	}
#else
	if (sysinfo(SI_HOSTNAME, name, sizeof (name)-1) == -1) {
		syslog(LOG_ERR, "can't get local hostname.\n");
		(void) kill (*child, SIGINT);
		endnetconfig(h);
		*fwding = FALSE;
		return;
	}
	if ((*client = clnt_tp_create(HOST_SELF_CONNECT, prognum,
			YPDNSVERS, nc)) == NULL) {
		syslog(LOG_ERR, "can't create resolv_clnt\n");
		(void) kill (*child, SIGINT);
		endnetconfig(h);
		*fwding = FALSE;
		return;
	}
	endnetconfig(h);
#endif

	/* ping for comfort */
	tv.tv_sec = 10; tv.tv_usec = 0;
	if ((stat = clnt_call(*client, 0, xdr_void, 0,
				xdr_void, 0, tv)) != RPC_SUCCESS) {
		syslog(LOG_ERR, "can't talk with resolv server\n");
		clnt_destroy (*client);
		(void) kill (*child, SIGINT);
		*fwding = FALSE;
		return;
	}

	if (verbose)
		syslog(LOG_INFO, "finished setup for dns fwding.\n");
}