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