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