xref: /freebsd/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c (revision 63d1fd5970ec814904aa0f4580b10a0d302d08b2)
1 /*	$NetBSD: t_rpc.c,v 1.10 2016/08/27 14:36:22 christos Exp $	*/
2 
3 #include <sys/cdefs.h>
4 __RCSID("$NetBSD: t_rpc.c,v 1.10 2016/08/27 14:36:22 christos Exp $");
5 
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <rpc/rpc.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <err.h>
12 #include <netdb.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <unistd.h>
16 
17 #ifndef TEST
18 #include <atf-c.h>
19 
20 #define ERRX(ev, msg, ...)	ATF_REQUIRE_MSG(0, msg, __VA_ARGS__)
21 
22 #define SKIPX(ev, msg, ...)	do {			\
23 	atf_tc_skip(msg, __VA_ARGS__);			\
24 	return ev;					\
25 } while(/*CONSTCOND*/0)
26 
27 #ifdef __FreeBSD__
28 #define SKIPXI(ev, msg, ...)	do {			\
29 	atf_tc_skip(msg, __VA_ARGS__);			\
30 	return ev;					\
31 } while(/*CONSTCOND*/0)
32 #endif
33 
34 #else
35 #define ERRX(ev, msg, ...)	errx(EXIT_FAILURE, msg, __VA_ARGS__)
36 #define SKIPX(ev, msg, ...)	errx(EXIT_FAILURE, msg, __VA_ARGS__)
37 #endif
38 
39 #ifdef DEBUG
40 #define DPRINTF(...)	printf(__VA_ARGS__)
41 #else
42 #define DPRINTF(...)
43 #endif
44 
45 
46 #define RPCBPROC_NULL 0
47 
48 static int
49 reply(caddr_t replyp, struct netbuf * raddrp, struct netconfig * nconf)
50 {
51 	char host[NI_MAXHOST];
52 	struct sockaddr *sock = raddrp->buf;
53 	int error;
54 
55 
56 	error = getnameinfo(sock, sock->sa_len, host, sizeof(host), NULL, 0, 0);
57 	if (error)
58 		warnx("Cannot resolve address (%s)", gai_strerror(error));
59 	else
60 		printf("response from: %s\n", host);
61 	return 0;
62 }
63 
64 #ifdef __FreeBSD__
65 #define	__rpc_control	rpc_control
66 #endif
67 
68 extern bool_t __rpc_control(int, void *);
69 
70 static void
71 onehost(const char *host, const char *transp)
72 {
73 	CLIENT         *clnt;
74 	struct netbuf   addr;
75 	struct timeval  tv;
76 
77 	/*
78 	 * Magic!
79 	 */
80 	tv.tv_sec = 0;
81 	tv.tv_usec = 500000;
82 #define CLCR_SET_RPCB_TIMEOUT   2
83 	__rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv);
84 
85 	if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL)
86 		SKIPX(, "clnt_create (%s)", clnt_spcreateerror(""));
87 
88 	tv.tv_sec = 1;
89 	tv.tv_usec = 0;
90 #ifdef __FreeBSD__
91 	if (clnt_call(clnt, RPCBPROC_NULL, (xdrproc_t)xdr_void, NULL,
92 	    (xdrproc_t)xdr_void, NULL, tv)
93 	    != RPC_SUCCESS)
94 #else
95 	if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv)
96 	    != RPC_SUCCESS)
97 #endif
98 		ERRX(, "clnt_call (%s)", clnt_sperror(clnt, ""));
99 	clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr);
100 	reply(NULL, &addr, NULL);
101 }
102 
103 #define PROGNUM 0x81
104 #define VERSNUM 0x01
105 #define PLUSONE 1
106 #define DESTROY 2
107 
108 static struct timeval 	tout = {1, 0};
109 
110 static void
111 server(struct svc_req *rqstp, SVCXPRT *transp)
112 {
113 	int num;
114 
115 	DPRINTF("Starting server\n");
116 
117 	switch (rqstp->rq_proc) {
118 	case NULLPROC:
119 		if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL))
120 			ERRX(, "svc_sendreply failed %d", 0);
121 		return;
122 	case PLUSONE:
123 		break;
124 	case DESTROY:
125 		if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL))
126 			ERRX(, "svc_sendreply failed %d", 0);
127 		svc_destroy(transp);
128 		exit(0);
129 	default:
130 		svcerr_noproc(transp);
131 		return;
132 	}
133 
134 	if (!svc_getargs(transp, (xdrproc_t)xdr_int, (void *)&num)) {
135 		svcerr_decode(transp);
136 		return;
137 	}
138 	DPRINTF("About to increment\n");
139 	num++;
140 	if (!svc_sendreply(transp, (xdrproc_t)xdr_int, (void *)&num))
141 		ERRX(, "svc_sendreply failed %d", 1);
142 	DPRINTF("Leaving server procedure.\n");
143 }
144 
145 static int
146 rawtest(const char *arg)
147 {
148 	CLIENT         *clnt;
149 	SVCXPRT        *svc;
150 	int 		num, resp;
151 	enum clnt_stat  rv;
152 
153 	if (arg)
154 		num = atoi(arg);
155 	else
156 		num = 0;
157 
158 	svc = svc_raw_create();
159 	if (svc == NULL)
160 		ERRX(EXIT_FAILURE, "Cannot create server %d", num);
161 	if (!svc_reg(svc, PROGNUM, VERSNUM, server, NULL))
162 		ERRX(EXIT_FAILURE, "Cannot register server %d", num);
163 
164 	clnt = clnt_raw_create(PROGNUM, VERSNUM);
165 	if (clnt == NULL)
166 		ERRX(EXIT_FAILURE, "%s",
167 		    clnt_spcreateerror("clnt_raw_create"));
168 	rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num,
169 	    (xdrproc_t)xdr_int, (void *)&resp, tout);
170 	if (rv != RPC_SUCCESS)
171 		ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv));
172 	DPRINTF("Got %d\n", resp);
173 	clnt_destroy(clnt);
174 	svc_destroy(svc);
175 	if (++num != resp)
176 		ERRX(EXIT_FAILURE, "expected %d got %d", num, resp);
177 
178 	return EXIT_SUCCESS;
179 }
180 
181 static int
182 regtest(const char *hostname, const char *transp, const char *arg, int p)
183 {
184 	CLIENT         *clnt;
185 	int 		num, resp;
186 	enum clnt_stat  rv;
187 	pid_t		pid;
188 
189 	if (arg)
190 		num = atoi(arg);
191 	else
192 		num = 0;
193 
194 #ifdef __NetBSD__
195 	svc_fdset_init(p ? SVC_FDSET_POLL : 0);
196 #endif
197 	if (!svc_create(server, PROGNUM, VERSNUM, transp))
198 	{
199 		SKIPXI(EXIT_FAILURE, "Cannot create server %d", num);
200 	}
201 
202 	switch ((pid = fork())) {
203 	case 0:
204 		DPRINTF("Calling svc_run\n");
205 		svc_run();
206 		ERRX(EXIT_FAILURE, "svc_run returned %d!", num);
207 	case -1:
208 		ERRX(EXIT_FAILURE, "Fork failed (%s)", strerror(errno));
209 	default:
210 		sleep(1);
211 		break;
212 	}
213 
214 	DPRINTF("Initializing client\n");
215 	clnt = clnt_create(hostname, PROGNUM, VERSNUM, transp);
216 	if (clnt == NULL)
217 		ERRX(EXIT_FAILURE, "%s",
218 		    clnt_spcreateerror("clnt_raw_create"));
219 	rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num,
220 	    (xdrproc_t)xdr_int, (void *)&resp, tout);
221 	if (rv != RPC_SUCCESS)
222 		ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv));
223 	DPRINTF("Got %d\n", resp);
224 	if (++num != resp)
225 		ERRX(EXIT_FAILURE, "expected %d got %d", num, resp);
226 	rv = clnt_call(clnt, DESTROY, (xdrproc_t)xdr_void, NULL,
227 	    (xdrproc_t)xdr_void, NULL, tout);
228 	if (rv != RPC_SUCCESS)
229 		ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv));
230 	clnt_destroy(clnt);
231 
232 	return EXIT_SUCCESS;
233 }
234 
235 
236 #ifdef TEST
237 static void
238 allhosts(const char *transp)
239 {
240 	enum clnt_stat  clnt_stat;
241 
242 	clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL,
243 	    (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void,
244 	    NULL, (resultproc_t)reply, transp);
245 	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
246 		ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat));
247 }
248 
249 int
250 main(int argc, char *argv[])
251 {
252 	int             ch;
253 	int		s, p;
254 	const char     *transp = "udp";
255 
256 	p = s = 0;
257 	while ((ch = getopt(argc, argv, "prstu")) != -1)
258 		switch (ch) {
259 		case 'p':
260 			p = 1;
261 			break;
262 		case 's':
263 			s = 1;
264 			break;
265 		case 't':
266 			transp = "tcp";
267 			break;
268 		case 'u':
269 			transp = "udp";
270 			break;
271 		case 'r':
272 			transp = NULL;
273 			break;
274 		default:
275 			fprintf(stderr,
276 			    "Usage: %s -[r|s|t|u] [<hostname>...]\n",
277 			    getprogname());
278 			return EXIT_FAILURE;
279 		}
280 
281 	if (argc == optind) {
282 		if  (transp)
283 			allhosts(transp);
284 		else
285 			rawtest(NULL);
286 	} else {
287 		for (; optind < argc; optind++) {
288 			if (transp)
289 				s == 0 ?
290 				    onehost(argv[optind], transp) :
291 				    regtest(argv[optind], transp, "1", p);
292 			else
293 				rawtest(argv[optind]);
294 		}
295 	}
296 
297 	return EXIT_SUCCESS;
298 }
299 
300 #else
301 
302 ATF_TC(get_svc_addr_tcp);
303 ATF_TC_HEAD(get_svc_addr_tcp, tc)
304 {
305 	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp");
306 
307 }
308 
309 ATF_TC_BODY(get_svc_addr_tcp, tc)
310 {
311 	onehost("localhost", "tcp");
312 
313 }
314 
315 ATF_TC(get_svc_addr_udp);
316 ATF_TC_HEAD(get_svc_addr_udp, tc)
317 {
318 	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp");
319 }
320 
321 ATF_TC_BODY(get_svc_addr_udp, tc)
322 {
323 	onehost("localhost", "udp");
324 
325 }
326 
327 ATF_TC(raw);
328 ATF_TC_HEAD(raw, tc)
329 {
330 	atf_tc_set_md_var(tc, "descr", "Checks svc raw");
331 }
332 
333 ATF_TC_BODY(raw, tc)
334 {
335 #ifdef __FreeBSD__
336 	atf_tc_expect_fail("fails with: clnt_call: "
337 	    "RPC: Can't decode result -- PR # 211804");
338 #endif
339 	rawtest(NULL);
340 
341 }
342 
343 ATF_TC(tcp);
344 ATF_TC_HEAD(tcp, tc)
345 {
346 	atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)");
347 #ifdef __FreeBSD__
348 	atf_tc_set_md_var(tc, "require.user", "root");
349 #endif
350 }
351 
352 ATF_TC_BODY(tcp, tc)
353 {
354 	regtest("localhost", "tcp", "1", 0);
355 
356 }
357 
358 ATF_TC(udp);
359 ATF_TC_HEAD(udp, tc)
360 {
361 	atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)");
362 #ifdef __FreeBSD__
363 	atf_tc_set_md_var(tc, "require.user", "root");
364 #endif
365 }
366 
367 ATF_TC_BODY(udp, tc)
368 {
369 	regtest("localhost", "udp", "1", 0);
370 
371 }
372 
373 ATF_TC(tcp_poll);
374 ATF_TC_HEAD(tcp_poll, tc)
375 {
376 	atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)");
377 #ifdef __FreeBSD__
378 	atf_tc_set_md_var(tc, "require.user", "root");
379 #endif
380 }
381 
382 ATF_TC_BODY(tcp_poll, tc)
383 {
384 	regtest("localhost", "tcp", "1", 1);
385 
386 }
387 
388 ATF_TC(udp_poll);
389 ATF_TC_HEAD(udp_poll, tc)
390 {
391 	atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)");
392 #ifdef __FreeBSD__
393 	atf_tc_set_md_var(tc, "require.user", "root");
394 #endif
395 }
396 
397 ATF_TC_BODY(udp_poll, tc)
398 {
399 	regtest("localhost", "udp", "1", 1);
400 
401 }
402 
403 ATF_TP_ADD_TCS(tp)
404 {
405 	ATF_TP_ADD_TC(tp, get_svc_addr_udp);
406 	ATF_TP_ADD_TC(tp, get_svc_addr_tcp);
407 	ATF_TP_ADD_TC(tp, raw);
408 	ATF_TP_ADD_TC(tp, tcp);
409 	ATF_TP_ADD_TC(tp, udp);
410 	ATF_TP_ADD_TC(tp, tcp_poll);
411 	ATF_TP_ADD_TC(tp, udp_poll);
412 
413 	return atf_no_error();
414 }
415 
416 #endif
417