Skip site navigation (1)Skip section navigation (2)
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>