xref: /freebsd/contrib/netbsd-tests/lib/libc/rpc/t_rpc.c (revision 1fb62fb074788ca4713551be09d6569966a3abee)
1 /*	$NetBSD: t_rpc.c,v 1.9 2015/11/27 13:59:40 christos Exp $	*/
2 
3 #include <sys/cdefs.h>
4 __RCSID("$NetBSD: t_rpc.c,v 1.9 2015/11/27 13:59:40 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;						\
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(ev, msg, __VA_ARGS__)
36 #define SKIPX(ev, msg, ...)	errx(ev, 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(EXIT_FAILURE, "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(EXIT_FAILURE, "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(EXIT_FAILURE, "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(EXIT_FAILURE, "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(EXIT_FAILURE, "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 #ifdef __NetBSD__
199 		ERRX(EXIT_FAILURE, "Cannot create server %d", num);
200 #else
201 	{
202 		SKIPXI(EXIT_FAILURE, "Cannot create server %d", num);
203 	}
204 #endif
205 
206 	switch ((pid = fork())) {
207 	case 0:
208 		DPRINTF("Calling svc_run\n");
209 		svc_run();
210 		ERRX(EXIT_FAILURE, "svc_run returned %d!", num);
211 	case -1:
212 		ERRX(EXIT_FAILURE, "Fork failed (%s)", strerror(errno));
213 	default:
214 		sleep(1);
215 		break;
216 	}
217 
218 	DPRINTF("Initializing client\n");
219 	clnt = clnt_create(hostname, PROGNUM, VERSNUM, transp);
220 	if (clnt == NULL)
221 		ERRX(EXIT_FAILURE, "%s",
222 		    clnt_spcreateerror("clnt_raw_create"));
223 	rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num,
224 	    (xdrproc_t)xdr_int, (void *)&resp, tout);
225 	if (rv != RPC_SUCCESS)
226 		ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv));
227 	DPRINTF("Got %d\n", resp);
228 	if (++num != resp)
229 		ERRX(EXIT_FAILURE, "expected %d got %d", num, resp);
230 	rv = clnt_call(clnt, DESTROY, (xdrproc_t)xdr_void, NULL,
231 	    (xdrproc_t)xdr_void, NULL, tout);
232 	if (rv != RPC_SUCCESS)
233 		ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv));
234 	clnt_destroy(clnt);
235 
236 	return EXIT_SUCCESS;
237 }
238 
239 
240 #ifdef TEST
241 static void
242 allhosts(const char *transp)
243 {
244 	enum clnt_stat  clnt_stat;
245 
246 	clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL,
247 	    (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void,
248 	    NULL, (resultproc_t)reply, transp);
249 	if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
250 		ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat));
251 }
252 
253 int
254 main(int argc, char *argv[])
255 {
256 	int             ch;
257 	int		s, p;
258 	const char     *transp = "udp";
259 
260 	p = s = 0;
261 	while ((ch = getopt(argc, argv, "prstu")) != -1)
262 		switch (ch) {
263 		case 'p':
264 			p = 1;
265 			break;
266 		case 's':
267 			s = 1;
268 			break;
269 		case 't':
270 			transp = "tcp";
271 			break;
272 		case 'u':
273 			transp = "udp";
274 			break;
275 		case 'r':
276 			transp = NULL;
277 			break;
278 		default:
279 			fprintf(stderr,
280 			    "Usage: %s -[r|s|t|u] [<hostname>...]\n",
281 			    getprogname());
282 			return EXIT_FAILURE;
283 		}
284 
285 	if (argc == optind) {
286 		if  (transp)
287 			allhosts(transp);
288 		else
289 			rawtest(NULL);
290 	} else {
291 		for (; optind < argc; optind++) {
292 			if (transp)
293 				s == 0 ?
294 				    onehost(argv[optind], transp) :
295 				    regtest(argv[optind], transp, "1", p);
296 			else
297 				rawtest(argv[optind]);
298 		}
299 	}
300 
301 	return EXIT_SUCCESS;
302 }
303 
304 #else
305 
306 ATF_TC(get_svc_addr_tcp);
307 ATF_TC_HEAD(get_svc_addr_tcp, tc)
308 {
309 	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp");
310 
311 }
312 
313 ATF_TC_BODY(get_svc_addr_tcp, tc)
314 {
315 	onehost("localhost", "tcp");
316 
317 }
318 
319 ATF_TC(get_svc_addr_udp);
320 ATF_TC_HEAD(get_svc_addr_udp, tc)
321 {
322 	atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp");
323 }
324 
325 ATF_TC_BODY(get_svc_addr_udp, tc)
326 {
327 	onehost("localhost", "udp");
328 
329 }
330 
331 ATF_TC(raw);
332 ATF_TC_HEAD(raw, tc)
333 {
334 	atf_tc_set_md_var(tc, "descr", "Checks svc raw");
335 }
336 
337 ATF_TC_BODY(raw, tc)
338 {
339 #ifdef __FreeBSD__
340 	atf_tc_expect_fail("fails with: clnt_call: "
341 	    "RPC: Can't decode result -- PR # 211804");
342 #endif
343 	rawtest(NULL);
344 
345 }
346 
347 ATF_TC(tcp);
348 ATF_TC_HEAD(tcp, tc)
349 {
350 	atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)");
351 #ifdef __FreeBSD__
352 	atf_tc_set_md_var(tc, "require.user", "root");
353 #endif
354 }
355 
356 ATF_TC_BODY(tcp, tc)
357 {
358 	regtest("localhost", "tcp", "1", 0);
359 
360 }
361 
362 ATF_TC(udp);
363 ATF_TC_HEAD(udp, tc)
364 {
365 	atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)");
366 #ifdef __FreeBSD__
367 	atf_tc_set_md_var(tc, "require.user", "root");
368 #endif
369 }
370 
371 ATF_TC_BODY(udp, tc)
372 {
373 	regtest("localhost", "udp", "1", 0);
374 
375 }
376 
377 ATF_TC(tcp_poll);
378 ATF_TC_HEAD(tcp_poll, tc)
379 {
380 	atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)");
381 #ifdef __FreeBSD__
382 	atf_tc_set_md_var(tc, "require.user", "root");
383 #endif
384 }
385 
386 ATF_TC_BODY(tcp_poll, tc)
387 {
388 	regtest("localhost", "tcp", "1", 1);
389 
390 }
391 
392 ATF_TC(udp_poll);
393 ATF_TC_HEAD(udp_poll, tc)
394 {
395 	atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)");
396 #ifdef __FreeBSD__
397 	atf_tc_set_md_var(tc, "require.user", "root");
398 #endif
399 }
400 
401 ATF_TC_BODY(udp_poll, tc)
402 {
403 	regtest("localhost", "udp", "1", 1);
404 
405 }
406 
407 ATF_TP_ADD_TCS(tp)
408 {
409 	ATF_TP_ADD_TC(tp, get_svc_addr_udp);
410 	ATF_TP_ADD_TC(tp, get_svc_addr_tcp);
411 	ATF_TP_ADD_TC(tp, raw);
412 	ATF_TP_ADD_TC(tp, tcp);
413 	ATF_TP_ADD_TC(tp, udp);
414 	ATF_TP_ADD_TC(tp, tcp_poll);
415 	ATF_TP_ADD_TC(tp, udp_poll);
416 
417 	return atf_no_error();
418 }
419 
420 #endif
421