1*640235e2SEnji Cooper /* $NetBSD: t_rpc.c,v 1.9 2015/11/27 13:59:40 christos Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper #include <sys/cdefs.h> 4*640235e2SEnji Cooper __RCSID("$NetBSD: t_rpc.c,v 1.9 2015/11/27 13:59:40 christos Exp $"); 557718be8SEnji Cooper 657718be8SEnji Cooper #include <sys/types.h> 757718be8SEnji Cooper #include <sys/socket.h> 857718be8SEnji Cooper #include <rpc/rpc.h> 957718be8SEnji Cooper #include <stdlib.h> 10*640235e2SEnji Cooper #include <string.h> 1157718be8SEnji Cooper #include <err.h> 1257718be8SEnji Cooper #include <netdb.h> 1357718be8SEnji Cooper #include <stdio.h> 14*640235e2SEnji Cooper #include <errno.h> 1557718be8SEnji Cooper #include <unistd.h> 1657718be8SEnji Cooper 1757718be8SEnji Cooper #ifndef TEST 1857718be8SEnji Cooper #include <atf-c.h> 1957718be8SEnji Cooper 2057718be8SEnji Cooper #define ERRX(ev, msg, ...) ATF_REQUIRE_MSG(0, msg, __VA_ARGS__) 2157718be8SEnji Cooper 2257718be8SEnji Cooper #define SKIPX(ev, msg, ...) do { \ 2357718be8SEnji Cooper atf_tc_skip(msg, __VA_ARGS__); \ 2457718be8SEnji Cooper return; \ 2557718be8SEnji Cooper } while(/*CONSTCOND*/0) 2657718be8SEnji Cooper 2757718be8SEnji Cooper #else 2857718be8SEnji Cooper #define ERRX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 2957718be8SEnji Cooper #define SKIPX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 3057718be8SEnji Cooper #endif 3157718be8SEnji Cooper 32*640235e2SEnji Cooper #ifdef DEBUG 33*640235e2SEnji Cooper #define DPRINTF(...) printf(__VA_ARGS__) 34*640235e2SEnji Cooper #else 35*640235e2SEnji Cooper #define DPRINTF(...) 36*640235e2SEnji Cooper #endif 37*640235e2SEnji Cooper 3857718be8SEnji Cooper 3957718be8SEnji Cooper #define RPCBPROC_NULL 0 4057718be8SEnji Cooper 4157718be8SEnji Cooper static int 4257718be8SEnji Cooper reply(caddr_t replyp, struct netbuf * raddrp, struct netconfig * nconf) 4357718be8SEnji Cooper { 4457718be8SEnji Cooper char host[NI_MAXHOST]; 4557718be8SEnji Cooper struct sockaddr *sock = raddrp->buf; 4657718be8SEnji Cooper int error; 4757718be8SEnji Cooper 4857718be8SEnji Cooper 4957718be8SEnji Cooper error = getnameinfo(sock, sock->sa_len, host, sizeof(host), NULL, 0, 0); 5057718be8SEnji Cooper if (error) 5157718be8SEnji Cooper warnx("Cannot resolve address (%s)", gai_strerror(error)); 5257718be8SEnji Cooper else 5357718be8SEnji Cooper printf("response from: %s\n", host); 5457718be8SEnji Cooper return 0; 5557718be8SEnji Cooper } 5657718be8SEnji Cooper 573fe8969aSEnji Cooper #ifdef __FreeBSD__ 583fe8969aSEnji Cooper #define __rpc_control rpc_control 593fe8969aSEnji Cooper #endif 603fe8969aSEnji Cooper 61*640235e2SEnji Cooper extern bool_t __rpc_control(int, void *); 6257718be8SEnji Cooper 6357718be8SEnji Cooper static void 6457718be8SEnji Cooper onehost(const char *host, const char *transp) 6557718be8SEnji Cooper { 6657718be8SEnji Cooper CLIENT *clnt; 6757718be8SEnji Cooper struct netbuf addr; 6857718be8SEnji Cooper struct timeval tv; 6957718be8SEnji Cooper 7057718be8SEnji Cooper /* 7157718be8SEnji Cooper * Magic! 7257718be8SEnji Cooper */ 7357718be8SEnji Cooper tv.tv_sec = 0; 7457718be8SEnji Cooper tv.tv_usec = 500000; 7557718be8SEnji Cooper #define CLCR_SET_RPCB_TIMEOUT 2 7657718be8SEnji Cooper __rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv); 7757718be8SEnji Cooper 7857718be8SEnji Cooper if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL) 7957718be8SEnji Cooper SKIPX(EXIT_FAILURE, "clnt_create (%s)", clnt_spcreateerror("")); 8057718be8SEnji Cooper 8157718be8SEnji Cooper tv.tv_sec = 1; 8257718be8SEnji Cooper tv.tv_usec = 0; 8328308194SEnji Cooper #ifdef __FreeBSD__ 8428308194SEnji Cooper if (clnt_call(clnt, RPCBPROC_NULL, (xdrproc_t)xdr_void, NULL, 8528308194SEnji Cooper (xdrproc_t)xdr_void, NULL, tv) 8628308194SEnji Cooper != RPC_SUCCESS) 8728308194SEnji Cooper #else 8857718be8SEnji Cooper if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv) 8957718be8SEnji Cooper != RPC_SUCCESS) 9028308194SEnji Cooper #endif 9157718be8SEnji Cooper ERRX(EXIT_FAILURE, "clnt_call (%s)", clnt_sperror(clnt, "")); 9257718be8SEnji Cooper clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr); 9357718be8SEnji Cooper reply(NULL, &addr, NULL); 9457718be8SEnji Cooper } 9557718be8SEnji Cooper 96*640235e2SEnji Cooper #define PROGNUM 0x81 97*640235e2SEnji Cooper #define VERSNUM 0x01 98*640235e2SEnji Cooper #define PLUSONE 1 99*640235e2SEnji Cooper #define DESTROY 2 100*640235e2SEnji Cooper 101*640235e2SEnji Cooper static struct timeval tout = {1, 0}; 102*640235e2SEnji Cooper 103*640235e2SEnji Cooper static void 104*640235e2SEnji Cooper server(struct svc_req *rqstp, SVCXPRT *transp) 105*640235e2SEnji Cooper { 106*640235e2SEnji Cooper int num; 107*640235e2SEnji Cooper 108*640235e2SEnji Cooper DPRINTF("Starting server\n"); 109*640235e2SEnji Cooper 110*640235e2SEnji Cooper switch (rqstp->rq_proc) { 111*640235e2SEnji Cooper case NULLPROC: 112*640235e2SEnji Cooper if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 113*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "svc_sendreply failed %d", 0); 114*640235e2SEnji Cooper return; 115*640235e2SEnji Cooper case PLUSONE: 116*640235e2SEnji Cooper break; 117*640235e2SEnji Cooper case DESTROY: 118*640235e2SEnji Cooper if (!svc_sendreply(transp, (xdrproc_t)xdr_void, NULL)) 119*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "svc_sendreply failed %d", 0); 120*640235e2SEnji Cooper svc_destroy(transp); 121*640235e2SEnji Cooper exit(0); 122*640235e2SEnji Cooper default: 123*640235e2SEnji Cooper svcerr_noproc(transp); 124*640235e2SEnji Cooper return; 125*640235e2SEnji Cooper } 126*640235e2SEnji Cooper 127*640235e2SEnji Cooper if (!svc_getargs(transp, (xdrproc_t)xdr_int, (void *)&num)) { 128*640235e2SEnji Cooper svcerr_decode(transp); 129*640235e2SEnji Cooper return; 130*640235e2SEnji Cooper } 131*640235e2SEnji Cooper DPRINTF("About to increment\n"); 132*640235e2SEnji Cooper num++; 133*640235e2SEnji Cooper if (!svc_sendreply(transp, (xdrproc_t)xdr_int, (void *)&num)) 134*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "svc_sendreply failed %d", 1); 135*640235e2SEnji Cooper DPRINTF("Leaving server procedure.\n"); 136*640235e2SEnji Cooper } 137*640235e2SEnji Cooper 138*640235e2SEnji Cooper static int 139*640235e2SEnji Cooper rawtest(const char *arg) 140*640235e2SEnji Cooper { 141*640235e2SEnji Cooper CLIENT *clnt; 142*640235e2SEnji Cooper SVCXPRT *svc; 143*640235e2SEnji Cooper int num, resp; 144*640235e2SEnji Cooper enum clnt_stat rv; 145*640235e2SEnji Cooper 146*640235e2SEnji Cooper if (arg) 147*640235e2SEnji Cooper num = atoi(arg); 148*640235e2SEnji Cooper else 149*640235e2SEnji Cooper num = 0; 150*640235e2SEnji Cooper 151*640235e2SEnji Cooper svc = svc_raw_create(); 152*640235e2SEnji Cooper if (svc == NULL) 153*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "Cannot create server %d", num); 154*640235e2SEnji Cooper if (!svc_reg(svc, PROGNUM, VERSNUM, server, NULL)) 155*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "Cannot register server %d", num); 156*640235e2SEnji Cooper 157*640235e2SEnji Cooper clnt = clnt_raw_create(PROGNUM, VERSNUM); 158*640235e2SEnji Cooper if (clnt == NULL) 159*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "%s", 160*640235e2SEnji Cooper clnt_spcreateerror("clnt_raw_create")); 161*640235e2SEnji Cooper rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num, 162*640235e2SEnji Cooper (xdrproc_t)xdr_int, (void *)&resp, tout); 163*640235e2SEnji Cooper if (rv != RPC_SUCCESS) 164*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 165*640235e2SEnji Cooper DPRINTF("Got %d\n", resp); 166*640235e2SEnji Cooper clnt_destroy(clnt); 167*640235e2SEnji Cooper svc_destroy(svc); 168*640235e2SEnji Cooper if (++num != resp) 169*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "expected %d got %d", num, resp); 170*640235e2SEnji Cooper 171*640235e2SEnji Cooper return EXIT_SUCCESS; 172*640235e2SEnji Cooper } 173*640235e2SEnji Cooper 174*640235e2SEnji Cooper static int 175*640235e2SEnji Cooper regtest(const char *hostname, const char *transp, const char *arg, int p) 176*640235e2SEnji Cooper { 177*640235e2SEnji Cooper CLIENT *clnt; 178*640235e2SEnji Cooper int num, resp; 179*640235e2SEnji Cooper enum clnt_stat rv; 180*640235e2SEnji Cooper pid_t pid; 181*640235e2SEnji Cooper 182*640235e2SEnji Cooper if (arg) 183*640235e2SEnji Cooper num = atoi(arg); 184*640235e2SEnji Cooper else 185*640235e2SEnji Cooper num = 0; 186*640235e2SEnji Cooper 187*640235e2SEnji Cooper #ifdef __NetBSD__ 188*640235e2SEnji Cooper svc_fdset_init(p ? SVC_FDSET_POLL : 0); 189*640235e2SEnji Cooper #endif 190*640235e2SEnji Cooper if (!svc_create(server, PROGNUM, VERSNUM, transp)) 191*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "Cannot create server %d", num); 192*640235e2SEnji Cooper 193*640235e2SEnji Cooper switch ((pid = fork())) { 194*640235e2SEnji Cooper case 0: 195*640235e2SEnji Cooper DPRINTF("Calling svc_run\n"); 196*640235e2SEnji Cooper svc_run(); 197*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "svc_run returned %d!", num); 198*640235e2SEnji Cooper case -1: 199*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "Fork failed (%s)", strerror(errno)); 200*640235e2SEnji Cooper default: 201*640235e2SEnji Cooper sleep(1); 202*640235e2SEnji Cooper break; 203*640235e2SEnji Cooper } 204*640235e2SEnji Cooper 205*640235e2SEnji Cooper DPRINTF("Initializing client\n"); 206*640235e2SEnji Cooper clnt = clnt_create(hostname, PROGNUM, VERSNUM, transp); 207*640235e2SEnji Cooper if (clnt == NULL) 208*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "%s", 209*640235e2SEnji Cooper clnt_spcreateerror("clnt_raw_create")); 210*640235e2SEnji Cooper rv = clnt_call(clnt, PLUSONE, (xdrproc_t)xdr_int, (void *)&num, 211*640235e2SEnji Cooper (xdrproc_t)xdr_int, (void *)&resp, tout); 212*640235e2SEnji Cooper if (rv != RPC_SUCCESS) 213*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 214*640235e2SEnji Cooper DPRINTF("Got %d\n", resp); 215*640235e2SEnji Cooper if (++num != resp) 216*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "expected %d got %d", num, resp); 217*640235e2SEnji Cooper rv = clnt_call(clnt, DESTROY, (xdrproc_t)xdr_void, NULL, 218*640235e2SEnji Cooper (xdrproc_t)xdr_void, NULL, tout); 219*640235e2SEnji Cooper if (rv != RPC_SUCCESS) 220*640235e2SEnji Cooper ERRX(EXIT_FAILURE, "clnt_call: %s", clnt_sperrno(rv)); 221*640235e2SEnji Cooper clnt_destroy(clnt); 222*640235e2SEnji Cooper 223*640235e2SEnji Cooper return EXIT_SUCCESS; 224*640235e2SEnji Cooper } 225*640235e2SEnji Cooper 226*640235e2SEnji Cooper 22757718be8SEnji Cooper #ifdef TEST 22857718be8SEnji Cooper static void 229*640235e2SEnji Cooper allhosts(const char *transp) 23057718be8SEnji Cooper { 23157718be8SEnji Cooper enum clnt_stat clnt_stat; 23257718be8SEnji Cooper 23357718be8SEnji Cooper clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL, 23457718be8SEnji Cooper (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, 23557718be8SEnji Cooper NULL, (resultproc_t)reply, transp); 23657718be8SEnji Cooper if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 23757718be8SEnji Cooper ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat)); 23857718be8SEnji Cooper } 23957718be8SEnji Cooper 24057718be8SEnji Cooper int 24157718be8SEnji Cooper main(int argc, char *argv[]) 24257718be8SEnji Cooper { 24357718be8SEnji Cooper int ch; 244*640235e2SEnji Cooper int s, p; 24557718be8SEnji Cooper const char *transp = "udp"; 24657718be8SEnji Cooper 247*640235e2SEnji Cooper p = s = 0; 248*640235e2SEnji Cooper while ((ch = getopt(argc, argv, "prstu")) != -1) 24957718be8SEnji Cooper switch (ch) { 250*640235e2SEnji Cooper case 'p': 251*640235e2SEnji Cooper p = 1; 252*640235e2SEnji Cooper break; 253*640235e2SEnji Cooper case 's': 254*640235e2SEnji Cooper s = 1; 255*640235e2SEnji Cooper break; 25657718be8SEnji Cooper case 't': 25757718be8SEnji Cooper transp = "tcp"; 25857718be8SEnji Cooper break; 25957718be8SEnji Cooper case 'u': 26057718be8SEnji Cooper transp = "udp"; 26157718be8SEnji Cooper break; 262*640235e2SEnji Cooper case 'r': 263*640235e2SEnji Cooper transp = NULL; 264*640235e2SEnji Cooper break; 26557718be8SEnji Cooper default: 266*640235e2SEnji Cooper fprintf(stderr, 267*640235e2SEnji Cooper "Usage: %s -[r|s|t|u] [<hostname>...]\n", 26857718be8SEnji Cooper getprogname()); 26957718be8SEnji Cooper return EXIT_FAILURE; 27057718be8SEnji Cooper } 27157718be8SEnji Cooper 272*640235e2SEnji Cooper if (argc == optind) { 273*640235e2SEnji Cooper if (transp) 274*640235e2SEnji Cooper allhosts(transp); 27557718be8SEnji Cooper else 276*640235e2SEnji Cooper rawtest(NULL); 277*640235e2SEnji Cooper } else { 278*640235e2SEnji Cooper for (; optind < argc; optind++) { 279*640235e2SEnji Cooper if (transp) 280*640235e2SEnji Cooper s == 0 ? 281*640235e2SEnji Cooper onehost(argv[optind], transp) : 282*640235e2SEnji Cooper regtest(argv[optind], transp, "1", p); 283*640235e2SEnji Cooper else 284*640235e2SEnji Cooper rawtest(argv[optind]); 285*640235e2SEnji Cooper } 286*640235e2SEnji Cooper } 28757718be8SEnji Cooper 28857718be8SEnji Cooper return EXIT_SUCCESS; 28957718be8SEnji Cooper } 29057718be8SEnji Cooper 29157718be8SEnji Cooper #else 29257718be8SEnji Cooper 29357718be8SEnji Cooper ATF_TC(get_svc_addr_tcp); 29457718be8SEnji Cooper ATF_TC_HEAD(get_svc_addr_tcp, tc) 29557718be8SEnji Cooper { 29657718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp"); 29757718be8SEnji Cooper 29857718be8SEnji Cooper } 29957718be8SEnji Cooper 30057718be8SEnji Cooper ATF_TC_BODY(get_svc_addr_tcp, tc) 30157718be8SEnji Cooper { 30257718be8SEnji Cooper onehost("localhost", "tcp"); 30357718be8SEnji Cooper 30457718be8SEnji Cooper } 30557718be8SEnji Cooper 30657718be8SEnji Cooper ATF_TC(get_svc_addr_udp); 30757718be8SEnji Cooper ATF_TC_HEAD(get_svc_addr_udp, tc) 30857718be8SEnji Cooper { 30957718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 31057718be8SEnji Cooper } 31157718be8SEnji Cooper 31257718be8SEnji Cooper ATF_TC_BODY(get_svc_addr_udp, tc) 31357718be8SEnji Cooper { 31457718be8SEnji Cooper onehost("localhost", "udp"); 31557718be8SEnji Cooper 31657718be8SEnji Cooper } 31757718be8SEnji Cooper 318*640235e2SEnji Cooper ATF_TC(raw); 319*640235e2SEnji Cooper ATF_TC_HEAD(raw, tc) 320*640235e2SEnji Cooper { 321*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks svc raw"); 322*640235e2SEnji Cooper } 323*640235e2SEnji Cooper 324*640235e2SEnji Cooper ATF_TC_BODY(raw, tc) 325*640235e2SEnji Cooper { 326*640235e2SEnji Cooper rawtest(NULL); 327*640235e2SEnji Cooper 328*640235e2SEnji Cooper } 329*640235e2SEnji Cooper 330*640235e2SEnji Cooper ATF_TC(tcp); 331*640235e2SEnji Cooper ATF_TC_HEAD(tcp, tc) 332*640235e2SEnji Cooper { 333*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks svc tcp (select)"); 334*640235e2SEnji Cooper } 335*640235e2SEnji Cooper 336*640235e2SEnji Cooper ATF_TC_BODY(tcp, tc) 337*640235e2SEnji Cooper { 338*640235e2SEnji Cooper regtest("localhost", "tcp", "1", 0); 339*640235e2SEnji Cooper 340*640235e2SEnji Cooper } 341*640235e2SEnji Cooper 342*640235e2SEnji Cooper ATF_TC(udp); 343*640235e2SEnji Cooper ATF_TC_HEAD(udp, tc) 344*640235e2SEnji Cooper { 345*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks svc udp (select)"); 346*640235e2SEnji Cooper } 347*640235e2SEnji Cooper 348*640235e2SEnji Cooper ATF_TC_BODY(udp, tc) 349*640235e2SEnji Cooper { 350*640235e2SEnji Cooper regtest("localhost", "udp", "1", 0); 351*640235e2SEnji Cooper 352*640235e2SEnji Cooper } 353*640235e2SEnji Cooper 354*640235e2SEnji Cooper ATF_TC(tcp_poll); 355*640235e2SEnji Cooper ATF_TC_HEAD(tcp_poll, tc) 356*640235e2SEnji Cooper { 357*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks svc tcp (poll)"); 358*640235e2SEnji Cooper } 359*640235e2SEnji Cooper 360*640235e2SEnji Cooper ATF_TC_BODY(tcp_poll, tc) 361*640235e2SEnji Cooper { 362*640235e2SEnji Cooper regtest("localhost", "tcp", "1", 1); 363*640235e2SEnji Cooper 364*640235e2SEnji Cooper } 365*640235e2SEnji Cooper 366*640235e2SEnji Cooper ATF_TC(udp_poll); 367*640235e2SEnji Cooper ATF_TC_HEAD(udp_poll, tc) 368*640235e2SEnji Cooper { 369*640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks svc udp (poll)"); 370*640235e2SEnji Cooper } 371*640235e2SEnji Cooper 372*640235e2SEnji Cooper ATF_TC_BODY(udp_poll, tc) 373*640235e2SEnji Cooper { 374*640235e2SEnji Cooper regtest("localhost", "udp", "1", 1); 375*640235e2SEnji Cooper 376*640235e2SEnji Cooper } 377*640235e2SEnji Cooper 37857718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 37957718be8SEnji Cooper { 38057718be8SEnji Cooper ATF_TP_ADD_TC(tp, get_svc_addr_udp); 38157718be8SEnji Cooper ATF_TP_ADD_TC(tp, get_svc_addr_tcp); 382*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, raw); 383*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, tcp); 384*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, udp); 385*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, tcp_poll); 386*640235e2SEnji Cooper ATF_TP_ADD_TC(tp, udp_poll); 38757718be8SEnji Cooper 38857718be8SEnji Cooper return atf_no_error(); 38957718be8SEnji Cooper } 39057718be8SEnji Cooper 39157718be8SEnji Cooper #endif 392