File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf / dbdes.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_dbdes2_packet
   15: {
   16:   struct ospf_packet hdr;
   17:   union ospf_auth auth;
   18: 
   19:   u16 iface_mtu;
   20:   u8 options;
   21:   u8 imms;			/* I, M, MS bits */
   22:   u32 ddseq;
   23: 
   24:   struct ospf_lsa_header lsas[];
   25: };
   26: 
   27: struct ospf_dbdes3_packet
   28: {
   29:   struct ospf_packet hdr;
   30: 
   31:   u32 options;
   32:   u16 iface_mtu;
   33:   u8 padding;
   34:   u8 imms;			/* I, M, MS bits */
   35:   u32 ddseq;
   36: 
   37:   struct ospf_lsa_header lsas[];
   38: };
   39: 
   40: 
   41: static inline uint
   42: ospf_dbdes_hdrlen(struct ospf_proto *p UNUSED4 UNUSED6)
   43: {
   44:   return ospf_is_v2(p) ?
   45:     sizeof(struct ospf_dbdes2_packet) : sizeof(struct ospf_dbdes3_packet);
   46: }
   47: 
   48: 
   49: static void
   50: ospf_dbdes_body(struct ospf_proto *p, struct ospf_packet *pkt,
   51: 		struct ospf_lsa_header **body, uint *count)
   52: {
   53:   uint plen = ntohs(pkt->length);
   54:   uint hlen = ospf_dbdes_hdrlen(p);
   55: 
   56:   *body = ((void *) pkt) + hlen;
   57:   *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
   58: }
   59: 
   60: static void
   61: ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
   62: {
   63:   struct ospf_lsa_header *lsas;
   64:   uint i, lsa_count;
   65:   u32 pkt_ddseq;
   66:   u16 pkt_iface_mtu;
   67:   u8 pkt_imms;
   68: 
   69:   ASSERT(pkt->type == DBDES_P);
   70:   ospf_dump_common(p, pkt);
   71: 
   72:   if (ospf_is_v2(p))
   73:   {
   74:     struct ospf_dbdes2_packet *ps = (void *) pkt;
   75:     pkt_iface_mtu = ntohs(ps->iface_mtu);
   76:     pkt_imms = ps->imms;
   77:     pkt_ddseq = ntohl(ps->ddseq);
   78:   }
   79:   else /* OSPFv3 */
   80:   {
   81:     struct ospf_dbdes3_packet *ps = (void *) pkt;
   82:     pkt_iface_mtu = ntohs(ps->iface_mtu);
   83:     pkt_imms = ps->imms;
   84:     pkt_ddseq = ntohl(ps->ddseq);
   85:   }
   86: 
   87:   log(L_TRACE "%s:     mtu      %u", p->p.name, pkt_iface_mtu);
   88:   log(L_TRACE "%s:     imms     %s%s%s", p->p.name,
   89:       (pkt_imms & DBDES_I) ? "I " : "",
   90:       (pkt_imms & DBDES_M) ? "M " : "",
   91:       (pkt_imms & DBDES_MS) ? "MS" : "");
   92:   log(L_TRACE "%s:     ddseq    %u", p->p.name, pkt_ddseq);
   93: 
   94:   ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
   95:   for (i = 0; i < lsa_count; i++)
   96:     ospf_dump_lsahdr(p, lsas + i);
   97: }
   98: 
   99: 
  100: static void
  101: ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
  102: {
  103:   struct ospf_iface *ifa = n->ifa;
  104:   struct ospf_packet *pkt;
  105:   uint length;
  106: 
  107:   u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
  108: 
  109:   /* Update DBDES buffer */
  110:   if (n->ldd_bsize != ifa->tx_length)
  111:   {
  112:     mb_free(n->ldd_buffer);
  113:     n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
  114:     n->ldd_bsize = ifa->tx_length;
  115:   }
  116: 
  117:   pkt = n->ldd_buffer;
  118:   ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
  119: 
  120:   if (ospf_is_v2(p))
  121:   {
  122:     struct ospf_dbdes2_packet *ps = (void *) pkt;
  123:     ps->iface_mtu = htons(iface_mtu);
  124:     ps->options = ifa->oa->options & ~OPT_N;
  125:     ps->imms = 0;	/* Will be set later */
  126:     ps->ddseq = htonl(n->dds);
  127:     length = sizeof(struct ospf_dbdes2_packet);
  128:   }
  129:   else /* OSPFv3 */
  130:   {
  131:     struct ospf_dbdes3_packet *ps = (void *) pkt;
  132:     ps->options = htonl(ifa->oa->options & ~OPT_N);
  133:     ps->iface_mtu = htons(iface_mtu);
  134:     ps->padding = 0;
  135:     ps->imms = 0;	/* Will be set later */
  136:     ps->ddseq = htonl(n->dds);
  137:     length = sizeof(struct ospf_dbdes3_packet);
  138:   }
  139: 
  140:   /* Prepare DBDES body */
  141:   if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M))
  142:   {
  143:     struct ospf_lsa_header *lsas;
  144:     struct top_hash_entry *en;
  145:     uint i = 0, lsa_max;
  146: 
  147:     ospf_dbdes_body(p, pkt, &lsas, &lsa_max);
  148:     en = (void *) s_get(&(n->dbsi));
  149: 
  150:     while (i < lsa_max)
  151:     {
  152:       if (!SNODE_VALID(en))
  153:       {
  154: 	n->myimms &= ~DBDES_M;	/* Unset More bit */
  155: 	break;
  156:       }
  157: 
  158:       if ((en->lsa.age < LSA_MAXAGE) &&
  159: 	  lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
  160:       {
  161: 	lsa_hton_hdr(&(en->lsa), lsas + i);
  162: 	i++;
  163:       }
  164: 
  165:       en = SNODE_NEXT(en);
  166:     }
  167: 
  168:     s_put(&(n->dbsi), SNODE en);
  169: 
  170:     length += i * sizeof(struct ospf_lsa_header);
  171:   }
  172: 
  173:   if (ospf_is_v2(p))
  174:     ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms;
  175:   else
  176:     ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms;
  177: 
  178:   pkt->length = htons(length);
  179: }
  180: 
  181: static void
  182: ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
  183: {
  184:   struct ospf_iface *ifa = n->ifa;
  185: 
  186:   OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
  187: 	      "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname);
  188:   sk_set_tbuf(ifa->sk, n->ldd_buffer);
  189:   ospf_send_to(ifa, n->ip);
  190:   sk_set_tbuf(ifa->sk, NULL);
  191: }
  192: 
  193: /**
  194:  * ospf_send_dbdes - transmit database description packet
  195:  * @p: OSPF protocol instance
  196:  * @n: neighbor
  197:  *
  198:  * Sending of a database description packet is described in 10.8 of RFC 2328.
  199:  * Reception of each packet is acknowledged in the sequence number of another.
  200:  * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
  201:  * does not reply, I don't create a new packet but just send the content
  202:  * of the buffer.
  203:  */
  204: void
  205: ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
  206: {
  207:   /* RFC 2328 10.8 */
  208: 
  209:   ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE));
  210: 
  211:   if (n->ifa->oa->rt == NULL)
  212:     return;
  213: 
  214:   ospf_prepare_dbdes(p, n);
  215:   ospf_do_send_dbdes(p, n);
  216: }
  217: 
  218: void
  219: ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
  220: {
  221:   ASSERT(n->state > NEIGHBOR_EXSTART);
  222: 
  223:   if (!n->ldd_buffer)
  224:   {
  225:     log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
  226:     ospf_neigh_sm(n, INM_SEQMIS);
  227:     return;
  228:   }
  229: 
  230:   /* Send last packet */
  231:   ospf_do_send_dbdes(p, n);
  232: }
  233: 
  234: static int
  235: ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
  236: {
  237:   struct ospf_iface *ifa = n->ifa;
  238:   struct ospf_lsa_header *lsas, lsa;
  239:   struct top_hash_entry *en, *req;
  240:   const char *err_dsc = NULL;
  241:   u32 lsa_type, lsa_domain;
  242:   uint i, lsa_count;
  243: 
  244:   ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
  245: 
  246:   for (i = 0; i < lsa_count; i++)
  247:   {
  248:     lsa_ntoh_hdr(lsas + i, &lsa);
  249:     lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
  250: 
  251:     /* RFC 2328 10.6 and RFC 5340 4.2.2 */
  252: 
  253:     if (!lsa_type)
  254:       DROP1("LSA of unknown type");
  255: 
  256:     if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
  257:       DROP1("LSA with AS scope in stub area");
  258: 
  259:     /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
  260:     if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
  261:       DROP1("rt-summary-LSA in stub area");
  262: 
  263:     /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
  264:     if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
  265:       DROP1("LSA with invalid scope");
  266: 
  267:     en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
  268:     if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
  269:     {
  270:       /* This should be splitted to ospf_lsa_lsrq_up() */
  271:       req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
  272: 
  273:       if (!SNODE_VALID(req))
  274: 	s_add_tail(&n->lsrql, SNODE req);
  275: 
  276:       if (!SNODE_VALID(n->lsrqi))
  277: 	n->lsrqi = req;
  278: 
  279:       req->lsa = lsa;
  280:       req->lsa_body = LSA_BODY_DUMMY;
  281: 
  282:       if (!tm_active(n->lsrq_timer))
  283: 	tm_start(n->lsrq_timer, 0);
  284:     }
  285:   }
  286: 
  287:   return 0;
  288: 
  289: drop:
  290:   LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt);
  291:   LOG_LSA2("  received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
  292: 
  293:   ospf_neigh_sm(n, INM_SEQMIS);
  294:   return -1;
  295: }
  296: 
  297: void
  298: ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
  299: 		   struct ospf_neighbor *n)
  300: {
  301:   struct ospf_proto *p = ifa->oa->po;
  302:   const char *err_dsc = NULL;
  303:   u32 rcv_ddseq, rcv_options;
  304:   u16 rcv_iface_mtu;
  305:   u8 rcv_imms;
  306:   uint plen, err_val = 0;
  307: 
  308:   /* RFC 2328 10.6 */
  309: 
  310:   plen = ntohs(pkt->length);
  311:   if (plen < ospf_dbdes_hdrlen(p))
  312:   {
  313:     LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
  314:     return;
  315:   }
  316: 
  317:   OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
  318: 
  319:   ospf_neigh_sm(n, INM_HELLOREC);
  320: 
  321:   if (ospf_is_v2(p))
  322:   {
  323:     struct ospf_dbdes2_packet *ps = (void *) pkt;
  324:     rcv_iface_mtu = ntohs(ps->iface_mtu);
  325:     rcv_options = ps->options;
  326:     rcv_imms = ps->imms;
  327:     rcv_ddseq = ntohl(ps->ddseq);
  328:   }
  329:   else /* OSPFv3 */
  330:   {
  331:     struct ospf_dbdes3_packet *ps = (void *) pkt;
  332:     rcv_options = ntohl(ps->options);
  333:     rcv_iface_mtu = ntohs(ps->iface_mtu);
  334:     rcv_imms = ps->imms;
  335:     rcv_ddseq = ntohl(ps->ddseq);
  336:   }
  337: 
  338:   switch (n->state)
  339:   {
  340:   case NEIGHBOR_DOWN:
  341:   case NEIGHBOR_ATTEMPT:
  342:   case NEIGHBOR_2WAY:
  343:     OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart");
  344:     return;
  345: 
  346:   case NEIGHBOR_INIT:
  347:     ospf_neigh_sm(n, INM_2WAYREC);
  348:     if (n->state != NEIGHBOR_EXSTART)
  349:       return;
  350:     /* fallthrough */
  351: 
  352:   case NEIGHBOR_EXSTART:
  353:     if ((ifa->type != OSPF_IT_VLINK) &&
  354: 	(rcv_iface_mtu != ifa->iface->mtu) &&
  355: 	(rcv_iface_mtu != 0) &&
  356: 	(ifa->iface->mtu != 0))
  357:       LOG_PKT_WARN("MTU mismatch with nbr %R on %s (remote %d, local %d)",
  358: 		   n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
  359: 
  360:     if ((rcv_imms == DBDES_IMMS) &&
  361: 	(n->rid > p->router_id) &&
  362: 	(plen == ospf_dbdes_hdrlen(p)))
  363:     {
  364:       /* I'm slave! */
  365:       n->dds = rcv_ddseq;
  366:       n->ddr = rcv_ddseq;
  367:       n->options = rcv_options;
  368:       n->myimms &= ~DBDES_MS;
  369:       n->imms = rcv_imms;
  370:       tm_stop(n->dbdes_timer);
  371:       ospf_neigh_sm(n, INM_NEGDONE);
  372:       ospf_send_dbdes(p, n);
  373:       break;
  374:     }
  375: 
  376:     if (!(rcv_imms & DBDES_I) &&
  377: 	!(rcv_imms & DBDES_MS) &&
  378: 	(n->rid < p->router_id) &&
  379: 	(n->dds == rcv_ddseq))
  380:     {
  381:       /* I'm master! */
  382:       n->options = rcv_options;
  383:       n->ddr = rcv_ddseq - 1;	/* It will be set corectly a few lines down */
  384:       n->imms = rcv_imms;
  385:       ospf_neigh_sm(n, INM_NEGDONE);
  386:       /* Continue to the NEIGHBOR_EXCHANGE case */
  387:     }
  388:     else
  389:     {
  390:       DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
  391:       break;
  392:     }
  393: 
  394:   case NEIGHBOR_EXCHANGE:
  395:     if ((rcv_imms == n->imms) &&
  396: 	(rcv_options == n->options) &&
  397: 	(rcv_ddseq == n->ddr))
  398:       goto duplicate;
  399: 
  400:     if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
  401:       DROP("MS-bit mismatch", rcv_imms);
  402: 
  403:     if (rcv_imms & DBDES_I)
  404:       DROP("I-bit mismatch", rcv_imms);
  405: 
  406:     if (rcv_options != n->options)
  407:       DROP("options mismatch", rcv_options);
  408: 
  409:     n->ddr = rcv_ddseq;
  410:     n->imms = rcv_imms;
  411: 
  412:     if (n->myimms & DBDES_MS)
  413:     {
  414:       /* MASTER */
  415: 
  416:       if (rcv_ddseq != n->dds)
  417: 	DROP("DD sequence number mismatch", rcv_ddseq);
  418: 
  419:       n->dds++;
  420: 
  421:       if (ospf_process_dbdes(p, pkt, n) < 0)
  422: 	return;
  423: 
  424:       if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
  425:       {
  426: 	tm_stop(n->dbdes_timer);
  427: 	ospf_neigh_sm(n, INM_EXDONE);
  428: 	break;
  429:       }
  430: 
  431:       ospf_send_dbdes(p, n);
  432:       tm_start(n->dbdes_timer, n->ifa->rxmtint);
  433:     }
  434:     else
  435:     {
  436:       /* SLAVE */
  437: 
  438:       if (rcv_ddseq != (n->dds + 1))
  439: 	DROP("DD sequence number mismatch", rcv_ddseq);
  440: 
  441:       n->ddr = rcv_ddseq;
  442:       n->dds = rcv_ddseq;
  443: 
  444:       if (ospf_process_dbdes(p, pkt, n) < 0)
  445: 	return;
  446: 
  447:       ospf_send_dbdes(p, n);
  448: 
  449:       if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
  450: 	ospf_neigh_sm(n, INM_EXDONE);
  451:     }
  452:     break;
  453: 
  454:   case NEIGHBOR_LOADING:
  455:   case NEIGHBOR_FULL:
  456:     if ((rcv_imms == n->imms) &&
  457: 	(rcv_options == n->options) &&
  458: 	(rcv_ddseq == n->ddr))
  459:       goto duplicate;
  460: 
  461:     DROP("too late for DD exchange", n->state);
  462: 
  463:   default:
  464:     bug("Undefined interface state");
  465:   }
  466:   return;
  467: 
  468: duplicate:
  469:   OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate");
  470: 
  471:   /* Slave should retransmit DBDES packet */
  472:   if (!(n->myimms & DBDES_MS))
  473:     ospf_rxmt_dbdes(p, n);
  474:   return;
  475: 
  476: drop:
  477:   LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
  478: 	  n->rid, ifa->ifname, err_dsc, err_val);
  479: 
  480:   ospf_neigh_sm(n, INM_SEQMIS);
  481:   return;
  482: }

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