Return to packet.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / 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 = ifa->autype; ! 33: } ! 34: ! 35: /* We assume OSPFv2 in ospf_pkt_finalize() */ ! 36: static void ! 37: ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen) ! 38: { ! 39: struct password_item *pass = NULL; ! 40: union ospf_auth *auth = (void *) (pkt + 1); ! 41: ! 42: pkt->checksum = 0; ! 43: pkt->autype = ifa->autype; ! 44: bzero(auth, sizeof(union ospf_auth)); ! 45: ! 46: /* Compatibility note: auth may contain anything if autype is ! 47: none, but nonzero values do not work with Mikrotik OSPF */ ! 48: ! 49: switch (ifa->autype) ! 50: { ! 51: case OSPF_AUTH_SIMPLE: ! 52: pass = password_find(ifa->passwords, 1); ! 53: if (!pass) ! 54: { ! 55: log(L_ERR "No suitable password found for authentication"); ! 56: return; ! 57: } ! 58: strncpy(auth->password, pass->password, sizeof(auth->password)); ! 59: ! 60: case OSPF_AUTH_NONE: ! 61: { ! 62: void *body = (void *) (auth + 1); ! 63: uint blen = *plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth); ! 64: pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL); ! 65: } ! 66: break; ! 67: ! 68: case OSPF_AUTH_CRYPT: ! 69: pass = password_find(ifa->passwords, 0); ! 70: if (!pass) ! 71: { ! 72: log(L_ERR "No suitable password found for authentication"); ! 73: return; ! 74: } ! 75: ! 76: /* Perhaps use random value to prevent replay attacks after ! 77: reboot when system does not have independent RTC? */ ! 78: if (!ifa->csn) ! 79: { ! 80: ifa->csn = (u32) now; ! 81: ifa->csn_use = now; ! 82: } ! 83: ! 84: /* We must have sufficient delay between sending a packet and increasing ! 85: CSN to prevent reordering of packets (in a network) with different CSNs */ ! 86: if ((now - ifa->csn_use) > 1) ! 87: ifa->csn++; ! 88: ! 89: ifa->csn_use = now; ! 90: ! 91: uint auth_len = mac_type_length(pass->alg); ! 92: byte *auth_tail = ((byte *) pkt + *plen); ! 93: *plen += auth_len; ! 94: ! 95: ASSERT(*plen < ifa->sk->tbsize); ! 96: ! 97: auth->c32.zero = 0; ! 98: auth->c32.keyid = pass->id; ! 99: auth->c32.len = auth_len; ! 100: auth->c32.csn = htonl(ifa->csn); ! 101: ! 102: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */ ! 103: if (pass->alg < ALG_HMAC) ! 104: strncpy(auth_tail, pass->password, auth_len); ! 105: else ! 106: memset32(auth_tail, HMAC_MAGIC, auth_len / 4); ! 107: ! 108: mac_fill(pass->alg, pass->password, pass->length, ! 109: (byte *) pkt, *plen, auth_tail); ! 110: break; ! 111: ! 112: default: ! 113: bug("Unknown authentication type"); ! 114: } ! 115: } ! 116: ! 117: ! 118: /* We assume OSPFv2 in ospf_pkt_checkauth() */ ! 119: static int ! 120: ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, uint len) ! 121: { ! 122: struct ospf_proto *p = ifa->oa->po; ! 123: union ospf_auth *auth = (void *) (pkt + 1); ! 124: struct password_item *pass = NULL; ! 125: const char *err_dsc = NULL; ! 126: uint err_val = 0; ! 127: ! 128: uint plen = ntohs(pkt->length); ! 129: u8 autype = pkt->autype; ! 130: ! 131: if (autype != ifa->autype) ! 132: DROP("authentication method mismatch", autype); ! 133: ! 134: switch (autype) ! 135: { ! 136: case OSPF_AUTH_NONE: ! 137: return 1; ! 138: ! 139: case OSPF_AUTH_SIMPLE: ! 140: pass = password_find(ifa->passwords, 1); ! 141: if (!pass) ! 142: DROP1("no password found"); ! 143: ! 144: if (!password_verify(pass, auth->password, sizeof(auth->password))) ! 145: DROP("wrong password", pass->id); ! 146: ! 147: return 1; ! 148: ! 149: case OSPF_AUTH_CRYPT: ! 150: pass = password_find_by_id(ifa->passwords, auth->c32.keyid); ! 151: if (!pass) ! 152: DROP("no suitable password found", auth->c32.keyid); ! 153: ! 154: uint auth_len = mac_type_length(pass->alg); ! 155: ! 156: if (plen + auth->c32.len > len) ! 157: DROP("packet length mismatch", len); ! 158: ! 159: if (auth->c32.len != auth_len) ! 160: DROP("wrong authentication length", auth->c32.len); ! 161: ! 162: u32 rcv_csn = ntohl(auth->c32.csn); ! 163: if (n && (rcv_csn < n->csn)) ! 164: // DROP("lower sequence number", rcv_csn); ! 165: { ! 166: /* We want to report both new and old CSN */ ! 167: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - " ! 168: "lower sequence number (rcv %u, old %u)", ! 169: n->rid, ifa->ifname, rcv_csn, n->csn); ! 170: return 0; ! 171: } ! 172: ! 173: byte *auth_tail = ((byte *) pkt) + plen; ! 174: byte *auth_data = alloca(auth_len); ! 175: memcpy(auth_data, auth_tail, auth_len); ! 176: ! 177: /* Append key for keyed hash, append padding for HMAC (RFC 5709 3.3) */ ! 178: if (pass->alg < ALG_HMAC) ! 179: strncpy(auth_tail, pass->password, auth_len); ! 180: else ! 181: memset32(auth_tail, HMAC_MAGIC, auth_len / 4); ! 182: ! 183: if (!mac_verify(pass->alg, pass->password, pass->length, ! 184: (byte *) pkt, plen + auth_len, auth_data)) ! 185: DROP("wrong authentication code", pass->id); ! 186: ! 187: if (n) ! 188: n->csn = rcv_csn; ! 189: ! 190: return 1; ! 191: ! 192: default: ! 193: bug("Unknown authentication type"); ! 194: } ! 195: ! 196: drop: ! 197: LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)", ! 198: (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val); ! 199: ! 200: return 0; ! 201: } ! 202: ! 203: /** ! 204: * ospf_rx_hook ! 205: * @sk: socket we received the packet. ! 206: * @len: size of the packet ! 207: * ! 208: * This is the entry point for messages from neighbors. Many checks (like ! 209: * authentication, checksums, size) are done before the packet is passed to ! 210: * non generic functions. ! 211: */ ! 212: int ! 213: ospf_rx_hook(sock *sk, uint len) ! 214: { ! 215: /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter ! 216: out other packets at kernel level and we receive all packets on all sockets */ ! 217: if (sk->lifindex != sk->iface->index) ! 218: return 1; ! 219: ! 220: DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n", ! 221: sk->iface->name, sk->faddr, sk->laddr); ! 222: ! 223: /* Initially, the packet is associated with the 'master' iface */ ! 224: struct ospf_iface *ifa = sk->data; ! 225: struct ospf_proto *p = ifa->oa->po; ! 226: const char *err_dsc = NULL; ! 227: uint err_val = 0; ! 228: ! 229: /* Should not happen */ ! 230: if (ifa->state <= OSPF_IS_LOOP) ! 231: return 1; ! 232: ! 233: int src_local, dst_local, dst_mcast; ! 234: src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); ! 235: dst_local = ipa_equal(sk->laddr, ifa->addr->ip); ! 236: dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers); ! 237: ! 238: if (ospf_is_v2(p)) ! 239: { ! 240: /* First, we eliminate packets with strange address combinations. ! 241: * In OSPFv2, they might be for other ospf_ifaces (with different IP ! 242: * prefix) on the same real iface, so we don't log it. We enforce ! 243: * that (src_local || dst_local), therefore we are eliminating all ! 244: * such cases. ! 245: */ ! 246: if (dst_mcast && !src_local) ! 247: return 1; ! 248: if (!dst_mcast && !dst_local) ! 249: return 1; ! 250: ! 251: /* Ignore my own broadcast packets */ ! 252: if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip)) ! 253: return 1; ! 254: } ! 255: else ! 256: { ! 257: /* In OSPFv3, src_local and dst_local mean link-local. ! 258: * RFC 5340 says that local (non-vlink) packets use ! 259: * link-local src address, but does not enforce it. Strange. ! 260: */ ! 261: if (dst_mcast && !src_local) ! 262: LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s", ! 263: sk->faddr, ifa->ifname); ! 264: } ! 265: ! 266: /* Second, we check packet length, checksum, and the protocol version */ ! 267: struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len); ! 268: ! 269: ! 270: if (pkt == NULL) ! 271: DROP("bad IP header", len); ! 272: ! 273: if (ifa->check_ttl && (sk->rcv_ttl < 255)) ! 274: DROP("wrong TTL", sk->rcv_ttl); ! 275: ! 276: if (len < sizeof(struct ospf_packet)) ! 277: DROP("too short", len); ! 278: ! 279: if (pkt->version != ospf_get_version(p)) ! 280: DROP("version mismatch", pkt->version); ! 281: ! 282: uint plen = ntohs(pkt->length); ! 283: if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0)) ! 284: DROP("invalid length", plen); ! 285: ! 286: if (sk->flags & SKF_TRUNCATED) ! 287: { ! 288: /* If we have dynamic buffers and received truncated message, we expand RX buffer */ ! 289: ! 290: uint bs = plen + 256; ! 291: bs = BIRD_ALIGN(bs, 1024); ! 292: ! 293: if (!ifa->cf->rx_buffer && (bs > sk->rbsize)) ! 294: sk_set_rbsize(sk, bs); ! 295: ! 296: DROP("truncated", plen); ! 297: } ! 298: ! 299: if (plen > len) ! 300: DROP("length mismatch", plen); ! 301: ! 302: if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) ! 303: { ! 304: uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth); ! 305: uint blen = plen - hlen; ! 306: void *body = ((void *) pkt) + hlen; ! 307: ! 308: if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) ! 309: DROP1("invalid checksum"); ! 310: } ! 311: ! 312: /* Third, we resolve associated iface and handle vlinks. */ ! 313: ! 314: u32 areaid = ntohl(pkt->areaid); ! 315: u32 rid = ntohl(pkt->routerid); ! 316: u8 instance_id = pkt->instance_id; ! 317: ! 318: if (areaid == ifa->oa->areaid) ! 319: { ! 320: /* Matching area ID */ ! 321: ! 322: if (instance_id != ifa->instance_id) ! 323: return 1; ! 324: ! 325: /* It is real iface, source should be local (in OSPFv2) */ ! 326: if (ospf_is_v2(p) && !src_local) ! 327: DROP1("strange source address"); ! 328: ! 329: goto found; ! 330: } ! 331: else if ((areaid == 0) && !dst_mcast) ! 332: { ! 333: /* Backbone area ID and possible vlink packet */ ! 334: ! 335: if ((p->areano == 1) || !oa_is_ext(ifa->oa)) ! 336: return 1; ! 337: ! 338: struct ospf_iface *iff = NULL; ! 339: WALK_LIST(iff, p->iface_list) ! 340: { ! 341: if ((iff->type == OSPF_IT_VLINK) && ! 342: (iff->voa == ifa->oa) && ! 343: (iff->instance_id == instance_id) && ! 344: (iff->vid == rid)) ! 345: { ! 346: /* Vlink should be UP */ ! 347: if (iff->state != OSPF_IS_PTP) ! 348: return 1; ! 349: ! 350: ifa = iff; ! 351: goto found; ! 352: } ! 353: } ! 354: ! 355: /* ! 356: * Cannot find matching vlink. It is either misconfigured vlink; NBMA or ! 357: * PtMP with misconfigured area ID, or packet for some other instance (that ! 358: * is possible even if instance_id == ifa->instance_id, because it may be ! 359: * also vlink packet in the other instance, which is different namespace). ! 360: */ ! 361: ! 362: return 1; ! 363: } ! 364: else ! 365: { ! 366: /* Non-matching area ID but cannot be vlink packet */ ! 367: ! 368: if (instance_id != ifa->instance_id) ! 369: return 1; ! 370: ! 371: DROP("area mismatch", areaid); ! 372: } ! 373: ! 374: ! 375: found: ! 376: if (ifa->stub) /* This shouldn't happen */ ! 377: return 1; ! 378: ! 379: if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0)) ! 380: return 1; ! 381: ! 382: if (rid == p->router_id) ! 383: DROP1("my own router ID"); ! 384: ! 385: if (rid == 0) ! 386: DROP1("zero router ID"); ! 387: ! 388: /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */ ! 389: uint t = ifa->type; ! 390: struct ospf_neighbor *n; ! 391: if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) ! 392: n = find_neigh_by_ip(ifa, sk->faddr); ! 393: else ! 394: n = find_neigh(ifa, rid); ! 395: ! 396: if (!n && (pkt->type != HELLO_P)) ! 397: { ! 398: OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I", ! 399: rid, ifa->ifname, sk->faddr); ! 400: return 1; ! 401: } ! 402: ! 403: /* ospf_pkt_checkauth() has its own error logging */ ! 404: if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len)) ! 405: return 1; ! 406: ! 407: switch (pkt->type) ! 408: { ! 409: case HELLO_P: ! 410: ospf_receive_hello(pkt, ifa, n, sk->faddr); ! 411: break; ! 412: ! 413: case DBDES_P: ! 414: ospf_receive_dbdes(pkt, ifa, n); ! 415: break; ! 416: ! 417: case LSREQ_P: ! 418: ospf_receive_lsreq(pkt, ifa, n); ! 419: break; ! 420: ! 421: case LSUPD_P: ! 422: ospf_receive_lsupd(pkt, ifa, n); ! 423: break; ! 424: ! 425: case LSACK_P: ! 426: ospf_receive_lsack(pkt, ifa, n); ! 427: break; ! 428: ! 429: default: ! 430: DROP("invalid packet type", pkt->type); ! 431: }; ! 432: return 1; ! 433: ! 434: drop: ! 435: LOG_PKT("Bad packet from %I via %s - %s (%u)", ! 436: sk->faddr, ifa->ifname, err_dsc, err_val); ! 437: ! 438: return 1; ! 439: } ! 440: ! 441: /* ! 442: void ! 443: ospf_tx_hook(sock * sk) ! 444: { ! 445: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); ! 446: // struct proto *p = (struct proto *) (ifa->oa->p); ! 447: log(L_ERR "OSPF: TX hook called on %s", ifa->ifname); ! 448: } ! 449: */ ! 450: ! 451: void ! 452: ospf_err_hook(sock * sk, int err) ! 453: { ! 454: struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); ! 455: struct ospf_proto *p = ifa->oa->po; ! 456: log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err); ! 457: } ! 458: ! 459: void ! 460: ospf_verr_hook(sock *sk, int err) ! 461: { ! 462: struct ospf_proto *p = (struct ospf_proto *) (sk->data); ! 463: log(L_ERR "%s: Vlink socket error: %M", p->p.name, err); ! 464: } ! 465: ! 466: void ! 467: ospf_send_to(struct ospf_iface *ifa, ip_addr dst) ! 468: { ! 469: sock *sk = ifa->sk; ! 470: struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; ! 471: uint plen = ntohs(pkt->length); ! 472: ! 473: if (ospf_is_v2(ifa->oa->po)) ! 474: ospf_pkt_finalize(ifa, pkt, &plen); ! 475: ! 476: int done = sk_send_to(sk, plen, dst, 0); ! 477: if (!done) ! 478: log(L_WARN "OSPF: TX queue full on %s", ifa->ifname); ! 479: } ! 480: ! 481: void ! 482: ospf_send_to_agt(struct ospf_iface *ifa, u8 state) ! 483: { ! 484: struct ospf_neighbor *n; ! 485: ! 486: WALK_LIST(n, ifa->neigh_list) ! 487: if (n->state >= state) ! 488: ospf_send_to(ifa, n->ip); ! 489: } ! 490: ! 491: void ! 492: ospf_send_to_bdr(struct ospf_iface *ifa) ! 493: { ! 494: if (ipa_nonzero(ifa->drip)) ! 495: ospf_send_to(ifa, ifa->drip); ! 496: if (ipa_nonzero(ifa->bdrip)) ! 497: ospf_send_to(ifa, ifa->bdrip); ! 498: }