socsvn commit: r239802 - in soc2012/exxo/freebsd-head:
include/rpcsvc usr.bin/ypwhich usr.sbin/ypbind
exxo at FreeBSD.org
exxo at FreeBSD.org
Thu Jul 26 13:53:35 UTC 2012
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);
}
}
More information about the svn-soc-all
mailing list