Commit bcbd8cc3 authored by Martin Mares's avatar Martin Mares
Browse files

Interface logic changes:

o  Introduced IF_LINK_UP flag corresponding to real link state.
o  Allowed addressless interfaces.
o  IF_UP is now automatically calculated and set iff the interface
   is administratively up, has link up and has an IP address assigned.
   It may be IF_IGNORED, though (as in case of the loopback).
o  Any changes which include up/down transition are considered small
   enough to not provoke artificial upping and downing of the interface.
o  When an interface disappears (i.e., it wasn't seen in the last scan),
   we announce this change only once.
o  IF_LOOPBACK implies IF_IGNORE.
parent 25287d6f
Loading
Loading
Loading
Loading
+19 −9
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ static list neigh_list;
static int
if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
{
  if (i->flags & (IF_ADMIN_DOWN | IF_IGNORE))
  if (!(i->flags & IF_UP))
    return 0;
  if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
    return 1;
@@ -41,8 +41,6 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
      ipa_equal(*a, i->brd) ||		/* Broadcast */
      ipa_equal(*a, i->ip))		/* Our own address */
    return -1;
  if (!(i->flags & IF_UP))
    return 0;
  return 1;
}

@@ -197,6 +195,10 @@ if_dump(struct iface *i)
    debug(" ADMIN-DOWN");
  if (i->flags & IF_UP)
    debug(" UP");
  else
    debug(" DOWN");
  if (i->flags & IF_LINK_UP)
    debug(" LINK-UP");
  if (i->flags & IF_MULTIACCESS)
    debug(" MA");
  if (i->flags & IF_UNNUMBERED)
@@ -229,14 +231,16 @@ if_dump_all(void)
static inline int
if_change_too_big_p(struct iface *i, struct iface *j)
{
  if (!ipa_equal(i->ip, j->ip) ||
  if ((i->flags ^ j->flags) & IF_UP)	/* Going up/down is always OK */
    return 0;
  if (!ipa_equal(i->ip, j->ip) ||	/* Address change isn't */
      !ipa_equal(i->prefix, j->prefix) ||
      i->pxlen != j->pxlen ||
      !ipa_equal(i->brd, j->brd) ||
      !ipa_equal(i->opposite, j->opposite))
    return 1;				/* Changed addresses */
  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED))
    return 1;
  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP))
    return 1;				/* Interface type change isn't as well */
  return 0;
}

@@ -295,6 +299,11 @@ if_update(struct iface *new)
  struct iface *i;
  unsigned c;

  if ((new->flags & IF_LINK_UP) && !(new->flags & IF_ADMIN_DOWN) && ipa_nonzero(new->ip))
    new->flags |= IF_UP;
  else
    new->flags &= ~IF_UP;

  WALK_LIST(i, iface_list)
    if (!strcmp(new->name, i->name))
      {
@@ -337,7 +346,8 @@ if_end_update(void)
    else
      {
	memcpy(&j, i, sizeof(struct iface));
	i->flags = (i->flags & ~IF_UP) | IF_ADMIN_DOWN;
	i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
	if (i->flags != j.flags)
	  if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i);
      }
}
@@ -362,7 +372,7 @@ auto_router_id(void) /* FIXME: What if we run IPv6??? */
  j = NULL;
  WALK_LIST(i, iface_list)
    if ((i->flags & IF_UP) &&
	!(i->flags & (IF_UNNUMBERED | IF_LOOPBACK | IF_IGNORE)) &&
	!(i->flags & (IF_UNNUMBERED | IF_IGNORE)) &&
	(!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip)))
      j = i;
  if (!j)
+4 −3
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ struct iface {
  unsigned flags;
  unsigned mtu;
  unsigned index;			/* OS-dependent interface index */
  ip_addr ip;				/* IP address of this host */
  ip_addr ip;				/* IP address of this host (0=unset) */
  ip_addr prefix;			/* Network prefix */
  unsigned pxlen;			/* Prefix length */
  ip_addr brd;				/* Broadcast address */
@@ -29,7 +29,7 @@ struct iface {
  struct neighbor *neigh;		/* List of neighbors on this interface */
};

#define IF_UP 1
#define IF_UP 1				/* IF_LINK_UP, not IF_IGNORE and IP address known */
#define IF_MULTIACCESS 2
#define IF_UNNUMBERED 4
#define IF_BROADCAST 8
@@ -38,7 +38,8 @@ struct iface {
#define IF_ADMIN_DOWN 64
#define IF_LOOPBACK 128
#define IF_IGNORE 256
#define IF_UPDATED 0x1000		/* Touched in last scan */
#define IF_LINK_UP 512
#define IF_UPDATED 0x40000000		/* Touched in last scan */

/* Interface change events */

+13 −9
Original line number Diff line number Diff line
@@ -42,16 +42,18 @@ scan_ifs(struct ifreq *r, int cnt)
      bzero(&i, sizeof(i));
      DBG("%s\n", r->ifr_ifrn.ifrn_name);
      strncpy(i.name, r->ifr_ifrn.ifrn_name, sizeof(i.name) - 1);
      i.name[sizeof(i.name) - 1] = 0;
      get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
      if (ipa_nonzero(i.ip))
	{
	  l = ipa_classify(i.ip);
	  if (l < 0 || !(l & IADDR_HOST))
	    {
	      log(L_ERR "%s: Invalid interface address", i.name);
	  goto bad;
	      i.ip = IPA_NONE;
	    }
      if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
	  else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
	    i.flags |= IF_LOOPBACK | IF_IGNORE;
	}

      if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
	{
@@ -59,12 +61,12 @@ scan_ifs(struct ifreq *r, int cnt)
	faulty:
	  log(L_ERR "%s(%s): %m", err, i.name);
	bad:
	  i.flags = (i.flags & ~IF_UP) | IF_ADMIN_DOWN;
	  i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN;
	  continue;
	}
      fl = r->ifr_flags;
      if (fl & IFF_UP)
	i.flags |= IF_UP;
	i.flags |= IF_LINK_UP;

      if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
	{ err = "SIOCGIFNETMASK"; goto faulty; }
@@ -120,6 +122,8 @@ scan_ifs(struct ifreq *r, int cnt)
	DBG("SIOCGIFINDEX failed: %m\n");
      else
	i.index = r->ifr_ifindex;
#else
      /* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
#endif

      if_update(&i);