t_rpc.c revision 318327
1193267Sjkim/* $NetBSD: t_rpc.c,v 1.10 2016/08/27 14:36:22 christos Exp $ */ 2193267Sjkim 3193267Sjkim#include <sys/cdefs.h> 4193267Sjkim__RCSID("$NetBSD: t_rpc.c,v 1.10 2016/08/27 14:36:22 christos Exp $"); 5193267Sjkim 6193267Sjkim#include <sys/types.h> 7316303Sjkim#include <sys/socket.h> 8316303Sjkim#include <rpc/rpc.h> 9316303Sjkim#include <stdlib.h> 10316303Sjkim#include <string.h> 11316303Sjkim#include <err.h> 12193267Sjkim#include <netdb.h> 13193267Sjkim#include <stdio.h> 14316303Sjkim#include <errno.h> 15316303Sjkim#include <unistd.h> 16316303Sjkim 17316303Sjkim#ifndef TEST 18316303Sjkim#include <atf-c.h> 19316303Sjkim 20316303Sjkim#define ERRX(ev, msg, ...) ATF_REQUIRE_MSG(0, msg, __VA_ARGS__) 21316303Sjkim 22316303Sjkim#define SKIPX(ev, msg, ...) do { \ 23316303Sjkim atf_tc_skip(msg, __VA_ARGS__); \ 24316303Sjkim return ev; \ 25316303Sjkim} while(/*CONSTCOND*/0) 26316303Sjkim 27316303Sjkim#else 28316303Sjkim#define ERRX(ev, msg, ...) errx(EXIT_FAILURE, msg, __VA_ARGS__) 29316303Sjkim#define SKIPX(ev, msg, ...) errx(EXIT_FAILURE, msg, __VA_ARGS__) 30316303Sjkim#endif 31316303Sjkim 32316303Sjkim#ifdef DEBUG 33316303Sjkim#define DPRINTF(...) printf(__VA_ARGS__) 34316303Sjkim#else 35316303Sjkim#define DPRINTF(...) 36316303Sjkim#endif 37316303Sjkim 38316303Sjkim 39316303Sjkim#define RPCBPROC_NULL 0 40316303Sjkim 41316303Sjkim/* XXX (ngie): for clarity on what needs to be reverted later. */ 42316303Sjkim#define __FreeBSD_bug_216954__ 43316303Sjkim#ifdef __FreeBSD_bug_216954__ 44316303Sjkim#include <signal.h> 45316303Sjkim#endif 46316303Sjkim 47316303Sjkimstatic int 48316303Sjkimreply(caddr_t replyp, struct netbuf * raddrp, struct netconfig * nconf) 49316303Sjkim{ 50316303Sjkim char host[NI_MAXHOST]; 51316303Sjkim struct sockaddr *sock = raddrp->buf; 52316303Sjkim int error; 53316303Sjkim 54316303Sjkim 55316303Sjkim error = getnameinfo(sock, sock->sa_len, host, sizeof(host), NULL, 0, 0); 56316303Sjkim if (error) 57316303Sjkim warnx("Cannot resolve address (%s)", gai_strerror(error)); 58316303Sjkim else 59316303Sjkim printf("response from: %s\n", host); 60316303Sjkim return 0; 61316303Sjkim} 62316303Sjkim 63316303Sjkim#ifdef __FreeBSD__ 64316303Sjkim#define __rpc_control rpc_control 65316303Sjkim#endif 66316303Sjkim 67316303Sjkimextern bool_t __rpc_control(int, void *); 68316303Sjkim 69316303Sjkimstatic void 70316303Sjkimonehost(const char *host, const char *transp) 71316303Sjkim{ 72316303Sjkim CLIENT *clnt; 73316303Sjkim struct netbuf addr; 74316303Sjkim struct timeval tv; 75316303Sjkim 76316303Sjkim /* 77316303Sjkim * Magic! 78316303Sjkim */ 79316303Sjkim tv.tv_sec = 0; 80316303Sjkim tv.tv_usec = 500000; 81316303Sjkim#define CLCR_SET_RPCB_TIMEOUT 2 82316303Sjkim __rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv); 83316303Sjkim 84316303Sjkim if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL) 85316303Sjkim SKIPX(, "clnt_create (%s)", clnt_spcreateerror("")); 86316303Sjkim 87316303Sjkim tv.tv_sec = 1; 88316303Sjkim tv.tv_usec = 0; 89316303Sjkim#ifdef __FreeBSD__ 90316303Sjkim if (clnt_call(clnt, RPCBPROC_NULL, (xdrproc_t)xdr_void, NULL, 91316303Sjkim (xdrproc_t)xdr_void, NULL, tv) 92316303Sjkim != RPC_SUCCESS) 93316303Sjkim#else 94316303Sjkim if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv) 95316303Sjkim != RPC_SUCCESS) 96316303Sjkim#endif 97316303Sjkim ERRX(, "clnt_call (%s)", clnt_sperror(clnt, "")); 98316303Sjkim clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr); 99316303Sjkim reply(NULL, &addr, NULL); 100316303Sjkim} 101316303Sjkim 102316303Sjkim#define PROGNUM 0x81 103316303Sjkim#define VERSNUM 0x01 104316303Sjkim#define PLUSONE 1 105316303Sjkim#define DESTROY 2 106316303Sjkim 107316303Sjkimstatic struct timeval tout = {1, 0}; 108316303Sjkim 109316303Sjkimstatic void 110316303Sjkimserver(struct svc_req *rqstp, SVCXPRT *transp) 111316303Sjkim{ 112316303Sjkim int num; 113316303Sjkim 114316303Sjkim DPRINTF("Starting server\n"); 115316303Sjkim 116316303Sjkim switch (rqstp->rq_proc) { 117316303Sjkim case NULLPROC: 118316303Sjkim if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 119217365Sjkim ERRX(, "svc_sendreply failed %d", 0); 120217365Sjkim return; 121217365Sjkim case PLUSONE: 122217365Sjkim break; 123217365Sjkim case DESTROY: 124217365Sjkim if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 125217365Sjkim ERRX(, "svc_sendreply failed %d", 0); 126217365Sjkim svc_destroy(transp); 127217365Sjkim exit(0); 128217365Sjkim default: 129217365Sjkim svcerr_noproc(transp); 130217365Sjkim return; 131217365Sjkim } 132217365Sjkim 133193267Sjkim if (!svc_getargs(transp, (xdrproc_t)xdr_int, (void *)&num)) { 134316303Sjkim svcerr_decode(transp); 135316303Sjkim return; 136316303Sjkim } 137316303Sjkim DPRINTF("About to increment\n"); 138316303Sjkim num++; 139316303Sjkim if (!svc_sendreply(transp, (xdrproc_t)xdr_int, (void *)&num)) 140316303Sjkim ERRX(, "svc_sendreply failed %d", 1); 141316303Sjkim DPRINTF("Leaving server procedure.\n"); 142316303Sjkim} 143316303Sjkim 144316303Sjkimstatic int 145316303Sjkimrawtest(const char *arg) 146316303Sjkim{ 147217365Sjkim CLIENT *clnt; 148217365Sjkim SVCXPRT *svc; 149193267Sjkim int num, resp; 150316303Sjkim enum clnt_stat rv; 151193267Sjkim 152193267Sjkim if (arg) 153193267Sjkim num = atoi(arg); 154193267Sjkim else 155193267Sjkim num = 0; 156193267Sjkim 157193267Sjkim svc = svc_raw_create(); 158193267Sjkim if (svc == NULL) 159193267Sjkim ERRX(EXIT_FAILURE, "Cannot create server %d", num); 160272444Sjkim if (!svc_reg(svc, PROGNUM, VERSNUM, server, NULL)) 161193267Sjkim ERRX(EXIT_FAILURE, "Cannot register server %d", num); 162193267Sjkim 163193267Sjkim clnt = clnt_raw_create(PROGNUM, VERSNUM); 164193267Sjkim if (clnt == NULL) 165193267Sjkim ERRX(EXIT_FAILURE, "%s", 166193267Sjkim clnt_spcreateerror("clnt_raw_create")); 167193267Sjkim rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num, 168249112Sjkim (xdrproc_t)xdr_int, (void *)&resp, tout); 169193267Sjkim if (rv != RPC_SUCCESS) 170193267Sjkim ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 171193267Sjkim DPRINTF("Got %d\n", resp); 172193267Sjkim clnt_destroy(clnt); 173193267Sjkim svc_destroy(svc); 174193267Sjkim if (++num != resp) 175272444Sjkim ERRX(EXIT_FAILURE, "expected %d got %d", num, resp); 176272444Sjkim 177193267Sjkim return EXIT_SUCCESS; 178249112Sjkim} 179249112Sjkim 180193267Sjkimstatic int 181193267Sjkimregtest(const char *hostname, const char *transp, const char *arg, int p) 182193267Sjkim{ 183193267Sjkim CLIENT *clnt; 184193267Sjkim int num, resp; 185193267Sjkim enum clnt_stat rv; 186249112Sjkim pid_t pid; 187249112Sjkim 188193267Sjkim if (arg) 189193267Sjkim num = atoi(arg); 190193267Sjkim else 191193267Sjkim num = 0; 192193267Sjkim 193193267Sjkim#ifdef __NetBSD__ 194193267Sjkim svc_fdset_init(p ? SVC_FDSET_POLL : 0); 195193267Sjkim#endif 196193267Sjkim if (!svc_create(server, PROGNUM, VERSNUM, transp)) 197193267Sjkim { 198249112Sjkim SKIPX(EXIT_FAILURE, "Cannot create server %d", num); 199249112Sjkim } 200193267Sjkim 201193267Sjkim switch ((pid = fork())) { 202249112Sjkim case 0: 203249112Sjkim DPRINTF("Calling svc_run\n"); 204193267Sjkim svc_run(); 205193267Sjkim ERRX(EXIT_FAILURE, "svc_run returned %d!", num); 206197104Sjkim case -1: 207197104Sjkim ERRX(EXIT_FAILURE, "Fork failed (%s)", strerror(errno)); 208197104Sjkim default: 209228110Sjkim sleep(1); 210249112Sjkim break; 211228110Sjkim } 212228110Sjkim 213228110Sjkim DPRINTF("Initializing client\n"); 214228110Sjkim clnt = clnt_create(hostname, PROGNUM, VERSNUM, transp); 215228110Sjkim if (clnt == NULL) 216228110Sjkim ERRX(EXIT_FAILURE, "%s", 217283092Sjkim clnt_spcreateerror("clnt_raw_create")); 218283092Sjkim rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num, 219283092Sjkim (xdrproc_t)xdr_int, (void *)&resp, tout); 220283092Sjkim if (rv != RPC_SUCCESS) 221283092Sjkim ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 222272444Sjkim DPRINTF("Got %d\n", resp); 223272444Sjkim if (++num != resp) 224272444Sjkim ERRX(EXIT_FAILURE, "expected %d got %d", num, resp); 225272444Sjkim rv = clnt_call(clnt, DESTROY, (xdrproc_t)xdr_void, NULL, 226272444Sjkim (xdrproc_t)xdr_void, NULL, tout); 227193267Sjkim if (rv != RPC_SUCCESS) 228193267Sjkim ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 229193267Sjkim clnt_destroy(clnt); 230193267Sjkim 231193267Sjkim return EXIT_SUCCESS; 232193267Sjkim} 233193267Sjkim 234193267Sjkim 235193267Sjkim#ifdef TEST 236193267Sjkimstatic void 237193267Sjkimallhosts(const char *transp) 238197104Sjkim{ 239228110Sjkim enum clnt_stat clnt_stat; 240272444Sjkim 241283092Sjkim clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL, 242298714Sjkim (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, 243298714Sjkim NULL, (resultproc_t)reply, transp); 244193267Sjkim if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 245193267Sjkim ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat)); 246193267Sjkim} 247249112Sjkim 248249112Sjkimint 249249112Sjkimmain(int argc, char *argv[]) 250249112Sjkim{ 251249112Sjkim int ch; 252249112Sjkim int s, p; 253249112Sjkim const char *transp = "udp"; 254249112Sjkim 255249663Sjkim p = s = 0; 256249663Sjkim while ((ch = getopt(argc, argv, "prstu")) != -1) 257249112Sjkim switch (ch) { 258249112Sjkim case 'p': 259249112Sjkim p = 1; 260249112Sjkim break; 261249112Sjkim case 's': 262249112Sjkim s = 1; 263249112Sjkim break; 264249112Sjkim case 't': 265249112Sjkim transp = "tcp"; 266249112Sjkim break; 267249112Sjkim case 'u': 268249112Sjkim transp = "udp"; 269249112Sjkim break; 270249112Sjkim case 'r': 271249112Sjkim transp = NULL; 272249112Sjkim break; 273249112Sjkim default: 274249112Sjkim fprintf(stderr, 275249112Sjkim "Usage: %s -[r|s|t|u] [<hostname>...]\n", 276249112Sjkim getprogname()); 277249112Sjkim return EXIT_FAILURE; 278249112Sjkim } 279249112Sjkim 280249112Sjkim if (argc == optind) { 281249112Sjkim if (transp) 282249112Sjkim allhosts(transp); 283249112Sjkim else 284249112Sjkim rawtest(NULL); 285249112Sjkim } else { 286249112Sjkim for (; optind < argc; optind++) { 287197104Sjkim if (transp) 288249112Sjkim s == 0 ? 289249112Sjkim onehost(argv[optind], transp) : 290193267Sjkim regtest(argv[optind], transp, "1", p); 291193267Sjkim else 292193267Sjkim rawtest(argv[optind]); 293193267Sjkim } 294193267Sjkim } 295283092Sjkim 296193267Sjkim return EXIT_SUCCESS; 297193267Sjkim} 298193267Sjkim 299197104Sjkim#else 300249112Sjkim 301193267SjkimATF_TC(get_svc_addr_tcp); 302193267SjkimATF_TC_HEAD(get_svc_addr_tcp, tc) 303193267Sjkim{ 304193267Sjkim atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp"); 305193267Sjkim 306193267Sjkim} 307193267Sjkim 308193267SjkimATF_TC_BODY(get_svc_addr_tcp, tc) 309193267Sjkim{ 310193267Sjkim onehost("localhost", "tcp"); 311249112Sjkim 312249112Sjkim} 313249112Sjkim 314249112SjkimATF_TC(get_svc_addr_udp); 315193267SjkimATF_TC_HEAD(get_svc_addr_udp, tc) 316193267Sjkim{ 317193267Sjkim atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 318193267Sjkim} 319193267Sjkim 320193267SjkimATF_TC_BODY(get_svc_addr_udp, tc) 321193267Sjkim{ 322193267Sjkim onehost("localhost", "udp"); 323193267Sjkim 324249112Sjkim} 325249112Sjkim 326249112SjkimATF_TC(raw); 327249112SjkimATF_TC_HEAD(raw, tc) 328249112Sjkim{ 329249112Sjkim atf_tc_set_md_var(tc, "descr", "Checks svc raw"); 330249112Sjkim} 331249112Sjkim 332249112SjkimATF_TC_BODY(raw, tc) 333249112Sjkim{ 334193267Sjkim#ifdef __FreeBSD__ 335249112Sjkim#ifdef __FreeBSD_bug_216954__ 336249112Sjkim atf_tc_expect_signal(SIGSEGV, 337193267Sjkim "fails with SIGSEGV only on ^/stable/10 -- bug # 216954"); 338249112Sjkim#endif 339249112Sjkim#endif 340193267Sjkim rawtest(NULL); 341249112Sjkim 342249112Sjkim} 343193267Sjkim 344249112SjkimATF_TC(tcp); 345249112SjkimATF_TC_HEAD(tcp, tc) 346193267Sjkim{ 347249112Sjkim atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)"); 348249112Sjkim#ifdef __FreeBSD__ 349193267Sjkim atf_tc_set_md_var(tc, "require.user", "root"); 350249112Sjkim#endif 351249112Sjkim} 352193267Sjkim 353249112SjkimATF_TC_BODY(tcp, tc) 354249112Sjkim{ 355193267Sjkim regtest("localhost", "tcp", "1", 0); 356249112Sjkim 357249112Sjkim} 358193267Sjkim 359249112SjkimATF_TC(udp); 360249112SjkimATF_TC_HEAD(udp, tc) 361193267Sjkim{ 362249112Sjkim atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)"); 363249112Sjkim#ifdef __FreeBSD__ 364193267Sjkim atf_tc_set_md_var(tc, "require.user", "root"); 365249112Sjkim#endif 366249112Sjkim} 367193267Sjkim 368249112SjkimATF_TC_BODY(udp, tc) 369249112Sjkim{ 370197104Sjkim regtest("localhost", "udp", "1", 0); 371249112Sjkim 372249112Sjkim} 373249112Sjkim 374193267SjkimATF_TC(tcp_poll); 375249112SjkimATF_TC_HEAD(tcp_poll, tc) 376249112Sjkim{ 377249112Sjkim atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)"); 378193267Sjkim#ifdef __FreeBSD__ 379249112Sjkim atf_tc_set_md_var(tc, "require.user", "root"); 380249112Sjkim#endif 381249112Sjkim} 382197104Sjkim 383249112SjkimATF_TC_BODY(tcp_poll, tc) 384249112Sjkim{ 385249112Sjkim regtest("localhost", "tcp", "1", 1); 386193267Sjkim 387249112Sjkim} 388249112Sjkim 389249112SjkimATF_TC(udp_poll); 390193267SjkimATF_TC_HEAD(udp_poll, tc) 391249112Sjkim{ 392249112Sjkim atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)"); 393249112Sjkim#ifdef __FreeBSD__ 394193267Sjkim atf_tc_set_md_var(tc, "require.user", "root"); 395249112Sjkim#endif 396249112Sjkim} 397249112Sjkim 398228110SjkimATF_TC_BODY(udp_poll, tc) 399249112Sjkim{ 400249112Sjkim regtest("localhost", "udp", "1", 1); 401249112Sjkim 402228110Sjkim} 403249112Sjkim 404249112SjkimATF_TP_ADD_TCS(tp) 405249112Sjkim{ 406193267Sjkim ATF_TP_ADD_TC(tp, get_svc_addr_udp); 407249112Sjkim ATF_TP_ADD_TC(tp, get_svc_addr_tcp); 408249112Sjkim ATF_TP_ADD_TC(tp, raw); 409249112Sjkim ATF_TP_ADD_TC(tp, tcp); 410193267Sjkim ATF_TP_ADD_TC(tp, udp); 411249112Sjkim ATF_TP_ADD_TC(tp, tcp_poll); 412249112Sjkim ATF_TP_ADD_TC(tp, udp_poll); 413228110Sjkim 414249112Sjkim return atf_no_error(); 415249112Sjkim} 416228110Sjkim 417249112Sjkim#endif 418249112Sjkim