Date: Thu, 26 Jul 2012 13:53:33 +0000 From: exxo@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r239802 - in soc2012/exxo/freebsd-head: include/rpcsvc usr.bin/ypwhich usr.sbin/ypbind Message-ID: <20120726135333.8984A1065670@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: exxo Date: Thu Jul 26 13:53:32 2012 New Revision: 239802 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=239802 Log: Complete rewrite of yp_ping.c (ypbind) Modified: soc2012/exxo/freebsd-head/include/rpcsvc/yp.x soc2012/exxo/freebsd-head/usr.bin/ypwhich/ypwhich.c soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Modified: soc2012/exxo/freebsd-head/include/rpcsvc/yp.x ============================================================================== --- soc2012/exxo/freebsd-head/include/rpcsvc/yp.x Thu Jul 26 12:18:23 2012 (r239801) +++ soc2012/exxo/freebsd-head/include/rpcsvc/yp.x Thu Jul 26 13:53:32 2012 (r239802) @@ -227,6 +227,8 @@ /* Backward compatibility for YPBIND protocol version 2 */ #ifdef YPBIND_COMPAT_V2 +const YPBINDVERS_2 = 2; + struct ypbind_binding_v2 { opaque ypbind_binding_addr[4]; /* In network order */ opaque ypbind_binding_port[2]; /* In network order */ Modified: soc2012/exxo/freebsd-head/usr.bin/ypwhich/ypwhich.c ============================================================================== --- soc2012/exxo/freebsd-head/usr.bin/ypwhich/ypwhich.c Thu Jul 26 12:18:23 2012 (r239801) +++ soc2012/exxo/freebsd-head/usr.bin/ypwhich/ypwhich.c Thu Jul 26 13:53:32 2012 (r239802) @@ -108,7 +108,7 @@ #endif static void -print_addr(union ypb_resp *ypbr, int version) +print_addr(const union ypb_resp *ypbr, int version) { struct hostent *hent = NULL; char str[ADDRSTRLEN]; Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c Thu Jul 26 12:18:23 2012 (r239801) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.c Thu Jul 26 13:53:32 2012 (r239802) @@ -103,6 +103,8 @@ */ +#if 0 /* TODO : Does __yp_getport achieve the same result ? */ + static struct timeval timeout = { 1, 0 }; static struct timeval tottimeout = { 1, 0 }; @@ -145,6 +147,7 @@ address->sin_port = 0; return (port); } +#endif /* * Transmit to YPPROC_DOMAIN_NONACK, return immediately. @@ -207,104 +210,222 @@ */ struct ping_req { - struct sockaddr_in sin; + struct sockaddr_storage sst; u_int32_t xid; }; +struct transport { + CLIENT *clnt; + u_int32_t xid_lookup; + struct sockaddr_storage *any; + int sock; + struct netbuf addr; +}; +#define V4 0 +#define V6 1 +#ifdef INET6 +# define TSP_LEN (V6 + 1) +#else +# define TSP_LEN (V4 + 1) +#endif + +static u_short +__yp_getport(const struct sockaddr_storage *host, const char *netid) +{ + struct sockaddr_storage sst; + struct netconfig *nconf; + struct netbuf svcaddr; + u_short port; + char str[ADDRSTRLEN]; + int family; + char *ptr; + + svcaddr.len = 0; + svcaddr.maxlen = sizeof(sst); + svcaddr.buf = &sst; + if (ss_extract(host, &family, &ptr, 0)) + return (0); + inet_ntop(family, ptr, str, ADDRSTRLEN); + if ((nconf = getnetconfigent(netid)) == NULL || + !rpcb_getaddr(YPPROG, YPVERS, nconf, &svcaddr, str)) + return (0); + switch (svcaddr.len) { + case sizeof(struct sockaddr_in) : + port = ss_to_sinport(svcaddr.buf); + break; +#ifdef INET6 + case sizeof(struct sockaddr_in6) : + port = ss_to_sin6port(svcaddr.buf); + break; +#endif + default : + port = 0; + } + return (port); /* Network byte order */ +} + +static int +rpc_init(struct transport *tsp) +{ + static timeval timenull; + int async = TRUE; + int dontblock = 1; + int validtransp = 0; + int i; + + for (i = 0; i < TSP_LEN; ++i) { + if (tsp[i]->any == NULL) + continue; +#ifdef INET6 + if (i == V6) { + tsp[i]->sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + tsp[i]->addr.len = sizeof(struct sockaddr_in6); + } + else /* V4 */ +#endif + { + tsp[i]->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + tsp[i]->addr.len = sizeof(struct sockaddr_in); + } + if (tsp[i]->sock < 0) + return (1); + tsp[i]->addr.buf = tsp[i]->any; + tsp[i]->clnt = clnt_dg_create(tsp[i]->sock, &tsp[i]->addr, YPPROG, YPVERS, 0, 0); + if (tsp[i]->clnt == NULL) + return (1); + tsp[i]->clnt->cl_auth = authsys_create_default(); + clnt_control(tsp[i]->clnt, CLSET_TIMEOUT, (char *)&timenull); + clnt_control(tsp[i]->clnt, CLSET_ASYNC, (char *)&async); + ioctl(tsp[i]->sock, FIONBIO, &dontblock); + ++validtransp; + } + return (!validtransp); +} + +static void +rpc_destroy(struct transport *tsp) +{ + int i; + + for (i = 0; i < TSP_LEN; ++i) { + if (tsp[i]->clnt) { + auth_destroy(tsp[i]->clnt->cl_auth); + clnt_destroy(tsp[i]->clnt); + tsp[i]->clnt = NULL; + } + tsp[i]->xid_lookup = 0; + tsp[i]->any = NULL; + close(tsp[i]->sock); + tsp[i]->sock = -1; + tsp[i]->addr.buf = NULL; + } +} + int -__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port) +__yp_ping(struct sockaddr_storage *restricted_addrs, int cnt, char *dom, short *port) { - struct timeval tv = { 5, 0 }; struct ping_req **reqs; unsigned long i; - int async; - struct sockaddr_in sin, *any = NULL; - struct netbuf addr; + int n; + struct sockaddr_storage *req_addr; int winner = -1; - u_int32_t xid_seed, xid_lookup; - int sock, dontblock = 1; - CLIENT *clnt; + u_int32_t xid_seed; char *foo = dom; int validsrvs = 0; + u_short yp_port; + struct transport tsp[TSP_LEN] = { +#ifdef INET6 + {NULL, 0, NULL, -1}, +#endif + {NULL, 0, NULL, -1} + }; /* Set up handles. */ reqs = calloc(1, sizeof(struct ping_req *) * cnt); xid_seed = time(NULL) ^ getpid(); for (i = 0; i < cnt; i++) { - bzero((char *)&sin, sizeof(sin)); - sin.sin_family = AF_INET; - bcopy((char *)&restricted_addrs[i], - (char *)&sin.sin_addr, sizeof(struct in_addr)); - sin.sin_port = htons(__pmap_getport(&sin, YPPROG, - YPVERS, IPPROTO_UDP)); - if (sin.sin_port == 0) + yp_port = __yp_getport(&restricted_addrs[i], "udp"); + if (yp_port == 0) continue; reqs[i] = calloc(1, sizeof(struct ping_req)); - bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin)); - any = &reqs[i]->sin; + req_addr = &reqs[i]->sst; + bcopy((char *)&restricted_addrs[i], (char *)req_addr, sizeof(*req_addr)); +#ifdef INET6 + if (ss_family(req_addr) == AF_INET6) { + ss_to_sin6port(req_addr) = yp_port; + tsp[V6].any = req_addr; + } + else /* AF_INET */ +#endif + { + ss_to_sinport(req_addr) = yp_port; + tsp[V4].any = req_addr; + } reqs[i]->xid = xid_seed; xid_seed++; validsrvs++; } /* Make sure at least one server was assigned */ - if (!validsrvs) { - free(reqs); - return(-1); - } - - /* Create RPC handle */ - sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock); - if (clnt == NULL) { - close(sock); - for (i = 0; i < cnt; i++) - if (reqs[i] != NULL) - free(reqs[i]); - free(reqs); - return(-1); - } - clnt->cl_auth = authunix_create_default(); - tv.tv_sec = 0; + if (!validsrvs) + goto err; - clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv); - async = TRUE; - clnt_control(clnt, CLSET_ASYNC, (char *)&async); - ioctl(sock, FIONBIO, &dontblock); + /* Create RPC transports + * an inet4 transport for any V4 address existing in `reqs' + * an inet6 transport for any V6 address existing in `reqs' + * otherwise, shutdown + * */ + if (rpc_init(tsp)) + goto err; /* Transmit */ - for (i = 0; i < cnt; i++) { + for (i = 0; i < cnt; i++) if (reqs[i] != NULL) { - clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid); - addr.len = sizeof(reqs[i]->sin); - addr.buf = (char *) &reqs[i]->sin; - clnt_control(clnt, CLSET_SVC_ADDR, &addr); - ypproc_domain_nonack_2_send(&foo, clnt); + req_addr = &reqs[i]->sst; + n = (ss_family(req_addr) == AF_INET ? V4 : V6); + clnt_control(tsp[n].clnt, CLSET_XID, (char *)&reqs[i]->xid); + tsp[n].addr.buf = (char *) req_addr; + clnt_control(tsp[n].clnt, CLSET_SVC_ADDR, &tsp[n].addr); + ypproc_domain_nonack_2_send(&foo, tsp[n].clnt); } - } /* Receive reply */ - ypproc_domain_nonack_2_recv(&foo, clnt); + for (i = 0; i < TSP_LEN; ++i) + if (tsp[i].clnt) + ypproc_domain_nonack_2_recv(&foo, tsp[i].clnt); + + /* Get the winner */ + for (i = 0; i < TSP_LEN; ++i) + if (tsp[i].clnt) + clnt_control(tsp[i].clnt, CLGET_XID, (char *)&tsp[i].xid_lookup); - /* Got a winner -- look him up. */ - clnt_control(clnt, CLGET_XID, (char *)&xid_lookup); - for (i = 0; i < cnt; i++) { - if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) { - winner = i; - *port = reqs[i]->sin.sin_port; + /* Look him up */ + for (i = 0; i < cnt; i++) + if (reqs[i] != NULL) { + for (n = 0; n < TSP_LEN; ++n) + if (reqs[i]->xid == tsp[n].xid_lookup) { +#ifdef INET6 + if (n == V6) + *port = ss_to_sin6port(&reqs[i]->sst); /* Network byte order */ + else /* V4 */ +#endif + *port = ss_to_sinport(&reqs[i]->sst); + winner = i; + break; + } + if (winner > 0) + break; } - } - + /* Shut everything down */ - auth_destroy(clnt->cl_auth); - clnt_destroy(clnt); - close(sock); - - for (i = 0; i < cnt; i++) - if (reqs[i] != NULL) - free(reqs[i]); +err: + rpc_destroy(tsp); + if (validsrvs) { + for (i = 0; i < cnt; i++) + if (reqs[i] != NULL) + free(reqs[i]); + } free(reqs); - return(winner); } Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h Thu Jul 26 12:18:23 2012 (r239801) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/yp_ping.h Thu Jul 26 13:53:32 2012 (r239802) @@ -2,4 +2,39 @@ * $FreeBSD$ */ -extern int __yp_ping(struct in_addr *, int, char *, short *); +#ifdef INET6 +# define ADDRSTRLEN INET6_ADDRSTRLEN +#else +# define ADDRSTRLEN INET_ADDRSTRLEN +#endif + +#define ss_family(x) (((struct sockaddr *) x)->sa_family) +#define ss_to_sinaddr(x) ((char *) &((struct sockaddr_in *) x)->sin_addr) +#define ss_to_sin6addr(x) ((char *) &((struct sockaddr_in6 *) x)->sin6_addr) +#define ss_to_sinport(x) ((u_short) ((struct sockaddr_in *) x)->sin_port) +#define ss_to_sin6port(x) ((u_short) ((struct sockaddr_in6 *) x)->sin6_port) + +static inline int +ss_extract(const struct sockaddr_storage *ss, int *family, char **addr, size_t *len) +{ + *family = ss_family(ss); + switch (*family) { + case AF_INET: + *addr = ss_to_sinaddr(ss); + if (len) + *len = sizeof(struct sockaddr_in); + break; +#ifdef INET6 + case AF_INET6: + *addr = ss_to_sin6addr(ss); + if (len) + *len = sizeof(struct sockaddr_in6); + break; +#endif + default: + return (1); + } + return (0); +} + +extern int __yp_ping(struct sockaddr_storage *, int, char *, short *); Modified: soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c ============================================================================== --- soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Thu Jul 26 12:18:23 2012 (r239801) +++ soc2012/exxo/freebsd-head/usr.sbin/ypbind/ypbind.c Thu Jul 26 13:53:32 2012 (r239802) @@ -76,7 +76,7 @@ struct _dom_binding { struct _dom_binding *dom_pnext; char dom_domain[YPMAXDOMAIN + 1]; - struct sockaddr_in dom_server_addr; + struct sockaddr_storage dom_server_addr; /* TODO */ long int dom_vers; int dom_lockfd; int dom_alive; @@ -128,7 +128,7 @@ #define RESTRICTED_SERVERS 10 int yp_restricted = 0; int yp_manycast = 0; -struct in_addr restricted_addrs[RESTRICTED_SERVERS]; +struct sockaddr_storage restricted_addrs[RESTRICTED_SERVERS]; /* No more than MAX_CHILDREN child broadcasters at a time. */ #ifndef MAX_CHILDREN @@ -154,8 +154,6 @@ int yplockfd; fd_set fdsr; -SVCXPRT *udptransp, *tcptransp; - void * ypbindproc_null_2_yp(SVCXPRT *transp, void *argp, CLIENT *clnt) { @@ -372,10 +370,32 @@ } close(yplockfd); unlink(YPBINDLOCK); - pmap_unset(YPBINDPROG, YPBINDVERS); + rpcb_unset(YPBINDPROG, YPBINDVERS, NULL); +#ifdef YPBIND_COMPAT_V2 + rpcb_unset(YPBINDPROG, YPBINDVERS_2, NULL); +#endif exit(0); } +/* The string `message' is evaluated two times, thus the correct format to add the address is %%s + * Beware of side effects using other %% notations */ +static void +logwaddr(int priority, const struct sockaddr_storage *addr, const char *message, ...) +{ + char buf[256]; /* Maximum message length */ + va_list args; + int family; + char *ptr; + char str[ADDRSTRLEN]; + + if (ss_extract(addr, &family, &ptr, 0)) + return; + va_start(args, message); + vsnprintf(buf, sizeof(buf), message, args); + syslog(priority, buf, inet_ntop(family, ptr, str, ADDRSTRLEN)); + va_end(args); +} + int main(int argc, char *argv[]) { @@ -430,22 +450,20 @@ err(1, "fork"); #endif - pmap_unset(YPBINDPROG, YPBINDVERS); - - udptransp = svcudp_create(RPC_ANYSOCK); - if (udptransp == NULL) + rpcb_unset(YPBINDPROG, YPBINDVERS, NULL); +#ifdef YPBIND_COMPAT_V2 + rpcb_unset(YPBINDPROG, YPBINDVERS_2, NULL); +#endif + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, "udp")) /* TODO see how to retrieve xp_port */ errx(1, "cannot create udp service"); - if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, - IPPROTO_UDP)) - errx(1, "unable to register (YPBINDPROG, YPBINDVERS, udp)"); - - tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); - if (tcptransp == NULL) + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS, "tcp")) errx(1, "cannot create tcp service"); - - if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, - IPPROTO_TCP)) - errx(1, "unable to register (YPBINDPROG, YPBINDVERS, tcp)"); +#ifdef YPBIND_COMPAT_V2 + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, "udp")) + errx(1, "cannot create udp service"); + if (!svc_create(ypbindprog_2, YPBINDPROG, YPBINDVERS_2, "tcp")) + errx(1, "cannot create tcp service"); +#endif /* build initial domain binding, make it "unsuccessful" */ ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); @@ -650,6 +668,7 @@ void broadcast(struct _dom_binding *ypdb) { + static struct sockaddr_storage null_addr; bool_t out = FALSE; enum clnt_stat stat; @@ -661,11 +680,13 @@ return; } - if (ypdb->dom_vers == -1 && (long)ypdb->dom_server_addr.sin_addr.s_addr) { + /* bcmp should be safe here due to the earlier dom_server_addr memset which + * prevents us from alignement issues */ + if (ypdb->dom_vers == -1 && bcmp(&ypdb->dom_server_addr, &null_addr, sizeof(null_addr))) { if (not_responding_count++ >= NOT_RESPONDING_HYSTERESIS) { not_responding_count = NOT_RESPONDING_HYSTERESIS; - syslog(LOG_WARNING, "NIS server [%s] for domain \"%s\" not responding", - inet_ntoa(ypdb->dom_server_addr.sin_addr), ypdb->dom_domain); + logwaddr(LOG_WARNING, &ypdb->dom_server_addr, + "NIS server [%%s] for domain \"%s\" not responding", ypdb->dom_domain); } }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120726135333.8984A1065670>