Annotation of embedaddon/bird2/proto/ospf/lsupd.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD -- OSPF
        !             3:  *
        !             4:  *     (c) 2000--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: /*
        !            15: struct ospf_lsupd_packet
        !            16: {
        !            17:   struct ospf_packet hdr;
        !            18:   // union ospf_auth auth;
        !            19: 
        !            20:   u32 lsa_count;
        !            21:   void lsas[];
        !            22: };
        !            23: */
        !            24: 
        !            25: 
        !            26: void
        !            27: ospf_dump_lsahdr(struct ospf_proto *p, struct ospf_lsa_header *lsa_n)
        !            28: {
        !            29:   struct ospf_lsa_header lsa;
        !            30:   u32 lsa_etype;
        !            31: 
        !            32:   lsa_ntoh_hdr(lsa_n, &lsa);
        !            33:   lsa_etype = lsa_get_etype(&lsa, p);
        !            34: 
        !            35:   log(L_TRACE "%s:     LSA      Type: %04x, Id: %R, Rt: %R, Seq: %08x, Age: %u, Sum: %04x",
        !            36:       p->p.name, lsa_etype, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
        !            37: }
        !            38: 
        !            39: void
        !            40: ospf_dump_common(struct ospf_proto *p, struct ospf_packet *pkt)
        !            41: {
        !            42:   log(L_TRACE "%s:     length   %d", p->p.name, ntohs(pkt->length));
        !            43:   log(L_TRACE "%s:     router   %R", p->p.name, ntohl(pkt->routerid));
        !            44: }
        !            45: 
        !            46: static inline uint
        !            47: ospf_lsupd_hdrlen(struct ospf_proto *p)
        !            48: {
        !            49:   return ospf_pkt_hdrlen(p) + 4; /* + u32 lsa count field */
        !            50: }
        !            51: 
        !            52: static inline u32
        !            53: ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, uint hdrlen)
        !            54: {
        !            55:   u32 *c = ((void *) pkt) + hdrlen - 4;
        !            56:   return ntohl(*c);
        !            57: }
        !            58: 
        !            59: static inline void
        !            60: ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val)
        !            61: {
        !            62:   u32 *c = ((void *) pkt) + hdrlen - 4;
        !            63:   *c = htonl(val);
        !            64: }
        !            65: 
        !            66: static inline void
        !            67: ospf_lsupd_body(struct ospf_proto *p, struct ospf_packet *pkt,
        !            68:                uint *offset, uint *lsa_count)
        !            69: {
        !            70:   uint hlen = ospf_lsupd_hdrlen(p);
        !            71:   *offset = hlen;
        !            72:   *lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen);
        !            73: }
        !            74: 
        !            75: static void
        !            76: ospf_dump_lsupd(struct ospf_proto *p, struct ospf_packet *pkt)
        !            77: {
        !            78:   uint offset, plen, i, lsa_count, lsa_len;
        !            79: 
        !            80:   ASSERT(pkt->type == LSUPD_P);
        !            81:   ospf_dump_common(p, pkt);
        !            82: 
        !            83:   plen = ntohs(pkt->length);
        !            84:   ospf_lsupd_body(p, pkt, &offset, &lsa_count);
        !            85:   for (i = 0; i < lsa_count; i++)
        !            86:   {
        !            87:     if ((offset + sizeof(struct ospf_lsa_header)) > plen)
        !            88:       goto invalid;
        !            89: 
        !            90:     struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
        !            91:     lsa_len = ntohs(lsa->length);
        !            92: 
        !            93:     if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
        !            94:       goto invalid;
        !            95: 
        !            96:     ospf_dump_lsahdr(p, lsa);
        !            97:     offset += lsa_len;
        !            98:   }
        !            99:   return;
        !           100: 
        !           101: invalid:
        !           102:   log(L_TRACE "%s:     LSA      invalid", p->p.name);
        !           103:   return;
        !           104: }
        !           105: 
        !           106: 
        !           107: static inline void
        !           108: ospf_lsa_lsrq_down(struct top_hash_entry *req, struct ospf_neighbor *n)
        !           109: {
        !           110:   if (req == n->lsrqi)
        !           111:     n->lsrqi = SNODE_NEXT(req);
        !           112: 
        !           113:   s_rem_node(SNODE req);
        !           114:   ospf_hash_delete(n->lsrqh, req);
        !           115: 
        !           116:   if (EMPTY_SLIST(n->lsrql))
        !           117:   {
        !           118:     tm_stop(n->lsrq_timer);
        !           119: 
        !           120:     if (n->state == NEIGHBOR_LOADING)
        !           121:       ospf_neigh_sm(n, INM_LOADDONE);
        !           122:   }
        !           123: }
        !           124: 
        !           125: static inline void
        !           126: ospf_lsa_lsrt_up(struct top_hash_entry *en, struct ospf_neighbor *n)
        !           127: {
        !           128:   struct top_hash_entry *ret = ospf_hash_get_entry(n->lsrth, en);
        !           129: 
        !           130:   if (!SNODE_VALID(ret))
        !           131:   {
        !           132:     en->ret_count++;
        !           133:     s_add_tail(&n->lsrtl, SNODE ret);
        !           134:   }
        !           135: 
        !           136:   ret->lsa = en->lsa;
        !           137:   ret->lsa_body = LSA_BODY_DUMMY;
        !           138: 
        !           139:   if (!tm_active(n->lsrt_timer))
        !           140:     tm_start(n->lsrt_timer, n->ifa->rxmtint S);
        !           141: }
        !           142: 
        !           143: void
        !           144: ospf_lsa_lsrt_down_(struct top_hash_entry *en, struct ospf_neighbor *n, struct top_hash_entry *ret)
        !           145: {
        !           146:   if (en)
        !           147:     en->ret_count--;
        !           148: 
        !           149:   s_rem_node(SNODE ret);
        !           150:   ospf_hash_delete(n->lsrth, ret);
        !           151: 
        !           152:   if (EMPTY_SLIST(n->lsrtl))
        !           153:     tm_stop(n->lsrt_timer);
        !           154: }
        !           155: 
        !           156: static inline int
        !           157: ospf_lsa_lsrt_down(struct top_hash_entry *en, struct ospf_neighbor *n)
        !           158: {
        !           159:   struct top_hash_entry *ret = ospf_hash_find_entry(n->lsrth, en);
        !           160: 
        !           161:   if (ret)
        !           162:     ospf_lsa_lsrt_down_(en, n, ret);
        !           163: 
        !           164:   return ret != NULL;
        !           165: }
        !           166: 
        !           167: void
        !           168: ospf_add_flushed_to_lsrt(struct ospf_proto *p, struct ospf_neighbor *n)
        !           169: {
        !           170:   struct top_hash_entry *en;
        !           171: 
        !           172:   WALK_SLIST(en, p->lsal)
        !           173:     if ((en->lsa.age == LSA_MAXAGE) && (en->lsa_body != NULL) &&
        !           174:        lsa_flooding_allowed(en->lsa_type, en->domain, n->ifa) &&
        !           175:         lsa_is_acceptable(en->lsa_type, n, p))
        !           176:       ospf_lsa_lsrt_up(en, n);
        !           177: 
        !           178:   /* If we found any flushed LSA, we send them ASAP */
        !           179:   if (tm_active(n->lsrt_timer))
        !           180:     tm_start(n->lsrt_timer, 0);
        !           181: }
        !           182: 
        !           183: static int ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa);
        !           184: 
        !           185: static void
        !           186: ospf_enqueue_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_iface *ifa)
        !           187: {
        !           188:   /* Exception for local Grace-LSA, they are flooded synchronously */
        !           189:   if ((en->lsa_type == LSA_T_GR) && (en->lsa.rt == p->router_id))
        !           190:   {
        !           191:     ospf_flood_lsupd(p, &en, 1, 1, ifa);
        !           192:     return;
        !           193:   }
        !           194: 
        !           195:   if (ifa->flood_queue_used == ifa->flood_queue_size)
        !           196:   {
        !           197:     /* If we already have full queue, we send some packets */
        !           198:     uint sent = ospf_flood_lsupd(p, ifa->flood_queue, ifa->flood_queue_used, ifa->flood_queue_used / 2, ifa);
        !           199:     uint i;
        !           200: 
        !           201:     for (i = 0; i < sent; i++)
        !           202:       ifa->flood_queue[i]->ret_count--;
        !           203: 
        !           204:     ifa->flood_queue_used -= sent;
        !           205:     memmove(ifa->flood_queue, ifa->flood_queue + sent, ifa->flood_queue_used * sizeof(void *));
        !           206:     bzero(ifa->flood_queue + ifa->flood_queue_used, sent * sizeof(void *));
        !           207:   }
        !           208: 
        !           209:   en->ret_count++;
        !           210:   ifa->flood_queue[ifa->flood_queue_used] = en;
        !           211:   ifa->flood_queue_used++;
        !           212: 
        !           213:   if (!ev_active(p->flood_event))
        !           214:     ev_schedule(p->flood_event);
        !           215: }
        !           216: 
        !           217: void
        !           218: ospf_flood_event(void *ptr)
        !           219: {
        !           220:   struct ospf_proto *p = ptr;
        !           221:   struct ospf_iface *ifa;
        !           222:   int i, count;
        !           223: 
        !           224:   WALK_LIST(ifa, p->iface_list)
        !           225:   {
        !           226:     if (ifa->flood_queue_used == 0)
        !           227:       continue;
        !           228: 
        !           229:     count = ifa->flood_queue_used;
        !           230:     ospf_flood_lsupd(p, ifa->flood_queue, count, count, ifa);
        !           231: 
        !           232:     for (i = 0; i < count; i++)
        !           233:       ifa->flood_queue[i]->ret_count--;
        !           234: 
        !           235:     ifa->flood_queue_used = 0;
        !           236:     bzero(ifa->flood_queue, count * sizeof(void *));
        !           237:   }
        !           238: }
        !           239: 
        !           240: 
        !           241: /**
        !           242:  * ospf_flood_lsa - send LSA to the neighbors
        !           243:  * @p: OSPF protocol instance
        !           244:  * @en: LSA entry
        !           245:  * @from: neighbor than sent this LSA (or NULL if LSA is local)
        !           246:  *
        !           247:  * return value - was the LSA flooded back?
        !           248:  */
        !           249: int
        !           250: ospf_flood_lsa(struct ospf_proto *p, struct top_hash_entry *en, struct ospf_neighbor *from)
        !           251: {
        !           252:   struct ospf_iface *ifa;
        !           253:   struct ospf_neighbor *n;
        !           254: 
        !           255:   /* RFC 2328 13.3 */
        !           256: 
        !           257:   int back = 0;
        !           258:   WALK_LIST(ifa, p->iface_list)
        !           259:   {
        !           260:     if (ifa->stub)
        !           261:       continue;
        !           262: 
        !           263:     if (! lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
        !           264:       continue;
        !           265: 
        !           266:     DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
        !           267:        hh->type, hh->id, hh->rt, hh->sn, hh->age);
        !           268: 
        !           269:     int used = 0;
        !           270:     WALK_LIST(n, ifa->neigh_list)
        !           271:     {
        !           272:       /* 13.3 (1a) */
        !           273:       if (n->state < NEIGHBOR_EXCHANGE)
        !           274:        continue;
        !           275: 
        !           276:       /* 13.3 (1b) */
        !           277:       if (n->state < NEIGHBOR_FULL)
        !           278:       {
        !           279:        struct top_hash_entry *req = ospf_hash_find_entry(n->lsrqh, en);
        !           280:        if (req != NULL)
        !           281:        {
        !           282:          int cmp = lsa_comp(&en->lsa, &req->lsa);
        !           283: 
        !           284:          /* If same or newer, remove LSA from the link state request list */
        !           285:          if (cmp > CMP_OLDER)
        !           286:            ospf_lsa_lsrq_down(req, n);
        !           287: 
        !           288:          /* If older or same, skip processing of this neighbor */
        !           289:          if (cmp < CMP_NEWER)
        !           290:            continue;
        !           291:        }
        !           292:       }
        !           293: 
        !           294:       /* 13.3 (1c) */
        !           295:       if (n == from)
        !           296:        continue;
        !           297: 
        !           298:       /* Check whether optional LSAs are supported by neighbor */
        !           299:       if (!lsa_is_acceptable(en->lsa_type, n, p))
        !           300:        continue;
        !           301: 
        !           302:       /* 13.3 (1d) - add LSA to the link state retransmission list */
        !           303:       ospf_lsa_lsrt_up(en, n);
        !           304: 
        !           305:       used = 1;
        !           306:     }
        !           307: 
        !           308:     /* 13.3 (2) */
        !           309:     if (!used)
        !           310:       continue;
        !           311: 
        !           312:     if (from && (from->ifa == ifa))
        !           313:     {
        !           314:       /* 13.3 (3) */
        !           315:       if ((from->rid == ifa->drid) || (from->rid == ifa->bdrid))
        !           316:        continue;
        !           317: 
        !           318:       /* 13.3 (4) */
        !           319:       if (ifa->state == OSPF_IS_BACKUP)
        !           320:        continue;
        !           321: 
        !           322:       back = 1;
        !           323:     }
        !           324: 
        !           325:     /* 13.3 (5) - finally flood the packet */
        !           326:     ospf_enqueue_lsa(p, en, ifa);
        !           327:   }
        !           328: 
        !           329:   return back;
        !           330: }
        !           331: 
        !           332: static uint
        !           333: ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
        !           334:                   struct top_hash_entry **lsa_list, uint lsa_count)
        !           335: {
        !           336:   struct ospf_packet *pkt;
        !           337:   uint hlen, pos, i, maxsize;
        !           338: 
        !           339:   pkt = ospf_tx_buffer(ifa);
        !           340:   hlen = ospf_lsupd_hdrlen(p);
        !           341:   maxsize = ospf_pkt_maxsize(ifa);
        !           342: 
        !           343:   ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
        !           344:   pos = hlen;
        !           345: 
        !           346:   for (i = 0; i < lsa_count; i++)
        !           347:   {
        !           348:     struct top_hash_entry *en = lsa_list[i];
        !           349:     uint len = en->lsa.length;
        !           350: 
        !           351:     if ((pos + len) > maxsize)
        !           352:     {
        !           353:       /* The packet if full, stop adding LSAs and sent it */
        !           354:       if (i > 0)
        !           355:        break;
        !           356: 
        !           357:       /* LSA is larger than MTU, check buffer size */
        !           358:       if (ospf_iface_assure_bufsize(ifa, pos + len) < 0)
        !           359:       {
        !           360:        /* Cannot fit in a tx buffer, skip that */
        !           361:        log(L_ERR "%s: LSA too large to send on %s (Type: %04x, Id: %R, Rt: %R)",
        !           362:            p->p.name, ifa->ifname, en->lsa_type, en->lsa.id, en->lsa.rt);
        !           363:        break;
        !           364:       }
        !           365: 
        !           366:       /* TX buffer could be reallocated */
        !           367:       pkt = ospf_tx_buffer(ifa);
        !           368:     }
        !           369: 
        !           370:     struct ospf_lsa_header *buf = ((void *) pkt) + pos;
        !           371:     lsa_hton_hdr(&en->lsa, buf);
        !           372:     lsa_hton_body(en->lsa_body, ((void *) buf) + sizeof(struct ospf_lsa_header),
        !           373:                  len - sizeof(struct ospf_lsa_header));
        !           374:     buf->age = htons(MIN(en->lsa.age + ifa->inftransdelay, LSA_MAXAGE));
        !           375: 
        !           376:     pos += len;
        !           377:   }
        !           378: 
        !           379:   ospf_lsupd_set_lsa_count(pkt, hlen, i);
        !           380:   pkt->length = htons(pos);
        !           381: 
        !           382:   return i;
        !           383: }
        !           384: 
        !           385: 
        !           386: static int
        !           387: ospf_flood_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, uint lsa_min_count, struct ospf_iface *ifa)
        !           388: {
        !           389:   uint i, c;
        !           390: 
        !           391:   for (i = 0; i < lsa_min_count; i += c)
        !           392:   {
        !           393:     c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i);
        !           394: 
        !           395:     if (!c)    /* Too large LSA */
        !           396:       { i++; continue; }
        !           397: 
        !           398:     OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
        !           399:                "LSUPD packet flooded via %s", ifa->ifname);
        !           400: 
        !           401:     if (ifa->type == OSPF_IT_BCAST)
        !           402:     {
        !           403:       if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
        !           404:        ospf_send_to_all(ifa);
        !           405:       else
        !           406:        ospf_send_to_des(ifa);
        !           407:     }
        !           408:     else
        !           409:       ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
        !           410:   }
        !           411: 
        !           412:   return i;
        !           413: }
        !           414: 
        !           415: int
        !           416: ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa_count, struct ospf_neighbor *n)
        !           417: {
        !           418:   struct ospf_iface *ifa = n->ifa;
        !           419:   uint i, c;
        !           420: 
        !           421:   for (i = 0; i < lsa_count; i += c)
        !           422:   {
        !           423:     c = ospf_prepare_lsupd(p, ifa, lsa_list + i, lsa_count - i);
        !           424: 
        !           425:     if (!c)    /* Too large LSA */
        !           426:       { i++; continue; }
        !           427: 
        !           428:     OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
        !           429:                "LSUPD packet sent to nbr %R on %s", n->rid, ifa->ifname);
        !           430: 
        !           431:     ospf_send_to(ifa, n->ip);
        !           432:   }
        !           433: 
        !           434:   return i;
        !           435: }
        !           436: 
        !           437: void
        !           438: ospf_rxmt_lsupd(struct ospf_proto *p, struct ospf_neighbor *n)
        !           439: {
        !           440:   uint max = 2 * n->ifa->flood_queue_size;
        !           441:   struct top_hash_entry *entries[max];
        !           442:   struct top_hash_entry *ret, *nxt, *en;
        !           443:   uint i = 0;
        !           444: 
        !           445:   /* ASSERT((n->state >= NEIGHBOR_EXCHANGE) && !EMPTY_SLIST(n->lsrtl)); */
        !           446: 
        !           447:   WALK_SLIST_DELSAFE(ret, nxt, n->lsrtl)
        !           448:   {
        !           449:     if (i == max)
        !           450:       break;
        !           451: 
        !           452:     en = ospf_hash_find_entry(p->gr, ret);
        !           453:     if (!en)
        !           454:     {
        !           455:       /* Probably flushed LSA, this should not happen */
        !           456:       log(L_WARN "%s: LSA disappeared (Type: %04x, Id: %R, Rt: %R)",
        !           457:          p->p.name, ret->lsa_type, ret->lsa.id, ret->lsa.rt);
        !           458: 
        !           459:       s_rem_node(SNODE ret);
        !           460:       ospf_hash_delete(n->lsrth, ret);
        !           461: 
        !           462:       continue;
        !           463:     }
        !           464: 
        !           465:     entries[i] = en;
        !           466:     i++;
        !           467:   }
        !           468: 
        !           469:   ospf_send_lsupd(p, entries, i, n);
        !           470: }
        !           471: 
        !           472: 
        !           473: static inline int
        !           474: ospf_addr_is_local(struct ospf_proto *p, struct ospf_area *oa, ip_addr ip)
        !           475: {
        !           476:   struct ospf_iface *ifa;
        !           477:   WALK_LIST(ifa, p->iface_list)
        !           478:     if ((ifa->oa == oa) && ifa->addr && ipa_equal(ifa->addr->ip, ip))
        !           479:       return 1;
        !           480: 
        !           481:   return 0;
        !           482: }
        !           483: 
        !           484: void
        !           485: ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
        !           486:                   struct ospf_neighbor *n)
        !           487: {
        !           488:   struct ospf_proto *p = ifa->oa->po;
        !           489:   const char *err_dsc = NULL;
        !           490:   uint plen, err_val = 0;
        !           491: 
        !           492:   /* RFC 2328 13. */
        !           493: 
        !           494:   plen = ntohs(pkt->length);
        !           495:   if (plen < ospf_lsupd_hdrlen(p))
        !           496:   {
        !           497:     LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
        !           498:     return;
        !           499:   }
        !           500: 
        !           501:   OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname);
        !           502: 
        !           503:   if (n->state < NEIGHBOR_EXCHANGE)
        !           504:   {
        !           505:     OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange");
        !           506:     return;
        !           507:   }
        !           508: 
        !           509:   ospf_neigh_sm(n, INM_HELLOREC);      /* Questionable */
        !           510: 
        !           511:   uint offset, i, lsa_count;
        !           512:   ospf_lsupd_body(p, pkt, &offset, &lsa_count);
        !           513: 
        !           514:   for (i = 0; i < lsa_count; i++)
        !           515:   {
        !           516:     struct ospf_lsa_header lsa, *lsa_n;
        !           517:     struct top_hash_entry *en;
        !           518:     u32 lsa_len, lsa_type, lsa_domain;
        !           519: 
        !           520:     if ((offset + sizeof(struct ospf_lsa_header)) > plen)
        !           521:       DROP("too short", plen);
        !           522: 
        !           523:     /* LSA header in network order */
        !           524:     lsa_n = ((void *) pkt) + offset;
        !           525:     lsa_len = ntohs(lsa_n->length);
        !           526:     offset += lsa_len;
        !           527: 
        !           528:     if (offset > plen)
        !           529:       DROP("too short", plen);
        !           530: 
        !           531:     if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
        !           532:       DROP("invalid LSA length", lsa_len);
        !           533: 
        !           534:     /* LSA header in host order */
        !           535:     lsa_ntoh_hdr(lsa_n, &lsa);
        !           536:     lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
        !           537: 
        !           538:     DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
        !           539:        lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
        !           540: 
        !           541:     /* RFC 2328 13. (1) - verify LSA checksum */
        !           542:     if ((lsa_n->checksum == 0) || !lsa_verify_checksum(lsa_n, lsa_len))
        !           543:       SKIP("invalid checksum");
        !           544: 
        !           545:     /* RFC 2328 13. (2) */
        !           546:     if (!lsa_type)
        !           547:       SKIP("unknown type");
        !           548: 
        !           549:     /* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */
        !           550:     if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
        !           551:       SKIP("AS scope in stub area");
        !           552: 
        !           553:     /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
        !           554:     if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
        !           555:       SKIP("rt-summary-LSA in stub area");
        !           556: 
        !           557:     /* RFC 5340 4.5.1 (3) */
        !           558:     if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
        !           559:       SKIP("invalid scope");
        !           560: 
        !           561:     /* Find local copy of LSA in link state database */
        !           562:     en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
        !           563: 
        !           564: #ifdef LOCAL_DEBUG
        !           565:     if (en)
        !           566:       DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
        !           567:          en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age, en->lsa.checksum);
        !           568: #endif
        !           569: 
        !           570:     /* 13. (4) - ignore maxage LSA if i have no local copy */
        !           571:     if ((lsa.age == LSA_MAXAGE) && !en && (p->padj == 0))
        !           572:     {
        !           573:       /* 13.5. - schedule ACKs (tbl 19, case 5) */
        !           574:       ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT);
        !           575:       continue;
        !           576:     }
        !           577: 
        !           578:     /* 13. (5) - received LSA is newer (or no local copy) */
        !           579:     if (!en || (lsa_comp(&lsa, &en->lsa) == CMP_NEWER))
        !           580:     {
        !           581:       /* 13. (5a) - enforce minimum time between updates for received LSAs */
        !           582:       /* We also use this to ratelimit reactions to received self-originated LSAs */
        !           583:       if (en && (lsa_inst_age(en) < MINLSARRIVAL))
        !           584:       {
        !           585:        OSPF_TRACE(D_EVENTS, "Skipping LSA received in less that MinLSArrival");
        !           586:        continue;
        !           587:       }
        !           588: 
        !           589:       /* Copy and validate LSA body */
        !           590:       int blen = lsa.length - sizeof(struct ospf_lsa_header);
        !           591:       void *body = mb_alloc(p->p.pool, blen);
        !           592:       lsa_ntoh_body(lsa_n + 1, body, blen);
        !           593: 
        !           594:       if (lsa_validate(&lsa, lsa_type, ospf_is_v2(p), body) == 0)
        !           595:       {
        !           596:        mb_free(body);
        !           597:        SKIP("invalid body");
        !           598:       }
        !           599: 
        !           600:       /* 13. (5f) - handle self-originated LSAs, see also 13.4. */
        !           601:       if (!p->gr_recovery &&
        !           602:          ((lsa.rt == p->router_id) ||
        !           603:           (ospf_is_v2(p) && (lsa_type == LSA_T_NET) && ospf_addr_is_local(p, ifa->oa, ipa_from_u32(lsa.id)))))
        !           604:       {
        !           605:        OSPF_TRACE(D_EVENTS, "Received unexpected self-originated LSA");
        !           606:        ospf_advance_lsa(p, en, &lsa, lsa_type, lsa_domain, body);
        !           607:        continue;
        !           608:       }
        !           609: 
        !           610:       /* 13. (5c) - remove old LSA from all retransmission lists
        !           611:        *
        !           612:        * We only need to remove it from the retransmission list of the neighbor
        !           613:        * that send us the new LSA. The old LSA is automatically replaced in
        !           614:        * retransmission lists by the new LSA.
        !           615:        */
        !           616:       if (en)
        !           617:        ospf_lsa_lsrt_down(en, n);
        !           618: 
        !           619: #if 0
        !           620:       /*
        !           621:        * Old code for removing LSA from all retransmission lists. Must be done
        !           622:        * before (5b), otherwise it also removes the new entries from (5b).
        !           623:        */
        !           624:       struct ospf_iface *ifi;
        !           625:       struct ospf_neighbor *ni;
        !           626: 
        !           627:       WALK_LIST(ifi, p->iface_list)
        !           628:        WALK_LIST(ni, ifi->neigh_list)
        !           629:          if (ni->state > NEIGHBOR_EXSTART)
        !           630:            ospf_lsa_lsrt_down(en, ni);
        !           631: #endif
        !           632: 
        !           633:       /* 13. (5d) - install new LSA into database */
        !           634:       en = ospf_install_lsa(p, &lsa, lsa_type, lsa_domain, body);
        !           635: 
        !           636:       /* RFC 5340 4.4.3 Events 6+7 - new Link LSA received */
        !           637:       if (lsa_type == LSA_T_LINK)
        !           638:        ospf_notify_net_lsa(ifa);
        !           639: 
        !           640:       /* RFC 3623 3.1 - entering graceful restart helper mode */
        !           641:       if (lsa_type == LSA_T_GR)
        !           642:        ospf_neigh_notify_grace_lsa(n, en);
        !           643: 
        !           644:       /* Link received pre-restart router LSA */
        !           645:       if (p->gr_recovery && (lsa_type == LSA_T_RT) && (lsa.rt == p->router_id))
        !           646:        ifa->oa->rt = en;
        !           647: 
        !           648:       /* 13. (5b) - flood new LSA */
        !           649:       int flood_back = ospf_flood_lsa(p, en, n);
        !           650: 
        !           651:       /* 13.5. - schedule ACKs (tbl 19, cases 1+2) */
        !           652:       if (! flood_back)
        !           653:        if ((ifa->state != OSPF_IS_BACKUP) || (n->rid == ifa->drid))
        !           654:          ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY);
        !           655: 
        !           656:       /* FIXME: remove LSA entry if it is LSA_MAXAGE and it is possible? */
        !           657: 
        !           658:       continue;
        !           659:     }
        !           660: 
        !           661:     /* 13. (6) - received LSA is in Link state request list (but not newer) */
        !           662:     if (ospf_hash_find_entry(n->lsrqh, en) != NULL)
        !           663:       DROP1("error in LSA database exchange");
        !           664: 
        !           665:     /* 13. (7) - received LSA is same */
        !           666:     if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
        !           667:     {
        !           668:       /* Duplicate LSA, treat as implicit ACK */
        !           669:       int implicit_ack = ospf_lsa_lsrt_down(en, n);
        !           670: 
        !           671:       /* 13.5. - schedule ACKs (tbl 19, cases 3+4) */
        !           672:       if (implicit_ack)
        !           673:       {
        !           674:        if ((ifa->state == OSPF_IS_BACKUP) && (n->rid == ifa->drid))
        !           675:          ospf_enqueue_lsack(n, lsa_n, ACKL_DELAY);
        !           676:       }
        !           677:       else
        !           678:        ospf_enqueue_lsack(n, lsa_n, ACKL_DIRECT);
        !           679: 
        !           680:       continue;
        !           681:     }
        !           682: 
        !           683:     /* 13. (8) - received LSA is older */
        !           684:     {
        !           685:       /* Seqnum is wrapping, wait until it is flushed */
        !           686:       if ((en->lsa.age == LSA_MAXAGE) && (en->lsa.sn == LSA_MAXSEQNO))
        !           687:        continue;
        !           688: 
        !           689:       /* Send newer local copy back to neighbor */
        !           690:       /* FIXME - check for MinLSArrival ? */
        !           691:       ospf_send_lsupd(p, &en, 1, n);
        !           692: 
        !           693:       continue;
        !           694:     }
        !           695: 
        !           696:   skip:
        !           697:     LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt);
        !           698:     LOG_LSA2("  received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
        !           699:   }
        !           700: 
        !           701:   /* Send direct LSACKs */
        !           702:   ospf_send_lsack(p, n, ACKL_DIRECT);
        !           703: 
        !           704:   /* Send enqueued LSAs immediately, do not wait for flood_event */
        !           705:   if (ev_active(p->flood_event))
        !           706:   {
        !           707:     ev_postpone(p->flood_event);
        !           708:     ospf_flood_event(p);
        !           709:   }
        !           710: 
        !           711:   /*
        !           712:    * During loading, we should ask for another batch of LSAs. This is only
        !           713:    * vaguely mentioned in RFC 2328. We send a new LSREQ if all requests sent in
        !           714:    * the last packet were already answered and/or removed from the LS request
        !           715:    * list and therefore lsrqi is pointing to the first node of the list.
        !           716:    */
        !           717:   if (!EMPTY_SLIST(n->lsrql) && (n->lsrqi == SHEAD(n->lsrql)))
        !           718:   {
        !           719:     ospf_send_lsreq(p, n);
        !           720:     tm_start(n->lsrq_timer, n->ifa->rxmtint S);
        !           721:   }
        !           722: 
        !           723:   return;
        !           724: 
        !           725: drop:
        !           726:   LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)",
        !           727:          n->rid, ifa->ifname, err_dsc, err_val);
        !           728: 
        !           729:   /* Malformed LSUPD - there is no defined error event, we abuse BadLSReq */
        !           730:   ospf_neigh_sm(n, INM_BADLSREQ);
        !           731:   return;
        !           732: }

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