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 41static int 42reply(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 61extern bool_t __rpc_control(int, void *); 62 63static void 64onehost(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 101static struct timeval tout = {1, 0}; 102 103static void 104server(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 138static int 139rawtest(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 174static int 175regtest(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 230static void 231allhosts(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 242int 243main(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 295ATF_TC(get_svc_addr_tcp); 296ATF_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 302ATF_TC_BODY(get_svc_addr_tcp, tc) 303{ 304 onehost("localhost", "tcp"); 305 306} 307 308ATF_TC(get_svc_addr_udp); 309ATF_TC_HEAD(get_svc_addr_udp, tc) 310{ 311 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 312} 313 314ATF_TC_BODY(get_svc_addr_udp, tc) 315{ 316 onehost("localhost", "udp"); 317 318} 319 320ATF_TC(raw); 321ATF_TC_HEAD(raw, tc) 322{ 323 atf_tc_set_md_var(tc, "descr", "Checks svc raw"); 324} 325 326ATF_TC_BODY(raw, tc) 327{ 328 rawtest(NULL); 329 330} 331 332ATF_TC(tcp); 333ATF_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 341ATF_TC_BODY(tcp, tc) 342{ 343 regtest("localhost", "tcp", "1", 0); 344 345} 346 347ATF_TC(udp); 348ATF_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 356ATF_TC_BODY(udp, tc) 357{ 358 regtest("localhost", "udp", "1", 0); 359 360} 361 362ATF_TC(tcp_poll); 363ATF_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 371ATF_TC_BODY(tcp_poll, tc) 372{ 373 regtest("localhost", "tcp", "1", 1); 374 375} 376 377ATF_TC(udp_poll); 378ATF_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 386ATF_TC_BODY(udp_poll, tc) 387{ 388 regtest("localhost", "udp", "1", 1); 389 390} 391 392ATF_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 406