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 #ifdef __FreeBSD__ 51 #define __rpc_control rpc_control 52 #endif 53 54 extern bool __rpc_control(int, void *); 55 56 static void 57 onehost(const char *host, const char *transp) 58 { 59 CLIENT *clnt; 60 struct netbuf addr; 61 struct timeval tv; 62 63 /* 64 * Magic! 65 */ 66 tv.tv_sec = 0; 67 tv.tv_usec = 500000; 68 #define CLCR_SET_RPCB_TIMEOUT 2 69 __rpc_control(CLCR_SET_RPCB_TIMEOUT, &tv); 70 71 if ((clnt = clnt_create(host, RPCBPROG, RPCBVERS, transp)) == NULL) 72 SKIPX(EXIT_FAILURE, "clnt_create (%s)", clnt_spcreateerror("")); 73 74 tv.tv_sec = 1; 75 tv.tv_usec = 0; 76 if (clnt_call(clnt, RPCBPROC_NULL, xdr_void, NULL, xdr_void, NULL, tv) 77 != RPC_SUCCESS) 78 ERRX(EXIT_FAILURE, "clnt_call (%s)", clnt_sperror(clnt, "")); 79 clnt_control(clnt, CLGET_SVC_ADDR, (char *) &addr); 80 reply(NULL, &addr, NULL); 81 } 82 83 #ifdef TEST 84 static void 85 allhosts(void) 86 { 87 enum clnt_stat clnt_stat; 88 89 clnt_stat = rpc_broadcast(RPCBPROG, RPCBVERS, RPCBPROC_NULL, 90 (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, 91 NULL, (resultproc_t)reply, transp); 92 if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) 93 ERRX(EXIT_FAILURE, "%s", clnt_sperrno(clnt_stat)); 94 } 95 96 int 97 main(int argc, char *argv[]) 98 { 99 int ch; 100 const char *transp = "udp"; 101 102 103 while ((ch = getopt(argc, argv, "ut")) != -1) 104 switch (ch) { 105 case 't': 106 transp = "tcp"; 107 break; 108 case 'u': 109 transp = "udp"; 110 break; 111 default: 112 fprintf(stderr, "Usage: %s -[t|u] [<hostname>...]\n", 113 getprogname()); 114 return EXIT_FAILURE; 115 } 116 117 if (argc == optind) 118 allhosts(); 119 else 120 for (; optind < argc; optind++) 121 onehost(argv[optind], transp); 122 123 return EXIT_SUCCESS; 124 } 125 126 #else 127 128 ATF_TC(get_svc_addr_tcp); 129 ATF_TC_HEAD(get_svc_addr_tcp, tc) 130 { 131 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for tcp"); 132 133 } 134 135 ATF_TC_BODY(get_svc_addr_tcp, tc) 136 { 137 onehost("localhost", "tcp"); 138 139 } 140 141 ATF_TC(get_svc_addr_udp); 142 ATF_TC_HEAD(get_svc_addr_udp, tc) 143 { 144 atf_tc_set_md_var(tc, "descr", "Checks CLGET_SVC_ADDR for udp"); 145 } 146 147 ATF_TC_BODY(get_svc_addr_udp, tc) 148 { 149 onehost("localhost", "udp"); 150 151 } 152 153 ATF_TP_ADD_TCS(tp) 154 { 155 ATF_TP_ADD_TC(tp, get_svc_addr_udp); 156 ATF_TP_ADD_TC(tp, get_svc_addr_tcp); 157 158 return atf_no_error(); 159 } 160 161 #endif 162