Annotation of embedaddon/quagga/pimd/pim_hello.c, revision 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: 
        !            27: #include "pimd.h"
        !            28: #include "pim_pim.h"
        !            29: #include "pim_str.h"
        !            30: #include "pim_tlv.h"
        !            31: #include "pim_util.h"
        !            32: #include "pim_hello.h"
        !            33: #include "pim_iface.h"
        !            34: #include "pim_neighbor.h"
        !            35: #include "pim_upstream.h"
        !            36: 
        !            37: static void on_trace(const char *label,
        !            38:                     struct interface *ifp, struct in_addr src)
        !            39: {
        !            40:   if (PIM_DEBUG_PIM_TRACE) {
        !            41:     char src_str[100];
        !            42:     pim_inet4_dump("<src?>", src, src_str, sizeof(src_str));
        !            43:     zlog_debug("%s: from %s on %s",
        !            44:               label, src_str, ifp->name);
        !            45:   }
        !            46: }
        !            47: 
        !            48: static void tlv_trace_bool(const char *label, const char *tlv_name,
        !            49:                           const char *ifname, struct in_addr src_addr,
        !            50:                           int isset, int value)
        !            51: {
        !            52:   if (isset) {
        !            53:     char src_str[100];
        !            54:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !            55:     zlog_debug("%s: PIM hello option from %s on interface %s: %s=%d",
        !            56:               label, 
        !            57:               src_str, ifname,
        !            58:               tlv_name, value);
        !            59:   }
        !            60: }
        !            61: 
        !            62: static void tlv_trace_uint16(const char *label, const char *tlv_name,
        !            63:                             const char *ifname, struct in_addr src_addr,
        !            64:                             int isset, uint16_t value)
        !            65: {
        !            66:   if (isset) {
        !            67:     char src_str[100];
        !            68:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !            69:     zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u",
        !            70:               label, 
        !            71:               src_str, ifname,
        !            72:               tlv_name, value);
        !            73:   }
        !            74: }
        !            75: 
        !            76: static void tlv_trace_uint32(const char *label, const char *tlv_name,
        !            77:                             const char *ifname, struct in_addr src_addr,
        !            78:                             int isset, uint32_t value)
        !            79: {
        !            80:   if (isset) {
        !            81:     char src_str[100];
        !            82:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !            83:     zlog_debug("%s: PIM hello option from %s on interface %s: %s=%u",
        !            84:               label, 
        !            85:               src_str, ifname,
        !            86:               tlv_name, value);
        !            87:   }
        !            88: }
        !            89: 
        !            90: static void tlv_trace_uint32_hex(const char *label, const char *tlv_name,
        !            91:                                 const char *ifname, struct in_addr src_addr,
        !            92:                                 int isset, uint32_t value)
        !            93: {
        !            94:   if (isset) {
        !            95:     char src_str[100];
        !            96:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !            97:     zlog_debug("%s: PIM hello option from %s on interface %s: %s=%08x",
        !            98:               label, 
        !            99:               src_str, ifname,
        !           100:               tlv_name, value);
        !           101:   }
        !           102: }
        !           103: 
        !           104: #if 0
        !           105: static void tlv_trace(const char *label, const char *tlv_name,
        !           106:                      const char *ifname, struct in_addr src_addr,
        !           107:                      int isset)
        !           108: {
        !           109:   if (isset) {
        !           110:     char src_str[100];
        !           111:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           112:     zlog_debug("%s: PIM hello option from %s on interface %s: %s",
        !           113:               label, 
        !           114:               src_str, ifname,
        !           115:               tlv_name);
        !           116:   }
        !           117: }
        !           118: #endif
        !           119: 
        !           120: static void tlv_trace_list(const char *label, const char *tlv_name,
        !           121:                           const char *ifname, struct in_addr src_addr,
        !           122:                           int isset, struct list *addr_list)
        !           123: {
        !           124:   if (isset) {
        !           125:     char src_str[100];
        !           126:     pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           127:     zlog_debug("%s: PIM hello option from %s on interface %s: %s size=%d list=%p",
        !           128:               label, 
        !           129:               src_str, ifname,
        !           130:               tlv_name,
        !           131:               addr_list ? ((int) listcount(addr_list)) : -1,
        !           132:               (void *) addr_list);
        !           133:   }
        !           134: }
        !           135: 
        !           136: #define FREE_ADDR_LIST \
        !           137:   if (hello_option_addr_list) { \
        !           138:     list_delete(hello_option_addr_list); \
        !           139:   }
        !           140: 
        !           141: #define FREE_ADDR_LIST_THEN_RETURN(code) \
        !           142: { \
        !           143:   FREE_ADDR_LIST \
        !           144:   return (code); \
        !           145: }
        !           146: 
        !           147: int pim_hello_recv(struct interface *ifp,
        !           148:                   struct in_addr src_addr,
        !           149:                   uint8_t *tlv_buf, int tlv_buf_size)
        !           150: {
        !           151:   struct pim_interface *pim_ifp;
        !           152:   struct pim_neighbor *neigh;
        !           153:   uint8_t *tlv_curr;
        !           154:   uint8_t *tlv_pastend;
        !           155:   pim_hello_options hello_options = 0; /* bit array recording options found */
        !           156:   uint16_t hello_option_holdtime = 0;
        !           157:   uint16_t hello_option_propagation_delay = 0;
        !           158:   uint16_t hello_option_override_interval = 0;
        !           159:   uint32_t hello_option_dr_priority = 0;
        !           160:   uint32_t hello_option_generation_id = 0;
        !           161:   struct list *hello_option_addr_list = 0;
        !           162: 
        !           163:   if (PIM_DEBUG_PIM_HELLO)
        !           164:     on_trace(__PRETTY_FUNCTION__, ifp, src_addr);
        !           165: 
        !           166:   pim_ifp = ifp->info;
        !           167:   zassert(pim_ifp);
        !           168: 
        !           169:   ++pim_ifp->pim_ifstat_hello_recv;
        !           170: 
        !           171:   /*
        !           172:     Parse PIM hello TLVs
        !           173:    */
        !           174:   zassert(tlv_buf_size >= 0);
        !           175:   tlv_curr = tlv_buf;
        !           176:   tlv_pastend = tlv_buf + tlv_buf_size;
        !           177: 
        !           178:   while (tlv_curr < tlv_pastend) {
        !           179:     uint16_t option_type; 
        !           180:     uint16_t option_len;
        !           181:     int remain = tlv_pastend - tlv_curr;
        !           182: 
        !           183:     if (remain < PIM_TLV_MIN_SIZE) {
        !           184:       if (PIM_DEBUG_PIM_HELLO) {
        !           185:        char src_str[100];
        !           186:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           187:        zlog_debug("%s: short PIM hello TLV size=%d < min=%d from %s on interface %s",
        !           188:                   __PRETTY_FUNCTION__,
        !           189:                   remain, PIM_TLV_MIN_SIZE,
        !           190:                   src_str, ifp->name);
        !           191:       }
        !           192:       FREE_ADDR_LIST_THEN_RETURN(-1);
        !           193:     }
        !           194: 
        !           195:     option_type = PIM_TLV_GET_TYPE(tlv_curr);
        !           196:     tlv_curr += PIM_TLV_TYPE_SIZE;
        !           197:     option_len = PIM_TLV_GET_LENGTH(tlv_curr);
        !           198:     tlv_curr += PIM_TLV_LENGTH_SIZE;
        !           199: 
        !           200:     if ((tlv_curr + option_len) > tlv_pastend) {
        !           201:       if (PIM_DEBUG_PIM_HELLO) {
        !           202:        char src_str[100];
        !           203:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           204:        zlog_debug("%s: long PIM hello TLV type=%d length=%d > left=%td from %s on interface %s",
        !           205:                   __PRETTY_FUNCTION__,
        !           206:                   option_type, option_len, tlv_pastend - tlv_curr,
        !           207:                   src_str, ifp->name);
        !           208:       }
        !           209:       FREE_ADDR_LIST_THEN_RETURN(-2);
        !           210:     }
        !           211: 
        !           212:     if (PIM_DEBUG_PIM_HELLO) {
        !           213:       char src_str[100];
        !           214:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           215:       zlog_debug("%s: parse left_size=%d: PIM hello TLV type=%d length=%d from %s on %s",
        !           216:                 __PRETTY_FUNCTION__,
        !           217:                 remain,
        !           218:                 option_type, option_len,
        !           219:                 src_str, ifp->name);
        !           220:     }
        !           221: 
        !           222:     switch (option_type) {
        !           223:     case PIM_MSG_OPTION_TYPE_HOLDTIME:
        !           224:       if (pim_tlv_parse_holdtime(ifp->name, src_addr,
        !           225:                                 &hello_options,
        !           226:                                 &hello_option_holdtime,
        !           227:                                 option_len,
        !           228:                                 tlv_curr)) {
        !           229:        FREE_ADDR_LIST_THEN_RETURN(-3);
        !           230:       }
        !           231:       break;
        !           232:     case PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY:
        !           233:       if (pim_tlv_parse_lan_prune_delay(ifp->name, src_addr,
        !           234:                                        &hello_options,
        !           235:                                        &hello_option_propagation_delay,
        !           236:                                        &hello_option_override_interval,
        !           237:                                        option_len,
        !           238:                                        tlv_curr)) {
        !           239:        FREE_ADDR_LIST_THEN_RETURN(-4);
        !           240:       }
        !           241:       break;
        !           242:     case PIM_MSG_OPTION_TYPE_DR_PRIORITY:
        !           243:       if (pim_tlv_parse_dr_priority(ifp->name, src_addr,
        !           244:                                    &hello_options,
        !           245:                                    &hello_option_dr_priority,
        !           246:                                    option_len,
        !           247:                                    tlv_curr)) {
        !           248:        FREE_ADDR_LIST_THEN_RETURN(-5);
        !           249:       }
        !           250:       break;
        !           251:     case PIM_MSG_OPTION_TYPE_GENERATION_ID:
        !           252:       if (pim_tlv_parse_generation_id(ifp->name, src_addr,
        !           253:                                      &hello_options,
        !           254:                                      &hello_option_generation_id,
        !           255:                                      option_len,
        !           256:                                      tlv_curr)) {
        !           257:        FREE_ADDR_LIST_THEN_RETURN(-6);
        !           258:       }
        !           259:       break;
        !           260:     case PIM_MSG_OPTION_TYPE_ADDRESS_LIST:
        !           261:       if (pim_tlv_parse_addr_list(ifp->name, src_addr,
        !           262:                                  &hello_options,
        !           263:                                  &hello_option_addr_list,
        !           264:                                  option_len,
        !           265:                                  tlv_curr)) {
        !           266:        return -7;
        !           267:       }
        !           268:       break;
        !           269:     case PIM_MSG_OPTION_TYPE_DM_STATE_REFRESH:
        !           270:       if (PIM_DEBUG_PIM_HELLO) {
        !           271:        char src_str[100];
        !           272:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           273:        zlog_debug("%s: ignoring PIM hello dense-mode state refresh TLV option type=%d length=%d from %s on interface %s",
        !           274:                   __PRETTY_FUNCTION__,
        !           275:                   option_type, option_len,
        !           276:                   src_str, ifp->name);
        !           277:       }
        !           278:       break;
        !           279:     default:
        !           280:       if (PIM_DEBUG_PIM_HELLO) {
        !           281:        char src_str[100];
        !           282:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           283:        zlog_debug("%s: ignoring unknown PIM hello TLV type=%d length=%d from %s on interface %s",
        !           284:                   __PRETTY_FUNCTION__,
        !           285:                   option_type, option_len,
        !           286:                   src_str, ifp->name);
        !           287:       }
        !           288:     }
        !           289: 
        !           290:     tlv_curr += option_len;
        !           291:   }
        !           292: 
        !           293:   /*
        !           294:     Check received PIM hello options
        !           295:   */
        !           296: 
        !           297:   if (PIM_DEBUG_PIM_HELLO) {
        !           298:     tlv_trace_uint16(__PRETTY_FUNCTION__, "holdtime",
        !           299:                     ifp->name, src_addr,
        !           300:                     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME),
        !           301:                     hello_option_holdtime);
        !           302:     tlv_trace_uint16(__PRETTY_FUNCTION__, "propagation_delay",
        !           303:                     ifp->name, src_addr,
        !           304:                     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY),
        !           305:                     hello_option_propagation_delay);
        !           306:     tlv_trace_uint16(__PRETTY_FUNCTION__, "override_interval",
        !           307:                     ifp->name, src_addr,
        !           308:                     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY),
        !           309:                     hello_option_override_interval);
        !           310:     tlv_trace_bool(__PRETTY_FUNCTION__, "can_disable_join_suppression",
        !           311:                   ifp->name, src_addr,
        !           312:                   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY),
        !           313:                   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_CAN_DISABLE_JOIN_SUPPRESSION));
        !           314:     tlv_trace_uint32(__PRETTY_FUNCTION__, "dr_priority",
        !           315:                     ifp->name, src_addr,
        !           316:                     PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY),
        !           317:                     hello_option_dr_priority);
        !           318:     tlv_trace_uint32_hex(__PRETTY_FUNCTION__, "generation_id",
        !           319:                         ifp->name, src_addr,
        !           320:                         PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID),
        !           321:                         hello_option_generation_id);
        !           322:     tlv_trace_list(__PRETTY_FUNCTION__, "address_list",
        !           323:                   ifp->name, src_addr,
        !           324:                   PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_ADDRESS_LIST),
        !           325:                   hello_option_addr_list);
        !           326:   }
        !           327: 
        !           328:   if (!PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
        !           329:     if (PIM_DEBUG_PIM_HELLO) {
        !           330:       char src_str[100];
        !           331:       pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           332:       zlog_debug("%s: PIM hello missing holdtime from %s on interface %s",
        !           333:                __PRETTY_FUNCTION__,
        !           334:                src_str, ifp->name);
        !           335:     }
        !           336:   }
        !           337: 
        !           338:   /*
        !           339:     New neighbor?
        !           340:   */
        !           341: 
        !           342:   neigh = pim_neighbor_find(ifp, src_addr);
        !           343:   if (!neigh) {
        !           344:     /* Add as new neighbor */
        !           345:     
        !           346:     neigh = pim_neighbor_add(ifp, src_addr,
        !           347:                             hello_options,
        !           348:                             hello_option_holdtime,
        !           349:                             hello_option_propagation_delay,
        !           350:                             hello_option_override_interval,
        !           351:                             hello_option_dr_priority,
        !           352:                             hello_option_generation_id,
        !           353:                             hello_option_addr_list);
        !           354:     if (!neigh) {
        !           355:       if (PIM_DEBUG_PIM_HELLO) {
        !           356:        char src_str[100];
        !           357:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           358:        zlog_warn("%s: failure creating PIM neighbor %s on interface %s",
        !           359:                  __PRETTY_FUNCTION__,
        !           360:                  src_str, ifp->name);
        !           361:       }
        !           362:       FREE_ADDR_LIST_THEN_RETURN(-8);
        !           363:     }
        !           364: 
        !           365:     /* actual addr list has been saved under neighbor */
        !           366:     return 0;
        !           367:   }
        !           368: 
        !           369:   /*
        !           370:     Received generation ID ?
        !           371:   */
        !           372:   
        !           373:   if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_GENERATION_ID)) {
        !           374:     /* GenID mismatch ? */
        !           375:     if (!PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_GENERATION_ID) ||
        !           376:        (hello_option_generation_id != neigh->generation_id)) {
        !           377: 
        !           378:       /* GenID changed */
        !           379: 
        !           380:       pim_upstream_rpf_genid_changed(neigh->source_addr);
        !           381: 
        !           382:       /* GenID mismatch, then replace neighbor */
        !           383:       
        !           384:       if (PIM_DEBUG_PIM_HELLO) {
        !           385:        char src_str[100];
        !           386:        pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           387:        zlog_debug("%s: GenId mismatch new=%08x old=%08x: replacing neighbor %s on %s",
        !           388:                   __PRETTY_FUNCTION__,
        !           389:                   hello_option_generation_id,
        !           390:                   neigh->generation_id,
        !           391:                   src_str, ifp->name);
        !           392:       }
        !           393: 
        !           394:       pim_upstream_rpf_genid_changed(neigh->source_addr);
        !           395:       
        !           396:       pim_neighbor_delete(ifp, neigh, "GenID mismatch");
        !           397:       neigh = pim_neighbor_add(ifp, src_addr,
        !           398:                               hello_options,
        !           399:                               hello_option_holdtime,
        !           400:                               hello_option_propagation_delay,
        !           401:                               hello_option_override_interval,
        !           402:                               hello_option_dr_priority,
        !           403:                               hello_option_generation_id,
        !           404:                               hello_option_addr_list);
        !           405:       if (!neigh) {
        !           406:        if (PIM_DEBUG_PIM_HELLO) {
        !           407:          char src_str[100];
        !           408:          pim_inet4_dump("<src?>", src_addr, src_str, sizeof(src_str));
        !           409:          zlog_debug("%s: failure re-creating PIM neighbor %s on interface %s",
        !           410:                     __PRETTY_FUNCTION__,
        !           411:                     src_str, ifp->name);
        !           412:        }
        !           413:        FREE_ADDR_LIST_THEN_RETURN(-9);
        !           414:       }
        !           415:       /* actual addr list is saved under neighbor */
        !           416:       return 0;
        !           417: 
        !           418:     } /* GenId mismatch: replace neighbor */
        !           419:     
        !           420:   } /* GenId received */
        !           421: 
        !           422:   /*
        !           423:     Update existing neighbor
        !           424:   */
        !           425: 
        !           426:   pim_neighbor_update(neigh,
        !           427:                      hello_options,
        !           428:                      hello_option_holdtime,
        !           429:                      hello_option_dr_priority,
        !           430:                      hello_option_addr_list);
        !           431:   /* actual addr list is saved under neighbor */
        !           432:   return 0;
        !           433: }
        !           434: 
        !           435: int pim_hello_build_tlv(const char *ifname,
        !           436:                        uint8_t *tlv_buf, int tlv_buf_size,
        !           437:                        uint16_t holdtime,
        !           438:                        uint32_t dr_priority,
        !           439:                        uint32_t generation_id,
        !           440:                        uint16_t propagation_delay,
        !           441:                        uint16_t override_interval,
        !           442:                        int can_disable_join_suppression,
        !           443:                        struct list *ifconnected)
        !           444: {
        !           445:   uint8_t *curr = tlv_buf;
        !           446:   uint8_t *pastend = tlv_buf + tlv_buf_size;
        !           447:   uint8_t *tmp;
        !           448: 
        !           449:   /*
        !           450:    * Append options
        !           451:    */
        !           452: 
        !           453:   /* Holdtime */
        !           454:   curr = pim_tlv_append_uint16(curr,
        !           455:                               pastend,
        !           456:                               PIM_MSG_OPTION_TYPE_HOLDTIME,
        !           457:                               holdtime);
        !           458:   if (!curr) {
        !           459:     if (PIM_DEBUG_PIM_HELLO) {
        !           460:       zlog_debug("%s: could not set PIM hello Holdtime option for interface %s",
        !           461:                 __PRETTY_FUNCTION__, ifname);
        !           462:     }
        !           463:     return -1;
        !           464:   }
        !           465: 
        !           466:   /* LAN Prune Delay */
        !           467:   tmp = pim_tlv_append_2uint16(curr,
        !           468:                               pastend,
        !           469:                               PIM_MSG_OPTION_TYPE_LAN_PRUNE_DELAY,
        !           470:                               propagation_delay,
        !           471:                               override_interval);
        !           472:   if (!tmp) {
        !           473:     if (PIM_DEBUG_PIM_HELLO) {
        !           474:       zlog_debug("%s: could not set PIM LAN Prune Delay option for interface %s",
        !           475:                 __PRETTY_FUNCTION__, ifname);
        !           476:     }
        !           477:     return -1;
        !           478:   }
        !           479:   if (can_disable_join_suppression) {
        !           480:     *((uint8_t*)(curr) + 4) |= 0x80; /* enable T bit */
        !           481:   }
        !           482:   curr = tmp;
        !           483: 
        !           484:   /* DR Priority */
        !           485:   curr = pim_tlv_append_uint32(curr,
        !           486:                               pastend,
        !           487:                               PIM_MSG_OPTION_TYPE_DR_PRIORITY,
        !           488:                               dr_priority);
        !           489:   if (!curr) {
        !           490:     if (PIM_DEBUG_PIM_HELLO) {
        !           491:       zlog_debug("%s: could not set PIM hello DR Priority option for interface %s",
        !           492:                 __PRETTY_FUNCTION__, ifname);
        !           493:     }
        !           494:     return -2;
        !           495:   }
        !           496: 
        !           497:   /* Generation ID */
        !           498:   curr = pim_tlv_append_uint32(curr,
        !           499:                               pastend,
        !           500:                               PIM_MSG_OPTION_TYPE_GENERATION_ID,
        !           501:                               generation_id);
        !           502:   if (!curr) {
        !           503:     if (PIM_DEBUG_PIM_HELLO) {
        !           504:       zlog_debug("%s: could not set PIM hello Generation ID option for interface %s",
        !           505:                 __PRETTY_FUNCTION__, ifname);
        !           506:     }
        !           507:     return -3;
        !           508:   }
        !           509: 
        !           510:   /* Secondary Address List */
        !           511:   if (ifconnected) {
        !           512:     curr = pim_tlv_append_addrlist_ucast(curr,
        !           513:                                         pastend,
        !           514:                                         ifconnected);
        !           515:     if (!curr) {
        !           516:       if (PIM_DEBUG_PIM_HELLO) {
        !           517:        zlog_debug("%s: could not set PIM hello Secondary Address List option for interface %s",
        !           518:                  __PRETTY_FUNCTION__, ifname);
        !           519:       }
        !           520:       return -4;
        !           521:     }
        !           522:   }
        !           523: 
        !           524:   return curr - tlv_buf;
        !           525: }
        !           526: 
        !           527: /*
        !           528:   RFC 4601: 4.3.1.  Sending Hello Messages
        !           529: 
        !           530:   Thus, if a router needs to send a Join/Prune or Assert message on an
        !           531:   interface on which it has not yet sent a Hello message with the
        !           532:   currently configured IP address, then it MUST immediately send the
        !           533:   relevant Hello message without waiting for the Hello Timer to
        !           534:   expire, followed by the Join/Prune or Assert message.
        !           535: */
        !           536: void pim_hello_require(struct interface *ifp)
        !           537: {
        !           538:   struct pim_interface *pim_ifp;
        !           539: 
        !           540:   zassert(ifp);
        !           541: 
        !           542:   pim_ifp = ifp->info;
        !           543: 
        !           544:   zassert(pim_ifp);
        !           545: 
        !           546:   if (pim_ifp->pim_ifstat_hello_sent)
        !           547:     return;
        !           548: 
        !           549:   pim_hello_restart_now(ifp); /* Send hello and restart timer */
        !           550: }

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