krb5 UDP daemons and IP pktinfo

Greg Hudson ghudson at mit.edu
Tue Jan 5 16:58:35 EST 2016


MIT krb5 contains two UDP daemons, krb5kdc and kadmind (for password
changes).  For UDP daemons, it is sometimes important to send replies
from the same address as the requests were sent to, or the replies may
be discarded by firewalls or NAT devices.  The BSD sockets interface
does not provide this functionality if you bind the server socket to the
wildcard address.  For IPv6, there is a standardized and widely
implemented extension (IPV6_PKTINFO) which provides the needed
functionality.  For IPv4, the situation is more fragmented (see below).
As a result, we have some complicated code in lib/apputils/net-server.c
which does the following for each of IPv4 and IPv6:

* If pktinfo suport is present, we bind to the wildcard address and set
  the socket to use pktinfo.

* Otherwise, we loop over the local interfaces and bind to each one.  We
  also bind to the routing socket.  When a message is received on the
  routing socket indicating that local interfaces have changed, we close
  all sockets (including active TCP connections) and rebind listener
  sockets from scratch.

In 2010 I asked for help doing a platform survey, and found that while
Linux and Solaris 11 implement an IPv4 variant of pktinfo (IP_PKTINFO),
other platforms do not (NetBSD added it in 2013).  Until yesterday, my
operating assumption was that we were stuck with the complex code for
the forseeable future.  Yesterday, I discovered that some operating
systems implement the same functionality in a different way
(IP_RECVDSTADDR).  If we handle both variants, then we can safely bind
to the IPv4 wildcard address on Linux, Solaris, all of the BSDs, and OS
X.

So, I think it might be reasonable to simplify the net-server.c code at
the expense of some degradation on the rare platforms which don't
implement either variant of IPv4 pktinfo.  My favored form of
degradation is that we always bind to the wildcard address, and if the
platform doesn't have IPv4 pktinfo support, we just let sendto() pick
the source address of the reply.  For those platforms, our UDP daemons
will continue to work on single-homed machines, but might not behave
properly on multi-homed machine depending on the routing configuration.

Do other people agree that this is reasonable?


More information about the krbdev mailing list