1272343Sngie/*	$NetBSD: t_rpc.c,v 1.3 2013/02/28 15:56:53 christos Exp $	*/
2272343Sngie
3272343Sngie#include <sys/cdefs.h>
4272343Sngie__RCSID("$NetBSD: t_rpc.c,v 1.3 2013/02/28 15:56:53 christos Exp $");
5272343Sngie
6272343Sngie#include <sys/types.h>
7272343Sngie#include <sys/socket.h>
8272343Sngie#include <rpc/rpc.h>
9272343Sngie#include <stdlib.h>
10272343Sngie#include <err.h>
11272343Sngie#include <netdb.h>
12272343Sngie#include <stdio.h>
13272343Sngie#include <unistd.h>
14272343Sngie
15272343Sngie
16272343Sngie#ifndef TEST
17272343Sngie#include <atf-c.h>
18272343Sngie
19272343Sngie#define ERRX(ev, msg, ...)	ATF_REQUIRE_MSG(0, msg, __VA_ARGS__)
20272343Sngie
21272343Sngie#define SKIPX(ev, msg, ...)	do {			\
22272343Sngie	atf_tc_skip(msg, __VA_ARGS__);			\
23272343Sngie	return;						\
24272343Sngie} while(/*CONSTCOND*/0)
25272343Sngie
26272343Sngie#else
27272343Sngie#define ERRX(ev, msg, ...)	errx(ev, msg, __VA_ARGS__)
28272343Sngie#define SKIPX(ev, msg, ...)	errx(ev, msg, __VA_ARGS__)
29272343Sngie#endif
30272343Sngie
31272343Sngie
32272343Sngie#define RPCBPROC_NULL 0
33272343Sngie
34272343Sngiestatic int
35272343Sngiereply(caddr_t replyp, struct netbuf * raddrp, struct netconfig * nconf)
36272343Sngie{
37272343Sngie	char host[NI_MAXHOST];
38272343Sngie	struct sockaddr *sock = raddrp->buf;
39272343Sngie	int error;
40272343Sngie
41272343Sngie
42272343Sngie	error = getnameinfo(sock, sock->sa_len, host, sizeof(host), NULL, 0, 0);
43272343Sngie	if (error)
44272343Sngie		warnx("Cannot resolve address (%s)", gai_strerror(error));
45272343Sngie	else
46272343Sngie		printf("response from: %s\n", host);
47272343Sngie	return 0;
48272343Sngie}
49272343Sngie
50276478Sngie#ifdef __FreeBSD__
51276478Sngie#define	__rpc_control	rpc_control
52276478Sngie#endif
53276478Sngie
54272343Sngieextern bool __rpc_control(int, void *);
55272343Sngie
56272343Sngiestatic void
57272343Sngieonehost(const char *host, const char *transp)
58272343Sngie{
59272343Sngie	CLIENT         *clnt;
60272343Sngie	struct netbuf   addr;
61272343Sngie	struct timeval  tv;
62272343Sngie
63272343Sngie	/*
64272343Sngie	 * Magic!
65272343Sngie	 */
66272343Sngie	tv.tv_sec = 0;
67272343Sngie	tv.tv_usec = 500000;
68272343Sngie#define CLCR_SET_RPCB_TIMEOUT   2
69272343Sngie	__rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv);
70272343Sngie
71272343Sngie	if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL)
72272343Sngie		SKIPX(EXIT_FAILURE, "clnt_create (%s)", clnt_spcreateerror(""));
73272343Sngie
74272343Sngie	tv.tv_sec = 1;
75272343Sngie	tv.tv_usec = 0;
76291177Sngie#ifdef __FreeBSD__
77291177Sngie	if (clnt_call(clnt, RPCBPROC_NULL, (xdrproc_t)xdr_void, NULL,
78291177Sngie	    (xdrproc_t)xdr_void, NULL, tv)
79291177Sngie	    != RPC_SUCCESS)
80291177Sngie#else
81272343Sngie	if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv)
82272343Sngie	    != RPC_SUCCESS)
83291177Sngie#endif
84272343Sngie		ERRX(EXIT_FAILURE, "clnt_call (%s)", clnt_sperror(clnt, ""));
85272343Sngie	clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr);
86272343Sngie	reply(NULL, &addr, NULL);
87272343Sngie}
88272343Sngie
89272343Sngie#ifdef TEST
90272343Sngiestatic void
91272343Sngieallhosts(void)
92272343Sngie{
93272343Sngie	enum clnt_stat  clnt_stat;
94272343Sngie
95272343Sngie	clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL,
96272343Sngie	    (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void,
97272343Sngie	    NULL, (resultproc_t)reply, transp);
98272343Sngie	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
99272343Sngie		ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat));
100272343Sngie}
101272343Sngie
102272343Sngieint
103272343Sngiemain(int argc, char *argv[])
104272343Sngie{
105272343Sngie	int             ch;
106272343Sngie	const char     *transp = "udp";
107272343Sngie
108272343Sngie
109272343Sngie	while ((ch = getopt(argc, argv, "ut")) != -1)
110272343Sngie		switch (ch) {
111272343Sngie		case 't':
112272343Sngie			transp = "tcp";
113272343Sngie			break;
114272343Sngie		case 'u':
115272343Sngie			transp = "udp";
116272343Sngie			break;
117272343Sngie		default:
118272343Sngie			fprintf(stderr, "Usage: %s -[t|u] [<hostname>...]\n",
119272343Sngie			    getprogname());
120272343Sngie			return EXIT_FAILURE;
121272343Sngie		}
122272343Sngie
123272343Sngie	if (argc == optind)
124272343Sngie		allhosts();
125272343Sngie	else
126272343Sngie		for (; optind < argc; optind++)
127272343Sngie			onehost(argv[optind], transp);
128272343Sngie
129272343Sngie	return EXIT_SUCCESS;
130272343Sngie}
131272343Sngie
132272343Sngie#else
133272343Sngie
134272343SngieATF_TC(get_svc_addr_tcp);
135272343SngieATF_TC_HEAD(get_svc_addr_tcp, tc)
136272343Sngie{
137272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp");
138272343Sngie
139272343Sngie}
140272343Sngie
141272343SngieATF_TC_BODY(get_svc_addr_tcp, tc)
142272343Sngie{
143272343Sngie	onehost("localhost", "tcp");
144272343Sngie
145272343Sngie}
146272343Sngie
147272343SngieATF_TC(get_svc_addr_udp);
148272343SngieATF_TC_HEAD(get_svc_addr_udp, tc)
149272343Sngie{
150272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp");
151272343Sngie}
152272343Sngie
153272343SngieATF_TC_BODY(get_svc_addr_udp, tc)
154272343Sngie{
155272343Sngie	onehost("localhost", "udp");
156272343Sngie
157272343Sngie}
158272343Sngie
159272343SngieATF_TP_ADD_TCS(tp)
160272343Sngie{
161272343Sngie	ATF_TP_ADD_TC(tp, get_svc_addr_udp);
162272343Sngie	ATF_TP_ADD_TC(tp, get_svc_addr_tcp);
163272343Sngie
164272343Sngie	return atf_no_error();
165272343Sngie}
166272343Sngie
167272343Sngie#endif
168