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