Annotation of embedaddon/quagga/pimd/pim_tlv.c, revision 1.1.1.1

1.1       misho       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
                     16:   along with this program; see the file COPYING; if not, write to the
                     17:   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
                     18:   MA 02110-1301 USA
                     19:   
                     20:   $QuaggaId: $Format:%an, %ai, %h$ $
                     21: */
                     22: 
                     23: #include <zebra.h>
                     24: 
                     25: #include "log.h"
                     26: #include "prefix.h"
                     27: 
                     28: #include "pimd.h"
                     29: #include "pim_int.h"
                     30: #include "pim_tlv.h"
                     31: #include "pim_str.h"
                     32: #include "pim_msg.h"
                     33: 
                     34: uint8_t *pim_tlv_append_uint16(uint8_t *buf,
                     35:                               const uint8_t *buf_pastend,
                     36:                               uint16_t option_type,
                     37:                               uint16_t option_value)
                     38: {
                     39:   uint16_t option_len = 2;
                     40: 
                     41:   if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
                     42:     return NULL;
                     43: 
                     44:   *(uint16_t *) buf = htons(option_type);
                     45:   buf += 2;
                     46:   *(uint16_t *) buf = htons(option_len);
                     47:   buf += 2;
                     48:   *(uint16_t *) buf = htons(option_value);
                     49:   buf += option_len;
                     50: 
                     51:   return buf;
                     52: }
                     53: 
                     54: uint8_t *pim_tlv_append_2uint16(uint8_t *buf,
                     55:                                const uint8_t *buf_pastend,
                     56:                                uint16_t option_type,
                     57:                                uint16_t option_value1,
                     58:                                uint16_t option_value2)
                     59: {
                     60:   uint16_t option_len = 4;
                     61: 
                     62:   if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
                     63:     return NULL;
                     64: 
                     65:   *(uint16_t *) buf = htons(option_type);
                     66:   buf += 2;
                     67:   *(uint16_t *) buf = htons(option_len);
                     68:   buf += 2;
                     69:   *(uint16_t *) buf = htons(option_value1);
                     70:   buf += 2;
                     71:   *(uint16_t *) buf = htons(option_value2);
                     72:   buf += 2;
                     73: 
                     74:   return buf;
                     75: }
                     76: 
                     77: uint8_t *pim_tlv_append_uint32(uint8_t *buf,
                     78:                               const uint8_t *buf_pastend,
                     79:                               uint16_t option_type,
                     80:                               uint32_t option_value)
                     81: {
                     82:   uint16_t option_len = 4;
                     83: 
                     84:   if ((buf + PIM_TLV_OPTION_SIZE(option_len)) > buf_pastend)
                     85:     return NULL;
                     86: 
                     87:   *(uint16_t *) buf = htons(option_type);
                     88:   buf += 2;
                     89:   *(uint16_t *) buf = htons(option_len);
                     90:   buf += 2;
                     91:   pim_write_uint32(buf, option_value);
                     92:   buf += option_len;
                     93: 
                     94:   return buf;
                     95: }
                     96: 
                     97: #define ucast_ipv4_encoding_len (2 + sizeof(struct in_addr))
                     98: 
                     99: uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf,
                    100:                                       const uint8_t *buf_pastend,
                    101:                                       struct list *ifconnected)
                    102: {
                    103:   struct listnode *node;
                    104:   uint16_t option_len = 0;
                    105: 
                    106:   uint8_t *curr;
                    107: 
                    108:   node = listhead(ifconnected);
                    109: 
                    110:   /* Empty address list ? */
                    111:   if (!node) {
                    112:     return buf;
                    113:   }
                    114: 
                    115:   /* Skip first address (primary) */
                    116:   node = listnextnode(node);
                    117: 
                    118:   /* Scan secondary address list */
                    119:   curr = buf + 4; /* skip T and L */
                    120:   for (; node; node = listnextnode(node)) {
                    121:     struct connected *ifc = listgetdata(node);
                    122:     struct prefix *p = ifc->address;
                    123:     
                    124:     if (p->family != AF_INET)
                    125:       continue;
                    126: 
                    127:     if ((curr + ucast_ipv4_encoding_len) > buf_pastend)
                    128:       return 0;
                    129: 
                    130:     /* Write encoded unicast IPv4 address */
                    131:     *(uint8_t *) curr = PIM_MSG_ADDRESS_FAMILY_IPV4; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
                    132:     ++curr;
                    133:     *(uint8_t *) curr = 0; /* ucast IPv4 native encoding type (RFC 4601: 4.9.1) */
                    134:     ++curr;
                    135:     memcpy(curr, &p->u.prefix4, sizeof(struct in_addr));
                    136:     curr += sizeof(struct in_addr);
                    137: 
                    138:     option_len += ucast_ipv4_encoding_len; 
                    139:   }
                    140: 
                    141:   if (PIM_DEBUG_PIM_TRACE) {
                    142:     zlog_debug("%s: number of encoded secondary unicast IPv4 addresses: %zu",
                    143:               __PRETTY_FUNCTION__,
                    144:               option_len / ucast_ipv4_encoding_len);
                    145:   }
                    146: 
                    147:   if (option_len < 1) {
                    148:     /* Empty secondary unicast IPv4 address list */
                    149:     return buf;
                    150:   }
                    151: 
                    152:   /*
                    153:    * Write T and L
                    154:    */
                    155:   *(uint16_t *) buf       = htons(PIM_MSG_OPTION_TYPE_ADDRESS_LIST);
                    156:   *(uint16_t *) (buf + 2) = htons(option_len);
                    157: 
                    158:   return curr;
                    159: }
                    160: 
                    161: static int check_tlv_length(const char *label, const char *tlv_name,
                    162:                            const char *ifname, struct in_addr src_addr,
                    163:                            int correct_len, int option_len)
                    164: {
                    165:   if (option_len != correct_len) {
                    166:     char src_str[100];
                    167:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    168:     zlog_warn("%s: PIM hello %s TLV with incorrect value size=%d correct=%d from %s on interface %s",
                    169:              label, tlv_name,
                    170:              option_len, correct_len,
                    171:              src_str, ifname);
                    172:     return -1;
                    173:   }
                    174: 
                    175:   return 0;
                    176: }
                    177: 
                    178: static void check_tlv_redefinition_uint16(const char *label, const char *tlv_name,
                    179:                                          const char *ifname, struct in_addr src_addr,
                    180:                                          pim_hello_options options,
                    181:                                          pim_hello_options opt_mask,
                    182:                                          uint16_t new, uint16_t old)
                    183: {
                    184:   if (PIM_OPTION_IS_SET(options, opt_mask)) {
                    185:     char src_str[100];
                    186:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    187:     zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
                    188:              label, tlv_name,
                    189:              new, old,
                    190:              src_str, ifname);
                    191:   }
                    192: }
                    193: 
                    194: static void check_tlv_redefinition_uint32(const char *label, const char *tlv_name,
                    195:                                          const char *ifname, struct in_addr src_addr,
                    196:                                          pim_hello_options options,
                    197:                                          pim_hello_options opt_mask,
                    198:                                          uint32_t new, uint32_t old)
                    199: {
                    200:   if (PIM_OPTION_IS_SET(options, opt_mask)) {
                    201:     char src_str[100];
                    202:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    203:     zlog_warn("%s: PIM hello TLV redefined %s=%u old=%u from %s on interface %s",
                    204:              label, tlv_name,
                    205:              new, old,
                    206:              src_str, ifname);
                    207:   }
                    208: }
                    209: 
                    210: static void check_tlv_redefinition_uint32_hex(const char *label, const char *tlv_name,
                    211:                                              const char *ifname, struct in_addr src_addr,
                    212:                                              pim_hello_options options,
                    213:                                              pim_hello_options opt_mask,
                    214:                                              uint32_t new, uint32_t old)
                    215: {
                    216:   if (PIM_OPTION_IS_SET(options, opt_mask)) {
                    217:     char src_str[100];
                    218:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    219:     zlog_warn("%s: PIM hello TLV redefined %s=%08x old=%08x from %s on interface %s",
                    220:              label, tlv_name,
                    221:              new, old,
                    222:              src_str, ifname);
                    223:   }
                    224: }
                    225: 
                    226: int pim_tlv_parse_holdtime(const char *ifname, struct in_addr src_addr,
                    227:                           pim_hello_options *hello_options,
                    228:                           uint16_t *hello_option_holdtime,
                    229:                           uint16_t option_len,
                    230:                           const uint8_t *tlv_curr) 
                    231: {
                    232:   const char *label = "holdtime";
                    233: 
                    234:   if (check_tlv_length(__PRETTY_FUNCTION__, label,
                    235:                       ifname, src_addr,
                    236:                       sizeof(uint16_t), option_len)) {
                    237:     return -1;
                    238:   }
                    239:   
                    240:   check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, label,
                    241:                                ifname, src_addr,
                    242:                                *hello_options, PIM_OPTION_MASK_HOLDTIME,
                    243:                                PIM_TLV_GET_HOLDTIME(tlv_curr),
                    244:                                *hello_option_holdtime);
                    245:   
                    246:   PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_HOLDTIME);
                    247:   
                    248:   *hello_option_holdtime = PIM_TLV_GET_HOLDTIME(tlv_curr);
                    249:   
                    250:   return 0;
                    251: }
                    252: 
                    253: int pim_tlv_parse_lan_prune_delay(const char *ifname, struct in_addr src_addr,
                    254:                                  pim_hello_options *hello_options,
                    255:                                  uint16_t *hello_option_propagation_delay,
                    256:                                  uint16_t *hello_option_override_interval,
                    257:                                  uint16_t option_len,
                    258:                                  const uint8_t *tlv_curr) 
                    259: {
                    260:   if (check_tlv_length(__PRETTY_FUNCTION__, "lan_prune_delay",
                    261:                       ifname, src_addr,
                    262:                       sizeof(uint32_t), option_len)) {
                    263:     return -1;
                    264:   }
                    265:   
                    266:   check_tlv_redefinition_uint16(__PRETTY_FUNCTION__, "propagation_delay",
                    267:                                ifname, src_addr,
                    268:                                *hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY,
                    269:                                PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr),
                    270:                                *hello_option_propagation_delay);
                    271:   
                    272:   PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY);
                    273:   
                    274:   *hello_option_propagation_delay = PIM_TLV_GET_PROPAGATION_DELAY(tlv_curr);
                    275:   if (PIM_TLV_GET_CAN_DISABLE_JOIN_SUPPRESSION(tlv_curr)) {
                    276:     PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
                    277:   }
                    278:   else {
                    279:     PIM_OPTION_UNSET(*hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION);
                    280:   }
                    281:   ++tlv_curr;
                    282:   ++tlv_curr;
                    283:   *hello_option_override_interval = PIM_TLV_GET_OVERRIDE_INTERVAL(tlv_curr);
                    284:   
                    285:   return 0;
                    286: }
                    287: 
                    288: int pim_tlv_parse_dr_priority(const char *ifname, struct in_addr src_addr,
                    289:                              pim_hello_options *hello_options,
                    290:                              uint32_t *hello_option_dr_priority,
                    291:                              uint16_t option_len,
                    292:                              const uint8_t *tlv_curr) 
                    293: {
                    294:   const char *label = "dr_priority";
                    295: 
                    296:   if (check_tlv_length(__PRETTY_FUNCTION__, label,
                    297:                       ifname, src_addr,
                    298:                       sizeof(uint32_t), option_len)) {
                    299:     return -1;
                    300:   }
                    301:   
                    302:   check_tlv_redefinition_uint32(__PRETTY_FUNCTION__, label,
                    303:                                ifname, src_addr,
                    304:                                *hello_options, PIM_OPTION_MASK_DR_PRIORITY,
                    305:                                PIM_TLV_GET_DR_PRIORITY(tlv_curr),
                    306:                                *hello_option_dr_priority);
                    307:   
                    308:   PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_DR_PRIORITY);
                    309:   
                    310:   *hello_option_dr_priority = PIM_TLV_GET_DR_PRIORITY(tlv_curr);
                    311: 
                    312:   return 0;
                    313: }
                    314: 
                    315: int pim_tlv_parse_generation_id(const char *ifname, struct in_addr src_addr,
                    316:                                pim_hello_options *hello_options,
                    317:                                uint32_t *hello_option_generation_id,
                    318:                                uint16_t option_len,
                    319:                                const uint8_t *tlv_curr) 
                    320: {
                    321:   const char *label = "generation_id";
                    322: 
                    323:   if (check_tlv_length(__PRETTY_FUNCTION__, label,
                    324:                       ifname, src_addr,
                    325:                       sizeof(uint32_t), option_len)) {
                    326:     return -1;
                    327:   }
                    328:   
                    329:   check_tlv_redefinition_uint32_hex(__PRETTY_FUNCTION__, label,
                    330:                                    ifname, src_addr,
                    331:                                    *hello_options, PIM_OPTION_MASK_GENERATION_ID,
                    332:                                    PIM_TLV_GET_GENERATION_ID(tlv_curr),
                    333:                                    *hello_option_generation_id);
                    334:   
                    335:   PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_GENERATION_ID);
                    336:   
                    337:   *hello_option_generation_id = PIM_TLV_GET_GENERATION_ID(tlv_curr);
                    338:   
                    339:   return 0;
                    340: }
                    341: 
                    342: int pim_parse_addr_ucast(const char *ifname, struct in_addr src_addr,
                    343:                         struct prefix *p,
                    344:                         const uint8_t *buf,
                    345:                         int buf_size)
                    346: {
                    347:   const int ucast_encoding_min_len = 3; /* 1 family + 1 type + 1 addr */
                    348:   const uint8_t *addr;
                    349:   const uint8_t *pastend;
                    350:   int family;
                    351:   int type;
                    352: 
                    353:   if (buf_size < ucast_encoding_min_len) {
                    354:     char src_str[100];
                    355:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    356:     zlog_warn("%s: unicast address encoding overflow: left=%d needed=%d from %s on %s",
                    357:              __PRETTY_FUNCTION__,
                    358:              buf_size, ucast_encoding_min_len,
                    359:              src_str, ifname);
                    360:     return -1;
                    361:   }
                    362: 
                    363:   addr = buf;
                    364:   pastend = buf + buf_size;
                    365: 
                    366:   family = *addr++;
                    367:   type = *addr++;
                    368: 
                    369:   switch (family) {
                    370:   case PIM_MSG_ADDRESS_FAMILY_IPV4:
                    371:     if (type) {
                    372:       char src_str[100];
                    373:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    374:       zlog_warn("%s: unknown unicast address encoding type=%d from %s on %s",
                    375:                __PRETTY_FUNCTION__,
                    376:                type, src_str, ifname);
                    377:       return -2;
                    378:     }
                    379: 
                    380:     if ((addr + sizeof(struct in_addr)) > pastend) {
                    381:       char src_str[100];
                    382:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    383:       zlog_warn("%s: IPv4 unicast address overflow: left=%zd needed=%zu from %s on %s",
                    384:                __PRETTY_FUNCTION__,
                    385:                pastend - addr, sizeof(struct in_addr),
                    386:                src_str, ifname);
                    387:       return -3;
                    388:     }
                    389: 
                    390:     p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
                    391:     memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
                    392: 
                    393:     addr += sizeof(struct in_addr);
                    394: 
                    395:     break;
                    396:   default:
                    397:     {
                    398:       char src_str[100];
                    399:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    400:       zlog_warn("%s: unknown unicast address encoding family=%d from %s on %s",
                    401:                __PRETTY_FUNCTION__,
                    402:                family, src_str, ifname);
                    403:       return -4;
                    404:     }
                    405:   }
                    406: 
                    407:   return addr - buf;
                    408: }
                    409: 
                    410: int pim_parse_addr_group(const char *ifname, struct in_addr src_addr,
                    411:                         struct prefix *p,
                    412:                         const uint8_t *buf,
                    413:                         int buf_size)
                    414: {
                    415:   const int grp_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
                    416:   const uint8_t *addr;
                    417:   const uint8_t *pastend;
                    418:   int family;
                    419:   int type;
                    420:   int mask_len;
                    421: 
                    422:   if (buf_size < grp_encoding_min_len) {
                    423:     char src_str[100];
                    424:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    425:     zlog_warn("%s: group address encoding overflow: left=%d needed=%d from %s on %s",
                    426:              __PRETTY_FUNCTION__,
                    427:              buf_size, grp_encoding_min_len,
                    428:              src_str, ifname);
                    429:     return -1;
                    430:   }
                    431: 
                    432:   addr = buf;
                    433:   pastend = buf + buf_size;
                    434: 
                    435:   family = *addr++;
                    436:   type = *addr++;
                    437:   //++addr;
                    438:   ++addr; /* skip b_reserved_z fields */
                    439:   mask_len = *addr++;
                    440: 
                    441:   switch (family) {
                    442:   case PIM_MSG_ADDRESS_FAMILY_IPV4:
                    443:     if (type) {
                    444:       char src_str[100];
                    445:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    446:       zlog_warn("%s: unknown group address encoding type=%d from %s on %s",
                    447:                __PRETTY_FUNCTION__,
                    448:                type, src_str, ifname);
                    449:       return -2;
                    450:     }
                    451: 
                    452:     if ((addr + sizeof(struct in_addr)) > pastend) {
                    453:       char src_str[100];
                    454:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    455:       zlog_warn("%s: IPv4 group address overflow: left=%zd needed=%zu from %s on %s",
                    456:                __PRETTY_FUNCTION__,
                    457:                pastend - addr, sizeof(struct in_addr),
                    458:                src_str, ifname);
                    459:       return -3;
                    460:     }
                    461: 
                    462:     p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
                    463:     memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
                    464:     p->prefixlen = mask_len;
                    465: 
                    466:     addr += sizeof(struct in_addr);
                    467: 
                    468:     break;
                    469:   default:
                    470:     {
                    471:       char src_str[100];
                    472:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    473:       zlog_warn("%s: unknown group address encoding family=%d from %s on %s",
                    474:                __PRETTY_FUNCTION__,
                    475:                family, src_str, ifname);
                    476:       return -4;
                    477:     }
                    478:   }
                    479: 
                    480:   return addr - buf;
                    481: }
                    482: 
                    483: int pim_parse_addr_source(const char *ifname,
                    484:                          struct in_addr src_addr,
                    485:                          struct prefix *p,
                    486:                          uint8_t *flags,
                    487:                          const uint8_t *buf,
                    488:                          int buf_size)
                    489: {
                    490:   const int src_encoding_min_len = 4; /* 1 family + 1 type + 1 reserved + 1 addr */
                    491:   const uint8_t *addr;
                    492:   const uint8_t *pastend;
                    493:   int family;
                    494:   int type;
                    495:   int mask_len;
                    496: 
                    497:   if (buf_size < src_encoding_min_len) {
                    498:     char src_str[100];
                    499:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    500:     zlog_warn("%s: source address encoding overflow: left=%d needed=%d from %s on %s",
                    501:              __PRETTY_FUNCTION__,
                    502:              buf_size, src_encoding_min_len,
                    503:              src_str, ifname);
                    504:     return -1;
                    505:   }
                    506: 
                    507:   addr = buf;
                    508:   pastend = buf + buf_size;
                    509: 
                    510:   family = *addr++;
                    511:   type = *addr++;
                    512:   *flags = *addr++;
                    513:   mask_len = *addr++;
                    514: 
                    515:   switch (family) {
                    516:   case PIM_MSG_ADDRESS_FAMILY_IPV4:
                    517:     if (type) {
                    518:       char src_str[100];
                    519:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    520:       zlog_warn("%s: unknown source address encoding type=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
                    521:                __PRETTY_FUNCTION__,
                    522:                type, src_str, ifname,
                    523:                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
                    524:       return -2;
                    525:     }
                    526: 
                    527:     if ((addr + sizeof(struct in_addr)) > pastend) {
                    528:       char src_str[100];
                    529:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    530:       zlog_warn("%s: IPv4 source address overflow: left=%zd needed=%zu from %s on %s",
                    531:                __PRETTY_FUNCTION__,
                    532:                pastend - addr, sizeof(struct in_addr),
                    533:                src_str, ifname);
                    534:       return -3;
                    535:     }
                    536: 
                    537:     p->family = AF_INET; /* notice: AF_INET != PIM_MSG_ADDRESS_FAMILY_IPV4 */
                    538:     memcpy(&p->u.prefix4, addr, sizeof(struct in_addr));
                    539:     p->prefixlen = mask_len;
                    540: 
                    541:     /* 
                    542:        RFC 4601: 4.9.1  Encoded Source and Group Address Formats
                    543: 
                    544:        Encoded-Source Address
                    545: 
                    546:        The mask length MUST be equal to the mask length in bits for
                    547:        the given Address Family and Encoding Type (32 for IPv4 native
                    548:        and 128 for IPv6 native).  A router SHOULD ignore any messages
                    549:        received with any other mask length.
                    550:     */
                    551:     if (p->prefixlen != 32) {
                    552:       char src_str[100];
                    553:       pim_inet4_dump("<src?>", p->u.prefix4, src_str, sizeof(src_str));
                    554:       zlog_warn("%s: IPv4 bad source address mask: %s/%d",
                    555:                __PRETTY_FUNCTION__, src_str, p->prefixlen);
                    556:       return -4;
                    557:     }
                    558: 
                    559:     addr += sizeof(struct in_addr);
                    560: 
                    561:     break;
                    562:   default:
                    563:     {
                    564:       char src_str[100];
                    565:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    566:       zlog_warn("%s: unknown source address encoding family=%d from %s on %s: %02x%02x%02x%02x%02x%02x%02x%02x",
                    567:                __PRETTY_FUNCTION__,
                    568:                family, src_str, ifname,
                    569:                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
                    570:       return -5;
                    571:     }
                    572:   }
                    573: 
                    574:   return addr - buf;
                    575: }
                    576: 
                    577: #define FREE_ADDR_LIST(hello_option_addr_list) \
                    578: { \
                    579:   if (hello_option_addr_list) { \
                    580:     list_delete(hello_option_addr_list); \
                    581:     hello_option_addr_list = 0; \
                    582:   } \
                    583: }
                    584: 
                    585: int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
                    586:                            pim_hello_options *hello_options,
                    587:                            struct list **hello_option_addr_list,
                    588:                            uint16_t option_len,
                    589:                            const uint8_t *tlv_curr) 
                    590: {
                    591:   const uint8_t *addr;
                    592:   const uint8_t *pastend;
                    593: 
                    594:   zassert(hello_option_addr_list);
                    595: 
                    596:   /*
                    597:     Scan addr list
                    598:    */
                    599:   addr = tlv_curr;
                    600:   pastend = tlv_curr + option_len;
                    601:   while (addr < pastend) {
                    602:     struct prefix tmp;
                    603:     int addr_offset;
                    604: 
                    605:     /*
                    606:       Parse ucast addr
                    607:      */
                    608:     addr_offset = pim_parse_addr_ucast(ifname, src_addr, &tmp,
                    609:                                       addr, pastend - addr);
                    610:     if (addr_offset < 1) {
                    611:       char src_str[100];
                    612:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    613:       zlog_warn("%s: pim_parse_addr_ucast() failure: from %s on %s",
                    614:                __PRETTY_FUNCTION__,
                    615:                src_str, ifname);
                    616:       FREE_ADDR_LIST(*hello_option_addr_list);
                    617:       return -1;
                    618:     }
                    619:     addr += addr_offset;
                    620: 
                    621:     /*
                    622:       Debug
                    623:      */
                    624:     if (PIM_DEBUG_PIM_TRACE) {
                    625:       switch (tmp.family) {
                    626:       case AF_INET:
                    627:        {
                    628:          char addr_str[100];
                    629:          char src_str[100];
                    630:          pim_inet4_dump("<addr?>", tmp.u.prefix4, addr_str, sizeof(addr_str));
                    631:          pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    632:          zlog_debug("%s: PIM hello TLV option: list_old_size=%d IPv4 address %s from %s on %s",
                    633:                     __PRETTY_FUNCTION__,
                    634:                     *hello_option_addr_list ?
                    635:                     ((int) listcount(*hello_option_addr_list)) : -1,
                    636:                     addr_str, src_str, ifname);
                    637:        }
                    638:        break;
                    639:       default:
                    640:        {
                    641:          char src_str[100];
                    642:          pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    643:          zlog_debug("%s: PIM hello TLV option: list_old_size=%d UNKNOWN address family from %s on %s",
                    644:                     __PRETTY_FUNCTION__,
                    645:                     *hello_option_addr_list ?
                    646:                     ((int) listcount(*hello_option_addr_list)) : -1,
                    647:                     src_str, ifname);
                    648:        }
                    649:       }
                    650:     }
                    651: 
                    652:     /*
                    653:       Exclude neighbor's primary address if incorrectly included in
                    654:       the secondary address list
                    655:      */
                    656:     if (tmp.family == AF_INET) {
                    657:       if (tmp.u.prefix4.s_addr == src_addr.s_addr) {
                    658:          char src_str[100];
                    659:          pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
                    660:          zlog_warn("%s: ignoring primary address in secondary list from %s on %s",
                    661:                    __PRETTY_FUNCTION__,
                    662:                    src_str, ifname);
                    663:          continue;
                    664:       }
                    665:     }
                    666: 
                    667:     /*
                    668:       Allocate list if needed
                    669:      */
                    670:     if (!*hello_option_addr_list) {
                    671:       *hello_option_addr_list = list_new();
                    672:       if (!*hello_option_addr_list) {
                    673:        zlog_err("%s %s: failure: hello_option_addr_list=list_new()",
                    674:                 __FILE__, __PRETTY_FUNCTION__);
                    675:        return -2;
                    676:       }
                    677:       (*hello_option_addr_list)->del = (void (*)(void *)) prefix_free;
                    678:     }
                    679: 
                    680:     /*
                    681:       Attach addr to list
                    682:      */
                    683:     {
                    684:       struct prefix *p;
                    685:       p = prefix_new();
                    686:       if (!p) {
                    687:        zlog_err("%s %s: failure: prefix_new()",
                    688:                 __FILE__, __PRETTY_FUNCTION__);
                    689:        FREE_ADDR_LIST(*hello_option_addr_list);
                    690:        return -3;
                    691:       }
                    692:       p->family = tmp.family;
                    693:       p->u.prefix4 = tmp.u.prefix4;
                    694:       listnode_add(*hello_option_addr_list, p);
                    695:     }
                    696: 
                    697:   } /* while (addr < pastend) */
                    698:   
                    699:   /*
                    700:     Mark hello option
                    701:    */
                    702:   PIM_OPTION_SET(*hello_options, PIM_OPTION_MASK_ADDRESS_LIST);
                    703:   
                    704:   return 0;
                    705: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>