Return to packet.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / ospf |
1.1 ! misho 1: /* ! 2: * BIRD -- OSPF ! 3: * ! 4: * (c) 1999--2005 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: #include "nest/password.h" ! 13: #include "lib/md5.h" ! 14: #include "lib/mac.h" ! 15: #include "lib/socket.h" ! 16: ! 17: void ! 18: ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) ! 19: { ! 20: struct ospf_proto *p = ifa->oa->po; ! 21: struct ospf_packet *pkt; ! 22: ! 23: pkt = (struct ospf_packet *) buf; ! 24: ! 25: pkt->version = ospf_get_version(p); ! 26: pkt->type = h_type; ! 27: pkt->length = htons(ospf_pkt_maxsize(ifa)); ! 28: pkt->routerid = htonl(p->router_id); ! 29: pkt->areaid = htonl(ifa->oa->areaid); ! 30: pkt->checksum = 0; ! 31: pkt->instance_id = ifa->instance_id; ! 32: pkt->autype = ospf_is_v2(p) ? ifa->autype : 0; ! 33: } ! 34: ! 35: /* We assume OSPFv2 in ospf_pkt_finalize() */ ! 36: static void ! 37: ospf_pkt_finalize2(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen) ! 38: { ! 39: struct ospf_proto *p = ifa->oa->po; ! 40: struct password_item *pass = NULL; ! 41: union ospf_auth2 *auth = (void *) (pkt + 1); ! 42: memset(auth, 0, sizeof(union ospf_auth2)); ! 43: ! 44: /* Compatibility note: auth may contain anything if autype is ! 45: none, but nonzero values do not work with Mikrotik OSPF */ ! 46: ! 47: pkt->checksum = 0; ! 48: pkt->autype = ifa->autype; ! 49: ! 50: switch (ifa->autype) ! 51: { ! 52: case OSPF_AUTH_SIMPLE: ! 53: pass = password_find(ifa->passwords, 1); ! 54: if (!pass) ! 55: { ! 56: log(L_ERR "No suitable password found for authentication"); ! 57: return; ! 58: } ! 59: strncpy(auth->password, pass->password, sizeof(auth->password)); ! 60: /* fallthrough */ ! 61: ! 62: case OSPF_AUTH_NONE: ! 63: { ! 64: void *body = (void *) (auth + 1); ! 65: uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth2); ! 66: pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL); ! 67: } ! 68: break; ! 69: ! 70: case OSPF_AUTH_CRYPT: ! 71: pass = password_find(ifa->passwords, 0); ! 72: if (!pass) ! 73: { ! 74: log(L_ERR "%s: No suitable password found for authentication", p->p.name); ! 75: return; ! 76: } ! 77: ! 78: /* Perhaps use random value to prevent replay attacks after ! 79: reboot when system does not have independent RTC? */ ! 80: if (!ifa->csn) ! 81: { ! 82: ifa->csn = (u32) (current_real_time() TO_S); ! 83: ifa->csn_use = current_time(); ! 84: } ! 85: ! 86: /* We must have sufficient delay between sending a packet and increasing ! 87: CSN to prevent reordering of packets (in a network) with different CSNs */ ! 88: if ((current_time() - ifa->csn_use) > 1 S) ! 89: ifa->csn++; ! 90: ! 91: ifa->csn_use = current_time(); ! 92: ! 93: uint auth_len = mac_type_length(pass->alg); ! 94: byte *auth_tail = ((byte *) pkt + *plen); ! 95: *plen += auth_len; ! 96: ! 97: ASSERT(*plen < ifa->sk->tbsize); ! 98: ! 99: auth->c32.zero = 0; ! 100: auth->c32.keyid = pass->id; ! 101: auth->c32.len = auth_len; ! 102: auth->c32.csn = htonl(ifa->csn); ! 103: ! 104: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */ ! 105: if (pass->alg < ALG_HMAC) ! 106: strncpy(auth_tail, pass->password, auth_len); ! 107: else ! 108: memset32(auth_tail, HMAC_MAGIC, auth_len / 4); ! 109: ! 110: mac_fill(pass->alg, pass->password, pass->length, (byte *) pkt, *plen, auth_tail); ! 111: break; ! 112: ! 113: default: ! 114: bug("Unknown authentication type"); ! 115: } ! 116: } ! 117: ! 118: /* ! 119: * Return an extra packet size that should be added to a final packet size ! 120: */ ! 121: static void ! 122: ospf_pkt_finalize3(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen, ip_addr src) ! 123: { ! 124: struct ospf_proto *p = ifa->oa->po; ! 125: struct ospf_auth3 *auth = (void *) ((byte *) pkt + *plen); ! 126: ! 127: pkt->checksum = 0; ! 128: pkt->autype = 0; ! 129: ! 130: if (ifa->autype != OSPF_AUTH_CRYPT) ! 131: return; ! 132: ! 133: struct password_item *pass = password_find(ifa->passwords, 0); ! 134: if (!pass) ! 135: { ! 136: log(L_ERR "%s: No suitable password found for authentication", p->p.name); ! 137: return; ! 138: } ! 139: ! 140: /* FIXME: Ensure persistence */ ! 141: p->csn64++; ! 142: ! 143: uint mac_len = mac_type_length(pass->alg); ! 144: uint auth_len = sizeof(struct ospf_auth3) + mac_len; ! 145: *plen += auth_len; ! 146: ! 147: ASSERT(*plen < ifa->sk->tbsize); ! 148: ! 149: memset(auth, 0, sizeof(struct ospf_auth3)); ! 150: auth->type = htons(OSPF3_AUTH_HMAC); ! 151: auth->length = htons(auth_len); ! 152: auth->reserved = 0; ! 153: auth->sa_id = htons(pass->id); ! 154: put_u64(&auth->csn, p->csn64); ! 155: ! 156: /* Initialize with src IP address padded with HMAC_MAGIC */ ! 157: put_ip6(auth->data, ipa_to_ip6(src)); ! 158: memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4); ! 159: ! 160: /* Attach OSPFv3 Cryptographic Protocol ID to the key */ ! 161: uint pass_len = pass->length + 2; ! 162: byte *pass_key = alloca(pass_len); ! 163: memcpy(pass_key, pass->password, pass->length); ! 164: put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID); ! 165: ! 166: mac_fill(pass->alg, pass_key, pass_len, (byte *) pkt, *plen, auth->data); ! 167: } ! 168: ! 169: ! 170: static int ! 171: ospf_pkt_checkauth2(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len) ! 172: { ! 173: struct ospf_proto *p = ifa->oa->po; ! 174: union ospf_auth2 *auth = (void *) (pkt + 1); ! 175: struct password_item *pass = NULL; ! 176: const char *err_dsc = NULL; ! 177: uint err_val = 0; ! 178: ! 179: uint plen = ntohs(pkt->length); ! 180: u8 autype = pkt->autype; ! 181: ! 182: if (autype != ifa->autype) ! 183: DROP("authentication method mismatch", autype); ! 184: ! 185: switch (autype) ! 186: { ! 187: case OSPF_AUTH_NONE: ! 188: return 1; ! 189: ! 190: case OSPF_AUTH_SIMPLE: ! 191: pass = password_find(ifa->passwords, 1); ! 192: if (!pass) ! 193: DROP1("no password found"); ! 194: ! 195: if (!password_verify(pass, auth->password, sizeof(auth->password))) ! 196: DROP("wrong password", pass->id); ! 197: ! 198: return 1; ! 199: ! 200: case OSPF_AUTH_CRYPT: ! 201: pass = password_find_by_id(ifa->passwords, auth->c32.keyid); ! 202: if (!pass) ! 203: DROP("no suitable password found", auth->c32.keyid); ! 204: ! 205: uint auth_len = mac_type_length(pass->alg); ! 206: ! 207: if (plen + auth->c32.len > len) ! 208: DROP("packet length mismatch", len); ! 209: ! 210: if (auth->c32.len != auth_len) ! 211: DROP("wrong authentication length", auth->c32.len); ! 212: ! 213: u32 rcv_csn = ntohl(auth->c32.csn); ! 214: if (n && (rcv_csn < n->csn)) ! 215: // DROP("lower sequence number", rcv_csn); ! 216: { ! 217: /* We want to report both new and old CSN */ ! 218: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - " ! 219: "lower sequence number (rcv %u, old %u)", ! 220: n->rid, ifa->ifname, rcv_csn, n->csn); ! 221: return 0; ! 222: } ! 223: ! 224: byte *auth_tail = ((byte *) pkt) + plen; ! 225: byte *auth_data = alloca(auth_len); ! 226: memcpy(auth_data, auth_tail, auth_len); ! 227: ! 228: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */ ! 229: if (pass->alg < ALG_HMAC) ! 230: strncpy(auth_tail, pass->password, auth_len); ! 231: else ! 232: memset32(auth_tail, HMAC_MAGIC, auth_len / 4); ! 233: ! 234: if (!mac_verify(pass->alg, pass->password, pass->length, ! 235: (byte *) pkt, plen + auth_len, auth_data)) ! 236: DROP("wrong authentication code", pass->id); ! 237: ! 238: if (n) ! 239: n->csn = rcv_csn; ! 240: ! 241: return 1; ! 242: ! 243: default: ! 244: bug("Unknown authentication type"); ! 245: } ! 246: ! 247: drop: ! 248: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)", ! 249: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val); ! 250: ! 251: return 0; ! 252: } ! 253: ! 254: static int ! 255: ospf_pkt_checkauth3(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len, ip_addr src) ! 256: { ! 257: struct ospf_proto *p = ifa->oa->po; ! 258: const char *err_dsc = NULL; ! 259: uint err_val = 0; ! 260: ! 261: uint plen = ntohs(pkt->length); ! 262: uint opts, lls_present, auth_present; ! 263: ! 264: /* ! 265: * When autentication is not enabled, ignore the trailer. This is different ! 266: * from OSPFv2, but it is necessary in order to support migration modes. Note ! 267: * that regular authenticated packets do not have valid checksum and will be ! 268: * dropped by OS on non-authenticated ifaces. ! 269: */ ! 270: if (ifa->autype != OSPF_AUTH_CRYPT) ! 271: return 1; ! 272: ! 273: switch(pkt->type) ! 274: { ! 275: case HELLO_P: ! 276: opts = ospf_hello3_options(pkt); ! 277: lls_present = opts & OPT_L_V3; ! 278: auth_present = opts & OPT_AT; ! 279: break; ! 280: ! 281: case DBDES_P: ! 282: opts = ospf_dbdes3_options(pkt); ! 283: lls_present = opts & OPT_L_V3; ! 284: auth_present = opts & OPT_AT; ! 285: break; ! 286: ! 287: default: ! 288: lls_present = 0; ! 289: auth_present = n->options & OPT_AT; ! 290: } ! 291: ! 292: if (!auth_present) ! 293: DROP1("missing authentication trailer"); ! 294: ! 295: if (lls_present) ! 296: { ! 297: if ((plen + sizeof(struct ospf_lls)) > len) ! 298: DROP("packet length mismatch", len); ! 299: ! 300: struct ospf_lls *lls = (void *) ((byte *) pkt + plen); ! 301: plen += ntohs(lls->length); ! 302: } ! 303: ! 304: if ((plen + sizeof(struct ospf_auth3)) > len) ! 305: DROP("packet length mismatch", len); ! 306: ! 307: struct ospf_auth3 *auth = (void *) ((byte *) pkt + plen); ! 308: ! 309: uint rcv_auth_type = ntohs(auth->type); ! 310: if (rcv_auth_type != OSPF3_AUTH_HMAC) ! 311: DROP("authentication method mismatch", rcv_auth_type); ! 312: ! 313: uint rcv_auth_len = ntohs(auth->length); ! 314: if (plen + rcv_auth_len > len) ! 315: DROP("packet length mismatch", len); ! 316: ! 317: uint rcv_key_id = ntohs(auth->sa_id); ! 318: struct password_item *pass = password_find_by_id(ifa->passwords, rcv_key_id); ! 319: if (!pass) ! 320: DROP("no suitable password found", rcv_key_id); ! 321: ! 322: uint mac_len = mac_type_length(pass->alg); ! 323: if (rcv_auth_len != (sizeof(struct ospf_auth3) + mac_len)) ! 324: DROP("wrong authentication length", rcv_auth_len); ! 325: ! 326: uint pt = pkt->type - 1; ! 327: u64 rcv_csn = get_u64(&auth->csn); ! 328: if (n && (rcv_csn <= n->csn64[pt])) ! 329: { ! 330: /* We want to report both new and old CSN */ ! 331: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - " ! 332: "lower sequence number (rcv %u, old %u)", ! 333: n->rid, ifa->ifname, (uint) rcv_csn, (uint) n->csn64[pt]); ! 334: return 0; ! 335: } ! 336: ! 337: /* Save the received authentication data */ ! 338: byte *auth_data = alloca(mac_len); ! 339: memcpy(auth_data, auth->data, mac_len); ! 340: ! 341: /* Initialize with src IP address padded with HMAC_MAGIC */ ! 342: put_ip6(auth->data, ipa_to_ip6(src)); ! 343: memset32(auth->data + 16, HMAC_MAGIC, (mac_len - 16) / 4); ! 344: ! 345: /* Attach OSPFv3 Cryptographic Protocol ID to the key */ ! 346: uint pass_len = pass->length + 2; ! 347: byte *pass_key = alloca(pass_len); ! 348: memcpy(pass_key, pass->password, pass->length); ! 349: put_u16(pass_key + pass->length, OSPF3_CRYPTO_ID); ! 350: ! 351: if (!mac_verify(pass->alg, pass_key, pass_len, ! 352: (byte *) pkt, plen + rcv_auth_len, auth_data)) ! 353: DROP("wrong authentication code", pass->id); ! 354: ! 355: if (n) ! 356: n->csn64[pt] = rcv_csn; ! 357: ! 358: return 1; ! 359: ! 360: drop: ! 361: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)", ! 362: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val); ! 363: ! 364: return 0; ! 365: } ! 366: ! 367: /** ! 368: * ospf_rx_hook ! 369: * @sk: socket we received the packet. ! 370: * @len: length of the packet ! 371: * ! 372: * This is the entry point for messages from neighbors. Many checks (like ! 373: * authentication, checksums, size) are done before the packet is passed to ! 374: * non generic functions. ! 375: */ ! 376: int ! 377: ospf_rx_hook(sock *sk, uint len) ! 378: { ! 379: /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter ! 380: out other packets at kernel level and we receive all packets on all sockets */ ! 381: if (sk->lifindex != sk->iface->index) ! 382: return 1; ! 383: ! 384: DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n", ! 385: sk->iface->name, sk->faddr, sk->laddr); ! 386: ! 387: /* Initially, the packet is associated with the 'master' iface */ ! 388: struct ospf_iface *ifa = sk->data; ! 389: struct ospf_proto *p = ifa->oa->po; ! 390: const char *err_dsc = NULL; ! 391: uint err_val = 0; ! 392: ! 393: /* Should not happen */ ! 394: if (ifa->state <= OSPF_IS_LOOP) ! 395: return 1; ! 396: ! 397: int src_local, dst_local, dst_mcast; ! 398: src_local = ipa_in_netX(sk->faddr, &ifa->addr->prefix); ! 399: dst_local = ipa_equal(sk->laddr, ifa->addr->ip); ! 400: dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers); ! 401: ! 402: if (ospf_is_v2(p)) ! 403: { ! 404: /* First, we eliminate packets with strange address combinations. ! 405: * In OSPFv2, they might be for other ospf_ifaces (with different IP ! 406: * prefix) on the same real iface, so we don't log it. We enforce ! 407: * that (src_local || dst_local), therefore we are eliminating all ! 408: * such cases. ! 409: */ ! 410: if (dst_mcast && !src_local) ! 411: return 1; ! 412: if (!dst_mcast && !dst_local) ! 413: return 1; ! 414: ! 415: /* Ignore my own broadcast packets */ ! 416: if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip)) ! 417: return 1; ! 418: } ! 419: else ! 420: { ! 421: /* In OSPFv3, src_local and dst_local mean link-local. ! 422: * RFC 5340 says that local (non-vlink) packets use ! 423: * link-local src address, but does not enforce it. Strange. ! 424: */ ! 425: if (dst_mcast && !src_local) ! 426: LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s", ! 427: sk->faddr, ifa->ifname); ! 428: } ! 429: ! 430: /* Second, we check packet length, checksum, and the protocol version */ ! 431: struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len); ! 432: ! 433: ! 434: if (pkt == NULL) ! 435: DROP("bad IP header", len); ! 436: ! 437: if (len < sizeof(struct ospf_packet)) ! 438: DROP("too short", len); ! 439: ! 440: if (pkt->version != ospf_get_version(p)) ! 441: DROP("version mismatch", pkt->version); ! 442: ! 443: uint plen = ntohs(pkt->length); ! 444: if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0)) ! 445: DROP("invalid length", plen); ! 446: ! 447: if (sk->flags & SKF_TRUNCATED) ! 448: { ! 449: /* If we have dynamic buffers and received truncated message, we expand RX buffer */ ! 450: ! 451: uint bs = plen + 256; ! 452: bs = BIRD_ALIGN(bs, 1024); ! 453: ! 454: if (!ifa->cf->rx_buffer && (bs > sk->rbsize)) ! 455: sk_set_rbsize(sk, bs); ! 456: ! 457: DROP("truncated", plen); ! 458: } ! 459: ! 460: if (plen > len) ! 461: DROP("length mismatch", plen); ! 462: ! 463: if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) ! 464: { ! 465: uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth2); ! 466: uint blen = plen - hlen; ! 467: void *body = ((void *) pkt) + hlen; ! 468: ! 469: if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) ! 470: DROP("invalid checksum", ntohs(pkt->checksum)); ! 471: } ! 472: ! 473: /* Third, we resolve associated iface and handle vlinks. */ ! 474: ! 475: u32 areaid = ntohl(pkt->areaid); ! 476: u32 rid = ntohl(pkt->routerid); ! 477: u8 instance_id = pkt->instance_id; ! 478: ! 479: if (areaid == ifa->oa->areaid) ! 480: { ! 481: /* Matching area ID */ ! 482: ! 483: if (instance_id != ifa->instance_id) ! 484: return 1; ! 485: ! 486: /* It is real iface, source should be local (in OSPFv2) */ ! 487: if (ospf_is_v2(p) && !src_local) ! 488: DROP1("strange source address"); ! 489: ! 490: goto found; ! 491: } ! 492: else if ((areaid == 0) && !dst_mcast) ! 493: { ! 494: /* Backbone area ID and possible vlink packet */ ! 495: ! 496: if ((p->areano == 1) || !oa_is_ext(ifa->oa)) ! 497: return 1; ! 498: ! 499: struct ospf_iface *iff = NULL; ! 500: WALK_LIST(iff, p->iface_list) ! 501: { ! 502: if ((iff->type == OSPF_IT_VLINK) && ! 503: (iff->voa == ifa->oa) && ! 504: (iff->instance_id == instance_id) && ! 505: (iff->vid == rid)) ! 506: { ! 507: /* Vlink should be UP */ ! 508: if (iff->state != OSPF_IS_PTP) ! 509: return 1; ! 510: ! 511: ifa = iff; ! 512: goto found; ! 513: } ! 514: } ! 515: ! 516: /* ! 517: * Cannot find matching vlink. It is either misconfigured vlink; NBMA or ! 518: * PtMP with misconfigured area ID, or packet for some other instance (that ! 519: * is possible even if instance_id == ifa->instance_id, because it may be ! 520: * also vlink packet in the other instance, which is different namespace). ! 521: */ ! 522: ! 523: return 1; ! 524: } ! 525: else ! 526: { ! 527: /* Non-matching area ID but cannot be vlink packet */ ! 528: ! 529: if (instance_id != ifa->instance_id) ! 530: return 1; ! 531: ! 532: DROP("area mismatch", areaid); ! 533: } ! 534: ! 535: ! 536: found: ! 537: if (ifa->stub) /* This shouldn't happen */ ! 538: return 1; ! 539: ! 540: if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0)) ! 541: return 1; ! 542: ! 543: /* TTL check must be done after instance dispatch */ ! 544: if (ifa->check_ttl && (sk->rcv_ttl < 255)) ! 545: DROP("wrong TTL", sk->rcv_ttl); ! 546: ! 547: if (rid == p->router_id) ! 548: DROP1("my own router ID"); ! 549: ! 550: if (rid == 0) ! 551: DROP1("zero router ID"); ! 552: ! 553: /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */ ! 554: uint t = ifa->type; ! 555: struct ospf_neighbor *n; ! 556: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) ! 557: n = find_neigh_by_ip(ifa, sk->faddr); ! 558: else ! 559: n = find_neigh(ifa, rid); ! 560: ! 561: if (!n && (pkt->type != HELLO_P)) ! 562: { ! 563: OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I", ! 564: rid, ifa->ifname, sk->faddr); ! 565: return 1; ! 566: } ! 567: ! 568: /* Check packet type here, ospf_pkt_checkauth3() expects valid values */ ! 569: if (pkt->type < HELLO_P || pkt->type > LSACK_P) ! 570: DROP("invalid packet type", pkt->type); ! 571: ! 572: /* ospf_pkt_checkauth() has its own error logging */ ! 573: if ((ospf_is_v2(p) ? ! 574: !ospf_pkt_checkauth2(n, ifa, pkt, len) : ! 575: !ospf_pkt_checkauth3(n, ifa, pkt, len, sk->faddr))) ! 576: return 1; ! 577: ! 578: switch (pkt->type) ! 579: { ! 580: case HELLO_P: ! 581: ospf_receive_hello(pkt, ifa, n, sk->faddr); ! 582: break; ! 583: ! 584: case DBDES_P: ! 585: ospf_receive_dbdes(pkt, ifa, n); ! 586: break; ! 587: ! 588: case LSREQ_P: ! 589: ospf_receive_lsreq(pkt, ifa, n); ! 590: break; ! 591: ! 592: case LSUPD_P: ! 593: ospf_receive_lsupd(pkt, ifa, n); ! 594: break; ! 595: ! 596: case LSACK_P: ! 597: ospf_receive_lsack(pkt, ifa, n); ! 598: break; ! 599: }; ! 600: return 1; ! 601: ! 602: drop: ! 603: LOG_PKT("Bad packet from %I via %s - %s (%u)", ! 604: sk->faddr, ifa->ifname, err_dsc, err_val); ! 605: ! 606: return 1; ! 607: } ! 608: ! 609: /* ! 610: void ! 611: ospf_tx_hook(sock * sk) ! 612: { ! 613: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); ! 614: // struct proto *p = (struct proto *) (ifa->oa->p); ! 615: log(L_ERR "OSPF: TX hook called on %s", ifa->ifname); ! 616: } ! 617: */ ! 618: ! 619: void ! 620: ospf_err_hook(sock * sk, int err) ! 621: { ! 622: struct ospf_iface *ifa = (struct ospf_iface *) (sk->data); ! 623: struct ospf_proto *p = ifa->oa->po; ! 624: log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err); ! 625: } ! 626: ! 627: void ! 628: ospf_verr_hook(sock *sk, int err) ! 629: { ! 630: struct ospf_proto *p = (struct ospf_proto *) (sk->data); ! 631: log(L_ERR "%s: Vlink socket error: %M", p->p.name, err); ! 632: } ! 633: ! 634: void ! 635: ospf_send_to(struct ospf_iface *ifa, ip_addr dst) ! 636: { ! 637: sock *sk = ifa->sk; ! 638: struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; ! 639: uint plen = ntohs(pkt->length); ! 640: ! 641: if (ospf_is_v2(ifa->oa->po)) ! 642: ospf_pkt_finalize2(ifa, pkt, &plen); ! 643: else ! 644: ospf_pkt_finalize3(ifa, pkt, &plen, sk->saddr); ! 645: ! 646: int done = sk_send_to(sk, plen, dst, 0); ! 647: if (!done) ! 648: log(L_WARN "OSPF: TX queue full on %s", ifa->ifname); ! 649: } ! 650: ! 651: void ! 652: ospf_send_to_agt(struct ospf_iface *ifa, u8 state) ! 653: { ! 654: struct ospf_neighbor *n; ! 655: ! 656: WALK_LIST(n, ifa->neigh_list) ! 657: if (n->state >= state) ! 658: ospf_send_to(ifa, n->ip); ! 659: } ! 660: ! 661: void ! 662: ospf_send_to_bdr(struct ospf_iface *ifa) ! 663: { ! 664: if (ipa_nonzero2(ifa->drip)) ! 665: ospf_send_to(ifa, ifa->drip); ! 666: if (ipa_nonzero2(ifa->bdrip)) ! 667: ospf_send_to(ifa, ifa->bdrip); ! 668: }