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