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