On Mon, Nov 15, 2021 at 12:19:48PM +0000, Klemens Nanni wrote:
> On Mon, Nov 15, 2021 at 02:08:33PM +1000, David Gwynne wrote:
> > The subject line only tells half the story. The other half is that
> > instead of hoping it only identifies Ethernet interfaces it now actually
> > checks and restricts itself to Ethernet interfaces. I couldn't help
> > myself.
> > 
> > If it helps my case for this code, I've been using this semantic for a
> > few years in a home grown dhcp-relay we run on our firewalls at
> > work. We used to run the dhcp-relay on a bunch of vlan(4) interfaces,
> > but we currently run them on carp(4). There's no significant difference
> > between using an Ethernet or carp interface from a dhcpd or relay point
> > of view, so the code accepts either.
> 
> This sounds reasonable, but I have no means to test these setups.
> 
> > The kernel lets you bind to addresses on down interfaces, so I don't
> > know why dhcpd has to be precious about it. We often start the
> > firewalls up with whole groups of these interfaces forced down.
> > We want DHCP packets to start moving when then interface comes up
> > though, therefore the daemon should start and be running even if
> > the interface is down.
> 
> I wondered about this as well but was hesitant to touch dhcpd(8) because
> I rarely use it.
> 
> FWIW, ISC DHCP has the same code and comment wrt. interface check,
> altough I didn't do any runtime tests.

our dhcpd came from isc dhcpd, and the guts havent been touched
much.

> > Should I warn if the interface is down on startup?
> 
> Wouldn't hurt, although you don't see it at boot time anyway, so not
> much help, imho.
> 
> > There's some other questionable code in here, but I'm going to take
> > some deep breaths and try to ignore them for now.
> 
> Here is the minimal diff I first used to fix my vport/DOWN issue,
> before going the implicit UP route.

this is a good start. im ok with you putting your change in, just get
someone else to ok it too.

> Regardless of vport's behaviour, this seemed sensible;  I mean, I can
> `nc -l' on down interfaces, other daemons don't care about UP and I'd
> rather have dhcpd running and pull interfaces UP to fix DHCP instead of
> restarting failed dhcpd (which could still serve on other UP interfaces).

exactly.

> 
> Index: dispatch.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/dhcpd/dispatch.c,v
> retrieving revision 1.43
> diff -u -p -r1.43 dispatch.c
> --- dispatch.c        12 Apr 2017 19:17:30 -0000      1.43
> +++ dispatch.c        13 Nov 2021 23:04:36 -0000
> @@ -112,13 +112,12 @@ discover_interfaces(int *rdomain)
>       for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
>               /*
>                * See if this is the sort of interface we want to
> -              * deal with.  Skip loopback, point-to-point and down
> +              * deal with.  Skip loopback and point-to-point
>                * interfaces, except don't skip down interfaces if we're
>                * trying to get a list of configurable interfaces.
>                */
>               if ((ifa->ifa_flags & IFF_LOOPBACK) ||
>                   (ifa->ifa_flags & IFF_POINTOPOINT) ||
> -                 (!(ifa->ifa_flags & IFF_UP)) ||
>                   (!(ifa->ifa_flags & IFF_BROADCAST)))
>                       continue;
>  
> 
> > OK?
> > 
> > Index: dispatch.c
> > ===================================================================
> > RCS file: /cvs/src/usr.sbin/dhcpd/dispatch.c,v
> > retrieving revision 1.43
> > diff -u -p -r1.43 dispatch.c
> > --- dispatch.c      12 Apr 2017 19:17:30 -0000      1.43
> > +++ dispatch.c      15 Nov 2021 03:50:46 -0000
> > @@ -47,6 +47,7 @@
> >  #include <net/if.h>
> >  #include <net/if_dl.h>
> >  #include <net/if_media.h>
> > +#include <net/if_types.h>
> >  
> >  #include <netinet/in.h>
> >  
> > @@ -112,14 +113,10 @@ discover_interfaces(int *rdomain)
> >     for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
> >             /*
> >              * See if this is the sort of interface we want to
> > -            * deal with.  Skip loopback, point-to-point and down
> > -            * interfaces, except don't skip down interfaces if we're
> > -            * trying to get a list of configurable interfaces.
> > +            * deal with, which is basically Ethernet.
> >              */
> >             if ((ifa->ifa_flags & IFF_LOOPBACK) ||
> > -               (ifa->ifa_flags & IFF_POINTOPOINT) ||
> > -               (!(ifa->ifa_flags & IFF_UP)) ||
> > -               (!(ifa->ifa_flags & IFF_BROADCAST)))
> > +               (ifa->ifa_flags & IFF_POINTOPOINT))
> >                     continue;
> >  
> >             /* See if we've seen an interface that matches this one. */
> > @@ -156,11 +153,27 @@ discover_interfaces(int *rdomain)
> >             /* If we have the capability, extract link information
> >                and record it in a linked list. */
> >             if (ifa->ifa_addr->sa_family == AF_LINK) {
> > -                   struct sockaddr_dl *sdl =
> > -                       ((struct sockaddr_dl *)(ifa->ifa_addr));
> > +                   struct if_data *ifi;
> > +                   struct sockaddr_dl *sdl;
> > +
> > +                   ifi = (struct if_data *)ifa->ifa_data;
> > +                   if (ifi->ifi_type != IFT_ETHER &&
> > +                       ifi->ifi_type != IFT_CARP) {
> > +                           /* this interface will be cleaned up later */
> > +                           continue;
> > +                   }
> > +
> > +                   sdl = ((struct sockaddr_dl *)(ifa->ifa_addr));
> > +                   if (sdl->sdl_alen > sizeof(tmp->hw_address.haddr)) {
> > +                           log_warnx("interface %s long hardware address",
> > +                               tmp->name);
> > +                           /* this interface will be cleaned up later */
> > +                           continue;
> > +                   }
> > +
> >                     tmp->index = sdl->sdl_index;
> >                     tmp->hw_address.hlen = sdl->sdl_alen;
> > -                   tmp->hw_address.htype = HTYPE_ETHER; /* XXX */
> > +                   tmp->hw_address.htype = HTYPE_ETHER;
> >                     memcpy(tmp->hw_address.haddr,
> >                         LLADDR(sdl), sdl->sdl_alen);
> >             } else if (ifa->ifa_addr->sa_family == AF_INET) {
> > @@ -236,6 +249,17 @@ discover_interfaces(int *rdomain)
> >     last = NULL;
> >     for (tmp = interfaces; tmp; tmp = next) {
> >             next = tmp->next;
> > +
> > +           if (tmp->index == 0) {
> > +                   log_warnx("Can't listen on %s - wrong interface type",
> > +                       tmp->name);
> > +                   /* Remove tmp from the list of interfaces. */
> > +                   if (!last)
> > +                           interfaces = interfaces->next;
> > +                   else
> > +                           last->next = tmp->next;
> > +                   continue;
> > +           }
> >  
> >             if (!tmp->ifp) {
> >                     log_warnx("Can't listen on %s - it has no IP address.",
> > 

Reply via email to