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