File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / ospf / dbdes.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:56 2019 UTC (5 years, 5 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

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

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