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