Annotation of embedaddon/bird2/proto/ospf/lsalib.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD -- OSPF
! 3: *
! 4: * (c) 1999--2004 Ondrej Filip <feela@network.cz>
! 5: * (c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org>
! 6: * (c) 2009--2015 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: #include "lib/fletcher16.h"
! 14:
! 15: #define HDRLEN sizeof(struct ospf_lsa_header)
! 16:
! 17:
! 18: #ifndef CPU_BIG_ENDIAN
! 19: void
! 20: lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
! 21: {
! 22: n->age = htons(h->age);
! 23: n->type_raw = htons(h->type_raw);
! 24: n->id = htonl(h->id);
! 25: n->rt = htonl(h->rt);
! 26: n->sn = htonl(h->sn);
! 27: n->checksum = htons(h->checksum);
! 28: n->length = htons(h->length);
! 29: }
! 30:
! 31: void
! 32: lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
! 33: {
! 34: h->age = ntohs(n->age);
! 35: h->type_raw = ntohs(n->type_raw);
! 36: h->id = ntohl(n->id);
! 37: h->rt = ntohl(n->rt);
! 38: h->sn = ntohl(n->sn);
! 39: h->checksum = ntohs(n->checksum);
! 40: h->length = ntohs(n->length);
! 41: }
! 42:
! 43: void
! 44: lsa_hton_body(void *h, void *n, u16 len)
! 45: {
! 46: u32 *hid = h;
! 47: u32 *nid = n;
! 48: uint i;
! 49:
! 50: for (i = 0; i < (len / sizeof(u32)); i++)
! 51: nid[i] = htonl(hid[i]);
! 52: }
! 53:
! 54: void
! 55: lsa_ntoh_body(void *n, void *h, u16 len)
! 56: {
! 57: u32 *nid = n;
! 58: u32 *hid = h;
! 59: uint i;
! 60:
! 61: for (i = 0; i < (len / sizeof(u32)); i++)
! 62: hid[i] = ntohl(nid[i]);
! 63: }
! 64: #endif /* little endian */
! 65:
! 66:
! 67: int
! 68: lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
! 69: {
! 70: /* Handle inactive vlinks */
! 71: if (ifa->state == OSPF_IS_DOWN)
! 72: return 0;
! 73:
! 74: /* 4.5.2 (Case 2) */
! 75: switch (LSA_SCOPE(type))
! 76: {
! 77: case LSA_SCOPE_LINK:
! 78: return ifa->iface_id == domain;
! 79:
! 80: case LSA_SCOPE_AREA:
! 81: return ifa->oa->areaid == domain;
! 82:
! 83: case LSA_SCOPE_AS:
! 84: if (ifa->type == OSPF_IT_VLINK)
! 85: return 0;
! 86: if (!oa_is_ext(ifa->oa))
! 87: return 0;
! 88: return 1;
! 89:
! 90: default:
! 91: log(L_ERR "OSPF: LSA with invalid scope");
! 92: return 0;
! 93: }
! 94: }
! 95:
! 96: int
! 97: lsa_is_acceptable(u32 type, struct ospf_neighbor *n, struct ospf_proto *p)
! 98: {
! 99: if (ospf_is_v2(p))
! 100: {
! 101: /* Do not check NSSA-LSA here, as OPT_N is only in HELLO packets */
! 102:
! 103: if (lsa_is_opaque(type))
! 104: return !!(n->options & OPT_O);
! 105:
! 106: return 1;
! 107: }
! 108: else
! 109: {
! 110: /*
! 111: * There should be check whether receiving router understands that type
! 112: * of LSA (for LSA types with U-bit == 0). But as we do not support any
! 113: * optional LSA types, this is not needed yet.
! 114: */
! 115:
! 116: return 1;
! 117: }
! 118: }
! 119:
! 120: static int
! 121: unknown_lsa_type(u32 type)
! 122: {
! 123: switch (type)
! 124: {
! 125: case LSA_T_RT:
! 126: case LSA_T_NET:
! 127: case LSA_T_SUM_NET:
! 128: case LSA_T_SUM_RT:
! 129: case LSA_T_EXT:
! 130: case LSA_T_NSSA:
! 131: case LSA_T_LINK:
! 132: case LSA_T_PREFIX:
! 133: case LSA_T_RI_LINK:
! 134: case LSA_T_RI_AREA:
! 135: case LSA_T_RI_AS:
! 136: return 0;
! 137:
! 138: default:
! 139: return 1;
! 140: }
! 141: }
! 142:
! 143: /* Maps OSPFv2 types to OSPFv3 types */
! 144: static const u16 lsa_v2_types[] = {
! 145: 0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA,
! 146: 0, LSA_T_OPAQUE_LINK, LSA_T_OPAQUE_AREA, LSA_T_OPAQUE_AS
! 147: };
! 148:
! 149: /* Maps OSPFv2 opaque types to OSPFv3 function codes */
! 150: static const u16 opaque_lsa_types[] = {
! 151: [LSA_OT_GR] = LSA_T_GR,
! 152: [LSA_OT_RI] = LSA_T_RI_,
! 153: };
! 154:
! 155: /* Maps (subset of) OSPFv3 function codes to OSPFv2 opaque types */
! 156: static const u8 opaque_lsa_types_inv[] = {
! 157: [LSA_T_GR] = LSA_OT_GR,
! 158: [LSA_T_RI_] = LSA_OT_RI,
! 159: };
! 160:
! 161: #define LOOKUP(a, i) ({ uint _i = (i); (_i < ARRAY_SIZE(a)) ? a[_i] : 0; })
! 162:
! 163: void
! 164: lsa_get_type_domain_(u32 type, u32 id, struct ospf_iface *ifa, u32 *otype, u32 *domain)
! 165: {
! 166: if (ospf_is_v2(ifa->oa->po))
! 167: {
! 168: type = type & LSA_T_V2_MASK;
! 169: type = LOOKUP(lsa_v2_types, type);
! 170:
! 171: uint code;
! 172: if (LSA_FUNCTION(type) == LSA_T_OPAQUE_)
! 173: if (code = LOOKUP(opaque_lsa_types, id >> 24))
! 174: {
! 175: type = code | LSA_UBIT | LSA_SCOPE(type);
! 176:
! 177: /* Hack for Grace-LSA: It does not use U-bit for link-scoped LSAs */
! 178: if (type == (LSA_T_GR | LSA_UBIT))
! 179: type = LSA_T_GR;
! 180: }
! 181: }
! 182: else
! 183: {
! 184: /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
! 185: if (unknown_lsa_type(type) && !(type & LSA_UBIT))
! 186: type = type & ~LSA_SCOPE_MASK;
! 187: }
! 188:
! 189: *otype = type;
! 190:
! 191: switch (LSA_SCOPE(type))
! 192: {
! 193: case LSA_SCOPE_LINK:
! 194: *domain = ifa->iface_id;
! 195: return;
! 196:
! 197: case LSA_SCOPE_AREA:
! 198: *domain = ifa->oa->areaid;
! 199: return;
! 200:
! 201: case LSA_SCOPE_AS:
! 202: default:
! 203: *domain = 0;
! 204: return;
! 205: }
! 206: }
! 207:
! 208: int
! 209: lsa_is_opaque(u32 type)
! 210: {
! 211: u32 fn = LSA_FUNCTION(type);
! 212: return LOOKUP(opaque_lsa_types_inv, fn) || (fn == LSA_T_OPAQUE_);
! 213: }
! 214:
! 215: u32
! 216: lsa_get_opaque_type(u32 type)
! 217: {
! 218: return LOOKUP(opaque_lsa_types_inv, LSA_FUNCTION(type));
! 219: }
! 220:
! 221:
! 222: void
! 223: lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body)
! 224: {
! 225: struct fletcher16_context ctx;
! 226: struct ospf_lsa_header hdr;
! 227: u16 len = lsa->length;
! 228:
! 229: /*
! 230: * lsa and body are in the host order, we need to compute Fletcher-16 checksum
! 231: * for data in the network order. We also skip the initial age field.
! 232: */
! 233:
! 234: lsa_hton_hdr(lsa, &hdr);
! 235: hdr.checksum = 0;
! 236:
! 237: fletcher16_init(&ctx);
! 238: fletcher16_update(&ctx, (u8 *) &hdr + 2, sizeof(struct ospf_lsa_header) - 2);
! 239: fletcher16_update_n32(&ctx, body, len - sizeof(struct ospf_lsa_header));
! 240: lsa->checksum = fletcher16_final(&ctx, len, OFFSETOF(struct ospf_lsa_header, checksum));
! 241: }
! 242:
! 243: u16
! 244: lsa_verify_checksum(const void *lsa_n, int lsa_len)
! 245: {
! 246: struct fletcher16_context ctx;
! 247:
! 248: /* The whole LSA is at lsa_n in net order, we just skip initial age field */
! 249:
! 250: fletcher16_init(&ctx);
! 251: fletcher16_update(&ctx, (u8 *) lsa_n + 2, lsa_len - 2);
! 252:
! 253: return fletcher16_compute(&ctx) == 0;
! 254: }
! 255:
! 256:
! 257: int
! 258: lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
! 259: /* Return codes from point of view of l1 */
! 260: {
! 261: u32 sn1, sn2;
! 262:
! 263: sn1 = l1->sn - LSA_INITSEQNO + 1;
! 264: sn2 = l2->sn - LSA_INITSEQNO + 1;
! 265:
! 266: if (sn1 > sn2)
! 267: return CMP_NEWER;
! 268: if (sn1 < sn2)
! 269: return CMP_OLDER;
! 270:
! 271: if (l1->checksum != l2->checksum)
! 272: return l1->checksum < l2->checksum ? CMP_OLDER : CMP_NEWER;
! 273:
! 274: if ((l1->age == LSA_MAXAGE) && (l2->age != LSA_MAXAGE))
! 275: return CMP_NEWER;
! 276: if ((l2->age == LSA_MAXAGE) && (l1->age != LSA_MAXAGE))
! 277: return CMP_OLDER;
! 278:
! 279: if (ABS(l1->age - l2->age) > LSA_MAXAGEDIFF)
! 280: return l1->age < l2->age ? CMP_NEWER : CMP_OLDER;
! 281:
! 282: return CMP_SAME;
! 283: }
! 284:
! 285:
! 286: #define LSA_TLV_LENGTH(tlv) \
! 287: (sizeof(struct ospf_tlv) + BIRD_ALIGN((tlv)->length, 4))
! 288:
! 289: #define LSA_NEXT_TLV(tlv) \
! 290: ((struct ospf_tlv *) ((byte *) (tlv) + LSA_TLV_LENGTH(tlv)))
! 291:
! 292: #define LSA_WALK_TLVS(tlv,buf,len) \
! 293: for(struct ospf_tlv *tlv = (void *) (buf); \
! 294: (byte *) tlv < (byte *) (buf) + (len); \
! 295: tlv = LSA_NEXT_TLV(tlv))
! 296:
! 297: struct ospf_tlv *
! 298: lsa_get_tlv(struct top_hash_entry *en, uint type)
! 299: {
! 300: LSA_WALK_TLVS(tlv, en->lsa_body, en->lsa.length - HDRLEN)
! 301: if (tlv->type == type)
! 302: return tlv;
! 303:
! 304: return NULL;
! 305: }
! 306:
! 307: int
! 308: lsa_validate_tlvs(byte *buf, uint len)
! 309: {
! 310: byte *pos = buf;
! 311: byte *end = buf + len;
! 312:
! 313: while (pos < end)
! 314: {
! 315: if ((pos + sizeof(struct ospf_tlv)) > end)
! 316: return 0;
! 317:
! 318: struct ospf_tlv *tlv = (void *) pos;
! 319: uint len = LSA_TLV_LENGTH(tlv);
! 320:
! 321: if ((pos + len) > end)
! 322: return 0;
! 323:
! 324: pos += len;
! 325: }
! 326:
! 327: return 1;
! 328: }
! 329:
! 330:
! 331: static inline int
! 332: lsa_walk_rt2(struct ospf_lsa_rt_walk *rt)
! 333: {
! 334: if (rt->buf >= rt->bufend)
! 335: return 0;
! 336:
! 337: struct ospf_lsa_rt2_link *l = rt->buf;
! 338: rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
! 339:
! 340: rt->type = l->type;
! 341: rt->metric = l->metric;
! 342: rt->id = l->id;
! 343: rt->data = l->data;
! 344: return 1;
! 345: }
! 346:
! 347: static inline int
! 348: lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
! 349: {
! 350: while (rt->buf >= rt->bufend)
! 351: {
! 352: rt->en = ospf_hash_find_rt3_next(rt->en);
! 353: if (!rt->en)
! 354: return 0;
! 355:
! 356: rt->buf = rt->en->lsa_body;
! 357: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
! 358: rt->buf += sizeof(struct ospf_lsa_rt);
! 359: }
! 360:
! 361: struct ospf_lsa_rt3_link *l = rt->buf;
! 362: rt->buf += sizeof(struct ospf_lsa_rt3_link);
! 363:
! 364: rt->type = l->type;
! 365: rt->metric = l->metric;
! 366: rt->lif = l->lif;
! 367: rt->nif = l->nif;
! 368: rt->id = l->id;
! 369: return 1;
! 370: }
! 371:
! 372: void
! 373: lsa_walk_rt_init(struct ospf_proto *p, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt)
! 374: {
! 375: rt->ospf2 = ospf_is_v2(p);
! 376: rt->id = rt->data = rt->lif = rt->nif = 0;
! 377:
! 378: if (rt->ospf2)
! 379: rt->en = act;
! 380: else
! 381: rt->en = ospf_hash_find_rt3_first(p->gr, act->domain, act->lsa.rt);
! 382:
! 383: rt->buf = rt->en->lsa_body;
! 384: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
! 385: rt->buf += sizeof(struct ospf_lsa_rt);
! 386: }
! 387:
! 388: int
! 389: lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
! 390: {
! 391: return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt);
! 392: }
! 393:
! 394:
! 395: void
! 396: lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, int af, net_addr *net, u8 *pxopts, u32 *metric)
! 397: {
! 398: if (ospf2)
! 399: {
! 400: uint opts = lsa_get_options(&en->lsa);
! 401: struct ospf_lsa_sum2 *ls = en->lsa_body;
! 402: net_fill_ip4(net, ip4_from_u32(en->lsa.id & ls->netmask), u32_masklen(ls->netmask));
! 403: *pxopts = (opts & OPT_DN) ? OPT_PX_DN : 0;
! 404: *metric = ls->metric & LSA_METRIC_MASK;
! 405: }
! 406: else
! 407: {
! 408: struct ospf_lsa_sum3_net *ls = en->lsa_body;
! 409: ospf3_get_prefix(ls->prefix, af, net, pxopts, NULL);
! 410: *metric = ls->metric & LSA_METRIC_MASK;
! 411: }
! 412: }
! 413:
! 414: void
! 415: lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options)
! 416: {
! 417: if (ospf2)
! 418: {
! 419: struct ospf_lsa_sum2 *ls = en->lsa_body;
! 420: *drid = en->lsa.id;
! 421: *metric = ls->metric & LSA_METRIC_MASK;
! 422: *options = 0;
! 423: }
! 424: else
! 425: {
! 426: struct ospf_lsa_sum3_rt *ls = en->lsa_body;
! 427: *drid = ls->drid;
! 428: *metric = ls->metric & LSA_METRIC_MASK;
! 429: *options = ls->options & LSA_OPTIONS_MASK;
! 430: }
! 431: }
! 432:
! 433: void
! 434: lsa_parse_ext(struct top_hash_entry *en, int ospf2, int af, struct ospf_lsa_ext_local *rt)
! 435: {
! 436: if (ospf2)
! 437: {
! 438: struct ospf_lsa_ext2 *ext = en->lsa_body;
! 439: net_fill_ip4(&rt->net,
! 440: ip4_from_u32(en->lsa.id & ext->netmask),
! 441: u32_masklen(ext->netmask));
! 442: rt->pxopts = 0;
! 443: rt->metric = ext->metric & LSA_METRIC_MASK;
! 444: rt->ebit = ext->metric & LSA_EXT2_EBIT;
! 445:
! 446: rt->fbit = ext->fwaddr;
! 447: rt->fwaddr = ipa_from_u32(ext->fwaddr);
! 448:
! 449: rt->tag = ext->tag;
! 450: rt->propagate = lsa_get_options(&en->lsa) & OPT_P;
! 451: rt->downwards = lsa_get_options(&en->lsa) & OPT_DN;
! 452: }
! 453: else
! 454: {
! 455: struct ospf_lsa_ext3 *ext = en->lsa_body;
! 456: u32 *buf = ospf3_get_prefix(ext->rest, af, &rt->net, &rt->pxopts, NULL);
! 457: rt->metric = ext->metric & LSA_METRIC_MASK;
! 458: rt->ebit = ext->metric & LSA_EXT3_EBIT;
! 459:
! 460: rt->fbit = ext->metric & LSA_EXT3_FBIT;
! 461: if (rt->fbit)
! 462: buf = ospf3_get_addr(buf, af, &rt->fwaddr);
! 463: else
! 464: rt->fwaddr = IPA_NONE;
! 465:
! 466: rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0;
! 467: rt->propagate = rt->pxopts & OPT_PX_P;
! 468: rt->downwards = rt->pxopts & OPT_PX_DN;
! 469: }
! 470: }
! 471:
! 472:
! 473: static int
! 474: lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
! 475: {
! 476: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
! 477: return 0;
! 478:
! 479: uint i = 0;
! 480: void *buf = body;
! 481: void *bufend = buf + lsa->length - HDRLEN;
! 482: buf += sizeof(struct ospf_lsa_rt);
! 483:
! 484: while (buf < bufend)
! 485: {
! 486: struct ospf_lsa_rt2_link *l = buf;
! 487: buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
! 488: i++;
! 489:
! 490: if (buf > bufend)
! 491: return 0;
! 492:
! 493: if (!((l->type == LSART_PTP) ||
! 494: (l->type == LSART_NET) ||
! 495: (l->type == LSART_STUB) ||
! 496: (l->type == LSART_VLNK)))
! 497: return 0;
! 498: }
! 499:
! 500: if ((body->options & LSA_RT2_LINKS) != i)
! 501: return 0;
! 502:
! 503: return 1;
! 504: }
! 505:
! 506:
! 507: static int
! 508: lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
! 509: {
! 510: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
! 511: return 0;
! 512:
! 513: void *buf = body;
! 514: void *bufend = buf + lsa->length - HDRLEN;
! 515: buf += sizeof(struct ospf_lsa_rt);
! 516:
! 517: while (buf < bufend)
! 518: {
! 519: struct ospf_lsa_rt3_link *l = buf;
! 520: buf += sizeof(struct ospf_lsa_rt3_link);
! 521:
! 522: if (buf > bufend)
! 523: return 0;
! 524:
! 525: if (!((l->type == LSART_PTP) ||
! 526: (l->type == LSART_NET) ||
! 527: (l->type == LSART_VLNK)))
! 528: return 0;
! 529: }
! 530: return 1;
! 531: }
! 532:
! 533: static int
! 534: lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
! 535: {
! 536: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
! 537: return 0;
! 538:
! 539: return 1;
! 540: }
! 541:
! 542: static int
! 543: lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body)
! 544: {
! 545: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2)))
! 546: return 0;
! 547:
! 548: /* First field should have TOS = 0, we ignore other TOS fields */
! 549: if ((body->metric & LSA_SUM2_TOS) != 0)
! 550: return 0;
! 551:
! 552: return 1;
! 553: }
! 554:
! 555: static inline int
! 556: pxlen(u32 *buf)
! 557: {
! 558: return *buf >> 24;
! 559: }
! 560:
! 561: static int
! 562: lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
! 563: {
! 564: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
! 565: return 0;
! 566:
! 567: u8 pxl = pxlen(body->prefix);
! 568: if (pxl > IP6_MAX_PREFIX_LENGTH)
! 569: return 0;
! 570:
! 571: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
! 572: IPV6_PREFIX_SPACE(pxl)))
! 573: return 0;
! 574:
! 575: return 1;
! 576: }
! 577:
! 578: static int
! 579: lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body UNUSED)
! 580: {
! 581: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
! 582: return 0;
! 583:
! 584: return 1;
! 585: }
! 586:
! 587: static int
! 588: lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body)
! 589: {
! 590: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2)))
! 591: return 0;
! 592:
! 593: /* First field should have TOS = 0, we ignore other TOS fields */
! 594: if ((body->metric & LSA_EXT2_TOS) != 0)
! 595: return 0;
! 596:
! 597: return 1;
! 598: }
! 599:
! 600: static int
! 601: lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
! 602: {
! 603: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
! 604: return 0;
! 605:
! 606: u8 pxl = pxlen(body->rest);
! 607: if (pxl > IP6_MAX_PREFIX_LENGTH)
! 608: return 0;
! 609:
! 610: int len = IPV6_PREFIX_SPACE(pxl);
! 611: if (body->metric & LSA_EXT3_FBIT) // forwarding address
! 612: len += 16;
! 613: if (body->metric & LSA_EXT3_TBIT) // route tag
! 614: len += 4;
! 615: if (*body->rest & 0xFFFF) // referenced LS type field
! 616: len += 4;
! 617:
! 618: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len))
! 619: return 0;
! 620:
! 621: return 1;
! 622: }
! 623:
! 624: static int
! 625: lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *pbuf)
! 626: {
! 627: uint bound = lsa->length - HDRLEN - 4;
! 628: u32 i;
! 629:
! 630: for (i = 0; i < pxcount; i++)
! 631: {
! 632: if (offset > bound)
! 633: return 0;
! 634:
! 635: u8 pxl = pxlen((u32 *) (pbuf + offset));
! 636: if (pxl > IP6_MAX_PREFIX_LENGTH)
! 637: return 0;
! 638:
! 639: offset += IPV6_PREFIX_SPACE(pxl);
! 640: }
! 641:
! 642: if (lsa->length != (HDRLEN + offset))
! 643: return 0;
! 644:
! 645: return 1;
! 646: }
! 647:
! 648: static int
! 649: lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body)
! 650: {
! 651: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link)))
! 652: return 0;
! 653:
! 654: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body);
! 655: }
! 656:
! 657: static int
! 658: lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
! 659: {
! 660: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix)))
! 661: return 0;
! 662:
! 663: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
! 664: }
! 665:
! 666: static int
! 667: lsa_validate_gr(struct ospf_lsa_header *lsa, void *body)
! 668: {
! 669: return lsa_validate_tlvs(body, lsa->length - HDRLEN);
! 670: }
! 671:
! 672: static int
! 673: lsa_validate_ri(struct ospf_lsa_header *lsa UNUSED, struct ospf_lsa_net *body UNUSED)
! 674: {
! 675: /*
! 676: * There should be proper validation. But we do not really process RI LSAs, so
! 677: * we can just accept them like another unknown opaque LSAs.
! 678: */
! 679:
! 680: return 1;
! 681: }
! 682:
! 683:
! 684: /**
! 685: * lsa_validate - check whether given LSA is valid
! 686: * @lsa: LSA header
! 687: * @lsa_type: internal LSA type (%LSA_T_xxx)
! 688: * @ospf2: %true for OSPFv2, %false for OSPFv3
! 689: * @body: pointer to LSA body
! 690: *
! 691: * Checks internal structure of given LSA body (minimal length,
! 692: * consistency). Returns true if valid.
! 693: */
! 694: int
! 695: lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
! 696: {
! 697: if (ospf2)
! 698: {
! 699: switch (lsa_type)
! 700: {
! 701: case LSA_T_RT:
! 702: return lsa_validate_rt2(lsa, body);
! 703: case LSA_T_NET:
! 704: return lsa_validate_net(lsa, body);
! 705: case LSA_T_SUM_NET:
! 706: return lsa_validate_sum2(lsa, body);
! 707: case LSA_T_SUM_RT:
! 708: return lsa_validate_sum2(lsa, body);
! 709: case LSA_T_EXT:
! 710: case LSA_T_NSSA:
! 711: return lsa_validate_ext2(lsa, body);
! 712: case LSA_T_GR:
! 713: return lsa_validate_gr(lsa, body);
! 714: case LSA_T_RI_LINK:
! 715: case LSA_T_RI_AREA:
! 716: case LSA_T_RI_AS:
! 717: return lsa_validate_ri(lsa, body);
! 718: case LSA_T_OPAQUE_LINK:
! 719: case LSA_T_OPAQUE_AREA:
! 720: case LSA_T_OPAQUE_AS:
! 721: return 1; /* Unknown Opaque LSAs */
! 722: default:
! 723: return 0; /* Should not happen, unknown LSAs are already rejected */
! 724: }
! 725: }
! 726: else
! 727: {
! 728: switch (lsa_type)
! 729: {
! 730: case LSA_T_RT:
! 731: return lsa_validate_rt3(lsa, body);
! 732: case LSA_T_NET:
! 733: return lsa_validate_net(lsa, body);
! 734: case LSA_T_SUM_NET:
! 735: return lsa_validate_sum3_net(lsa, body);
! 736: case LSA_T_SUM_RT:
! 737: return lsa_validate_sum3_rt(lsa, body);
! 738: case LSA_T_EXT:
! 739: case LSA_T_NSSA:
! 740: return lsa_validate_ext3(lsa, body);
! 741: case LSA_T_LINK:
! 742: return lsa_validate_link(lsa, body);
! 743: case LSA_T_PREFIX:
! 744: return lsa_validate_prefix(lsa, body);
! 745: case LSA_T_GR:
! 746: return lsa_validate_gr(lsa, body);
! 747: case LSA_T_RI_LINK:
! 748: case LSA_T_RI_AREA:
! 749: case LSA_T_RI_AS:
! 750: return lsa_validate_ri(lsa, body);
! 751: default:
! 752: return 1; /* Unknown LSAs are OK in OSPFv3 */
! 753: }
! 754: }
! 755: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>