]> git.puffer.fish Git - matthieu/frr.git/commitdiff
2005-11-03 Paul Jakma <paul.jakma@sun.com>
authorpaul <paul>
Thu, 3 Nov 2005 12:35:21 +0000 (12:35 +0000)
committerpaul <paul>
Thu, 3 Nov 2005 12:35:21 +0000 (12:35 +0000)
* connected.{c,h}: Include memory.h
  (connected_add_ipv4) Use MTYPE for ifc label.
  (connected_add_ipv6) Also should accept label. Store it in ifp.
  (connected_del_ipv4) Taking label as argument is pointless.
* rt_netlink.c: (netlink_interface_addr) update label usage
  for connected_{add,delete} functions.
* if_ioctl.c: (if_getaddrs) NULL label for connected_add_ipv6.
* if_ioctl_solaris.c: (interface_list_ioctl) Pass LIFC_NOXMIT
  so we also find out about NOXMIT interfaces like VNI.
  Bit of hackery to turn interface names into the primary
  interface name, later with routing socket messages we only
  will about primary interfaces anyway, so we must normalise
  the name.
  (if_get_addr) take label as argument, so it can
  be passed to connected_add.
  If label is provided, then it is interface name to issue the
  ioctl for address information on, not the ifp name.
  (interface_list) List AF_UNSPEC too, just in case.
* if_proc.c: (ifaddr_proc_ipv6) label for connected_add_ipv6.
* interface.c: (if_addr_wakeup) Some very bogus code - sets
  IFF_RUNNING - add comment.
  (if_refresh)
  (ip_address_install) Use MTYPE for ifc label.
* ioctl_solaris.c: (if_mangle_up) New function. Hackery to make
  IFF_UP reflect whether any addresses are left on the
  interface, as we get signalled for IFF_UP flags change on the
  primary interface only. Logical interfaces dont generate
  IFINFO, but we do get an RTM_DELADDR.
  (if_get_flags) Call if_mangle_up before return.
* kernel_socket.c: (ifam_read) Fixup calls to
  connected_{add,delete} to match above changes. Rename gate
  variable to brd, less confusing.
  Pass the interface name as a label, if it is not same name
  as ifp->name.

zebra/ChangeLog
zebra/connected.c
zebra/connected.h
zebra/if_ioctl.c
zebra/if_ioctl_solaris.c
zebra/if_proc.c
zebra/interface.c
zebra/ioctl_solaris.c
zebra/kernel_socket.c
zebra/rt_netlink.c

index 0d69e75117cca08d6e16ac72296d5aef1bd7e30c..e172360362121f2eb14507bd23ae9de3b37ee634 100644 (file)
@@ -1,3 +1,40 @@
+2005-11-03 Paul Jakma <paul.jakma@sun.com>
+
+       * connected.{c,h}: Include memory.h
+         (connected_add_ipv4) Use MTYPE for ifc label.
+         (connected_add_ipv6) Also should accept label. Store it in ifp.
+         (connected_del_ipv4) Taking label as argument is pointless.
+       * rt_netlink.c: (netlink_interface_addr) update label usage
+         for connected_{add,delete} functions.
+       * if_ioctl.c: (if_getaddrs) NULL label for connected_add_ipv6.
+       * if_ioctl_solaris.c: (interface_list_ioctl) Pass LIFC_NOXMIT
+         so we also find out about NOXMIT interfaces like VNI.
+         Bit of hackery to turn interface names into the primary
+         interface name, later with routing socket messages we only
+         will about primary interfaces anyway, so we must normalise
+         the name.
+         (if_get_addr) take label as argument, so it can
+         be passed to connected_add.
+         If label is provided, then it is interface name to issue the
+         ioctl for address information on, not the ifp name.
+         (interface_list) List AF_UNSPEC too, just in case.
+       * if_proc.c: (ifaddr_proc_ipv6) label for connected_add_ipv6.
+       * interface.c: (if_addr_wakeup) Some very bogus code - sets
+         IFF_RUNNING - add comment.
+         (if_refresh)
+         (ip_address_install) Use MTYPE for ifc label.
+       * ioctl_solaris.c: (if_mangle_up) New function. Hackery to make
+         IFF_UP reflect whether any addresses are left on the
+         interface, as we get signalled for IFF_UP flags change on the 
+         primary interface only. Logical interfaces dont generate
+         IFINFO, but we do get an RTM_DELADDR.
+         (if_get_flags) Call if_mangle_up before return.
+       * kernel_socket.c: (ifam_read) Fixup calls to
+         connected_{add,delete} to match above changes. Rename gate
+         variable to brd, less confusing.
+         Pass the interface name as a label, if it is not same name 
+         as ifp->name.
+
 2005-10-11 Paul Jakma <paul.jakma@sun.com>
 
        * connected.{c,h}: (connected_{add,delete}_ipv4) label should
index 58d964fc5b74977917ec7dc52d53e45b1dda5f2e..105e4b1165eebd440906b4b554974fb0920dab76 100644 (file)
@@ -29,6 +29,7 @@
 #include "rib.h"
 #include "table.h"
 #include "log.h"
+#include "memory.h"
 
 #include "zebra/zserv.h"
 #include "zebra/redistribute.h"
@@ -219,7 +220,7 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
 
   /* Label of this address. */
   if (label)
-    ifc->label = strdup (label);
+    ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
 
   /* Check same connected route. */
   if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
@@ -267,8 +268,7 @@ connected_down_ipv4 (struct interface *ifp, struct connected *ifc)
 /* Delete connected IPv4 route to the interface. */
 void
 connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
-                      u_char prefixlen, struct in_addr *broad,
-                      const char *label)
+                      u_char prefixlen, struct in_addr *broad)
 {
   struct prefix_ipv4 p;
   struct connected *ifc;
@@ -330,7 +330,7 @@ connected_up_ipv6 (struct interface *ifp, struct connected *ifc)
 /* Add connected IPv6 route to the interface. */
 void
 connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
-                   u_char prefixlen, struct in6_addr *broad)
+                   u_char prefixlen, struct in6_addr *broad, char *label)
 {
   struct prefix_ipv6 *p;
   struct connected *ifc;
@@ -356,6 +356,10 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr,
       ifc->destination = (struct prefix *) p;
     }
 
+  /* Label of this address. */
+  if (label)
+    ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
+  
   if ((current = connected_check (ifp, (struct prefix *) ifc->address)))
     connected_withdraw (current); /* implicit update of existing address */
   
index 26e809c465e78f99ad79e7cc61dfb7a3d35c7cbd..289b03c7f5810541e23993b9e1e301a34424fdf9 100644 (file)
@@ -33,8 +33,7 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
 
 extern void
 connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr,
-                      u_char prefixlen, struct in_addr *broad,
-                      const char *label);
+                      u_char prefixlen, struct in_addr *broad);
 
 extern void connected_up_ipv4 (struct interface *, struct connected *);
 extern void connected_down_ipv4 (struct interface *, struct connected *);
@@ -42,7 +41,7 @@ extern void connected_down_ipv4 (struct interface *, struct connected *);
 #ifdef HAVE_IPV6
 extern void
 connected_add_ipv6 (struct interface *ifp, struct in6_addr *address,
-                   u_char prefixlen, struct in6_addr *broad);
+                   u_char prefixlen, struct in6_addr *broad, char *label);
 extern void
 connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address,
                       u_char prefixlen, struct in6_addr *broad);
index 66d8327dd24580588c76e04bb10293a73d6fcdae..b00a29cdec9880090ef5bf35287f5c9f670c7b8f 100644 (file)
@@ -305,7 +305,8 @@ if_getaddrs (void)
            }   
 #endif          
 
-         connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, dest_pnt);
+         connected_add_ipv6 (ifp, &addr->sin6_addr, prefixlen, 
+                             dest_pnt, NULL);
        }
 #endif /* HAVE_IPV6 */
     }
index efa6506056dc0298ad112509a2fb294284eae5e3..898c16109dc4bfeb0cf5ea0223b7f981db059a4d 100644 (file)
@@ -34,7 +34,7 @@
 #include "zebra/interface.h"
 
 void lifreq_set_name (struct lifreq *, struct interface *);
-static int if_get_addr (struct interface *, struct sockaddr *);
+static int if_get_addr (struct interface *, struct sockaddr *, const char *);
 static void interface_info_ioctl (struct interface *);
 extern struct zebra_privs_t zserv_privs;
 
@@ -71,7 +71,7 @@ interface_list_ioctl (int af)
 
 calculate_lifc_len:     /* must hold privileges to enter here */
   lifn.lifn_family = af;
-  lifn.lifn_flags = 0;
+  lifn.lifn_flags = LIFC_NOXMIT; /* we want NOXMIT interfaces too */
   ret = ioctl (sock, SIOCGLIFNUM, &lifn);
   save_errno = errno;
   
@@ -108,7 +108,7 @@ calculate_lifc_len:     /* must hold privileges to enter here */
   lastneeded = needed;
 
   lifconf.lifc_family = af;
-  lifconf.lifc_flags = 0;
+  lifconf.lifc_flags = LIFC_NOXMIT;
   lifconf.lifc_len = needed;
   lifconf.lifc_buf = buf;
 
@@ -138,9 +138,22 @@ calculate_lifc_len:     /* must hold privileges to enter here */
 
   for (n = 0; n < lifconf.lifc_len; n += sizeof (struct lifreq))
     {
-      ifp = if_get_by_name_len(lifreq->lifr_name,
-                              strnlen(lifreq->lifr_name,
-                                      sizeof(lifreq->lifr_name)));
+      /* we treat Solaris logical interfaces as addresses, because that is
+       * how PF_ROUTE on Solaris treats them. Hence we can not directly use
+       * the lifreq_name to get the ifp.  We need to normalise the name
+       * before attempting get.
+       *
+       * Solaris logical interface names are in the form of:
+       * <interface name>:<logical interface id>
+       */
+      unsigned int normallen = 0;
+      
+      while ( (normallen < sizeof(lifreq->lifr_name))
+             && ( *(lifreq->lifr_name + normallen) != '\0')
+             && ( *(lifreq->lifr_name + normallen) != ':') )
+        normallen++;
+      
+      ifp = if_get_by_name_len(lifreq->lifr_name, normallen);
 
       if (lifreq->lifr_addr.ss_family == AF_INET)
         ifp->flags |= IFF_IPV4;
@@ -158,7 +171,15 @@ calculate_lifc_len:     /* must hold privileges to enter here */
       if_add_update (ifp);
 
       interface_info_ioctl (ifp);
-      if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr);
+      
+      /* If a logical interface pass the full name so it can be
+       * as a label on the address
+       */
+      if ( *(lifreq->lifr_name + normallen) != '\0')
+        if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr,
+                     lifreq->lifr_name);
+      else
+        if_get_addr (ifp, (struct sockaddr *) &lifreq->lifr_addr, NULL);
       lifreq++;
     }
 
@@ -209,8 +230,9 @@ if_get_index (struct interface *ifp)
 #define SIN(s) ((struct sockaddr_in *)(s))
 #define SIN6(s) ((struct sockaddr_in6 *)(s))
 
+/* Retrieve address information for the given ifp */
 static int
-if_get_addr (struct interface *ifp, struct sockaddr *addr)
+if_get_addr (struct interface *ifp, struct sockaddr *addr, const char *label)
 {
   int ret;
   struct lifreq lifreq;
@@ -219,8 +241,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr)
   u_char prefixlen = 0;
   afi_t af;
 
-  /* Interface's name and address family. */
-  strncpy (lifreq.lifr_name, ifp->name, IFNAMSIZ);
+  /* Interface's name and address family.
+   * We need to use the logical interface name / label, if we've been
+   * given one, in order to get the right address
+   */
+  strncpy (lifreq.lifr_name, (label : label ? ifp->name), IFNAMSIZ);
 
   /* Interface's address. */
   memcpy (&lifreq.lifr_addr, addr, ADDRLEN (addr));
@@ -306,11 +331,11 @@ if_get_addr (struct interface *ifp, struct sockaddr *addr)
   /* Set address to the interface. */
   if (af == AF_INET)
     connected_add_ipv4 (ifp, 0, &SIN (addr)->sin_addr, prefixlen,
-                        (struct in_addr *) dest_pnt, NULL);
+                        (struct in_addr *) dest_pnt, label);
 #ifdef HAVE_IPV6
   else if (af == AF_INET6)
     connected_add_ipv6 (ifp, &SIN6 (addr)->sin6_addr, prefixlen,
-                        (struct in6_addr *) dest_pnt);
+                        (struct in6_addr *) dest_pnt, label);
 #endif /* HAVE_IPV6 */
 
   return 0;
@@ -332,6 +357,7 @@ interface_list ()
 {
   interface_list_ioctl (AF_INET);
   interface_list_ioctl (AF_INET6);
+  interface_list_ioctl (AF_UNSPEC);
 }
 
 struct connected *
index 3257d03cfae0953be68fd318bd10d1921da034e1..6002595ad3020493c23687a174622409b605ee90 100644 (file)
@@ -240,7 +240,7 @@ ifaddr_proc_ipv6 ()
       str2in6_addr (addr, &p.prefix);
       p.prefixlen = plen;
 
-      connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL);
+      connected_add_ipv6 (ifp, &p.prefix, p.prefixlen, NULL, ifname);
     }
   fclose (fp);
   return 0;
index 49fffcf5de8dade19ec021a17d6172d8ebb27be2..5f9c7a234e40324134343d0ea96494ed8201d880 100644 (file)
@@ -209,6 +209,16 @@ if_addr_wakeup (struct interface *ifp)
            {
              if (! if_is_up (ifp))
                {
+                 /* XXX: WTF is it trying to set flags here?
+                  * caller has just gotten a new interface, has been
+                   * handed the flags already. This code has no business
+                   * trying to override administrative status of the interface.
+                   * The only call path to here which doesn't originate from
+                   * kernel event is irdp - what on earth is it trying to do?
+                   *
+                   * further RUNNING is not a settable flag on any system
+                   * I (paulj) am aware of.
+                   */
                  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
                  if_refresh (ifp);
                }
@@ -236,6 +246,7 @@ if_addr_wakeup (struct interface *ifp)
            {
              if (! if_is_up (ifp))
                {
+                 /* XXX: See long comment above */
                  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
                  if_refresh (ifp);
                }
@@ -1172,7 +1183,7 @@ ip_address_install (struct vty *vty, struct interface *ifp,
 
       /* Label. */
       if (label)
-       ifc->label = strdup (label);
+       ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
 
       /* Add to linked list. */
       listnode_add (ifp->connected, ifc);
@@ -1363,7 +1374,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp,
 
       /* Label. */
       if (label)
-       ifc->label = strdup (label);
+       ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
 
       /* Add to linked list. */
       listnode_add (ifp->connected, ifc);
index 43e1e83f9608402e559826c1c3ca53d3236ec187..ec1d2c440384855ba94f5e84c99d4d3dbeaadf4e 100644 (file)
@@ -274,11 +274,35 @@ if_unset_prefix (struct interface *ifp, struct connected *ifc)
   return 0;
 }
 
+/* Solaris IFF_UP flag reflects only the primary interface as the
+ * routing socket only sends IFINFO for the primary interface.  Hence  
+ * ~IFF_UP does not per se imply all the logical interfaces are also   
+ * down - which we only know of as addresses. Instead we must determine
+ * whether the interface really is up or not according to how many   
+ * addresses are still attached. (Solaris always sends RTM_DELADDR if
+ * an interface, logical or not, goes ~IFF_UP).
+ *
+ * Ie, we mangle IFF_UP to reflect whether or not there are addresses
+ * left in struct connected, not the actual underlying IFF_UP flag
+ * (which corresponds to just one address of all the logical interfaces)
+ *
+ * Setting IFF_UP within zebra to administratively shutdown the
+ * interface will affect only the primary interface/address on Solaris.
+ */
+static inline void
+if_mangle_up (struct interface *ifp)
+{
+  if (listcount(ifp->connected) > 0)
+    SET_FLAG (ifp->flags, IFF_UP);
+  else
+    UNSET_FLAG (ifp->flags, IFF_UP);
+}
+
 /* get interface flags */
 void
 if_get_flags (struct interface *ifp)
 {
-  int ret;
+  int ret4, ret6;
   struct lifreq lifreq;
   unsigned long flags4 = 0, flags6 = 0;
 
@@ -286,25 +310,27 @@ if_get_flags (struct interface *ifp)
     {
       lifreq_set_name (&lifreq, ifp);
       
-      ret = AF_IOCTL (AF_INET, SIOCGLIFFLAGS, (caddr_t) & lifreq);
-
-      flags4 = (lifreq.lifr_flags & 0xffffffff);
-      if (!(flags4 & IFF_UP))
-        flags4 &= ~IFF_IPV4;
+      ret4 = AF_IOCTL (AF_INET, SIOCGLIFFLAGS, (caddr_t) & lifreq);
+      
+      if (!ret4)
+        flags4 = (lifreq.lifr_flags & 0xffffffff);
     }
 
   if (ifp->flags & IFF_IPV6)
     {
       lifreq_set_name (&lifreq, ifp);
       
-      ret = AF_IOCTL (AF_INET6, SIOCGLIFFLAGS, (caddr_t) & lifreq);
-              
-      flags6 = (lifreq.lifr_flags & 0xffffffff);
-      if (!(flags6 & IFF_UP))
-        flags6 &= ~IFF_IPV6;
+      ret6 = AF_IOCTL (AF_INET6, SIOCGLIFFLAGS, (caddr_t) & lifreq);
+      
+      if (!ret6)
+        flags6 = (lifreq.lifr_flags & 0xffffffff);
     }
+  
+  /* only update flags if one of above succeeded */
+  if ( !(ret4 && ret6) )
+    ifp->flags = (flags4 | flags6);
 
-  ifp->flags = (flags4 | flags6);
+  if_mangle_up (ifp);
 }
 
 /* Set interface flags */
index f391d53a05a34dbd1df5c7f86649f2e94143eed3..c264437d15a8e781e50d81dc38c932fcaef48656 100644 (file)
@@ -465,7 +465,7 @@ int
 ifam_read (struct ifa_msghdr *ifam)
 {
   struct interface *ifp;
-  union sockunion addr, mask, gate;
+  union sockunion addr, mask, brd;
 
   /* Check does this interface exist or not. */
   ifp = if_lookup_by_index (ifam->ifam_index);
@@ -476,7 +476,7 @@ ifam_read (struct ifa_msghdr *ifam)
     }
 
   /* Allocate and read address information. */
-  ifam_read_mesg (ifam, &addr, &mask, &gate);
+  ifam_read_mesg (ifam, &addr, &mask, &brd);
 
   /* Check interface flag for implicit up of the interface. */
   if_refresh (ifp);
@@ -488,11 +488,12 @@ ifam_read (struct ifa_msghdr *ifam)
       if (ifam->ifam_type == RTM_NEWADDR)
        connected_add_ipv4 (ifp, 0, &addr.sin.sin_addr, 
                            ip_masklen (mask.sin.sin_addr),
-                           &gate.sin.sin_addr, NULL);
+                           &brd.sin.sin_addr,
+                           (isalias ? ifname : NULL) );
       else
        connected_delete_ipv4 (ifp, 0, &addr.sin.sin_addr, 
                               ip_masklen (mask.sin.sin_addr),
-                              &gate.sin.sin_addr, NULL);
+                              &brd.sin.sin_addr);
       break;
 #ifdef HAVE_IPV6
     case AF_INET6:
@@ -505,12 +506,13 @@ ifam_read (struct ifa_msghdr *ifam)
        connected_add_ipv6 (ifp,
                            &addr.sin6.sin6_addr, 
                            ip6_masklen (mask.sin6.sin6_addr),
-                           &gate.sin6.sin6_addr);
+                           &brd.sin6.sin6_addr,
+                           (isalias ? ifname : NULL) );
       else
        connected_delete_ipv6 (ifp,
                               &addr.sin6.sin6_addr, 
                               ip6_masklen (mask.sin6.sin6_addr),
-                              &gate.sin6.sin6_addr);
+                              &brd.sin6.sin6_addr);
       break;
 #endif /* HAVE_IPV6 */
     default:
index 254c3bd7af1e7c3ce7de8716150e559b41702471..6db8496de6ae29f318c16527de72964d3ec3258c 100644 (file)
@@ -686,7 +686,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
       else
         connected_delete_ipv4 (ifp, flags,
                                (struct in_addr *) addr, ifa->ifa_prefixlen,
-                               (struct in_addr *) broad, label);
+                               (struct in_addr *) broad);
     }
 #ifdef HAVE_IPV6
   if (ifa->ifa_family == AF_INET6)
@@ -694,7 +694,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h)
       if (h->nlmsg_type == RTM_NEWADDR)
         connected_add_ipv6 (ifp,
                             (struct in6_addr *) addr, ifa->ifa_prefixlen,
-                            (struct in6_addr *) broad);
+                            (struct in6_addr *) broad, label);
       else
         connected_delete_ipv6 (ifp,
                                (struct in6_addr *) addr, ifa->ifa_prefixlen,