back to topotato report
topotato coverage report
Current view: top level - pimd - pim_tlv.c (source / functions) Hit Total Coverage
Test: test_pim_crp.py::PIMCandidateBSRTest Lines: 173 304 56.9 %
Date: 2023-02-16 02:09:37 Functions: 11 16 68.8 %

          Line data    Source code
       1             : /*
       2             :  * PIM for Quagga
       3             :  * Copyright (C) 2008  Everton da Silva Marques
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation; either version 2 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful, but
      11             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13             :  * General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License along
      16             :  * with this program; see the file COPYING; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      18             :  */
      19             : 
      20             : #include <zebra.h>
      21             : 
      22             : #include "log.h"
      23             : #include "prefix.h"
      24             : #include "if.h"
      25             : 
      26             : #include "pimd.h"
      27             : #include "pim_instance.h"
      28             : #include "pim_int.h"
      29             : #include "pim_tlv.h"
      30             : #include "pim_str.h"
      31             : #include "pim_msg.h"
      32             : #include "pim_iface.h"
      33             : #include "pim_addr.h"
      34             : 
      35             : #if PIM_IPV == 4
      36             : #define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4
      37             : #else
      38             : #define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV6
      39             : #endif
      40             : 
      41          74 : uint8_t *pim_tlv_append_uint16(uint8_t *buf, const uint8_t *buf_pastend,
      42             :                                uint16_t option_type, uint16_t option_value)
      43             : {
      44          74 :         uint16_t option_len = 2;
      45             : 
      46          74 :         if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
      47             :                 return NULL;
      48             : 
      49          74 :         *(uint16_t *)buf = htons(option_type);
      50          74 :         buf += 2;
      51          74 :         *(uint16_t *)buf = htons(option_len);
      52          74 :         buf += 2;
      53          74 :         *(uint16_t *)buf = htons(option_value);
      54          74 :         buf += option_len;
      55             : 
      56          74 :         return buf;
      57             : }
      58             : 
      59          74 : uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend,
      60             :                                 uint16_t option_type, uint16_t option_value1,
      61             :                                 uint16_t option_value2)
      62             : {
      63          74 :         uint16_t option_len = 4;
      64             : 
      65          74 :         if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
      66             :                 return NULL;
      67             : 
      68          74 :         *(uint16_t *)buf = htons(option_type);
      69          74 :         buf += 2;
      70          74 :         *(uint16_t *)buf = htons(option_len);
      71          74 :         buf += 2;
      72          74 :         *(uint16_t *)buf = htons(option_value1);
      73          74 :         buf += 2;
      74          74 :         *(uint16_t *)buf = htons(option_value2);
      75          74 :         buf += 2;
      76             : 
      77          74 :         return buf;
      78             : }
      79             : 
      80         148 : uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
      81             :                                uint16_t option_type, uint32_t option_value)
      82             : {
      83         148 :         uint16_t option_len = 4;
      84             : 
      85         148 :         if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
      86             :                 return NULL;
      87             : 
      88         148 :         *(uint16_t *)buf = htons(option_type);
      89         148 :         buf += 2;
      90         148 :         *(uint16_t *)buf = htons(option_len);
      91         148 :         buf += 2;
      92         148 :         pim_write_uint32(buf, option_value);
      93         148 :         buf += option_len;
      94             : 
      95         148 :         return buf;
      96             : }
      97             : 
      98             : #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
      99             : #define ucast_ipv6_encoding_len (2 + sizeof(struct in6_addr))
     100             : 
     101             : /*
     102             :  * An Encoded-Unicast address takes the following format:
     103             :  *
     104             :  *   0                   1                   2                   3
     105             :  *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     106             :  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     107             :  *  |  Addr Family  | Encoding Type |     Unicast Address
     108             :  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
     109             :  *
     110             :  *  Addr Family
     111             :  *       The PIM address family of the 'Unicast Address' field of this
     112             :  *       address.
     113             :  *
     114             :  *       Values 0-127 are as assigned by the IANA for Internet Address   *
     115             :  * Families in [7].  Values 128-250 are reserved to be assigned by
     116             :  *       the IANA for PIM-specific Address Families.  Values 251 though
     117             :  *       255 are designated for private use.  As there is no assignment
     118             :  *       authority for this space, collisions should be expected.
     119             :  *
     120             :  *  Encoding Type
     121             :  *       The type of encoding used within a specific Address Family.  The
     122             :  *       value '0' is reserved for this field and represents the native
     123             :  *       encoding of the Address Family.
     124             :  *
     125             :  *  Unicast Address
     126             :  *       The unicast address as represented by the given Address Family
     127             :  *       and Encoding Type.
     128             :  */
     129           0 : int pim_encode_addr_ucast(uint8_t *buf, pim_addr addr)
     130             : {
     131           0 :         uint8_t *start = buf;
     132             : 
     133           0 :         *buf++ = PIM_MSG_ADDRESS_FAMILY;
     134           0 :         *buf++ = 0;
     135           0 :         memcpy(buf, &addr, sizeof(addr));
     136           0 :         buf += sizeof(addr);
     137             : 
     138           0 :         return buf - start;
     139             : }
     140             : 
     141         129 : int pim_encode_addr_ucast_prefix(uint8_t *buf, struct prefix *p)
     142             : {
     143         129 :         switch (p->family) {
     144          11 :         case AF_INET:
     145          11 :                 *buf = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET !=
     146             :                                                        PIM_MSG_ADDRESS_FAMILY_IPV4
     147             :                                                        */
     148          11 :                 ++buf;
     149          11 :                 *buf = 0; /* ucast IPv4 native encoding type (RFC
     150             :                                         4601: 4.9.1) */
     151          11 :                 ++buf;
     152          11 :                 memcpy(buf, &p->u.prefix4, sizeof(struct in_addr));
     153          11 :                 return ucast_ipv4_encoding_len;
     154         118 :         case AF_INET6:
     155         118 :                 *buf = PIM_MSG_ADDRESS_FAMILY_IPV6;
     156         118 :                 ++buf;
     157         118 :                 *buf = 0;
     158         118 :                 ++buf;
     159         118 :                 memcpy(buf, &p->u.prefix6, sizeof(struct in6_addr));
     160         118 :                 return ucast_ipv6_encoding_len;
     161             :         default:
     162             :                 return 0;
     163             :         }
     164             : }
     165             : 
     166             : #define group_ipv4_encoding_len (4 + sizeof(struct in_addr))
     167             : 
     168             : /*
     169             :  * Encoded-Group addresses take the following format:
     170             :  *
     171             :  *   0                   1                   2                   3
     172             :  *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     173             :  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     174             :  *  |  Addr Family  | Encoding Type |B| Reserved  |Z|  Mask Len     |
     175             :  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     176             :  *  |                Group multicast Address
     177             :  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+...
     178             :  *
     179             :  *  Addr Family
     180             :  *       Described above.
     181             :  *
     182             :  *  Encoding Type
     183             :  *       Described above.
     184             :  *
     185             :  *  [B]idirectional PIM
     186             :  *       Indicates the group range should use Bidirectional PIM [13].
     187             :  *       For PIM-SM defined in this specification, this bit MUST be zero.
     188             :  *
     189             :  *  Reserved
     190             :  *       Transmitted as zero.  Ignored upon receipt.
     191             :  *
     192             :  *  Admin Scope [Z]one
     193             :  *       indicates the group range is an admin scope zone.  This is used
     194             :  *       in the Bootstrap Router Mechanism [11] only.  For all other
     195             :  *       purposes, this bit is set to zero and ignored on receipt.
     196             :  *
     197             :  *  Mask Len
     198             :  *       The Mask length field is 8 bits.  The value is the number of
     199             :  *       contiguous one bits that are left justified and used as a mask;
     200             :  *       when combined with the group address, it describes a range of
     201             :  *       groups.  It is less than or equal to the address length in bits
     202             :  *       for the given Address Family and Encoding Type.  If the message
     203             :  *       is sent for a single group, then the Mask length must equal the
     204             :  *       address length in bits for the given Address Family and Encoding
     205             :  *       Type (e.g., 32 for IPv4 native encoding, 128 for IPv6 native
     206             :  *       encoding).
     207             :  *
     208             :  *  Group multicast Address
     209             :  *       Contains the group address.
     210             :  */
     211           0 : int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
     212             :                           pim_addr group)
     213             : {
     214           0 :         uint8_t *start = buf;
     215           0 :         uint8_t flags = 0;
     216             : 
     217           0 :         flags |= bidir << 8;
     218           0 :         flags |= scope;
     219             : 
     220           0 :         *buf++ = PIM_MSG_ADDRESS_FAMILY;
     221           0 :         *buf++ = 0;
     222           0 :         *buf++ = flags;
     223           0 :         *buf++ = sizeof(group) * 8;
     224           0 :         memcpy(buf, &group, sizeof(group));
     225           0 :         buf += sizeof(group);
     226             : 
     227           0 :         return buf - start;
     228             : }
     229             : 
     230         148 : uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
     231             :                                        struct interface *ifp, int family)
     232             : {
     233         148 :         struct listnode *node;
     234         148 :         uint16_t option_len = 0;
     235         148 :         uint8_t *curr;
     236         148 :         size_t uel;
     237         148 :         struct list *ifconnected = ifp->connected;
     238         148 :         struct pim_interface *pim_ifp = ifp->info;
     239         148 :         pim_addr addr;
     240             : 
     241         224 :         node = listhead(ifconnected);
     242             : 
     243             :         /* Empty address list ? */
     244         148 :         if (!node) {
     245             :                 return buf;
     246             :         }
     247             : 
     248         148 :         if (family == AF_INET)
     249             :                 uel = ucast_ipv4_encoding_len;
     250             :         else
     251          74 :                 uel = ucast_ipv6_encoding_len;
     252             : 
     253             :         /* Scan secondary address list */
     254         148 :         curr = buf + 4; /* skip T and L */
     255         546 :         for (; node; node = listnextnode(node)) {
     256         398 :                 struct connected *ifc = listgetdata(node);
     257         398 :                 struct prefix *p = ifc->address;
     258         398 :                 int l_encode;
     259             : 
     260         398 :                 addr = pim_addr_from_prefix(p);
     261         398 :                 if (!pim_addr_cmp(pim_ifp->primary_address, addr))
     262             :                         /* don't add the primary address
     263             :                          * into the secondary address list */
     264         140 :                         continue;
     265             : 
     266         258 :                 if ((curr + uel) > buf_pastend)
     267             :                         return 0;
     268             : 
     269         258 :                 if (p->family != family)
     270         129 :                         continue;
     271             : 
     272         129 :                 l_encode = pim_encode_addr_ucast_prefix(curr, p);
     273         129 :                 curr += l_encode;
     274         129 :                 option_len += l_encode;
     275             :         }
     276             : 
     277         148 :         if (PIM_DEBUG_PIM_TRACE_DETAIL) {
     278           0 :                 zlog_debug(
     279             :                         "%s: number of encoded secondary unicast IPv4 addresses: %zu",
     280             :                         __func__, option_len / uel);
     281             :         }
     282             : 
     283         148 :         if (option_len < 1) {
     284             :                 /* Empty secondary unicast IPv4 address list */
     285             :                 return buf;
     286             :         }
     287             : 
     288             :         /*
     289             :          * Write T and L
     290             :          */
     291          72 :         *(uint16_t *)buf = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
     292          72 :         *(uint16_t *)(buf + 2) = htons(option_len);
     293             : 
     294          72 :         return curr;
     295             : }
     296             : 
     297         416 : static int check_tlv_length(const char *label, const char *tlv_name,
     298             :                             const char *ifname, pim_addr src_addr,
     299             :                             int correct_len, int option_len)
     300             : {
     301         416 :         if (option_len != correct_len) {
     302           0 :                 zlog_warn(
     303             :                         "%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %pPAs on interface %s",
     304             :                         label, tlv_name, option_len, correct_len, &src_addr,
     305             :                         ifname);
     306           0 :                 return -1;
     307             :         }
     308             : 
     309             :         return 0;
     310             : }
     311             : 
     312         208 : static void check_tlv_redefinition_uint16(const char *label,
     313             :                                           const char *tlv_name,
     314             :                                           const char *ifname, pim_addr src_addr,
     315             :                                           pim_hello_options options,
     316             :                                           pim_hello_options opt_mask,
     317             :                                           uint16_t new, uint16_t old)
     318             : {
     319         208 :         if (PIM_OPTION_IS_SET(options, opt_mask))
     320           0 :                 zlog_warn(
     321             :                         "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
     322             :                         label, tlv_name, new, old, &src_addr, ifname);
     323             : }
     324             : 
     325         104 : static void check_tlv_redefinition_uint32(const char *label,
     326             :                                           const char *tlv_name,
     327             :                                           const char *ifname, pim_addr src_addr,
     328             :                                           pim_hello_options options,
     329             :                                           pim_hello_options opt_mask,
     330             :                                           uint32_t new, uint32_t old)
     331             : {
     332         104 :         if (PIM_OPTION_IS_SET(options, opt_mask))
     333           0 :                 zlog_warn(
     334             :                         "%s: PIM hello TLV redefined %s=%u old=%u from %pPAs on interface %s",
     335             :                         label, tlv_name, new, old, &src_addr, ifname);
     336             : }
     337             : 
     338         104 : static void check_tlv_redefinition_uint32_hex(
     339             :         const char *label, const char *tlv_name, const char *ifname,
     340             :         pim_addr src_addr, pim_hello_options options,
     341             :         pim_hello_options opt_mask, uint32_t new, uint32_t old)
     342             : {
     343         104 :         if (PIM_OPTION_IS_SET(options, opt_mask))
     344           0 :                 zlog_warn(
     345             :                         "%s: PIM hello TLV redefined %s=%08x old=%08x from %pPAs on interface %s",
     346             :                         label, tlv_name, new, old, &src_addr, ifname);
     347             : }
     348             : 
     349         104 : int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
     350             :                            pim_hello_options *hello_options,
     351             :                            uint16_t *hello_option_holdtime, uint16_t option_len,
     352             :                            const uint8_t *tlv_curr)
     353             : {
     354         104 :         const char *label = "holdtime";
     355             : 
     356         104 :         if (check_tlv_length(__func__, label, ifname, src_addr,
     357             :                              sizeof(uint16_t), option_len)) {
     358           0 :                 return -1;
     359             :         }
     360             : 
     361         208 :         check_tlv_redefinition_uint16(__func__, label, ifname, src_addr,
     362             :                                       *hello_options, PIM_OPTION_MASK_HOLDTIME,
     363         104 :                                       PIM_TLV_GET_HOLDTIME(tlv_curr),
     364         104 :                                       *hello_option_holdtime);
     365             : 
     366         104 :         PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
     367             : 
     368         104 :         *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
     369             : 
     370         104 :         return 0;
     371             : }
     372             : 
     373         104 : int pim_tlv_parse_lan_prune_delay(const char *ifname, pim_addr src_addr,
     374             :                                   pim_hello_options *hello_options,
     375             :                                   uint16_t *hello_option_propagation_delay,
     376             :                                   uint16_t *hello_option_override_interval,
     377             :                                   uint16_t option_len, const uint8_t *tlv_curr)
     378             : {
     379         104 :         if (check_tlv_length(__func__, "lan_prune_delay", ifname, src_addr,
     380             :                              sizeof(uint32_t), option_len)) {
     381           0 :                 return -1;
     382             :         }
     383             : 
     384         208 :         check_tlv_redefinition_uint16(__func__, "propagation_delay", ifname,
     385             :                                       src_addr, *hello_options,
     386             :                                       PIM_OPTION_MASK_LAN_PRUNE_DELAY,
     387         104 :                                       PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
     388         104 :                                       *hello_option_propagation_delay);
     389             : 
     390         104 :         PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
     391             : 
     392         104 :         *hello_option_propagation_delay =
     393         104 :                 PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
     394         104 :         if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
     395           0 :                 PIM_OPTION_SET(*hello_options,
     396             :                                PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
     397             :         } else {
     398         104 :                 PIM_OPTION_UNSET(*hello_options,
     399             :                                  PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
     400             :         }
     401         104 :         ++tlv_curr;
     402         104 :         ++tlv_curr;
     403         104 :         *hello_option_override_interval =
     404         104 :                 PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
     405             : 
     406         104 :         return 0;
     407             : }
     408             : 
     409         104 : int pim_tlv_parse_dr_priority(const char *ifname, pim_addr src_addr,
     410             :                               pim_hello_options *hello_options,
     411             :                               uint32_t *hello_option_dr_priority,
     412             :                               uint16_t option_len, const uint8_t *tlv_curr)
     413             : {
     414         104 :         const char *label = "dr_priority";
     415             : 
     416         104 :         if (check_tlv_length(__func__, label, ifname, src_addr,
     417             :                              sizeof(uint32_t), option_len)) {
     418           0 :                 return -1;
     419             :         }
     420             : 
     421         208 :         check_tlv_redefinition_uint32(
     422             :                 __func__, label, ifname, src_addr, *hello_options,
     423         104 :                 PIM_OPTION_MASK_DR_PRIORITY, PIM_TLV_GET_DR_PRIORITY(tlv_curr),
     424             :                 *hello_option_dr_priority);
     425             : 
     426         104 :         PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
     427             : 
     428         104 :         *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
     429             : 
     430         104 :         return 0;
     431             : }
     432             : 
     433         104 : int pim_tlv_parse_generation_id(const char *ifname, pim_addr src_addr,
     434             :                                 pim_hello_options *hello_options,
     435             :                                 uint32_t *hello_option_generation_id,
     436             :                                 uint16_t option_len, const uint8_t *tlv_curr)
     437             : {
     438         104 :         const char *label = "generation_id";
     439             : 
     440         104 :         if (check_tlv_length(__func__, label, ifname, src_addr,
     441             :                              sizeof(uint32_t), option_len)) {
     442           0 :                 return -1;
     443             :         }
     444             : 
     445         208 :         check_tlv_redefinition_uint32_hex(__func__, label, ifname, src_addr,
     446             :                                           *hello_options,
     447             :                                           PIM_OPTION_MASK_GENERATION_ID,
     448         104 :                                           PIM_TLV_GET_GENERATION_ID(tlv_curr),
     449             :                                           *hello_option_generation_id);
     450             : 
     451         104 :         PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
     452             : 
     453         104 :         *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
     454             : 
     455         104 :         return 0;
     456             : }
     457             : 
     458         208 : int pim_parse_addr_ucast_prefix(struct prefix *p, const uint8_t *buf,
     459             :                                 int buf_size)
     460             : {
     461         208 :         const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
     462         208 :         const uint8_t *addr;
     463         208 :         const uint8_t *pastend;
     464         208 :         int family;
     465         208 :         int type;
     466             : 
     467         208 :         if (buf_size < ucast_encoding_min_len) {
     468           0 :                 zlog_warn(
     469             :                         "%s: unicast address encoding overflow: left=%d needed=%d",
     470             :                         __func__, buf_size, ucast_encoding_min_len);
     471           0 :                 return -1;
     472             :         }
     473             : 
     474         208 :         addr = buf;
     475         208 :         pastend = buf + buf_size;
     476             : 
     477         208 :         family = *addr++;
     478         208 :         type = *addr++;
     479             : 
     480         208 :         if (type) {
     481           0 :                 zlog_warn("%s: unknown unicast address encoding type=%d",
     482             :                           __func__, type);
     483           0 :                 return -2;
     484             :         }
     485             : 
     486         208 :         switch (family) {
     487           0 :         case PIM_MSG_ADDRESS_FAMILY_IPV4:
     488           0 :                 if ((addr + sizeof(struct in_addr)) > pastend) {
     489           0 :                         zlog_warn(
     490             :                                 "%s: IPv4 unicast address overflow: left=%td needed=%zu",
     491             :                                 __func__, pastend - addr,
     492             :                                 sizeof(struct in_addr));
     493           0 :                         return -3;
     494             :                 }
     495             : 
     496           0 :                 p->family = AF_INET; /* notice: AF_INET !=
     497             :                                         PIM_MSG_ADDRESS_FAMILY_IPV4 */
     498           0 :                 memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
     499           0 :                 p->prefixlen = IPV4_MAX_BITLEN;
     500           0 :                 addr += sizeof(struct in_addr);
     501             : 
     502           0 :                 break;
     503         208 :         case PIM_MSG_ADDRESS_FAMILY_IPV6:
     504         208 :                 if ((addr + sizeof(struct in6_addr)) > pastend) {
     505           0 :                         zlog_warn(
     506             :                                 "%s: IPv6 unicast address overflow: left=%td needed %zu",
     507             :                                 __func__, pastend - addr,
     508             :                                 sizeof(struct in6_addr));
     509           0 :                         return -3;
     510             :                 }
     511             : 
     512         208 :                 p->family = AF_INET6;
     513         208 :                 p->prefixlen = IPV6_MAX_BITLEN;
     514         208 :                 memcpy(&p->u.prefix6, addr, sizeof(struct in6_addr));
     515         208 :                 addr += sizeof(struct in6_addr);
     516             : 
     517         208 :                 break;
     518           0 :         default: {
     519           0 :                 zlog_warn("%s: unknown unicast address encoding family=%d from",
     520             :                           __func__, family);
     521           0 :                 return -4;
     522             :         }
     523             :         }
     524             : 
     525         208 :         return addr - buf;
     526             : }
     527             : 
     528           0 : int pim_parse_addr_ucast(pim_addr *out, const uint8_t *buf, int buf_size,
     529             :                          bool *wrong_af)
     530             : {
     531           0 :         struct prefix p;
     532           0 :         int ret;
     533             : 
     534           0 :         ret = pim_parse_addr_ucast_prefix(&p, buf, buf_size);
     535           0 :         if (ret < 0)
     536             :                 return ret;
     537             : 
     538           0 :         if (p.family != PIM_AF) {
     539           0 :                 *wrong_af = true;
     540           0 :                 return -5;
     541             :         }
     542             : 
     543           0 :         memcpy(out, &p.u.val, sizeof(*out));
     544           0 :         return ret;
     545             : }
     546             : 
     547           0 : int pim_parse_addr_group(pim_sgaddr *sg, const uint8_t *buf, int buf_size)
     548             : {
     549           0 :         const int grp_encoding_min_len =
     550             :                 4; /* 1 family + 1 type + 1 reserved + 1 addr */
     551           0 :         const uint8_t *addr;
     552           0 :         const uint8_t *pastend;
     553           0 :         int family;
     554           0 :         int type;
     555           0 :         int mask_len;
     556             : 
     557           0 :         if (buf_size < grp_encoding_min_len) {
     558           0 :                 zlog_warn(
     559             :                         "%s: group address encoding overflow: left=%d needed=%d",
     560             :                         __func__, buf_size, grp_encoding_min_len);
     561           0 :                 return -1;
     562             :         }
     563             : 
     564           0 :         addr = buf;
     565           0 :         pastend = buf + buf_size;
     566             : 
     567           0 :         family = *addr++;
     568           0 :         type = *addr++;
     569           0 :         ++addr; /* skip b_reserved_z fields */
     570           0 :         mask_len = *addr++;
     571             : 
     572           0 :         if (type) {
     573           0 :                 zlog_warn("%s: unknown group address encoding type=%d from",
     574             :                           __func__, type);
     575           0 :                 return -2;
     576             :         }
     577             : 
     578           0 :         if (family != PIM_MSG_ADDRESS_FAMILY) {
     579           0 :                 zlog_warn(
     580             :                         "%s: unknown group address encoding family=%d mask_len=%d from",
     581             :                         __func__, family, mask_len);
     582           0 :                 return -4;
     583             :         }
     584             : 
     585           0 :         if ((addr + sizeof(sg->grp)) > pastend) {
     586           0 :                 zlog_warn(
     587             :                         "%s: group address overflow: left=%td needed=%zu from",
     588             :                         __func__, pastend - addr, sizeof(sg->grp));
     589           0 :                 return -3;
     590             :         }
     591             : 
     592           0 :         memcpy(&sg->grp, addr, sizeof(sg->grp));
     593           0 :         addr += sizeof(sg->grp);
     594             : 
     595           0 :         return addr - buf;
     596             : }
     597             : 
     598           0 : int pim_parse_addr_source(pim_sgaddr *sg, uint8_t *flags, const uint8_t *buf,
     599             :                           int buf_size)
     600             : {
     601           0 :         const int src_encoding_min_len =
     602             :                 4; /* 1 family + 1 type + 1 reserved + 1 addr */
     603           0 :         const uint8_t *addr;
     604           0 :         const uint8_t *pastend;
     605           0 :         int family;
     606           0 :         int type;
     607           0 :         int mask_len;
     608             : 
     609           0 :         if (buf_size < src_encoding_min_len) {
     610           0 :                 zlog_warn(
     611             :                         "%s: source address encoding overflow: left=%d needed=%d",
     612             :                         __func__, buf_size, src_encoding_min_len);
     613           0 :                 return -1;
     614             :         }
     615             : 
     616           0 :         addr = buf;
     617           0 :         pastend = buf + buf_size;
     618             : 
     619           0 :         family = *addr++;
     620           0 :         type = *addr++;
     621           0 :         *flags = *addr++;
     622           0 :         mask_len = *addr++;
     623             : 
     624           0 :         if (type) {
     625           0 :                 zlog_warn(
     626             :                         "%s: unknown source address encoding type=%d: %02x%02x%02x%02x",
     627             :                         __func__, type, buf[0], buf[1], buf[2], buf[3]);
     628           0 :                 return -2;
     629             :         }
     630             : 
     631           0 :         switch (family) {
     632           0 :         case PIM_MSG_ADDRESS_FAMILY:
     633           0 :                 if ((addr + sizeof(sg->src)) > pastend) {
     634           0 :                         zlog_warn(
     635             :                                 "%s: IP source address overflow: left=%td needed=%zu",
     636             :                                 __func__, pastend - addr, sizeof(sg->src));
     637           0 :                         return -3;
     638             :                 }
     639             : 
     640           0 :                 memcpy(&sg->src, addr, sizeof(sg->src));
     641             : 
     642             :                 /*
     643             :                    RFC 4601: 4.9.1  Encoded Source and Group Address Formats
     644             : 
     645             :                    Encoded-Source Address
     646             : 
     647             :                    The mask length MUST be equal to the mask length in bits for
     648             :                    the given Address Family and Encoding Type (32 for IPv4
     649             :                    native and 128 for IPv6 native).  A router SHOULD ignore any
     650             :                    messages received with any other mask length.
     651             :                 */
     652           0 :                 if (mask_len != PIM_MAX_BITLEN) {
     653           0 :                         zlog_warn("%s: IP bad source address mask: %d",
     654             :                                   __func__, mask_len);
     655           0 :                         return -4;
     656             :                 }
     657             : 
     658           0 :                 addr += sizeof(sg->src);
     659             : 
     660             :                 break;
     661           0 :         default:
     662           0 :                 zlog_warn(
     663             :                         "%s: unknown source address encoding family=%d: %02x%02x%02x%02x",
     664             :                         __func__, family, buf[0], buf[1], buf[2], buf[3]);
     665           0 :                 return -5;
     666             :         }
     667             : 
     668             :         return addr - buf;
     669             : }
     670             : 
     671             : #define FREE_ADDR_LIST(hello_option_addr_list)                                 \
     672             :         {                                                                      \
     673             :                 if (hello_option_addr_list) {                                  \
     674             :                         list_delete(&hello_option_addr_list);                  \
     675             :                         hello_option_addr_list = 0;                            \
     676             :                 }                                                              \
     677             :         }
     678             : 
     679         104 : int pim_tlv_parse_addr_list(const char *ifname, pim_addr src_addr,
     680             :                             pim_hello_options *hello_options,
     681             :                             struct list **hello_option_addr_list,
     682             :                             uint16_t option_len, const uint8_t *tlv_curr)
     683             : {
     684         104 :         const uint8_t *addr;
     685         104 :         const uint8_t *pastend;
     686             : 
     687         104 :         assert(hello_option_addr_list);
     688             : 
     689             :         /*
     690             :           Scan addr list
     691             :          */
     692         104 :         addr = tlv_curr;
     693         104 :         pastend = tlv_curr + option_len;
     694         312 :         while (addr < pastend) {
     695         208 :                 struct prefix tmp, src_pfx;
     696         208 :                 int addr_offset;
     697             : 
     698             :                 /*
     699             :                   Parse ucast addr
     700             :                  */
     701         208 :                 addr_offset =
     702         208 :                         pim_parse_addr_ucast_prefix(&tmp, addr, pastend - addr);
     703         208 :                 if (addr_offset < 1) {
     704           0 :                         zlog_warn(
     705             :                                 "%s: pim_parse_addr_ucast() failure: from %pPAs on %s",
     706             :                                 __func__, &src_addr, ifname);
     707           0 :                         FREE_ADDR_LIST(*hello_option_addr_list);
     708           0 :                         return -1;
     709             :                 }
     710         208 :                 addr += addr_offset;
     711             : 
     712             :                 /*
     713             :                   Debug
     714             :                  */
     715         208 :                 if (PIM_DEBUG_PIM_TRACE) {
     716           0 :                         switch (tmp.family) {
     717           0 :                         case AF_INET: {
     718           0 :                                 char addr_str[INET_ADDRSTRLEN];
     719           0 :                                 pim_inet4_dump("<addr?>", tmp.u.prefix4,
     720             :                                                addr_str, sizeof(addr_str));
     721           0 :                                 zlog_debug(
     722             :                                         "%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %pPAs on %s",
     723             :                                         __func__,
     724             :                                         *hello_option_addr_list
     725             :                                                 ? ((int)listcount(
     726             :                                                           *hello_option_addr_list))
     727             :                                                 : -1,
     728             :                                         addr_str, &src_addr, ifname);
     729           0 :                         } break;
     730             :                         case AF_INET6:
     731             :                                 break;
     732           0 :                         default:
     733           0 :                                 zlog_debug(
     734             :                                         "%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %pPAs on %s",
     735             :                                         __func__,
     736             :                                         *hello_option_addr_list
     737             :                                                 ? ((int)listcount(
     738             :                                                           *hello_option_addr_list))
     739             :                                                 : -1,
     740             :                                         &src_addr, ifname);
     741             :                         }
     742             :                 }
     743             : 
     744             :                 /*
     745             :                   Exclude neighbor's primary address if incorrectly included in
     746             :                   the secondary address list
     747             :                  */
     748         208 :                 pim_addr_to_prefix(&src_pfx, src_addr);
     749         208 :                 if (!prefix_cmp(&tmp, &src_pfx)) {
     750           0 :                         zlog_warn(
     751             :                                 "%s: ignoring primary address in secondary list from %pPAs on %s",
     752             :                                 __func__, &src_addr, ifname);
     753           0 :                         continue;
     754             :                 }
     755             : 
     756             :                 /*
     757             :                   Allocate list if needed
     758             :                  */
     759         208 :                 if (!*hello_option_addr_list) {
     760         104 :                         *hello_option_addr_list = list_new();
     761         104 :                         (*hello_option_addr_list)->del = prefix_free_lists;
     762             :                 }
     763             : 
     764             :                 /*
     765             :                   Attach addr to list
     766             :                  */
     767             :                 {
     768         208 :                         struct prefix *p;
     769         208 :                         p = prefix_new();
     770         208 :                         prefix_copy(p, &tmp);
     771         208 :                         listnode_add(*hello_option_addr_list, p);
     772             :                 }
     773             : 
     774             :         } /* while (addr < pastend) */
     775             : 
     776             :         /*
     777             :           Mark hello option
     778             :          */
     779         104 :         PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
     780             : 
     781         104 :         return 0;
     782             : }

Generated by: LCOV version v1.16-topotato