]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Add ability to encode/decode v6 secondary addresses
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 30 Mar 2017 04:07:18 +0000 (00:07 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 30 Mar 2017 13:34:03 +0000 (09:34 -0400)
Add ability to encode/decode the v6 secondary addresses
if they are passed to us.

This also fixes the issue where if we are passed
a v6 secondary address list we will not refuse
to form neighbors.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_hello.c
pimd/pim_tlv.c
pimd/pim_tlv.h

index 3d7ae4ad22bdc977bdd2b45848aab3157341b1a3..d9b04ea9526fb7eab0cead5d6a79ac4a44edcdd8 100644 (file)
@@ -507,7 +507,8 @@ int pim_hello_build_tlv(const char *ifname,
   if (ifconnected) {
     curr = pim_tlv_append_addrlist_ucast(curr,
                                         pastend,
-                                        ifconnected);
+                                        ifconnected,
+                                         AF_INET);
     if (!curr) {
       if (PIM_DEBUG_PIM_HELLO) {
        zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s",
index 5223f60e1b223aa6be5769ce42e1b22e7ca8d05d..1d58ce3ac63f7f5bd3e54cd5478b51c15d937091 100644 (file)
@@ -94,6 +94,7 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,
 }
 
 #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
+#define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr))
 
 /*
  * An Encoded-Unicast address takes the following format:
@@ -135,6 +136,14 @@ pim_encode_addr_ucast (uint8_t *buf, struct prefix *p)
       memcpy (buf, &p->u.prefix4, sizeof (struct in_addr));
       return ucast_ipv4_encoding_len;
       break;
+    case AF_INET6:
+      *(uint8_t *)buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
+      ++buf;
+      *(uint8_t *)buf = 0;
+      ++buf;
+      memcpy (buf, &p->u.prefix6, sizeof (struct in6_addr));
+      return ucast_ipv6_encoding_len;
+      break;
     default:
       return 0;
       break;
@@ -216,12 +225,13 @@ pim_encode_addr_group (uint8_t *buf, afi_t afi, int bidir, int scope, struct in_
 
 uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
                                       const uint8_t *buf_pastend,
-                                      struct list *ifconnected)
+                                      struct list *ifconnected,
+                                       int family)
 {
   struct listnode *node;
   uint16_t option_len = 0;
-
   uint8_t *curr;
+  size_t uel;
 
   node = listhead(ifconnected);
 
@@ -230,8 +240,10 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
     return buf;
   }
 
-  /* Skip first address (primary) */
-  node = listnextnode(node);
+  if (family == AF_INET)
+    uel = ucast_ipv4_encoding_len;
+  else
+    uel = ucast_ipv6_encoding_len;
 
   /* Scan secondary address list */
   curr = buf + 4; /* skip T and L */
@@ -240,8 +252,14 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
     struct prefix *p = ifc->address;
     int l_encode;
 
-    if ((curr + ucast_ipv4_encoding_len) > buf_pastend)
-      return 0;
+    if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+      continue;
+
+    if ((curr + uel) > buf_pastend)
+          return 0;
+
+    if (p->family != family)
+      continue;
 
     l_encode = pim_encode_addr_ucast (curr, p);
     curr += l_encode;
@@ -251,7 +269,7 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
   if (PIM_DEBUG_PIM_TRACE_DETAIL) {
     zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu",
               __PRETTY_FUNCTION__,
-              option_len / ucast_ipv4_encoding_len);
+              option_len / uel);
   }
 
   if (option_len < 1) {
@@ -491,9 +509,23 @@ pim_parse_addr_ucast (struct prefix *p,
 
     p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
     memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
-
+    p->prefixlen = IPV4_MAX_PREFIXLEN;
     addr += sizeof(struct in_addr);
 
+    break;
+  case PIM_MSG_ADDRESS_FAMILY_IPV6:
+    if ((addr + sizeof(struct in6_addr)) > pastend) {
+      zlog_warn ("%s: IPv6 unicast address overflow: left=%zd needed %zu",
+                 __PRETTY_FUNCTION__,
+                 pastend - addr, sizeof(struct in6_addr));
+      return -3;
+    }
+
+    p->family = AF_INET6;
+    p->prefixlen = IPV6_MAX_PREFIXLEN;
+    memcpy(&p->u.prefix6, addr, 16);
+    addr += sizeof(struct in6_addr);
+
     break;
   default:
     {
@@ -706,6 +738,8 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
                     addr_str, src_str, ifname);
        }
        break;
+      case AF_INET6:
+        break;
       default:
        {
          char src_str[INET_ADDRSTRLEN];
@@ -759,8 +793,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
        FREE_ADDR_LIST(*hello_option_addr_list);
        return -3;
       }
-      p->family = tmp.family;
-      p->u.prefix4 = tmp.u.prefix4;
+      prefix_copy(p, &tmp);
       listnode_add(*hello_option_addr_list, p);
     }
 
index 9c4ebc9f0f86d5468e31d4cf5341096ce6bc43e2..7e0a8a147f9e9ea8f0ea293ab60af23b1f4a0e0e 100644 (file)
@@ -80,7 +80,8 @@ uint8_t *pim_tlv_append_uint32(uint8_t *buf,
                               uint32_t option_value);
 uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
                                       const uint8_t *buf_pastend,
-                                      struct list *ifconnected);
+                                      struct list *ifconnected,
+                                       int family);
 
 int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
                           pim_hello_options *hello_options,