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 #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(EXIT_FAILURE, msg, __VA_ARGS__) 36 #define SKIPX(ev, msg, ...) errx(EXIT_FAILURE, 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 static int 49 reply(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 68 extern bool_t __rpc_control(int, void *); 69 70 static void 71 onehost(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(, "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(, "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 108 static struct timeval tout = {1, 0}; 109 110 static void 111 server(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(, "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(, "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(, "svc_sendreply failed %d", 1); 142 DPRINTF("Leaving server procedure.\n"); 143 } 144 145 static int 146 rawtest(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 181 static int 182 regtest(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 { 199 SKIPXI(EXIT_FAILURE, "Cannot create server %d", num); 200 } 201 202 switch ((pid = fork())) { 203 case 0: 204 DPRINTF("Calling svc_run\n"); 205 svc_run(); 206 ERRX(EXIT_FAILURE, "svc_run returned %d!", num); 207 case -1: 208 ERRX(EXIT_FAILURE, "Fork failed (%s)", strerror(errno)); 209 default: 210 sleep(1); 211 break; 212 } 213 214 DPRINTF("Initializing client\n"); 215 clnt = clnt_create(hostname, PROGNUM, VERSNUM, transp); 216 if (clnt == NULL) 217 ERRX(EXIT_FAILURE, "%s", 218 clnt_spcreateerror("clnt_raw_create")); 219 rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num, 220 (xdrproc_t)xdr_int, (void *)&resp, tout); 221 if (rv != RPC_SUCCESS) 222 ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 223 DPRINTF("Got %d\n", resp); 224 if (++num != resp) 225 ERRX(EXIT_FAILURE, "expected %d got %d", num, resp); 226 rv = clnt_call(clnt, DESTROY, (xdrproc_t)xdr_void, NULL, 227 (xdrproc_t)xdr_void, NULL, tout); 228 if (rv != RPC_SUCCESS) 229 ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 230 clnt_destroy(clnt); 231 232 return EXIT_SUCCESS; 233 } 234 235 236 #ifdef TEST 237 static void 238 allhosts(const char *transp) 239 { 240 enum clnt_stat clnt_stat; 241 242 clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL, 243 (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, 244 NULL, (resultproc_t)reply, transp); 245 if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 246 ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat)); 247 } 248 249 int 250 main(int argc, char *argv[]) 251 { 252 int ch; 253 int s, p; 254 const char *transp = "udp"; 255 256 p = s = 0; 257 while ((ch = getopt(argc, argv, "prstu")) != -1) 258 switch (ch) { 259 case 'p': 260 p = 1; 261 break; 262 case 's': 263 s = 1; 264 break; 265 case 't': 266 transp = "tcp"; 267 break; 268 case 'u': 269 transp = "udp"; 270 break; 271 case 'r': 272 transp = NULL; 273 break; 274 default: 275 fprintf(stderr, 276 "Usage: %s -[r|s|t|u] [<hostname>...]\n", 277 getprogname()); 278 return EXIT_FAILURE; 279 } 280 281 if (argc == optind) { 282 if (transp) 283 allhosts(transp); 284 else 285 rawtest(NULL); 286 } else { 287 for (; optind < argc; optind++) { 288 if (transp) 289 s == 0 ? 290 onehost(argv[optind], transp) : 291 regtest(argv[optind], transp, "1", p); 292 else 293 rawtest(argv[optind]); 294 } 295 } 296 297 return EXIT_SUCCESS; 298 } 299 300 #else 301 302 ATF_TC(get_svc_addr_tcp); 303 ATF_TC_HEAD(get_svc_addr_tcp, tc) 304 { 305 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp"); 306 307 } 308 309 ATF_TC_BODY(get_svc_addr_tcp, tc) 310 { 311 onehost("localhost", "tcp"); 312 313 } 314 315 ATF_TC(get_svc_addr_udp); 316 ATF_TC_HEAD(get_svc_addr_udp, tc) 317 { 318 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 319 } 320 321 ATF_TC_BODY(get_svc_addr_udp, tc) 322 { 323 onehost("localhost", "udp"); 324 325 } 326 327 ATF_TC(raw); 328 ATF_TC_HEAD(raw, tc) 329 { 330 atf_tc_set_md_var(tc, "descr", "Checks svc raw"); 331 } 332 333 ATF_TC_BODY(raw, tc) 334 { 335 #ifdef __FreeBSD__ 336 atf_tc_expect_fail("fails with: clnt_call: " 337 "RPC: Can't decode result -- PR # 211804"); 338 #endif 339 rawtest(NULL); 340 341 } 342 343 ATF_TC(tcp); 344 ATF_TC_HEAD(tcp, tc) 345 { 346 atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)"); 347 #ifdef __FreeBSD__ 348 atf_tc_set_md_var(tc, "require.user", "root"); 349 #endif 350 } 351 352 ATF_TC_BODY(tcp, tc) 353 { 354 regtest("localhost", "tcp", "1", 0); 355 356 } 357 358 ATF_TC(udp); 359 ATF_TC_HEAD(udp, tc) 360 { 361 atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)"); 362 #ifdef __FreeBSD__ 363 atf_tc_set_md_var(tc, "require.user", "root"); 364 #endif 365 } 366 367 ATF_TC_BODY(udp, tc) 368 { 369 regtest("localhost", "udp", "1", 0); 370 371 } 372 373 ATF_TC(tcp_poll); 374 ATF_TC_HEAD(tcp_poll, tc) 375 { 376 atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)"); 377 #ifdef __FreeBSD__ 378 atf_tc_set_md_var(tc, "require.user", "root"); 379 #endif 380 } 381 382 ATF_TC_BODY(tcp_poll, tc) 383 { 384 regtest("localhost", "tcp", "1", 1); 385 386 } 387 388 ATF_TC(udp_poll); 389 ATF_TC_HEAD(udp_poll, tc) 390 { 391 atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)"); 392 #ifdef __FreeBSD__ 393 atf_tc_set_md_var(tc, "require.user", "root"); 394 #endif 395 } 396 397 ATF_TC_BODY(udp_poll, tc) 398 { 399 regtest("localhost", "udp", "1", 1); 400 401 } 402 403 ATF_TP_ADD_TCS(tp) 404 { 405 ATF_TP_ADD_TC(tp, get_svc_addr_udp); 406 ATF_TP_ADD_TC(tp, get_svc_addr_tcp); 407 ATF_TP_ADD_TC(tp, raw); 408 ATF_TP_ADD_TC(tp, tcp); 409 ATF_TP_ADD_TC(tp, udp); 410 ATF_TP_ADD_TC(tp, tcp_poll); 411 ATF_TP_ADD_TC(tp, udp_poll); 412 413 return atf_no_error(); 414 } 415 416 #endif 417