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