Annotation of embedaddon/quagga/pimd/pim_hello.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: 
                     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>