File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / hello.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, 6 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--2004 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: 
   13: 
   14: struct ospf_hello2_packet
   15: {
   16:   struct ospf_packet hdr;
   17:   union ospf_auth auth;
   18: 
   19:   u32 netmask;
   20:   u16 helloint;
   21:   u8 options;
   22:   u8 priority;
   23:   u32 deadint;
   24:   u32 dr;
   25:   u32 bdr;
   26: 
   27:   u32 neighbors[];
   28: };
   29: 
   30: struct ospf_hello3_packet
   31: {
   32:   struct ospf_packet hdr;
   33: 
   34:   u32 iface_id;
   35:   u8 priority;
   36:   u8 options3;
   37:   u8 options2;
   38:   u8 options;
   39:   u16 helloint;
   40:   u16 deadint;
   41:   u32 dr;
   42:   u32 bdr;
   43: 
   44:   u32 neighbors[];
   45: };
   46: 
   47: 
   48: void
   49: ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
   50: {
   51:   struct ospf_proto *p = ifa->oa->po;
   52:   struct ospf_packet *pkt;
   53:   struct ospf_neighbor *neigh, *n1;
   54:   struct nbma_node *nb;
   55:   u32 *neighbors;
   56:   uint length;
   57:   int i, max;
   58: 
   59:   if (ifa->state <= OSPF_IS_LOOP)
   60:     return;
   61: 
   62:   if (ifa->stub)
   63:     return;
   64: 
   65: 
   66:   pkt = ospf_tx_buffer(ifa);
   67:   ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
   68: 
   69:   if (ospf_is_v2(p))
   70:   {
   71:     struct ospf_hello2_packet *ps = (void *) pkt;
   72: 
   73:     if ((ifa->type == OSPF_IT_VLINK) ||
   74: 	((ifa->type == OSPF_IT_PTP) && !ifa->ptp_netmask))
   75:       ps->netmask = 0;
   76:     else
   77:       ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
   78: 
   79:     ps->helloint = ntohs(ifa->helloint);
   80:     ps->options = ifa->oa->options;
   81:     ps->priority = ifa->priority;
   82:     ps->deadint = htonl(ifa->deadint);
   83:     ps->dr = htonl(ipa_to_u32(ifa->drip));
   84:     ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
   85: 
   86:     length = sizeof(struct ospf_hello2_packet);
   87:     neighbors = ps->neighbors;
   88:   }
   89:   else
   90:   {
   91:     struct ospf_hello3_packet *ps = (void *) pkt;
   92: 
   93:     ps->iface_id = htonl(ifa->iface_id);
   94:     ps->priority = ifa->priority;
   95:     ps->options3 = ifa->oa->options >> 16;
   96:     ps->options2 = ifa->oa->options >> 8;
   97:     ps->options = ifa->oa->options;
   98:     ps->helloint = ntohs(ifa->helloint);
   99:     ps->deadint = htons(ifa->deadint);
  100:     ps->dr = htonl(ifa->drid);
  101:     ps->bdr = htonl(ifa->bdrid);
  102: 
  103:     length = sizeof(struct ospf_hello3_packet);
  104:     neighbors = ps->neighbors;
  105:   }
  106: 
  107:   i = 0;
  108:   max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32);
  109: 
  110:   /* Fill all neighbors */
  111:   if (kind != OHS_SHUTDOWN)
  112:   {
  113:     WALK_LIST(neigh, ifa->neigh_list)
  114:     {
  115:       if (i == max)
  116:       {
  117: 	log(L_WARN "%s: Too many neighbors on %s", p->p.name, ifa->ifname);
  118: 	break;
  119:       }
  120:       neighbors[i] = htonl(neigh->rid);
  121:       i++;
  122:     }
  123:   }
  124: 
  125:   length += i * sizeof(u32);
  126:   pkt->length = htons(length);
  127: 
  128:   OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s", ifa->ifname);
  129: 
  130:   switch(ifa->type)
  131:   {
  132:   case OSPF_IT_BCAST:
  133:   case OSPF_IT_PTP:
  134:     ospf_send_to_all(ifa);
  135:     break;
  136: 
  137:   case OSPF_IT_NBMA:
  138:     if (dirn)		/* Response to received hello */
  139:     {
  140:       ospf_send_to(ifa, dirn->ip);
  141:       break;
  142:     }
  143: 
  144:     int to_all = ifa->state > OSPF_IS_DROTHER;
  145:     int me_elig = ifa->priority > 0;
  146: 
  147:     if (kind == OHS_POLL)	/* Poll timer */
  148:     {
  149:       WALK_LIST(nb, ifa->nbma_list)
  150: 	if (!nb->found && (to_all || (me_elig && nb->eligible)))
  151: 	  ospf_send_to(ifa, nb->ip);
  152:     }
  153:     else			/* Hello timer */
  154:     {
  155:       WALK_LIST(n1, ifa->neigh_list)
  156: 	if (to_all || (me_elig && (n1->priority > 0)) ||
  157: 	    (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid))
  158: 	  ospf_send_to(ifa, n1->ip);
  159:     }
  160:     break;
  161: 
  162:   case OSPF_IT_PTMP:
  163:     WALK_LIST(n1, ifa->neigh_list)
  164:       ospf_send_to(ifa, n1->ip);
  165: 
  166:     WALK_LIST(nb, ifa->nbma_list)
  167:       if (!nb->found)
  168: 	ospf_send_to(ifa, nb->ip);
  169: 
  170:     /* If there is no other target, we also send HELLO packet to the other end */
  171:     if (ipa_nonzero(ifa->addr->opposite) && !ifa->strictnbma &&
  172: 	EMPTY_LIST(ifa->neigh_list) && EMPTY_LIST(ifa->nbma_list))
  173:       ospf_send_to(ifa, ifa->addr->opposite);
  174:     break;
  175: 
  176:   case OSPF_IT_VLINK:
  177:     ospf_send_to(ifa, ifa->vip);
  178:     break;
  179: 
  180:   default:
  181:     bug("Bug in ospf_send_hello()");
  182:   }
  183: }
  184: 
  185: 
  186: void
  187: ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
  188: 		   struct ospf_neighbor *n, ip_addr faddr)
  189: {
  190:   struct ospf_proto *p = ifa->oa->po;
  191:   const char *err_dsc = NULL;
  192:   u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
  193:   u8 rcv_options, rcv_priority;
  194:   u32 *neighbors;
  195:   u32 neigh_count;
  196:   uint plen, i, err_val = 0;
  197: 
  198:   /* RFC 2328 10.5 */
  199: 
  200:   /*
  201:    * We may not yet havethe associate neighbor, so we use Router ID from the
  202:    * packet instead of one from the neighbor structure for log messages.
  203:    */
  204:   u32 rcv_rid = ntohl(pkt->routerid);
  205:   OSPF_TRACE(D_PACKETS, "HELLO packet received from nbr %R on %s", rcv_rid, ifa->ifname);
  206: 
  207:   plen = ntohs(pkt->length);
  208: 
  209:   if (ospf_is_v2(p))
  210:   {
  211:     struct ospf_hello2_packet *ps = (void *) pkt;
  212: 
  213:     if (plen < sizeof(struct ospf_hello2_packet))
  214:       DROP("too short", plen);
  215: 
  216:     rcv_iface_id = 0;
  217:     rcv_helloint = ntohs(ps->helloint);
  218:     rcv_deadint = ntohl(ps->deadint);
  219:     rcv_dr = ntohl(ps->dr);
  220:     rcv_bdr = ntohl(ps->bdr);
  221:     rcv_options = ps->options;
  222:     rcv_priority = ps->priority;
  223: 
  224:     int pxlen = u32_masklen(ntohl(ps->netmask));
  225:     if (pxlen < 0)
  226:       DROP("prefix garbled", ntohl(ps->netmask));
  227: 
  228:     if ((ifa->type != OSPF_IT_VLINK) &&
  229: 	(ifa->type != OSPF_IT_PTP) &&
  230: 	((uint) pxlen != ifa->addr->pxlen))
  231:       DROP("prefix length mismatch", pxlen);
  232: 
  233:     neighbors = ps->neighbors;
  234:     neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
  235:   }
  236:   else /* OSPFv3 */
  237:   {
  238:     struct ospf_hello3_packet *ps = (void *) pkt;
  239: 
  240:     if (plen < sizeof(struct ospf_hello3_packet))
  241:       DROP("too short", plen);
  242: 
  243:     rcv_iface_id = ntohl(ps->iface_id);
  244:     rcv_helloint = ntohs(ps->helloint);
  245:     rcv_deadint = ntohs(ps->deadint);
  246:     rcv_dr = ntohl(ps->dr);
  247:     rcv_bdr = ntohl(ps->bdr);
  248:     rcv_options = ps->options;
  249:     rcv_priority = ps->priority;
  250: 
  251:     neighbors = ps->neighbors;
  252:     neigh_count = (plen - sizeof(struct ospf_hello3_packet)) / sizeof(u32);
  253:   }
  254: 
  255:   if (rcv_helloint != ifa->helloint)
  256:     DROP("hello interval mismatch", rcv_helloint);
  257: 
  258:   if (rcv_deadint != ifa->deadint)
  259:     DROP("dead interval mismatch", rcv_deadint);
  260: 
  261:   /* Check whether bits E, N match */
  262:   if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
  263:     DROP("area type mismatch", rcv_options);
  264: 
  265:   /* Check consistency of existing neighbor entry */
  266:   if (n)
  267:   {
  268:     uint t = ifa->type;
  269:     if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
  270:     {
  271:       /* Neighbor identified by IP address; Router ID may change */
  272:       if (n->rid != rcv_rid)
  273:       {
  274: 	OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R",
  275: 		   n->rid, ifa->ifname, rcv_rid);
  276: 	ospf_neigh_sm(n, INM_KILLNBR);
  277: 	n = NULL;
  278:       }
  279:     }
  280:     else /* OSPFv3 or OSPFv2/PtP */
  281:     {
  282:       /* Neighbor identified by Router ID; IP address may change */
  283:       if (!ipa_equal(faddr, n->ip))
  284:       {
  285: 	OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed IP address to %I",
  286: 		   n->rid, ifa->ifname, faddr);
  287: 	n->ip = faddr;
  288:       }
  289:     }
  290:   }
  291: 
  292:   if (!n)
  293:   {
  294:     if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
  295:     {
  296:       struct nbma_node *nn = find_nbma_node(ifa, faddr);
  297: 
  298:       if (!nn && ifa->strictnbma)
  299: 	DROP1("new neighbor denied");
  300: 
  301:       if (nn && (ifa->type == OSPF_IT_NBMA) &&
  302: 	  (((rcv_priority == 0) && nn->eligible) ||
  303: 	   ((rcv_priority > 0) && !nn->eligible)))
  304: 	DROP("eligibility mismatch", rcv_priority);
  305: 
  306:       if (nn)
  307: 	nn->found = 1;
  308:     }
  309: 
  310:     OSPF_TRACE(D_EVENTS, "New neighbor %R on %s, IP address %I",
  311: 	       rcv_rid, ifa->ifname, faddr);
  312: 
  313:     n = ospf_neighbor_new(ifa);
  314: 
  315:     n->rid = rcv_rid;
  316:     n->ip = faddr;
  317:     n->dr = rcv_dr;
  318:     n->bdr = rcv_bdr;
  319:     n->priority = rcv_priority;
  320:     n->iface_id = rcv_iface_id;
  321: 
  322:     if (n->ifa->cf->bfd)
  323:       ospf_neigh_update_bfd(n, n->ifa->bfd);
  324:   }
  325: 
  326:   u32 n_id = ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid;
  327: 
  328:   u32 old_dr = n->dr;
  329:   u32 old_bdr = n->bdr;
  330:   u32 old_priority = n->priority;
  331:   u32 old_iface_id = n->iface_id;
  332: 
  333:   n->dr = rcv_dr;
  334:   n->bdr = rcv_bdr;
  335:   n->priority = rcv_priority;
  336:   n->iface_id = rcv_iface_id;
  337: 
  338: 
  339:   /* Update inactivity timer */
  340:   ospf_neigh_sm(n, INM_HELLOREC);
  341: 
  342:   /* RFC 2328 9.5.1 - non-eligible routers reply to hello on NBMA nets */
  343:   if (ifa->type == OSPF_IT_NBMA)
  344:     if ((ifa->priority == 0) && (n->priority > 0))
  345:       ospf_send_hello(n->ifa, OHS_HELLO, n);
  346: 
  347: 
  348:   /* Examine list of neighbors */
  349:   for (i = 0; i < neigh_count; i++)
  350:     if (neighbors[i] == htonl(p->router_id))
  351:       goto found_self;
  352: 
  353:   ospf_neigh_sm(n, INM_1WAYREC);
  354:   return;
  355: 
  356: found_self:
  357:   ospf_neigh_sm(n, INM_2WAYREC);
  358: 
  359: 
  360:   if (n->iface_id != old_iface_id)
  361:   {
  362:     /* If neighbor is DR, also update cached DR interface ID */
  363:     if (ifa->drid == n->rid)
  364:       ifa->dr_iface_id = n->iface_id;
  365: 
  366:     /* RFC 5340 4.4.3 Event 4 - change of neighbor's interface ID */
  367:     ospf_notify_rt_lsa(ifa->oa);
  368: 
  369:     /* Missed in RFC 5340 4.4.3 Event 4 - (Px-)Net-LSA uses iface_id to ref Link-LSAs */
  370:     ospf_notify_net_lsa(ifa);
  371:   }
  372: 
  373:   if (ifa->state == OSPF_IS_WAITING)
  374:   {
  375:     /* Neighbor is declaring itself DR (and there is no BDR) or as BDR */
  376:     if (((n->dr == n_id) && (n->bdr == 0)) || (n->bdr == n_id))
  377:       ospf_iface_sm(ifa, ISM_BACKS);
  378:   }
  379:   else if (ifa->state >= OSPF_IS_DROTHER)
  380:   {
  381:     /* Neighbor changed priority or started/stopped declaring itself as DR/BDR */
  382:     if ((n->priority != old_priority) ||
  383: 	((n->dr == n_id) && (old_dr != n_id)) ||
  384: 	((n->dr != n_id) && (old_dr == n_id)) ||
  385: 	((n->bdr == n_id) && (old_bdr != n_id)) ||
  386: 	((n->bdr != n_id) && (old_bdr == n_id)))
  387:       ospf_iface_sm(ifa, ISM_NEICH);
  388:   }
  389: 
  390:   return;
  391: 
  392: drop:
  393:   LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
  394: 	  rcv_rid, ifa->ifname, err_dsc, err_val);
  395: }

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