Return to lsalib.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / proto / ospf |
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: #ifndef CPU_BIG_ENDIAN ! 16: void ! 17: lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n) ! 18: { ! 19: n->age = htons(h->age); ! 20: n->type_raw = htons(h->type_raw); ! 21: n->id = htonl(h->id); ! 22: n->rt = htonl(h->rt); ! 23: n->sn = htonl(h->sn); ! 24: n->checksum = htons(h->checksum); ! 25: n->length = htons(h->length); ! 26: } ! 27: ! 28: void ! 29: lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h) ! 30: { ! 31: h->age = ntohs(n->age); ! 32: h->type_raw = ntohs(n->type_raw); ! 33: h->id = ntohl(n->id); ! 34: h->rt = ntohl(n->rt); ! 35: h->sn = ntohl(n->sn); ! 36: h->checksum = ntohs(n->checksum); ! 37: h->length = ntohs(n->length); ! 38: } ! 39: ! 40: void ! 41: lsa_hton_body(void *h, void *n, u16 len) ! 42: { ! 43: u32 *hid = h; ! 44: u32 *nid = n; ! 45: uint i; ! 46: ! 47: for (i = 0; i < (len / sizeof(u32)); i++) ! 48: nid[i] = htonl(hid[i]); ! 49: } ! 50: ! 51: void ! 52: lsa_ntoh_body(void *n, void *h, u16 len) ! 53: { ! 54: u32 *nid = n; ! 55: u32 *hid = h; ! 56: uint i; ! 57: ! 58: for (i = 0; i < (len / sizeof(u32)); i++) ! 59: hid[i] = ntohl(nid[i]); ! 60: } ! 61: #endif /* little endian */ ! 62: ! 63: ! 64: ! 65: int ! 66: lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa) ! 67: { ! 68: /* Handle inactive vlinks */ ! 69: if (ifa->state == OSPF_IS_DOWN) ! 70: return 0; ! 71: ! 72: /* 4.5.2 (Case 2) */ ! 73: switch (LSA_SCOPE(type)) ! 74: { ! 75: case LSA_SCOPE_LINK: ! 76: return ifa->iface_id == domain; ! 77: ! 78: case LSA_SCOPE_AREA: ! 79: return ifa->oa->areaid == domain; ! 80: ! 81: case LSA_SCOPE_AS: ! 82: if (ifa->type == OSPF_IT_VLINK) ! 83: return 0; ! 84: if (!oa_is_ext(ifa->oa)) ! 85: return 0; ! 86: return 1; ! 87: ! 88: default: ! 89: log(L_ERR "OSPF: LSA with invalid scope"); ! 90: return 0; ! 91: } ! 92: } ! 93: ! 94: ! 95: static int ! 96: unknown_lsa_type(u32 type) ! 97: { ! 98: switch (type) ! 99: { ! 100: case LSA_T_RT: ! 101: case LSA_T_NET: ! 102: case LSA_T_SUM_NET: ! 103: case LSA_T_SUM_RT: ! 104: case LSA_T_EXT: ! 105: case LSA_T_NSSA: ! 106: case LSA_T_LINK: ! 107: case LSA_T_PREFIX: ! 108: return 0; ! 109: ! 110: default: ! 111: return 1; ! 112: } ! 113: } ! 114: ! 115: #define LSA_V2_TMAX 8 ! 116: static const u16 lsa_v2_types[LSA_V2_TMAX] = ! 117: {0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA}; ! 118: ! 119: void ! 120: lsa_get_type_domain_(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain) ! 121: { ! 122: if (ospf_is_v2(ifa->oa->po)) ! 123: { ! 124: itype = itype & LSA_T_V2_MASK; ! 125: itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0; ! 126: } ! 127: else ! 128: { ! 129: /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */ ! 130: if (unknown_lsa_type(itype) && !(itype & LSA_UBIT)) ! 131: itype = itype & ~LSA_SCOPE_MASK; ! 132: } ! 133: ! 134: *otype = itype; ! 135: ! 136: switch (LSA_SCOPE(itype)) ! 137: { ! 138: case LSA_SCOPE_LINK: ! 139: *domain = ifa->iface_id; ! 140: return; ! 141: ! 142: case LSA_SCOPE_AREA: ! 143: *domain = ifa->oa->areaid; ! 144: return; ! 145: ! 146: case LSA_SCOPE_AS: ! 147: default: ! 148: *domain = 0; ! 149: return; ! 150: } ! 151: } ! 152: ! 153: ! 154: void ! 155: lsa_generate_checksum(struct ospf_lsa_header *lsa, const u8 *body) ! 156: { ! 157: struct fletcher16_context ctx; ! 158: struct ospf_lsa_header hdr; ! 159: u16 len = lsa->length; ! 160: ! 161: /* ! 162: * lsa and body are in the host order, we need to compute Fletcher-16 checksum ! 163: * for data in the network order. We also skip the initial age field. ! 164: */ ! 165: ! 166: lsa_hton_hdr(lsa, &hdr); ! 167: hdr.checksum = 0; ! 168: ! 169: fletcher16_init(&ctx); ! 170: fletcher16_update(&ctx, (u8 *) &hdr + 2, sizeof(struct ospf_lsa_header) - 2); ! 171: fletcher16_update_n32(&ctx, body, len - sizeof(struct ospf_lsa_header)); ! 172: lsa->checksum = fletcher16_final(&ctx, len, OFFSETOF(struct ospf_lsa_header, checksum)); ! 173: } ! 174: ! 175: u16 ! 176: lsa_verify_checksum(const void *lsa_n, int lsa_len) ! 177: { ! 178: struct fletcher16_context ctx; ! 179: ! 180: /* The whole LSA is at lsa_n in net order, we just skip initial age field */ ! 181: ! 182: fletcher16_init(&ctx); ! 183: fletcher16_update(&ctx, (u8 *) lsa_n + 2, lsa_len - 2); ! 184: ! 185: return fletcher16_compute(&ctx) == 0; ! 186: } ! 187: ! 188: ! 189: int ! 190: lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2) ! 191: /* Return codes from point of view of l1 */ ! 192: { ! 193: u32 sn1, sn2; ! 194: ! 195: sn1 = l1->sn - LSA_INITSEQNO + 1; ! 196: sn2 = l2->sn - LSA_INITSEQNO + 1; ! 197: ! 198: if (sn1 > sn2) ! 199: return CMP_NEWER; ! 200: if (sn1 < sn2) ! 201: return CMP_OLDER; ! 202: ! 203: if (l1->checksum != l2->checksum) ! 204: return l1->checksum < l2->checksum ? CMP_OLDER : CMP_NEWER; ! 205: ! 206: if ((l1->age == LSA_MAXAGE) && (l2->age != LSA_MAXAGE)) ! 207: return CMP_NEWER; ! 208: if ((l2->age == LSA_MAXAGE) && (l1->age != LSA_MAXAGE)) ! 209: return CMP_OLDER; ! 210: ! 211: if (ABS(l1->age - l2->age) > LSA_MAXAGEDIFF) ! 212: return l1->age < l2->age ? CMP_NEWER : CMP_OLDER; ! 213: ! 214: return CMP_SAME; ! 215: } ! 216: ! 217: ! 218: static inline int ! 219: lsa_walk_rt2(struct ospf_lsa_rt_walk *rt) ! 220: { ! 221: if (rt->buf >= rt->bufend) ! 222: return 0; ! 223: ! 224: struct ospf_lsa_rt2_link *l = rt->buf; ! 225: rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos); ! 226: ! 227: rt->type = l->type; ! 228: rt->metric = l->metric; ! 229: rt->id = l->id; ! 230: rt->data = l->data; ! 231: return 1; ! 232: } ! 233: ! 234: static inline int ! 235: lsa_walk_rt3(struct ospf_lsa_rt_walk *rt) ! 236: { ! 237: while (rt->buf >= rt->bufend) ! 238: { ! 239: rt->en = ospf_hash_find_rt3_next(rt->en); ! 240: if (!rt->en) ! 241: return 0; ! 242: ! 243: rt->buf = rt->en->lsa_body; ! 244: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header); ! 245: rt->buf += sizeof(struct ospf_lsa_rt); ! 246: } ! 247: ! 248: struct ospf_lsa_rt3_link *l = rt->buf; ! 249: rt->buf += sizeof(struct ospf_lsa_rt3_link); ! 250: ! 251: rt->type = l->type; ! 252: rt->metric = l->metric; ! 253: rt->lif = l->lif; ! 254: rt->nif = l->nif; ! 255: rt->id = l->id; ! 256: return 1; ! 257: } ! 258: ! 259: void ! 260: lsa_walk_rt_init(struct ospf_proto *p, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt) ! 261: { ! 262: rt->ospf2 = ospf_is_v2(p); ! 263: rt->id = rt->data = rt->lif = rt->nif = 0; ! 264: ! 265: if (rt->ospf2) ! 266: rt->en = act; ! 267: else ! 268: rt->en = ospf_hash_find_rt3_first(p->gr, act->domain, act->lsa.rt); ! 269: ! 270: rt->buf = rt->en->lsa_body; ! 271: rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header); ! 272: rt->buf += sizeof(struct ospf_lsa_rt); ! 273: } ! 274: ! 275: int ! 276: lsa_walk_rt(struct ospf_lsa_rt_walk *rt) ! 277: { ! 278: return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt); ! 279: } ! 280: ! 281: ! 282: void ! 283: lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric) ! 284: { ! 285: if (ospf2) ! 286: { ! 287: struct ospf_lsa_sum2 *ls = en->lsa_body; ! 288: *ip = ipa_from_u32(en->lsa.id & ls->netmask); ! 289: *pxlen = u32_masklen(ls->netmask); ! 290: *pxopts = 0; ! 291: *metric = ls->metric & LSA_METRIC_MASK; ! 292: } ! 293: else ! 294: { ! 295: struct ospf_lsa_sum3_net *ls = en->lsa_body; ! 296: u16 rest; ! 297: lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest); ! 298: *metric = ls->metric & LSA_METRIC_MASK; ! 299: } ! 300: } ! 301: ! 302: void ! 303: lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options) ! 304: { ! 305: if (ospf2) ! 306: { ! 307: struct ospf_lsa_sum2 *ls = en->lsa_body; ! 308: *drid = en->lsa.id; ! 309: *metric = ls->metric & LSA_METRIC_MASK; ! 310: *options = 0; ! 311: } ! 312: else ! 313: { ! 314: struct ospf_lsa_sum3_rt *ls = en->lsa_body; ! 315: *drid = ls->drid; ! 316: *metric = ls->metric & LSA_METRIC_MASK; ! 317: *options = ls->options & LSA_OPTIONS_MASK; ! 318: } ! 319: } ! 320: ! 321: void ! 322: lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt) ! 323: { ! 324: if (ospf2) ! 325: { ! 326: struct ospf_lsa_ext2 *ext = en->lsa_body; ! 327: rt->ip = ipa_from_u32(en->lsa.id & ext->netmask); ! 328: rt->pxlen = u32_masklen(ext->netmask); ! 329: rt->pxopts = 0; ! 330: rt->metric = ext->metric & LSA_METRIC_MASK; ! 331: rt->ebit = ext->metric & LSA_EXT2_EBIT; ! 332: ! 333: rt->fbit = ext->fwaddr; ! 334: rt->fwaddr = ipa_from_u32(ext->fwaddr); ! 335: ! 336: rt->tag = ext->tag; ! 337: rt->propagate = lsa_get_options(&en->lsa) & OPT_P; ! 338: } ! 339: else ! 340: { ! 341: struct ospf_lsa_ext3 *ext = en->lsa_body; ! 342: u16 rest; ! 343: u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest); ! 344: rt->metric = ext->metric & LSA_METRIC_MASK; ! 345: rt->ebit = ext->metric & LSA_EXT3_EBIT; ! 346: ! 347: rt->fbit = ext->metric & LSA_EXT3_FBIT; ! 348: if (rt->fbit) ! 349: buf = lsa_get_ipv6_addr(buf, &rt->fwaddr); ! 350: else ! 351: rt->fwaddr = IPA_NONE; ! 352: ! 353: rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0; ! 354: rt->propagate = rt->pxopts & OPT_PX_P; ! 355: } ! 356: } ! 357: ! 358: #define HDRLEN sizeof(struct ospf_lsa_header) ! 359: ! 360: static int ! 361: lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body) ! 362: { ! 363: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt))) ! 364: return 0; ! 365: ! 366: uint i = 0; ! 367: void *buf = body; ! 368: void *bufend = buf + lsa->length - HDRLEN; ! 369: buf += sizeof(struct ospf_lsa_rt); ! 370: ! 371: while (buf < bufend) ! 372: { ! 373: struct ospf_lsa_rt2_link *l = buf; ! 374: buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos); ! 375: i++; ! 376: ! 377: if (buf > bufend) ! 378: return 0; ! 379: ! 380: if (!((l->type == LSART_PTP) || ! 381: (l->type == LSART_NET) || ! 382: (l->type == LSART_STUB) || ! 383: (l->type == LSART_VLNK))) ! 384: return 0; ! 385: } ! 386: ! 387: if ((body->options & LSA_RT2_LINKS) != i) ! 388: return 0; ! 389: ! 390: return 1; ! 391: } ! 392: ! 393: ! 394: static int ! 395: lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body) ! 396: { ! 397: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt))) ! 398: return 0; ! 399: ! 400: void *buf = body; ! 401: void *bufend = buf + lsa->length - HDRLEN; ! 402: buf += sizeof(struct ospf_lsa_rt); ! 403: ! 404: while (buf < bufend) ! 405: { ! 406: struct ospf_lsa_rt3_link *l = buf; ! 407: buf += sizeof(struct ospf_lsa_rt3_link); ! 408: ! 409: if (buf > bufend) ! 410: return 0; ! 411: ! 412: if (!((l->type == LSART_PTP) || ! 413: (l->type == LSART_NET) || ! 414: (l->type == LSART_VLNK))) ! 415: return 0; ! 416: } ! 417: return 1; ! 418: } ! 419: ! 420: static int ! 421: lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED) ! 422: { ! 423: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net))) ! 424: return 0; ! 425: ! 426: return 1; ! 427: } ! 428: ! 429: static int ! 430: lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body) ! 431: { ! 432: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2))) ! 433: return 0; ! 434: ! 435: /* First field should have TOS = 0, we ignore other TOS fields */ ! 436: if ((body->metric & LSA_SUM2_TOS) != 0) ! 437: return 0; ! 438: ! 439: return 1; ! 440: } ! 441: ! 442: static inline int ! 443: pxlen(u32 *buf) ! 444: { ! 445: return *buf >> 24; ! 446: } ! 447: ! 448: static int ! 449: lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body) ! 450: { ! 451: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4)) ! 452: return 0; ! 453: ! 454: u8 pxl = pxlen(body->prefix); ! 455: if (pxl > MAX_PREFIX_LENGTH) ! 456: return 0; ! 457: ! 458: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + ! 459: IPV6_PREFIX_SPACE(pxl))) ! 460: return 0; ! 461: ! 462: return 1; ! 463: } ! 464: ! 465: static int ! 466: lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body UNUSED) ! 467: { ! 468: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt))) ! 469: return 0; ! 470: ! 471: return 1; ! 472: } ! 473: ! 474: static int ! 475: lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body) ! 476: { ! 477: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2))) ! 478: return 0; ! 479: ! 480: /* First field should have TOS = 0, we ignore other TOS fields */ ! 481: if ((body->metric & LSA_EXT2_TOS) != 0) ! 482: return 0; ! 483: ! 484: return 1; ! 485: } ! 486: ! 487: static int ! 488: lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body) ! 489: { ! 490: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4)) ! 491: return 0; ! 492: ! 493: u8 pxl = pxlen(body->rest); ! 494: if (pxl > MAX_PREFIX_LENGTH) ! 495: return 0; ! 496: ! 497: int len = IPV6_PREFIX_SPACE(pxl); ! 498: if (body->metric & LSA_EXT3_FBIT) // forwardinf address ! 499: len += 16; ! 500: if (body->metric & LSA_EXT3_TBIT) // route tag ! 501: len += 4; ! 502: if (*body->rest & 0xFFFF) // referenced LS type field ! 503: len += 4; ! 504: ! 505: if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len)) ! 506: return 0; ! 507: ! 508: return 1; ! 509: } ! 510: ! 511: static int ! 512: lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *pbuf) ! 513: { ! 514: uint bound = lsa->length - HDRLEN - 4; ! 515: u32 i; ! 516: ! 517: for (i = 0; i < pxcount; i++) ! 518: { ! 519: if (offset > bound) ! 520: return 0; ! 521: ! 522: u8 pxl = pxlen((u32 *) (pbuf + offset)); ! 523: if (pxl > MAX_PREFIX_LENGTH) ! 524: return 0; ! 525: ! 526: offset += IPV6_PREFIX_SPACE(pxl); ! 527: } ! 528: ! 529: if (lsa->length != (HDRLEN + offset)) ! 530: return 0; ! 531: ! 532: return 1; ! 533: } ! 534: ! 535: static int ! 536: lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body) ! 537: { ! 538: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link))) ! 539: return 0; ! 540: ! 541: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body); ! 542: } ! 543: ! 544: static int ! 545: lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body) ! 546: { ! 547: if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix))) ! 548: return 0; ! 549: ! 550: return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body); ! 551: } ! 552: ! 553: ! 554: /** ! 555: * lsa_validate - check whether given LSA is valid ! 556: * @lsa: LSA header ! 557: * @lsa_type: one of %LSA_T_xxx ! 558: * @ospf2: %true means OSPF version 2, %false means OSPF version 3 ! 559: * @body: pointer to LSA body ! 560: * ! 561: * Checks internal structure of given LSA body (minimal length, ! 562: * consistency). Returns true if valid. ! 563: */ ! 564: int ! 565: lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body) ! 566: { ! 567: if (ospf2) ! 568: { ! 569: switch (lsa_type) ! 570: { ! 571: case LSA_T_RT: ! 572: return lsa_validate_rt2(lsa, body); ! 573: case LSA_T_NET: ! 574: return lsa_validate_net(lsa, body); ! 575: case LSA_T_SUM_NET: ! 576: return lsa_validate_sum2(lsa, body); ! 577: case LSA_T_SUM_RT: ! 578: return lsa_validate_sum2(lsa, body); ! 579: case LSA_T_EXT: ! 580: case LSA_T_NSSA: ! 581: return lsa_validate_ext2(lsa, body); ! 582: default: ! 583: return 0; /* Should not happen, unknown LSAs are already rejected */ ! 584: } ! 585: } ! 586: else ! 587: { ! 588: switch (lsa_type) ! 589: { ! 590: case LSA_T_RT: ! 591: return lsa_validate_rt3(lsa, body); ! 592: case LSA_T_NET: ! 593: return lsa_validate_net(lsa, body); ! 594: case LSA_T_SUM_NET: ! 595: return lsa_validate_sum3_net(lsa, body); ! 596: case LSA_T_SUM_RT: ! 597: return lsa_validate_sum3_rt(lsa, body); ! 598: case LSA_T_EXT: ! 599: case LSA_T_NSSA: ! 600: return lsa_validate_ext3(lsa, body); ! 601: case LSA_T_LINK: ! 602: return lsa_validate_link(lsa, body); ! 603: case LSA_T_PREFIX: ! 604: return lsa_validate_prefix(lsa, body); ! 605: default: ! 606: return 1; /* Unknown LSAs are OK in OSPFv3 */ ! 607: } ! 608: } ! 609: }