1 /* $NetBSD: t_rpc.c,v 1.3 2013/02/28 15:56:53 christos Exp $ */ 2 3 #include <sys/cdefs.h> 4 __RCSID("$NetBSD: t_rpc.c,v 1.3 2013/02/28 15:56:53 christos Exp $"); 5 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 #include <rpc/rpc.h> 9 #include <stdlib.h> 10 #include <err.h> 11 #include <netdb.h> 12 #include <stdio.h> 13 #include <unistd.h> 14 15 16 #ifndef TEST 17 #include <atf-c.h> 18 19 #define ERRX(ev, msg, ...) ATF_REQUIRE_MSG(0, msg, __VA_ARGS__) 20 21 #define SKIPX(ev, msg, ...) do { \ 22 atf_tc_skip(msg, __VA_ARGS__); \ 23 return; \ 24 } while(/*CONSTCOND*/0) 25 26 #else 27 #define ERRX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 28 #define SKIPX(ev, msg, ...) errx(ev, msg, __VA_ARGS__) 29 #endif 30 31 32 #define RPCBPROC_NULL 0 33 34 static int 35 reply(caddr_t replyp, struct netbuf * raddrp, struct netconfig * nconf) 36 { 37 char host[NI_MAXHOST]; 38 struct sockaddr *sock = raddrp->buf; 39 int error; 40 41 42 error = getnameinfo(sock, sock->sa_len, host, sizeof(host), NULL, 0, 0); 43 if (error) 44 warnx("Cannot resolve address (%s)", gai_strerror(error)); 45 else 46 printf("response from: %s\n", host); 47 return 0; 48 } 49 50 extern bool __rpc_control(int, void *); 51 52 static void 53 onehost(const char *host, const char *transp) 54 { 55 CLIENT *clnt; 56 struct netbuf addr; 57 struct timeval tv; 58 59 /* 60 * Magic! 61 */ 62 tv.tv_sec = 0; 63 tv.tv_usec = 500000; 64 #define CLCR_SET_RPCB_TIMEOUT 2 65 __rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv); 66 67 if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL) 68 SKIPX(EXIT_FAILURE, "clnt_create (%s)", clnt_spcreateerror("")); 69 70 tv.tv_sec = 1; 71 tv.tv_usec = 0; 72 if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv) 73 != RPC_SUCCESS) 74 ERRX(EXIT_FAILURE, "clnt_call (%s)", clnt_sperror(clnt, "")); 75 clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr); 76 reply(NULL, &addr, NULL); 77 } 78 79 #ifdef TEST 80 static void 81 allhosts(void) 82 { 83 enum clnt_stat clnt_stat; 84 85 clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL, 86 (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, 87 NULL, (resultproc_t)reply, transp); 88 if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 89 ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat)); 90 } 91 92 int 93 main(int argc, char *argv[]) 94 { 95 int ch; 96 const char *transp = "udp"; 97 98 99 while ((ch = getopt(argc, argv, "ut")) != -1) 100 switch (ch) { 101 case 't': 102 transp = "tcp"; 103 break; 104 case 'u': 105 transp = "udp"; 106 break; 107 default: 108 fprintf(stderr, "Usage: %s -[t|u] [<hostname>...]\n", 109 getprogname()); 110 return EXIT_FAILURE; 111 } 112 113 if (argc == optind) 114 allhosts(); 115 else 116 for (; optind < argc; optind++) 117 onehost(argv[optind], transp); 118 119 return EXIT_SUCCESS; 120 } 121 122 #else 123 124 ATF_TC(get_svc_addr_tcp); 125 ATF_TC_HEAD(get_svc_addr_tcp, tc) 126 { 127 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp"); 128 129 } 130 131 ATF_TC_BODY(get_svc_addr_tcp, tc) 132 { 133 onehost("localhost", "tcp"); 134 135 } 136 137 ATF_TC(get_svc_addr_udp); 138 ATF_TC_HEAD(get_svc_addr_udp, tc) 139 { 140 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 141 } 142 143 ATF_TC_BODY(get_svc_addr_udp, tc) 144 { 145 onehost("localhost", "udp"); 146 147 } 148 149 ATF_TP_ADD_TCS(tp) 150 { 151 ATF_TP_ADD_TC(tp, get_svc_addr_udp); 152 ATF_TP_ADD_TC(tp, get_svc_addr_tcp); 153 154 return atf_no_error(); 155 } 156 157 #endif 158