File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / iface.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 19:50:23 2021 UTC (3 years, 4 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, HEAD
bird 1.6.8

    1: /*
    2:  *	BIRD -- OSPF
    3:  *
    4:  *	(c) 1999--2005 Ondrej Filip <feela@network.cz>
    5:  *	(c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
    6:  *	(c) 2009--2014 CZ.NIC z.s.p.o.
    7:  *
    8:  *	Can be freely distributed and used under the terms of the GNU GPL.
    9:  */
   10: 
   11: #include "ospf.h"
   12: #include "nest/password.h"
   13: 
   14: 
   15: const char *ospf_is_names[] = {
   16:   "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR"
   17: };
   18: 
   19: const char *ospf_ism_names[] = {
   20:   "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange",
   21:   "LoopInd", "UnloopInd", "InterfaceDown"
   22: };
   23: 
   24: const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
   25: 
   26: 
   27: static void
   28: poll_timer_hook(timer * timer)
   29: {
   30:   ospf_send_hello(timer->data, OHS_POLL, NULL);
   31: }
   32: 
   33: static void
   34: hello_timer_hook(timer * timer)
   35: {
   36:   ospf_send_hello(timer->data, OHS_HELLO, NULL);
   37: }
   38: 
   39: static void
   40: wait_timer_hook(timer * timer)
   41: {
   42:   struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
   43:   struct ospf_proto *p = ifa->oa->po;
   44: 
   45:   OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname);
   46:   ospf_iface_sm(ifa, ISM_WAITF);
   47: }
   48: 
   49: static inline uint
   50: ifa_tx_length(struct ospf_iface *ifa)
   51: {
   52:   return ifa->cf->tx_length ?: ifa->iface->mtu;
   53: }
   54: 
   55: static inline uint
   56: ifa_tx_hdrlen(struct ospf_iface *ifa)
   57: {
   58:   uint hlen = SIZE_OF_IP_HEADER;
   59: 
   60:   /* Relevant just for OSPFv2 */
   61:   if (ifa->autype == OSPF_AUTH_CRYPT)
   62:     hlen += max_mac_length(ifa->passwords);
   63: 
   64:   return hlen;
   65: }
   66: 
   67: static inline uint
   68: ifa_bufsize(struct ospf_iface *ifa)
   69: {
   70:   uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
   71:   return MAX(bsize, ifa->tx_length);
   72: }
   73: 
   74: static inline uint
   75: ifa_flood_queue_size(struct ospf_iface *ifa)
   76: {
   77:   return ifa->tx_length / 24;
   78: }
   79: 
   80: int
   81: ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
   82: {
   83:   plen += ifa->tx_hdrlen;
   84: 
   85:   if (plen <= ifa->sk->tbsize)
   86:     return 0;
   87: 
   88:   if (ifa->cf->rx_buffer || (plen > 0xffff))
   89:     return -1;
   90: 
   91:   plen = BIRD_ALIGN(plen, 1024);
   92:   plen = MIN(plen, 0xffff);
   93:   sk_set_tbsize(ifa->sk, plen);
   94:   return 1;
   95: }
   96: 
   97: 
   98: struct nbma_node *
   99: find_nbma_node_(list *nnl, ip_addr ip)
  100: {
  101:   struct nbma_node *nn;
  102: 
  103:   WALK_LIST(nn, *nnl)
  104:     if (ipa_equal(nn->ip, ip))
  105:       return nn;
  106: 
  107:   return NULL;
  108: }
  109: 
  110: 
  111: static int
  112: ospf_sk_open(struct ospf_iface *ifa)
  113: {
  114:   struct ospf_proto *p = ifa->oa->po;
  115: 
  116:   sock *sk = sk_new(ifa->pool);
  117:   sk->type = SK_IP;
  118:   sk->dport = OSPF_PROTO;
  119:   sk->saddr = ifa->addr->ip;
  120:   sk->iface = ifa->iface;
  121:   sk->vrf = p->p.vrf;
  122: 
  123:   sk->tos = ifa->cf->tx_tos;
  124:   sk->priority = ifa->cf->tx_priority;
  125:   sk->rx_hook = ospf_rx_hook;
  126:   // sk->tx_hook = ospf_tx_hook;
  127:   sk->err_hook = ospf_err_hook;
  128:   sk->rbsize = sk->tbsize = ifa_bufsize(ifa);
  129:   sk->data = (void *) ifa;
  130:   sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
  131:   sk->ttl = ifa->cf->ttl_security ? 255 : 1;
  132: 
  133:   if (sk_open(sk) < 0)
  134:     goto err;
  135: 
  136:   /* 12 is an offset of the checksum in an OSPFv3 packet */
  137:   if (ospf_is_v3(p))
  138:     if (sk_set_ipv6_checksum(sk, 12) < 0)
  139:       goto err;
  140: 
  141:   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
  142:   {
  143:     if (ifa->cf->real_bcast)
  144:     {
  145:       ifa->all_routers = ifa->addr->brd;
  146:       ifa->des_routers = IPA_NONE;
  147: 
  148:       if (sk_setup_broadcast(sk) < 0)
  149: 	goto err;
  150:     }
  151:     else
  152:     {
  153:       ifa->all_routers = ospf_is_v2(p) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
  154:       ifa->des_routers = ospf_is_v2(p) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
  155: 
  156:       if (sk_setup_multicast(sk) < 0)
  157: 	goto err;
  158: 
  159:       if (sk_join_group(sk, ifa->all_routers) < 0)
  160: 	goto err;
  161:     }
  162:   }
  163: 
  164:   ifa->sk = sk;
  165:   ifa->sk_dr = 0;
  166:   return 1;
  167: 
  168:  err:
  169:   sk_log_error(sk, p->p.name);
  170:   rfree(sk);
  171:   return 0;
  172: }
  173: 
  174: static inline void
  175: ospf_sk_join_dr(struct ospf_iface *ifa)
  176: {
  177:   if (ifa->sk_dr)
  178:     return;
  179: 
  180:   if (sk_join_group(ifa->sk, ifa->des_routers) < 0)
  181:     sk_log_error(ifa->sk, ifa->oa->po->p.name);
  182: 
  183:   ifa->sk_dr = 1;
  184: }
  185: 
  186: static inline void
  187: ospf_sk_leave_dr(struct ospf_iface *ifa)
  188: {
  189:   if (!ifa->sk_dr)
  190:     return;
  191: 
  192:   if (sk_leave_group(ifa->sk, ifa->des_routers) < 0)
  193:     sk_log_error(ifa->sk, ifa->oa->po->p.name);
  194: 
  195:   ifa->sk_dr = 0;
  196: }
  197: 
  198: void
  199: ospf_open_vlink_sk(struct ospf_proto *p)
  200: {
  201:   sock *sk = sk_new(p->p.pool);
  202:   sk->type = SK_IP;
  203:   sk->dport = OSPF_PROTO;
  204:   sk->vrf = p->p.vrf;
  205: 
  206:   /* FIXME: configurable tos/priority ? */
  207:   sk->tos = IP_PREC_INTERNET_CONTROL;
  208:   sk->priority = sk_priority_control;
  209:   sk->err_hook = ospf_verr_hook;
  210: 
  211:   sk->rbsize = 0;
  212:   sk->tbsize = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
  213:   sk->data = (void *) p;
  214:   sk->flags = 0;
  215: 
  216:   if (sk_open(sk) < 0)
  217:     goto err;
  218: 
  219:   /* 12 is an offset of the checksum in an OSPFv3 packet */
  220:   if (ospf_is_v3(p))
  221:     if (sk_set_ipv6_checksum(sk, 12) < 0)
  222:       goto err;
  223: 
  224:   p->vlink_sk = sk;
  225:   return;
  226: 
  227:  err:
  228:   sk_log_error(sk, p->p.name);
  229:   log(L_ERR "%s: Cannot open virtual link socket", p->p.name);
  230:   rfree(sk);
  231: }
  232: 
  233: static void
  234: ospf_iface_down(struct ospf_iface *ifa)
  235: {
  236:   struct ospf_proto *p = ifa->oa->po;
  237:   struct ospf_neighbor *n, *nx;
  238:   struct ospf_iface *iff;
  239: 
  240:   if (ifa->type != OSPF_IT_VLINK)
  241:   {
  242:     if (ospf_is_v3(ifa->oa->po))
  243:       OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
  244: 		 ifa->ifname, ifa->instance_id, ifa->oa->areaid);
  245:     else if (ifa->addr->flags & IA_PEER)
  246:       OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
  247: 		 ifa->ifname, ifa->addr->opposite, ifa->oa->areaid);
  248:     else
  249:       OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
  250: 		 ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
  251: 
  252:     /* First of all kill all the related vlinks */
  253:     WALK_LIST(iff, p->iface_list)
  254:     {
  255:       if ((iff->type == OSPF_IT_VLINK) && (iff->vifa == ifa))
  256: 	ospf_iface_sm(iff, ISM_DOWN);
  257:     }
  258:   }
  259: 
  260:   WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
  261:     ospf_neigh_sm(n, INM_KILLNBR);
  262: 
  263:   if (ifa->hello_timer)
  264:     tm_stop(ifa->hello_timer);
  265: 
  266:   if (ifa->poll_timer)
  267:     tm_stop(ifa->poll_timer);
  268: 
  269:   if (ifa->wait_timer)
  270:     tm_stop(ifa->wait_timer);
  271: 
  272:   ospf_flush2_lsa(p, &ifa->link_lsa);
  273:   ospf_flush2_lsa(p, &ifa->net_lsa);
  274:   ospf_flush2_lsa(p, &ifa->pxn_lsa);
  275: 
  276:   if (ifa->type == OSPF_IT_VLINK)
  277:   {
  278:     ifa->vifa = NULL;
  279:     ifa->addr = NULL;
  280:     ifa->cost = 0;
  281:     ifa->vip = IPA_NONE;
  282:   }
  283: 
  284:   ifa->rt_pos_beg = 0;
  285:   ifa->rt_pos_end = 0;
  286:   ifa->px_pos_beg = 0;
  287:   ifa->px_pos_end = 0;
  288: }
  289: 
  290: 
  291: void
  292: ospf_iface_remove(struct ospf_iface *ifa)
  293: {
  294:   struct ospf_proto *p = ifa->oa->po;
  295:   int i;
  296: 
  297:   if (ifa->type == OSPF_IT_VLINK)
  298:     OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
  299: 
  300:   /* Release LSAs from flood queue */
  301:   if (!ifa->stub)
  302:     for (i = 0; i < ifa->flood_queue_used; i++)
  303:       ifa->flood_queue[i]->ret_count--;
  304: 
  305:   ospf_iface_sm(ifa, ISM_DOWN);
  306:   rem_node(NODE ifa);
  307:   rfree(ifa->pool);
  308: }
  309: 
  310: void
  311: ospf_iface_shutdown(struct ospf_iface *ifa)
  312: {
  313:   if (ifa->state > OSPF_IS_DOWN)
  314:     ospf_send_hello(ifa, OHS_SHUTDOWN, NULL);
  315: }
  316: 
  317: /**
  318:  * ospf_iface_chstate - handle changes of interface state
  319:  * @ifa: OSPF interface
  320:  * @state: new state
  321:  *
  322:  * Many actions must be taken according to interface state changes. New network
  323:  * LSAs must be originated, flushed, new multicast sockets to listen for messages for
  324:  * %ALLDROUTERS have to be opened, etc.
  325:  */
  326: void
  327: ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
  328: {
  329:   struct ospf_proto *p = ifa->oa->po;
  330:   u8 oldstate = ifa->state;
  331: 
  332:   if (state == oldstate)
  333:     return;
  334: 
  335:   OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s",
  336: 	     ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]);
  337: 
  338:   ifa->state = state;
  339: 
  340:   if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
  341:   {
  342:     if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
  343:       ospf_sk_join_dr(ifa);
  344:     else
  345:       ospf_sk_leave_dr(ifa);
  346:   }
  347: 
  348:   if ((oldstate > OSPF_IS_LOOP) && (state <= OSPF_IS_LOOP))
  349:     ospf_iface_down(ifa);
  350: 
  351:   /* RFC 2328 12.4 Event 2 - iface state change */
  352:   ospf_notify_rt_lsa(ifa->oa);
  353: 
  354:   /* RFC 5340 4.4.3 Event 1 - iface state change */
  355:   ospf_notify_link_lsa(ifa);
  356: 
  357:   /* RFC 2328 12.4 Event 3 - iface enters/leaves DR state */
  358:   ospf_notify_net_lsa(ifa);
  359: }
  360: 
  361: /**
  362:  * ospf_iface_sm - OSPF interface state machine
  363:  * @ifa: OSPF interface
  364:  * @event: event comming to state machine
  365:  *
  366:  * This fully respects 9.3 of RFC 2328 except we have slightly
  367:  * different handling of %DOWN and %LOOP state. We remove intefaces
  368:  * that are %DOWN. %DOWN state is used when an interface is waiting
  369:  * for a lock. %LOOP state is used when an interface does not have a
  370:  * link.
  371:  */
  372: void
  373: ospf_iface_sm(struct ospf_iface *ifa, int event)
  374: {
  375:   DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]);
  376: 
  377:   switch (event)
  378:   {
  379:   case ISM_UP:
  380:     if (ifa->state <= OSPF_IS_LOOP)
  381:     {
  382:       /* Now, nothing should be adjacent */
  383:       if ((ifa->type == OSPF_IT_PTP) ||
  384: 	  (ifa->type == OSPF_IT_PTMP) ||
  385: 	  (ifa->type == OSPF_IT_VLINK))
  386:       {
  387: 	ospf_iface_chstate(ifa, OSPF_IS_PTP);
  388:       }
  389:       else
  390:       {
  391: 	if (ifa->priority == 0)
  392: 	  ospf_iface_chstate(ifa, OSPF_IS_DROTHER);
  393: 	else
  394: 	{
  395: 	  ospf_iface_chstate(ifa, OSPF_IS_WAITING);
  396: 	  if (ifa->wait_timer)
  397: 	    tm_start(ifa->wait_timer, ifa->waitint);
  398: 	}
  399:       }
  400: 
  401:       if (ifa->hello_timer)
  402: 	tm_start(ifa->hello_timer, ifa->helloint);
  403: 
  404:       if (ifa->poll_timer)
  405: 	tm_start(ifa->poll_timer, ifa->pollint);
  406: 
  407:       ospf_send_hello(ifa, OHS_HELLO, NULL);
  408:     }
  409:     break;
  410: 
  411:   case ISM_BACKS:
  412:   case ISM_WAITF:
  413:     if (ifa->state == OSPF_IS_WAITING)
  414:       ospf_dr_election(ifa);
  415:     break;
  416: 
  417:   case ISM_NEICH:
  418:     if (ifa->state >= OSPF_IS_DROTHER)
  419:       ospf_dr_election(ifa);
  420:     break;
  421: 
  422:   case ISM_LOOP:
  423:     if ((ifa->state > OSPF_IS_LOOP) && ifa->check_link)
  424:       ospf_iface_chstate(ifa, OSPF_IS_LOOP);
  425:     break;
  426: 
  427:   case ISM_UNLOOP:
  428:     /* Immediate go UP */
  429:     if (ifa->state == OSPF_IS_LOOP)
  430:       ospf_iface_sm(ifa, ISM_UP);
  431:     break;
  432: 
  433:   case ISM_DOWN:
  434:     ospf_iface_chstate(ifa, OSPF_IS_DOWN);
  435:     break;
  436: 
  437:   default:
  438:     bug("OSPF_I_SM - Unknown event?");
  439:     break;
  440:   }
  441: 
  442: }
  443: 
  444: static u8
  445: ospf_iface_classify_(struct iface *ifa, struct ifa *addr)
  446: {
  447:   if (ipa_nonzero(addr->opposite))
  448:     return (ifa->flags & IF_MULTICAST) ? OSPF_IT_PTP :  OSPF_IT_PTMP;
  449: 
  450:   if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) ==
  451:       (IF_MULTIACCESS | IF_MULTICAST))
  452:     return OSPF_IT_BCAST;
  453: 
  454:   if ((ifa->flags & (IF_MULTIACCESS | IF_MULTICAST)) == IF_MULTIACCESS)
  455:     return OSPF_IT_NBMA;
  456: 
  457:   return OSPF_IT_PTP;
  458: }
  459: 
  460: static inline u8
  461: ospf_iface_classify(u8 type, struct ifa *addr)
  462: {
  463:   return (type != OSPF_IT_UNDEF) ? type : ospf_iface_classify_(addr->iface, addr);
  464: }
  465: 
  466: 
  467: struct ospf_iface *
  468: ospf_iface_find(struct ospf_proto *p, struct iface *what)
  469: {
  470:   struct ospf_iface *ifa;
  471: 
  472:   WALK_LIST(ifa, p->iface_list)
  473:     if ((ifa->iface == what) && (ifa->type != OSPF_IT_VLINK))
  474:       return ifa;
  475: 
  476:   return NULL;
  477: }
  478: 
  479: static void
  480: ospf_iface_add(struct object_lock *lock)
  481: {
  482:   struct ospf_iface *ifa = lock->data;
  483:   struct ospf_proto *p = ifa->oa->po;
  484: 
  485:   /* Open socket if interface is not stub */
  486:   if (! ifa->stub && ! ospf_sk_open(ifa))
  487:   {
  488:     log(L_ERR "%s: Cannot open socket for %s, declaring as stub", p->p.name, ifa->ifname);
  489:     ifa->ioprob = OSPF_I_SK;
  490:     ifa->stub = 1;
  491:   }
  492: 
  493:   if (! ifa->stub)
  494:   {
  495:     ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
  496: 
  497:     if (ifa->type == OSPF_IT_NBMA)
  498:       ifa->poll_timer = tm_new_set(ifa->pool, poll_timer_hook, ifa, 0, ifa->pollint);
  499: 
  500:     if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
  501:       ifa->wait_timer = tm_new_set(ifa->pool, wait_timer_hook, ifa, 0, 0);
  502: 
  503:     ifa->flood_queue_size = ifa_flood_queue_size(ifa);
  504:     ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
  505:   }
  506: 
  507:   /* Do iface UP, unless there is no link (then wait in LOOP state) */
  508:   if (!ifa->check_link || (ifa->iface->flags & IF_LINK_UP))
  509:     ospf_iface_sm(ifa, ISM_UP);
  510:   else
  511:     ospf_iface_chstate(ifa, OSPF_IS_LOOP);
  512: }
  513: 
  514: static inline void
  515: add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
  516: {
  517:   struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
  518:   add_tail(&ifa->nbma_list, NODE n);
  519:   n->ip = src->ip;
  520:   n->eligible = src->eligible;
  521:   n->found = found;
  522: }
  523: 
  524: static int
  525: ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
  526: {
  527:   /* vlink cannot be stub */
  528:   if (ip->type == OSPF_IT_VLINK)
  529:     return 0;
  530: 
  531:   /* a host address */
  532:   if (addr->flags & IA_HOST)
  533:     return 1;
  534: 
  535:   /* a loopback iface */
  536:   if (addr->iface->flags & IF_LOOPBACK)
  537:     return 1;
  538: 
  539:   /*
  540:    * For compatibility reasons on BSD systems, we force OSPF
  541:    * interfaces with non-primary IP prefixes to be stub.
  542:    */
  543: #if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
  544:   if (!ip->bsd_secondary && !(addr->flags & IA_PRIMARY))
  545:     return 1;
  546: #endif
  547: 
  548:   return ip->stub;
  549: }
  550: 
  551: void
  552: ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
  553: {
  554:   struct ospf_proto *p = oa->po;
  555:   struct iface *iface = addr->iface;
  556:   struct ospf_iface *ifa;
  557:   struct pool *pool;
  558: 
  559:   if (ospf_is_v3(p))
  560:     OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
  561: 	       iface->name, ip->instance_id, oa->areaid);
  562:   else if (addr->flags & IA_PEER)
  563:     OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
  564: 	       iface->name, addr->opposite, oa->areaid);
  565:   else
  566:     OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
  567: 	       iface->name, addr->prefix, addr->pxlen, oa->areaid);
  568: 
  569:   pool = rp_new(p->p.pool, "OSPF Interface");
  570:   ifa = mb_allocz(pool, sizeof(struct ospf_iface));
  571:   ifa->iface = iface;
  572:   ifa->addr = addr;
  573:   ifa->oa = oa;
  574:   ifa->cf = ip;
  575:   ifa->pool = pool;
  576: 
  577:   ifa->iface_id = iface->index;
  578:   ifa->ifname = iface->name;
  579: 
  580:   ifa->cost = ip->cost;
  581:   ifa->rxmtint = ip->rxmtint;
  582:   ifa->inftransdelay = ip->inftransdelay;
  583:   ifa->priority = ip->priority;
  584:   ifa->helloint = ip->helloint;
  585:   ifa->pollint = ip->pollint;
  586:   ifa->strictnbma = ip->strictnbma;
  587:   ifa->waitint = ip->waitint;
  588:   ifa->deadint = ip->deadint;
  589:   ifa->stub = ospf_iface_stubby(ip, addr);
  590:   ifa->ioprob = OSPF_I_OK;
  591:   ifa->tx_length = ifa_tx_length(ifa);
  592:   ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
  593:   ifa->check_link = ip->check_link;
  594:   ifa->ecmp_weight = ip->ecmp_weight;
  595:   ifa->check_ttl = (ip->ttl_security == 1);
  596:   ifa->bfd = ip->bfd;
  597:   ifa->autype = ip->autype;
  598:   ifa->passwords = ip->passwords;
  599:   ifa->instance_id = ip->instance_id;
  600: 
  601:   ifa->ptp_netmask = !(addr->flags & IA_PEER);
  602:   if (ip->ptp_netmask < 2)
  603:     ifa->ptp_netmask = ip->ptp_netmask;
  604: 
  605: 
  606:   ifa->type = ospf_iface_classify(ip->type, addr);
  607: 
  608:   /* Check validity of interface type */
  609:   int old_type = ifa->type;
  610:   u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
  611: 
  612:   if (ospf_is_v2(p) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
  613:     ifa->type = OSPF_IT_PTP;
  614: 
  615:   if (ospf_is_v2(p) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
  616:     ifa->type = OSPF_IT_PTMP;
  617: 
  618:   if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag) && !ifa->stub)
  619:     ifa->type = OSPF_IT_NBMA;
  620: 
  621:   if ((ifa->type == OSPF_IT_PTP) && !(iface->flags & if_multi_flag) && !ifa->stub)
  622:     ifa->type = OSPF_IT_PTMP;
  623: 
  624:   if (ifa->type != old_type)
  625:     log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
  626: 	p->p.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
  627: 
  628: 
  629:   if ((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP))
  630:     ifa->link_lsa_suppression = ip->link_lsa_suppression;
  631: 
  632:   ifa->state = OSPF_IS_DOWN;
  633:   init_list(&ifa->neigh_list);
  634:   init_list(&ifa->nbma_list);
  635: 
  636:   struct nbma_node *nb;
  637:   WALK_LIST(nb, ip->nbma_list)
  638:   {
  639:     /* In OSPFv3, addr is link-local while configured neighbors could
  640:        have global IP (although RFC 5340 C.5 says link-local addresses
  641:        should be used). Because OSPFv3 iface is not subnet-specific,
  642:        there is no need for ipa_in_net() check */
  643: 
  644:     if (ospf_is_v2(p) && !ipa_in_net(nb->ip, addr->prefix, addr->pxlen))
  645:       continue;
  646: 
  647:     if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
  648:       log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
  649: 	  p->p.name, nb->ip);
  650: 
  651:     add_nbma_node(ifa, nb, 0);
  652:   }
  653: 
  654:   add_tail(&oa->po->iface_list, NODE ifa);
  655: 
  656:   struct object_lock *lock = olock_new(pool);
  657:   lock->addr = ospf_is_v2(p) ? ifa->addr->prefix : IPA_NONE;
  658:   lock->type = OBJLOCK_IP;
  659:   lock->port = OSPF_PROTO;
  660:   lock->inst = ifa->instance_id;
  661:   lock->iface = iface;
  662:   lock->data = ifa;
  663:   lock->hook = ospf_iface_add;
  664: 
  665:   olock_acquire(lock);
  666: }
  667: 
  668: void
  669: ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip)
  670: {
  671:   struct ospf_iface *ifa;
  672:   struct pool *pool;
  673: 
  674:   if (!p->vlink_sk)
  675:     return;
  676: 
  677:   OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
  678: 
  679:   /* Vlink ifname is stored just after the ospf_iface structure */
  680: 
  681:   pool = rp_new(p->p.pool, "OSPF Vlink");
  682:   ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
  683:   ifa->oa = p->backbone;
  684:   ifa->cf = ip;
  685:   ifa->pool = pool;
  686: 
  687:   /* Assign iface ID, for vlinks, this is ugly hack */
  688:   u32 vlink_id = p->last_vlink_id++;
  689:   ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET;
  690:   ifa->ifname = (void *) (ifa + 1);
  691:   bsprintf(ifa->ifname, "vlink%d", vlink_id);
  692: 
  693:   ifa->voa = ospf_find_area(p, ip->voa);
  694:   ifa->vid = ip->vid;
  695:   ifa->sk = p->vlink_sk;
  696: 
  697:   ifa->helloint = ip->helloint;
  698:   ifa->rxmtint = ip->rxmtint;
  699:   ifa->waitint = ip->waitint;
  700:   ifa->deadint = ip->deadint;
  701:   ifa->inftransdelay = ip->inftransdelay;
  702:   ifa->tx_length = ospf_is_v2(p) ? IP4_MIN_MTU : IP6_MIN_MTU;
  703:   ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
  704:   ifa->autype = ip->autype;
  705:   ifa->passwords = ip->passwords;
  706:   ifa->instance_id = ip->instance_id;
  707: 
  708:   ifa->type = OSPF_IT_VLINK;
  709: 
  710:   ifa->state = OSPF_IS_DOWN;
  711:   init_list(&ifa->neigh_list);
  712:   init_list(&ifa->nbma_list);
  713: 
  714:   add_tail(&p->iface_list, NODE ifa);
  715: 
  716:   ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
  717: 
  718:   ifa->flood_queue_size = ifa_flood_queue_size(ifa);
  719:   ifa->flood_queue = mb_allocz(ifa->pool, ifa->flood_queue_size * sizeof(void *));
  720: }
  721: 
  722: static void
  723: ospf_iface_change_timer(timer *tm, uint val)
  724: {
  725:   if (!tm)
  726:     return;
  727: 
  728:   tm->recurrent = val;
  729: 
  730:   if (tm->expires)
  731:     tm_start(tm, val);
  732: }
  733: 
  734: static inline void
  735: ospf_iface_update_flood_queue_size(struct ospf_iface *ifa)
  736: {
  737:   uint old_size = ifa->flood_queue_size;
  738:   uint new_size = ifa_flood_queue_size(ifa);
  739: 
  740:   if (new_size <= old_size)
  741:     return;
  742: 
  743:   ifa->flood_queue_size = new_size;
  744:   ifa->flood_queue = mb_realloc(ifa->flood_queue, new_size * sizeof(void *));
  745:   bzero(ifa->flood_queue + old_size, (new_size - old_size) * sizeof(void *));
  746: }
  747: 
  748: int
  749: ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
  750: {
  751:   struct ospf_proto *p = ifa->oa->po;
  752:   struct ospf_iface_patt *old = ifa->cf;
  753:   char *ifname = ifa->ifname;
  754: 
  755:   /* Type could be changed in ospf_iface_new(),
  756:      but if config values are same then also results are same */
  757:   int old_type = ospf_iface_classify(old->type, ifa->addr);
  758:   int new_type = ospf_iface_classify(new->type, ifa->addr);
  759:   if (old_type != new_type)
  760:     return 0;
  761: 
  762:   int new_stub = ospf_iface_stubby(new, ifa->addr);
  763:   if (ifa->stub != new_stub)
  764:     return 0;
  765: 
  766:   /* Change of these options would require to reset the iface socket */
  767:   if ((new->real_bcast != old->real_bcast) ||
  768:       (new->tx_tos != old->tx_tos) ||
  769:       (new->tx_priority != old->tx_priority) ||
  770:       (new->ttl_security != old->ttl_security))
  771:     return 0;
  772: 
  773:   ifa->cf = new;
  774:   ifa->marked = 0;
  775: 
  776: 
  777:   /* HELLO TIMER */
  778:   if (ifa->helloint != new->helloint)
  779:   {
  780:     OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d",
  781: 	       ifname, ifa->helloint, new->helloint);
  782: 
  783:     ifa->helloint = new->helloint;
  784:     ospf_iface_change_timer(ifa->hello_timer, ifa->helloint);
  785:   }
  786: 
  787:   /* RXMT TIMER */
  788:   if (ifa->rxmtint != new->rxmtint)
  789:   {
  790:     OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d",
  791: 	       ifname, ifa->rxmtint, new->rxmtint);
  792: 
  793:     ifa->rxmtint = new->rxmtint;
  794:     /* FIXME: Update neighbors' timers */
  795:   }
  796: 
  797:   /* POLL TIMER */
  798:   if (ifa->pollint != new->pollint)
  799:   {
  800:     OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d",
  801: 	       ifname, ifa->pollint, new->pollint);
  802: 
  803:     ifa->pollint = new->pollint;
  804:     ospf_iface_change_timer(ifa->poll_timer, ifa->pollint);
  805:   }
  806: 
  807:   /* WAIT TIMER */
  808:   if (ifa->waitint != new->waitint)
  809:   {
  810:     OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d",
  811: 	       ifname, ifa->waitint, new->waitint);
  812: 
  813:     ifa->waitint = new->waitint;
  814:     if (ifa->wait_timer && ifa->wait_timer->expires)
  815:       tm_start(ifa->wait_timer, ifa->waitint);
  816:   }
  817: 
  818:   /* DEAD TIMER */
  819:   if (ifa->deadint != new->deadint)
  820:   {
  821:     OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d",
  822: 	       ifname, ifa->deadint, new->deadint);
  823:     ifa->deadint = new->deadint;
  824:   }
  825: 
  826:   /* INFTRANS */
  827:   if (ifa->inftransdelay != new->inftransdelay)
  828:   {
  829:     OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d",
  830: 		     ifname, ifa->inftransdelay, new->inftransdelay);
  831:     ifa->inftransdelay = new->inftransdelay;
  832:   }
  833: 
  834:   /* AUTHENTICATION */
  835:   if (ifa->autype != new->autype)
  836:   {
  837:     OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname);
  838:     ifa->autype = new->autype;
  839:   }
  840: 
  841:   /* Update passwords */
  842:   ifa->passwords = new->passwords;
  843: 
  844:   /* Update header length */
  845:   ifa->tx_hdrlen = ifa_tx_hdrlen(ifa);
  846: 
  847:   /* Remaining options are just for proper interfaces */
  848:   if (ifa->type == OSPF_IT_VLINK)
  849:     return 1;
  850: 
  851: 
  852:   /* COST */
  853:   if (ifa->cost != new->cost)
  854:   {
  855:     OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d",
  856: 	       ifname, ifa->cost, new->cost);
  857: 
  858:     ifa->cost = new->cost;
  859:   }
  860: 
  861:   /* PRIORITY */
  862:   if (ifa->priority != new->priority)
  863:   {
  864:     OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d",
  865: 	       ifname, ifa->priority, new->priority);
  866: 
  867:     ifa->priority = new->priority;
  868:     ospf_iface_sm(ifa, ISM_NEICH);
  869:     ospf_notify_link_lsa(ifa);
  870:   }
  871: 
  872:   /* STRICT NBMA */
  873:   if (ifa->strictnbma != new->strictnbma)
  874:   {
  875:     OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d",
  876: 	       ifname, ifa->strictnbma, new->strictnbma);
  877:     ifa->strictnbma = new->strictnbma;
  878:   }
  879: 
  880:   struct nbma_node *nb, *nbx;
  881: 
  882:   /* NBMA LIST - remove or update old */
  883:   WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
  884:   {
  885:     struct nbma_node *nb2 = find_nbma_node_(&new->nbma_list, nb->ip);
  886:     if (nb2)
  887:     {
  888:       if (nb->eligible != nb2->eligible)
  889:       {
  890: 	OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s",
  891: 		   nb->ip, ifname);
  892: 	nb->eligible = nb2->eligible;
  893:       }
  894:     }
  895:     else
  896:     {
  897:       OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s",
  898: 		       nb->ip, ifname);
  899:       rem_node(NODE nb);
  900:       mb_free(nb);
  901:     }
  902:   }
  903: 
  904:   /* NBMA LIST - add new */
  905:   WALK_LIST(nb, new->nbma_list)
  906:   {
  907:     /* See related note in ospf_iface_new() */
  908:     if (ospf_is_v2(p) && !ipa_in_net(nb->ip, ifa->addr->prefix, ifa->addr->pxlen))
  909:       continue;
  910: 
  911:     if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
  912:       log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
  913: 	  p->p.name, nb->ip);
  914: 
  915:     if (! find_nbma_node(ifa, nb->ip))
  916:     {
  917:       OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s",
  918: 		 nb->ip, ifname);
  919:       add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
  920:     }
  921:   }
  922: 
  923:   int update_buffers = 0;
  924: 
  925:   /* TX LENGTH */
  926:   if (old->tx_length != new->tx_length)
  927:   {
  928:     OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d",
  929: 	       ifname, old->tx_length, new->tx_length);
  930: 
  931:     /* ifa cannot be vlink */
  932:     ifa->tx_length = ifa_tx_length(ifa);
  933:     update_buffers = 1;
  934: 
  935:     if (!ifa->stub)
  936:       ospf_iface_update_flood_queue_size(ifa);
  937:   }
  938: 
  939:   /* RX BUFFER */
  940:   if (old->rx_buffer != new->rx_buffer)
  941:   {
  942:     OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d",
  943: 	       ifname, old->rx_buffer, new->rx_buffer);
  944: 
  945:     /* ifa cannot be vlink */
  946:     update_buffers = 1;
  947:   }
  948: 
  949:   /* Buffer size depends on both tx_length and rx_buffer options */
  950:   if (update_buffers && ifa->sk)
  951:   {
  952:     uint bsize = ifa_bufsize(ifa);
  953:     sk_set_rbsize(ifa->sk, bsize);
  954:     sk_set_tbsize(ifa->sk, bsize);
  955:   }
  956: 
  957:   /* LINK */
  958:   if (ifa->check_link != new->check_link)
  959:   {
  960:     OSPF_TRACE(D_EVENTS, "%s link check for %s",
  961: 	       new->check_link ? "Enabling" : "Disabling", ifname);
  962:     ifa->check_link = new->check_link;
  963: 
  964:     /* ifa cannot be vlink */
  965:     if (!(ifa->iface->flags & IF_LINK_UP))
  966:       ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
  967:   }
  968: 
  969:   /* ECMP weight */
  970:   if (ifa->ecmp_weight != new->ecmp_weight)
  971:   {
  972:     OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d",
  973: 	       ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
  974:     ifa->ecmp_weight = new->ecmp_weight;
  975:   }
  976: 
  977:   /* Link LSA suppression */
  978:   if (((ifa->type == OSPF_IT_PTP) || (ifa->type == OSPF_IT_PTMP)) &&
  979:       (ifa->link_lsa_suppression != new->link_lsa_suppression))
  980:   {
  981:     OSPF_TRACE(D_EVENTS, "Changing link LSA suppression of %s from %d to %d",
  982: 	       ifname, ifa->link_lsa_suppression, new->link_lsa_suppression);
  983: 
  984:     ifa->link_lsa_suppression = new->link_lsa_suppression;
  985:     ospf_notify_link_lsa(ifa);
  986:   }
  987: 
  988:   /* BFD */
  989:   if (ifa->bfd != new->bfd)
  990:   {
  991:     OSPF_TRACE(D_EVENTS, "%s BFD for %s",
  992: 	       new->bfd ? "Enabling" : "Disabling", ifname);
  993:     ifa->bfd = new->bfd;
  994: 
  995:     struct ospf_neighbor *n;
  996:     WALK_LIST(n, ifa->neigh_list)
  997:       ospf_neigh_update_bfd(n, ifa->bfd);
  998:   }
  999: 
 1000: 
 1001:   /* instance_id is not updated - it is part of key */
 1002: 
 1003:   return 1;
 1004: }
 1005: 
 1006: 
 1007: /*
 1008:  * State for matching iface pattterns walk
 1009:  *
 1010:  * This is significantly different in OSPFv2 and OSPFv3.
 1011:  * In OSPFv2, OSPF ifaces are created for each IP prefix (struct ifa)
 1012:  * In OSPFv3, OSPF ifaces are created based on real iface (struct iface)
 1013:  * We support instance_id for both OSPFv2 (RFC 6549) and OSPFv3.
 1014:  *
 1015:  * We process one ifa/iface and match it for all configured instance IDs. We
 1016:  * maintain bitfields to track whether given instance ID was already matched.
 1017:  * We have two bitfields, one global (active) and one per area (ignore), to
 1018:  * detect misconfigured cases where one iface with one instance ID matches in
 1019:  * multiple areas.
 1020:  */
 1021: 
 1022: struct ospf_mip_walk {
 1023:   u32 active[8];		/* Bitfield of active instance IDs */
 1024:   u32 ignore[8];		/* Bitfield of instance IDs matched in current area */
 1025:   struct ospf_area *oa;		/* Current area */
 1026:   struct ospf_iface_patt *ip;	/* Current iface pattern */
 1027:   struct iface *iface;		/* Specified iface (input) */
 1028:   struct ifa *a;		/* Specified ifa (input) */
 1029:   int warn;			/* Whether iface matched in multiple areas */
 1030: };
 1031: 
 1032: static int
 1033: ospf_walk_matching_iface_patts(struct ospf_proto *p, struct ospf_mip_walk *s)
 1034: {
 1035:   int id;
 1036: 
 1037:   if (s->ip)
 1038:     goto step;
 1039: 
 1040:   WALK_LIST(s->oa, p->area_list)
 1041:   {
 1042:     if (s->oa->marked)
 1043:       continue;
 1044: 
 1045:     WALK_LIST(s->ip, s->oa->ac->patt_list)
 1046:     {
 1047:       id = s->ip->instance_id;
 1048:       if (BIT32_TEST(s->ignore, id))
 1049: 	continue;
 1050: 
 1051:       if (iface_patt_match(&s->ip->i, s->iface, s->a))
 1052:       {
 1053: 	/* Now we matched ifa/iface/instance_id for the first time in current area */
 1054: 	BIT32_SET(s->ignore, id);
 1055: 
 1056: 	/* If we already found it in previous areas, ignore it and add warning */
 1057: 	if (BIT32_TEST(s->active, id))
 1058: 	  { s->warn = 1; continue; }
 1059: 
 1060: 	BIT32_SET(s->active, id);
 1061: 	return 1;
 1062:       step:
 1063: 	;
 1064:       }
 1065:     }
 1066:     BIT32_ZERO(s->ignore, 256);
 1067:   }
 1068: 
 1069:   if (s->warn)
 1070:     log(L_WARN "%s: Interface %s matches for multiple areas", p->p.name, s->iface->name);
 1071: 
 1072:   return 0;
 1073: }
 1074: 
 1075: 
 1076: static struct ospf_iface *
 1077: ospf_iface_find_by_key(struct ospf_proto *p, struct ifa *a, int instance_id)
 1078: {
 1079:   struct ospf_iface *ifa;
 1080: 
 1081:   WALK_LIST(ifa, p->iface_list)
 1082:     if ((ifa->addr == a) && (ifa->instance_id == instance_id) &&
 1083: 	(ifa->type != OSPF_IT_VLINK))
 1084:       return ifa;
 1085: 
 1086:   return NULL;
 1087: }
 1088: 
 1089: 
 1090: void
 1091: ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a)
 1092: {
 1093:   struct ospf_proto *p = (struct ospf_proto *) P;
 1094: 
 1095:   if (a->flags & IA_SECONDARY)
 1096:     return;
 1097: 
 1098:   if (a->scope <= SCOPE_LINK)
 1099:     return;
 1100: 
 1101:   /* In OSPFv2, we create OSPF iface for each address. */
 1102:   if (flags & IF_CHANGE_UP)
 1103:   {
 1104:     struct ospf_mip_walk s = { .iface = a->iface, .a = a };
 1105:     while (ospf_walk_matching_iface_patts(p, &s))
 1106:       ospf_iface_new(s.oa, a, s.ip);
 1107:   }
 1108: 
 1109:   if (flags & IF_CHANGE_DOWN)
 1110:   {
 1111:     struct ospf_iface *ifa, *ifx;
 1112:     WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
 1113:       if ((ifa->type != OSPF_IT_VLINK) && (ifa->addr == a))
 1114: 	ospf_iface_remove(ifa);
 1115:     /* See a note in ospf_iface_notify() */
 1116:   }
 1117: }
 1118: 
 1119: void
 1120: ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a)
 1121: {
 1122:   struct ospf_proto *p = (struct ospf_proto *) P;
 1123: 
 1124:   if (a->flags & IA_SECONDARY)
 1125:     return;
 1126: 
 1127:   if (a->scope < SCOPE_LINK)
 1128:     return;
 1129: 
 1130:   /* In OSPFv3, we create OSPF iface for link-local address,
 1131:      other addresses are used for link-LSA. */
 1132:   if (a->scope == SCOPE_LINK)
 1133:   {
 1134:     if (flags & IF_CHANGE_UP)
 1135:     {
 1136:       struct ospf_mip_walk s = { .iface = a->iface };
 1137:       while (ospf_walk_matching_iface_patts(p, &s))
 1138: 	ospf_iface_new(s.oa, a, s.ip);
 1139:     }
 1140: 
 1141:     if (flags & IF_CHANGE_DOWN)
 1142:     {
 1143:       struct ospf_iface *ifa, *ifx;
 1144:       WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
 1145: 	if ((ifa->addr == a) && (ifa->type != OSPF_IT_VLINK))
 1146: 	  ospf_iface_remove(ifa);
 1147:     }
 1148:   }
 1149:   else
 1150:   {
 1151:     struct ospf_iface *ifa;
 1152:     WALK_LIST(ifa, p->iface_list)
 1153:       if (ifa->iface == a->iface)
 1154:       {
 1155: 	/* RFC 5340 4.4.3 Event 5 - prefix added/deleted */
 1156: 	ospf_notify_link_lsa(ifa);
 1157: 	ospf_notify_rt_lsa(ifa->oa);
 1158:       }
 1159:   }
 1160: }
 1161: 
 1162: 
 1163: static void
 1164: ospf_reconfigure_ifaces2(struct ospf_proto *p)
 1165: {
 1166:   struct iface *iface;
 1167:   struct ifa *a;
 1168: 
 1169:   WALK_LIST(iface, iface_list)
 1170:   {
 1171:     if (! (iface->flags & IF_UP))
 1172:       continue;
 1173: 
 1174:     WALK_LIST(a, iface->addrs)
 1175:     {
 1176:       if (a->flags & IA_SECONDARY)
 1177: 	continue;
 1178: 
 1179:       if (a->scope <= SCOPE_LINK)
 1180: 	continue;
 1181: 
 1182:       struct ospf_mip_walk s = { .iface = iface, .a = a };
 1183:       while (ospf_walk_matching_iface_patts(p, &s))
 1184:       {
 1185: 	/* Main inner loop */
 1186: 	struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
 1187: 	if (ifa)
 1188: 	{
 1189: 	  if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
 1190: 	      ospf_iface_reconfigure(ifa, s.ip))
 1191: 	    continue;
 1192: 
 1193: 	  /* Hard restart */
 1194: 	  log(L_INFO "%s: Restarting interface %s (%I/%d) in area %R",
 1195: 	      p->p.name, ifa->ifname, a->prefix, a->pxlen, s.oa->areaid);
 1196: 	  ospf_iface_shutdown(ifa);
 1197: 	  ospf_iface_remove(ifa);
 1198: 	}
 1199: 
 1200: 	ospf_iface_new(s.oa, a, s.ip);
 1201:       }
 1202:     }
 1203:   }
 1204: }
 1205: 
 1206: static void
 1207: ospf_reconfigure_ifaces3(struct ospf_proto *p)
 1208: {
 1209:   struct iface *iface;
 1210:   struct ifa *a;
 1211: 
 1212:   WALK_LIST(iface, iface_list)
 1213:   {
 1214:     if (! (iface->flags & IF_UP))
 1215:       continue;
 1216: 
 1217:     WALK_LIST(a, iface->addrs)
 1218:     {
 1219:       if (a->flags & IA_SECONDARY)
 1220: 	continue;
 1221: 
 1222:       if (a->scope != SCOPE_LINK)
 1223: 	continue;
 1224: 
 1225:       struct ospf_mip_walk s = { .iface = iface };
 1226:       while (ospf_walk_matching_iface_patts(p, &s))
 1227:       {
 1228: 	/* Main inner loop */
 1229: 	struct ospf_iface *ifa = ospf_iface_find_by_key(p, a, s.ip->instance_id);
 1230: 	if (ifa)
 1231: 	{
 1232: 	  if ((ifa->oa == s.oa) && (ifa->marked < 2) &&
 1233: 	      ospf_iface_reconfigure(ifa, s.ip))
 1234: 	    continue;
 1235: 
 1236: 	  /* Hard restart */
 1237: 	  log(L_INFO "%s: Restarting interface %s (IID %d) in area %R",
 1238: 	      p->p.name, ifa->ifname, ifa->instance_id, s.oa->areaid);
 1239: 	  ospf_iface_shutdown(ifa);
 1240: 	  ospf_iface_remove(ifa);
 1241: 	}
 1242: 
 1243: 	ospf_iface_new(s.oa, a, s.ip);
 1244:       }
 1245:     }
 1246:   }
 1247: }
 1248: 
 1249: void
 1250: ospf_reconfigure_ifaces(struct ospf_proto *p)
 1251: {
 1252:   if (ospf_is_v2(p))
 1253:     ospf_reconfigure_ifaces2(p);
 1254:   else
 1255:     ospf_reconfigure_ifaces3(p);
 1256: }
 1257: 
 1258: 
 1259: static void
 1260: ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
 1261: {
 1262:   /* ifa is not vlink */
 1263: 
 1264:   OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d",
 1265: 	     ifa->ifname, ifa->iface->mtu);
 1266: 
 1267:   ifa->tx_length = ifa_tx_length(ifa);
 1268: 
 1269:   if (!ifa->sk)
 1270:     return;
 1271: 
 1272:   /* We do not shrink dynamic buffers */
 1273:   uint bsize = ifa_bufsize(ifa);
 1274:   if (bsize > ifa->sk->rbsize)
 1275:     sk_set_rbsize(ifa->sk, bsize);
 1276:   if (bsize > ifa->sk->tbsize)
 1277:     sk_set_tbsize(ifa->sk, bsize);
 1278: 
 1279:   if (!ifa->stub)
 1280:     ospf_iface_update_flood_queue_size(ifa);
 1281: }
 1282: 
 1283: static void
 1284: ospf_iface_notify(struct ospf_proto *p, uint flags, struct ospf_iface *ifa)
 1285: {
 1286:   /* ifa is not vlink */
 1287: 
 1288:   if (flags & IF_CHANGE_DOWN)
 1289:   {
 1290:     ospf_iface_remove(ifa);
 1291:     return;
 1292:   }
 1293: 
 1294:   if (flags & IF_CHANGE_LINK)
 1295:     ospf_iface_sm(ifa, (ifa->iface->flags & IF_LINK_UP) ? ISM_UNLOOP : ISM_LOOP);
 1296: 
 1297:   if (flags & IF_CHANGE_MTU)
 1298:     ospf_iface_change_mtu(p, ifa);
 1299: }
 1300: 
 1301: void
 1302: ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
 1303: {
 1304:   struct ospf_proto *p = (struct ospf_proto *) P;
 1305: 
 1306:   /*
 1307:   if (iface->flags & IF_IGNORE)
 1308:     return;
 1309:   */
 1310: 
 1311:   /* Going up means that there are no such ifaces yet */
 1312:   if (flags & IF_CHANGE_UP)
 1313:     return;
 1314: 
 1315:   struct ospf_iface *ifa, *ifx;
 1316:   WALK_LIST_DELSAFE(ifa, ifx, p->iface_list)
 1317:     if (ifa->iface == iface)
 1318:       ospf_iface_notify(p, flags, ifa);
 1319: 
 1320:   /* We use here that even shutting down iface also shuts down
 1321:      the vlinks, but vlinks are not freed and stays in the
 1322:      iface_list even when down */
 1323: }
 1324: 
 1325: void
 1326: ospf_iface_info(struct ospf_iface *ifa)
 1327: {
 1328:   char *more = "";
 1329: 
 1330:   if (ifa->strictnbma &&
 1331:       ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)))
 1332:     more = " (strict)";
 1333: 
 1334:   if (ifa->cf->real_bcast &&
 1335:       ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP)))
 1336:     more = " (real)";
 1337: 
 1338:   if (ifa->type == OSPF_IT_VLINK)
 1339:   {
 1340:     cli_msg(-1015, "Virtual link %s to %R", ifa->ifname, ifa->vid);
 1341:     cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
 1342:     cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid);
 1343:   }
 1344:   else
 1345:   {
 1346:     if (ospf_is_v3(ifa->oa->po))
 1347:       cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id);
 1348:     else if (ifa->addr->flags & IA_PEER)
 1349:       cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite);
 1350:     else
 1351:       cli_msg(-1015, "Interface %s (%I/%d)", ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen);
 1352: 
 1353:     cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
 1354:     cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
 1355:   }
 1356:   cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : "");
 1357:   cli_msg(-1015, "\tPriority: %u", ifa->priority);
 1358:   cli_msg(-1015, "\tCost: %u", ifa->cost);
 1359:   if (ifa->oa->po->ecmp)
 1360:     cli_msg(-1015, "\tECMP weight: %d", ((int) ifa->ecmp_weight) + 1);
 1361:   cli_msg(-1015, "\tHello timer: %u", ifa->helloint);
 1362: 
 1363:   if (ifa->type == OSPF_IT_NBMA)
 1364:   {
 1365:     cli_msg(-1015, "\tPoll timer: %u", ifa->pollint);
 1366:   }
 1367:   cli_msg(-1015, "\tWait timer: %u", ifa->waitint);
 1368:   cli_msg(-1015, "\tDead timer: %u", ifa->deadint);
 1369:   cli_msg(-1015, "\tRetransmit timer: %u", ifa->rxmtint);
 1370:   if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
 1371:   {
 1372:     cli_msg(-1015, "\tDesignated router (ID): %R", ifa->drid);
 1373:     cli_msg(-1015, "\tDesignated router (IP): %I", ifa->drip);
 1374:     cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid);
 1375:     cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip);
 1376:   }
 1377: }

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