Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.sbin/ypbind Load up with comments.



details:   https://anonhg.NetBSD.org/src/rev/7f5739afc905
branches:  trunk
changeset: 329812:7f5739afc905
user:      dholland <dholland%NetBSD.org@localhost>
date:      Tue Jun 10 17:19:12 2014 +0000

description:
Load up with comments.

diffstat:

 usr.sbin/ypbind/ypbind.c |  354 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 325 insertions(+), 29 deletions(-)

diffs (truncated from 712 to 300 lines):

diff -r fcf91ba7b8d7 -r 7f5739afc905 usr.sbin/ypbind/ypbind.c
--- a/usr.sbin/ypbind/ypbind.c  Tue Jun 10 17:19:00 2014 +0000
+++ b/usr.sbin/ypbind/ypbind.c  Tue Jun 10 17:19:12 2014 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ypbind.c,v 1.94 2014/06/10 17:19:00 dholland Exp $     */
+/*     $NetBSD: ypbind.c,v 1.95 2014/06/10 17:19:12 dholland Exp $     */
 
 /*
  * Copyright (c) 1992, 1993 Theo de Raadt <deraadt%fsa.ca@localhost>
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef LINT
-__RCSID("$NetBSD: ypbind.c,v 1.94 2014/06/10 17:19:00 dholland Exp $");
+__RCSID("$NetBSD: ypbind.c,v 1.95 2014/06/10 17:19:12 dholland Exp $");
 #endif
 
 #include <sys/types.h>
@@ -102,24 +102,33 @@
 
 #define BUFSIZE                1400
 
+/* the list of all domains */
 static struct domain *domains;
 static int check;
 
+/* option settings */
 static ypbind_mode_t default_ypbindmode;
-
 static int allow_local_ypset = 0, allow_any_ypset = 0;
 static int insecure;
 
+/* the sockets we use to interact with servers */
 static int rpcsock, pingsock;
+
+/* stuff used for manually interacting with servers */
 static struct rmtcallargs rmtca;
 static struct rmtcallres rmtcr;
 static bool_t rmtcr_outval;
 static unsigned long rmtcr_port;
+
+/* The ypbind service transports */
 static SVCXPRT *udptransp, *tcptransp;
 
 ////////////////////////////////////////////////////////////
 // utilities
 
+/*
+ * Combo of open() and flock().
+ */
 static int
 open_locked(const char *path, int flags, mode_t mode)
 {
@@ -148,6 +157,9 @@
 
 static void yp_log(int, const char *, ...) __printflike(2, 3);
 
+/*
+ * Log some stuff, to syslog or stderr depending on the debug setting.
+ */
 static void
 yp_log(int pri, const char *fmt, ...)
 {
@@ -185,6 +197,20 @@
 ////////////////////////////////////////////////////////////
 // struct domain
 
+/*
+ * State transition is done like this: 
+ *
+ * STATE       EVENT           ACTION                  NEWSTATE        TIMEOUT
+ * no binding  timeout         broadcast               no binding      5 sec
+ * no binding  answer          --                      binding         60 sec
+ * binding     timeout         ping server             checking        5 sec
+ * checking    timeout         ping server + broadcast checking        5 sec
+ * checking    answer          --                      binding         60 sec
+ */
+
+/*
+ * Look up a domain by the XID we assigned it.
+ */
 static struct domain *
 domain_find(uint32_t xid)
 {
@@ -196,6 +222,11 @@
        return dom;
 }
 
+/*
+ * Pick an XID for a domain.
+ *
+ * XXX: this should just generate a random number.
+ */
 static uint32_t
 unique_xid(struct domain *dom)
 {
@@ -208,6 +239,10 @@
        return tmp_xid;
 }
 
+/*
+ * Construct a new domain. Adds it to the global linked list of all
+ * domains.
+ */
 static struct domain *
 domain_create(const char *name)
 {
@@ -263,6 +298,10 @@
 ////////////////////////////////////////////////////////////
 // locks
 
+/*
+ * Open a new binding file. Does not write the contents out; the
+ * caller (there's only one) does that.
+ */
 static int
 makelock(struct domain *dom)
 {
@@ -284,6 +323,9 @@
        return fd;
 }
 
+/*
+ * Remove a binding file.
+ */
 static void
 removelock(struct domain *dom)
 {
@@ -295,12 +337,14 @@
 }
 
 /*
- * purge_bindingdir: remove old binding files (i.e. "rm BINDINGDIR\/\*.[0-9]")
+ * purge_bindingdir: remove old binding files (i.e. "rm *.[0-9]" in BINDINGDIR)
  *
- * local YP functions [e.g. yp_master()] will fail without even talking
- * to ypbind if there is a stale (non-flock'd) binding file present.
- * we have to scan the entire BINDINGDIR for binding files, because
- * ypbind may bind more than just the yp_get_default_domain() domain.
+ * The local YP functions [e.g. yp_master()] will fail without even
+ * talking to ypbind if there is a stale (non-flock'd) binding file
+ * present.
+ *
+ * We have to remove all binding files in BINDINGDIR, not just the one
+ * for the default domain.
  */
 static int
 purge_bindingdir(const char *dirpath)
@@ -364,7 +408,17 @@
 }
 
 /*
- * LOOPBACK IS MORE IMPORTANT: PUT IN HACK
+ * Take note of the fact that we've received a reply from a ypserver.
+ * Or, in the case of being ypset, that we've been ypset, which
+ * functions much the same.
+ *
+ * Note that FORCE is set if and only if IS_YPSET is set.
+ *
+ * This function has also for the past 20+ years carried the annotation
+ *
+ *      LOOPBACK IS MORE IMPORTANT: PUT IN HACK
+ *
+ * whose meaning isn't entirely clear.
  */
 static void
 rpc_received(char *dom_name, struct sockaddr_in *raddrp, int force,
@@ -379,26 +433,50 @@
        DPRINTF("returned from %s about %s\n",
                inet_ntoa(raddrp->sin_addr), dom_name);
 
+       /* validate some stuff */
        if (!rpc_is_valid_response(dom_name, raddrp)) {
                return;
        }
 
+       /* look for the domain */
        for (dom = domains; dom != NULL; dom = dom->dom_next)
                if (!strcmp(dom->dom_name, dom_name))
                        break;
 
+       /* if not found, create it, but only if FORCE; otherwise ignore */
        if (dom == NULL) {
                if (force == 0)
                        return;
                dom = domain_create(dom_name);
        }
 
+       /* the domain needs to know if it's been explicitly ypset */
        if (is_ypset) {
                dom->dom_been_ypset = 1;
        }
 
-       /* soft update, alive */
+       /*
+        * If the domain is alive and we aren't ypset, we don't need
+        * to do anything.
+        *
+        * This code is unreachable (AFAIK) unless we receive an
+        * unsolicited ping reply from the ypserver: because dom_alive
+        * is 0 until we have a binding, but set from 1 to 2 when we
+        * ping, it will never normally be 1 when a reply comes in,
+        * even a reply to a ping. In the case where we lost the
+        * binding and are getting a reply arising from nag_servers,
+        * we lost the binding because we never got a ping response so
+        * in that case dom_alive will also be 2.
+        *
+        * This logic is clearly wrong. XXX.
+        */
        if (dom->dom_alive == 1 && force == 0) {
+               /*
+                * If the reply came from the server we expect, set
+                * dom_alive back to 1 and ping again in 60 seconds.
+                *
+                * If it came from somewhere else, ignore it.
+                */
                if (!memcmp(&dom->dom_server_addr, raddrp,
                            sizeof(dom->dom_server_addr))) {
                        dom->dom_alive = 1;
@@ -407,23 +485,63 @@
                }
                return;
        }
-       
+
+       /*
+        * Take the address we got the message from (or in the case of
+        * ypset, the explicit address we were given) as the server
+        * address for this domain, mark the domain alive, and we'll
+        * check it again in 60 seconds.
+        *
+        * XXX: it looks like if we get a random unsolicited reply
+        * from somewhere, we'll silently switch to that server
+        * address, regardless of merit.
+        *
+        * 1. If we have a foo.ypservers file the address should be
+        * checked against it and rejected if it's not one of the
+        * addresses of one of the listed hostnames. Note that it
+        * might not be the same address we sent to; even fairly smart
+        * UDP daemons don't always handle multihomed hosts correctly
+        * and we can't expect sunrpc code to do anything intelligent
+        * at all.
+        *
+        * 2. If we're in broadcast mode the address should be
+        * checked against the local addresses and netmasks so we
+        * don't accept responses from Mars.
+        *
+        * 2a. If we're in broadcast mode and we've been ypset, we
+        * should not accept anything else until we drop the ypset
+        * state for not responding.
+        *
+        * 3. Either way we should not accept a response from an
+        * arbitrary host unless we don't currently have a binding.
+        * (The logic in the previous if statement is probably
+        * supposed to handle this, but it doesn't currently work.)
+        *
+        * Note that for a random unsolicited reply to work it has to
+        * carry the XID of one of the domains we know about; but
+        * those values are predictable.
+        */
        (void)memcpy(&dom->dom_server_addr, raddrp,
            sizeof(dom->dom_server_addr));
        /* recheck binding in 60 seconds */
        dom->dom_checktime = time(NULL) + 60;
        dom->dom_alive = 1;
 
+       /*
+        * Generate a new binding file. If this fails, forget about it.
+        * (But we keep the binding and we'll report it to anyone who
+        * asks via the ypbind service.) XXX: this will interact badly,
+        * maybe very badly, with the code in HEURISTIC.
+        *
+        * Note that makelock() doesn't log on failure.
+        */
+
        if (dom->dom_lockfd != -1)
                (void)close(dom->dom_lockfd);
 
        if ((fd = makelock(dom)) == -1)
                return;
 
-       /*
-        * ok, if BINDINGDIR exists, and we can create the binding file,
-        * then write to it..
-        */
        dom->dom_lockfd = fd;
 
        iov[0].iov_base = &(udptransp->xp_port);
@@ -450,6 +568,10 @@
        }
 }
 
+/*
+ * The NULL call: do nothing. This is obliged to exist because of
+ * sunrpc silliness.
+ */
 static void *
 /*ARGSUSED*/
 ypbindproc_null_2(SVCXPRT *transp, void *argp)
@@ -461,6 +583,9 @@



Home | Main Index | Thread Index | Old Index