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