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