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