diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2015-02-21 11:39:45 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2015-02-21 11:39:45 +0100 |
commit | 7730553b7eeb33d21e5597f110334ca584ad532d (patch) | |
tree | c80bf6d48fc91bafd7f0aefc859a033d3b472c89 /proto/ospf/packet.c | |
parent | 0da562a7cb25ed2b8724248ad6f841b1831a09c3 (diff) | |
parent | ec2194fa7a20a2768ca0027b5f3c024f0a251866 (diff) |
Merge remote-tracking branch 'origin/soft-int'
Diffstat (limited to 'proto/ospf/packet.c')
-rw-r--r-- | proto/ospf/packet.c | 661 |
1 files changed, 298 insertions, 363 deletions
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 1240b05c..fb63e61c 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -2,6 +2,8 @@ * BIRD -- OSPF * * (c) 1999--2005 Ondrej Filip <feela@network.cz> + * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org> + * (c) 2009--2014 CZ.NIC z.s.p.o. * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -13,233 +15,195 @@ void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type) { - struct proto_ospf *po = ifa->oa->po; + struct ospf_proto *p = ifa->oa->po; struct ospf_packet *pkt; pkt = (struct ospf_packet *) buf; - pkt->version = OSPF_VERSION; - + pkt->version = ospf_get_version(p); pkt->type = h_type; - - pkt->routerid = htonl(po->router_id); + pkt->length = htons(ospf_pkt_maxsize(ifa)); + pkt->routerid = htonl(p->router_id); pkt->areaid = htonl(ifa->oa->areaid); - -#ifdef OSPFv3 - pkt->instance_id = ifa->instance_id; -#endif - -#ifdef OSPFv2 - pkt->autype = htons(ifa->autype); -#endif - pkt->checksum = 0; + pkt->instance_id = ifa->instance_id; + pkt->autype = ifa->autype; } -unsigned +uint ospf_pkt_maxsize(struct ospf_iface *ifa) { - unsigned headers = SIZE_OF_IP_HEADER; + uint headers = SIZE_OF_IP_HEADER; -#ifdef OSPFv2 + /* Relevant just for OSPFv2 */ if (ifa->autype == OSPF_AUTH_CRYPT) headers += OSPF_AUTH_CRYPT_SIZE; -#endif return ifa->tx_length - headers; } -#ifdef OSPFv2 - +/* We assume OSPFv2 in ospf_pkt_finalize() */ static void ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) { struct password_item *passwd = NULL; - void *tail; - struct MD5Context ctxt; - char password[OSPF_AUTH_CRYPT_SIZE]; + union ospf_auth *auth = (void *) (pkt + 1); + uint plen = ntohs(pkt->length); pkt->checksum = 0; - pkt->autype = htons(ifa->autype); - bzero(&pkt->u, sizeof(union ospf_auth)); + pkt->autype = ifa->autype; + bzero(auth, sizeof(union ospf_auth)); - /* Compatibility note: pkt->u may contain anything if autype is + /* Compatibility note: auth may contain anything if autype is none, but nonzero values do not work with Mikrotik OSPF */ - switch(ifa->autype) + switch (ifa->autype) { - case OSPF_AUTH_SIMPLE: - passwd = password_find(ifa->passwords, 1); - if (!passwd) - { - log( L_ERR "No suitable password found for authentication" ); - return; - } - password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth)); - case OSPF_AUTH_NONE: - pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) - - sizeof(union ospf_auth), (pkt + 1), - ntohs(pkt->length) - - sizeof(struct ospf_packet), NULL); - break; - case OSPF_AUTH_CRYPT: - passwd = password_find(ifa->passwords, 0); - if (!passwd) - { - log( L_ERR "No suitable password found for authentication" ); - return; - } + case OSPF_AUTH_SIMPLE: + passwd = password_find(ifa->passwords, 1); + if (!passwd) + { + log(L_ERR "No suitable password found for authentication"); + return; + } + strncpy(auth->password, passwd->password, sizeof(auth->password)); - /* Perhaps use random value to prevent replay attacks after - reboot when system does not have independent RTC? */ - if (!ifa->csn) - { - ifa->csn = (u32) now; - ifa->csn_use = now; - } + case OSPF_AUTH_NONE: + { + void *body = (void *) (auth + 1); + uint blen = plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth); + pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL); + } + break; - /* We must have sufficient delay between sending a packet and increasing - CSN to prevent reordering of packets (in a network) with different CSNs */ - if ((now - ifa->csn_use) > 1) - ifa->csn++; + case OSPF_AUTH_CRYPT: + passwd = password_find(ifa->passwords, 0); + if (!passwd) + { + log(L_ERR "No suitable password found for authentication"); + return; + } + /* Perhaps use random value to prevent replay attacks after + reboot when system does not have independent RTC? */ + if (!ifa->csn) + { + ifa->csn = (u32) now; ifa->csn_use = now; + } + + /* We must have sufficient delay between sending a packet and increasing + CSN to prevent reordering of packets (in a network) with different CSNs */ + if ((now - ifa->csn_use) > 1) + ifa->csn++; - pkt->u.md5.keyid = passwd->id; - pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE; - pkt->u.md5.zero = 0; - pkt->u.md5.csn = htonl(ifa->csn); - tail = ((void *)pkt) + ntohs(pkt->length); - MD5Init(&ctxt); - MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length)); - password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE); - MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); - MD5Final(tail, &ctxt); - break; - default: - bug("Unknown authentication type"); + ifa->csn_use = now; + + auth->md5.zero = 0; + auth->md5.keyid = passwd->id; + auth->md5.len = OSPF_AUTH_CRYPT_SIZE; + auth->md5.csn = htonl(ifa->csn); + + void *tail = ((void *) pkt) + plen; + char password[OSPF_AUTH_CRYPT_SIZE]; + strncpy(password, passwd->password, sizeof(password)); + + struct MD5Context ctxt; + MD5Init(&ctxt); + MD5Update(&ctxt, (char *) pkt, plen); + MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); + MD5Final(tail, &ctxt); + break; + + default: + bug("Unknown authentication type"); } } + +/* We assume OSPFv2 in ospf_pkt_checkauth() */ static int -ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) +ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int len) { - struct proto_ospf *po = ifa->oa->po; - struct proto *p = &po->proto; - struct password_item *pass = NULL, *ptmp; - void *tail; - char md5sum[OSPF_AUTH_CRYPT_SIZE]; - char password[OSPF_AUTH_CRYPT_SIZE]; - struct MD5Context ctxt; + struct ospf_proto *p = ifa->oa->po; + union ospf_auth *auth = (void *) (pkt + 1); + struct password_item *pass = NULL; + const char *err_dsc = NULL; + uint err_val = 0; + uint plen = ntohs(pkt->length); + u8 autype = pkt->autype; - if (pkt->autype != htons(ifa->autype)) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype)); - return 0; - } + if (autype != ifa->autype) + DROP("authentication method mismatch", autype); - switch(ifa->autype) + switch (autype) { - case OSPF_AUTH_NONE: - return 1; - break; - case OSPF_AUTH_SIMPLE: - pass = password_find(ifa->passwords, 1); - if (!pass) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found"); - return 0; - } - password_cpy(password, pass->password, sizeof(union ospf_auth)); - - if (memcmp(pkt->u.password, password, sizeof(union ospf_auth))) - { - char ppass[sizeof(union ospf_auth) + 1]; - bzero(ppass, (sizeof(union ospf_auth) + 1)); - memcpy(ppass, pkt->u.password, sizeof(union ospf_auth)); - OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords (%s)", ppass); - return 0; - } - return 1; - break; - case OSPF_AUTH_CRYPT: - if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest"); - return 0; - } + case OSPF_AUTH_NONE: + return 1; - if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)", - ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size); - return 0; - } + case OSPF_AUTH_SIMPLE: + pass = password_find(ifa->passwords, 1); + if (!pass) + DROP1("no password found"); - tail = ((void *)pkt) + ntohs(pkt->length); + if (!password_verify(pass, auth->password, sizeof(auth->password))) + DROP("wrong password", pass->id); - if (ifa->passwords) - { - WALK_LIST(ptmp, *(ifa->passwords)) - { - if (pkt->u.md5.keyid != ptmp->id) continue; - if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue; - pass = ptmp; - break; - } - } + return 1; - if (!pass) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found"); - return 0; - } + case OSPF_AUTH_CRYPT: + if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE) + DROP("invalid MD5 digest length", auth->md5.len); - if (n) - { - u32 rcv_csn = ntohl(pkt->u.md5.csn); - if(rcv_csn < n->csn) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn); - return 0; - } - - n->csn = rcv_csn; - } + if (plen + OSPF_AUTH_CRYPT_SIZE > len) + DROP("length mismatch", len); - MD5Init(&ctxt); - MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length)); - password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE); - MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); - MD5Final(md5sum, &ctxt); - if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE)) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest"); - return 0; - } - return 1; - break; - default: - OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); + u32 rcv_csn = ntohl(auth->md5.csn); + if (n && (rcv_csn < n->csn)) + // DROP("lower sequence number", rcv_csn); + { + /* We want to report both new and old CSN */ + LOG_PKT_AUTH("Authentication failed for nbr %R on %s - " + "lower sequence number (rcv %u, old %u)", + n->rid, ifa->ifname, rcv_csn, n->csn); return 0; - } -} + } -#else + pass = password_find_by_id(ifa->passwords, auth->md5.keyid); + if (!pass) + DROP("no suitable password found", auth->md5.keyid); -/* OSPFv3 authentication not yet supported */ + void *tail = ((void *) pkt) + plen; + char passwd[OSPF_AUTH_CRYPT_SIZE]; + char md5sum[OSPF_AUTH_CRYPT_SIZE]; -static inline void -ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) -{ } + strncpy(passwd, pass->password, OSPF_AUTH_CRYPT_SIZE); -static int -ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) -{ return 1; } - -#endif + struct MD5Context ctxt; + MD5Init(&ctxt); + MD5Update(&ctxt, (char *) pkt, plen); + MD5Update(&ctxt, passwd, OSPF_AUTH_CRYPT_SIZE); + MD5Final(md5sum, &ctxt); + + if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE)) + DROP("wrong MD5 digest", pass->id); + + if (n) + n->csn = rcv_csn; + + return 1; + + default: + bug("Unknown authentication type"); + } +drop: + LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)", + (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val); + + return 0; +} /** * ospf_rx_hook @@ -251,13 +215,10 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_ * non generic functions. */ int -ospf_rx_hook(sock *sk, int size) +ospf_rx_hook(sock *sk, int len) { - char *mesg = "OSPF: Bad packet from "; - - /* We want just packets from sk->iface. Unfortunately, on BSD we - cannot filter out other packets at kernel level and we receive - all packets on all sockets */ + /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter + out other packets at kernel level and we receive all packets on all sockets */ if (sk->lifindex != sk->iface->index) return 1; @@ -266,71 +227,65 @@ ospf_rx_hook(sock *sk, int size) /* Initially, the packet is associated with the 'master' iface */ struct ospf_iface *ifa = sk->data; - struct proto_ospf *po = ifa->oa->po; - // struct proto *p = &po->proto; + struct ospf_proto *p = ifa->oa->po; + const char *err_dsc = NULL; + uint err_val = 0; - int src_local, dst_local UNUSED, dst_mcast; + int src_local, dst_local, dst_mcast; src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); dst_local = ipa_equal(sk->laddr, ifa->addr->ip); - dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters); - -#ifdef OSPFv2 - /* First, we eliminate packets with strange address combinations. - * In OSPFv2, they might be for other ospf_ifaces (with different IP - * prefix) on the same real iface, so we don't log it. We enforce - * that (src_local || dst_local), therefore we are eliminating all - * such cases. - */ - if (dst_mcast && !src_local) - return 1; - if (!dst_mcast && !dst_local) - return 1; + dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers); - /* Ignore my own broadcast packets */ - if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip)) - return 1; -#else /* OSPFv3 */ - - /* In OSPFv3, src_local and dst_local mean link-local. - * RFC 5340 says that local (non-vlink) packets use - * link-local src address, but does not enforce it. Strange. - */ - if (dst_mcast && !src_local) - log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr); -#endif - - /* Second, we check packet size, checksum, and the protocol version */ - struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); + if (ospf_is_v2(p)) + { + /* First, we eliminate packets with strange address combinations. + * In OSPFv2, they might be for other ospf_ifaces (with different IP + * prefix) on the same real iface, so we don't log it. We enforce + * that (src_local || dst_local), therefore we are eliminating all + * such cases. + */ + if (dst_mcast && !src_local) + return 1; + if (!dst_mcast && !dst_local) + return 1; - if (ps == NULL) + /* Ignore my own broadcast packets */ + if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip)) + return 1; + } + else { - log(L_ERR "%s%I - bad IP header", mesg, sk->faddr); - return 1; + /* In OSPFv3, src_local and dst_local mean link-local. + * RFC 5340 says that local (non-vlink) packets use + * link-local src address, but does not enforce it. Strange. + */ + if (dst_mcast && !src_local) + LOG_PKT_WARN("Multicast packet received from non-link-local %I via %s", + sk->faddr, ifa->ifname); } + /* Second, we check packet length, checksum, and the protocol version */ + struct ospf_packet *pkt = (void *) sk_rx_buffer(sk, &len); + + + if (pkt == NULL) + DROP("bad IP header", len); + if (ifa->check_ttl && (sk->rcv_ttl < 255)) - { - log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl); - return 1; - } + DROP("wrong TTL", sk->rcv_ttl); - if ((unsigned) size < sizeof(struct ospf_packet)) - { - log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size); - return 1; - } + if (len < sizeof(struct ospf_packet)) + DROP("too short", len); - uint plen = ntohs(ps->length); + if (pkt->version != ospf_get_version(p)) + DROP("version mismatch", pkt->version); + + uint plen = ntohs(pkt->length); if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0)) - { - log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen); - return 1; - } + DROP("invalid length", plen); if (sk->flags & SKF_TRUNCATED) { - log(L_WARN "%s%I - too large (%d/%d)", mesg, sk->faddr, plen, size); - /* If we have dynamic buffers and received truncated message, we expand RX buffer */ uint bs = plen + 256; @@ -339,168 +294,149 @@ ospf_rx_hook(sock *sk, int size) if (!ifa->cf->rx_buffer && (bs > sk->rbsize)) sk_set_rbsize(sk, bs); - return 1; + DROP("truncated", plen); } - if (plen > size) - { - log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size); - return 1; - } + if (plen > len) + DROP("length mismatch", plen); - if (ps->version != OSPF_VERSION) + if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) { - log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version); - return 1; - } + uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth); + uint blen = plen - hlen; + void *body = ((void *) pkt) + hlen; -#ifdef OSPFv2 - if ((ps->autype != htons(OSPF_AUTH_CRYPT)) && - (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet), - plen - sizeof(struct ospf_packet), NULL))) - { - log(L_ERR "%s%I - bad checksum", mesg, sk->faddr); - return 1; + if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) + DROP1("invalid checksum"); } -#endif - /* Third, we resolve associated iface and handle vlinks. */ - u32 areaid = ntohl(ps->areaid); - u32 rid = ntohl(ps->routerid); + u32 areaid = ntohl(pkt->areaid); + u32 rid = ntohl(pkt->routerid); + u8 instance_id = pkt->instance_id; - if ((areaid == ifa->oa->areaid) -#ifdef OSPFv3 - && (ps->instance_id == ifa->instance_id) -#endif - ) + if (areaid == ifa->oa->areaid) { - /* It is real iface, source should be local (in OSPFv2) */ -#ifdef OSPFv2 - if (!src_local) + /* Matching area ID */ + + if (instance_id != ifa->instance_id) return 1; -#endif - } - else if (dst_mcast || (areaid != 0)) - { - /* Obvious mismatch */ - -#ifdef OSPFv2 - /* We ignore mismatch in OSPFv3, because there might be - other instance with different instance ID */ - log(L_ERR "%s%I - area does not match (%R vs %R)", - mesg, sk->faddr, areaid, ifa->oa->areaid); -#endif - return 1; + + /* It is real iface, source should be local (in OSPFv2) */ + if (ospf_is_v2(p) && !src_local) + DROP1("strange source address"); + + goto found; } - else + else if ((areaid == 0) && !dst_mcast) { - /* Some vlink? */ - struct ospf_iface *iff = NULL; + /* Backbone area ID and possible vlink packet */ - WALK_LIST(iff, po->iface_list) + if ((p->areano == 1) || !oa_is_ext(ifa->oa)) + return 1; + + struct ospf_iface *iff = NULL; + WALK_LIST(iff, p->iface_list) { - if ((iff->type == OSPF_IT_VLINK) && + if ((iff->type == OSPF_IT_VLINK) && (iff->voa == ifa->oa) && -#ifdef OSPFv3 - (iff->instance_id == ps->instance_id) && -#endif + (iff->instance_id == instance_id) && (iff->vid == rid)) - { - /* Vlink should be UP */ - if (iff->state != OSPF_IS_PTP) - return 1; - - ifa = iff; - goto found; - } + { + /* Vlink should be UP */ + if (iff->state != OSPF_IS_PTP) + return 1; + + ifa = iff; + goto found; + } } -#ifdef OSPFv2 - log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr); -#endif + /* + * Cannot find matching vlink. It is either misconfigured vlink; NBMA or + * PtMP with misconfigured area ID, or packet for some other instance (that + * is possible even if instance_id == ifa->instance_id, because it may be + * also vlink packet in the other instance, which is different namespace). + */ + return 1; } + else + { + /* Non-matching area ID but cannot be vlink packet */ - found: + if (instance_id != ifa->instance_id) + return 1; + + DROP("area mismatch", areaid); + } + + +found: if (ifa->stub) /* This shouldn't happen */ return 1; - if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0)) + if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0)) return 1; - if (rid == po->router_id) - { - log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr); - return 1; - } + if (rid == p->router_id) + DROP1("my own router ID"); if (rid == 0) - { - log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr); - return 1; - } + DROP1("zero router ID"); -#ifdef OSPFv2 - /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */ + /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */ + uint t = ifa->type; struct ospf_neighbor *n; - if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)) + if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) n = find_neigh_by_ip(ifa, sk->faddr); else n = find_neigh(ifa, rid); -#else - struct ospf_neighbor *n = find_neigh(ifa, rid); -#endif - if(!n && (ps->type != HELLO_P)) + if (!n && (pkt->type != HELLO_P)) { - log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)", - sk->faddr, ifa->ifname); + OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I", + rid, ifa->ifname, sk->faddr); return 1; } - if (!ospf_pkt_checkauth(n, ifa, ps, size)) - { - log(L_ERR "%s%I - authentication failed", mesg, sk->faddr); + /* ospf_pkt_checkauth() has its own error logging */ + if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len)) return 1; - } - - /* Dump packet - pu8=(u8 *)(sk->rbuf+5*4); - for(i=0;i<ntohs(ps->length);i+=4) - DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2], - pu8[i+3]); - DBG("%s: received size: %u\n",p->name,size); - */ - switch (ps->type) + switch (pkt->type) { case HELLO_P: - DBG("%s: Hello received.\n", p->name); - ospf_hello_receive(ps, ifa, n, sk->faddr); + ospf_receive_hello(pkt, ifa, n, sk->faddr); break; + case DBDES_P: - DBG("%s: Database description received.\n", p->name); - ospf_dbdes_receive(ps, ifa, n); + ospf_receive_dbdes(pkt, ifa, n); break; + case LSREQ_P: - DBG("%s: Link state request received.\n", p->name); - ospf_lsreq_receive(ps, ifa, n); + ospf_receive_lsreq(pkt, ifa, n); break; + case LSUPD_P: - DBG("%s: Link state update received.\n", p->name); - ospf_lsupd_receive(ps, ifa, n); + ospf_receive_lsupd(pkt, ifa, n); break; + case LSACK_P: - DBG("%s: Link state ack received.\n", p->name); - ospf_lsack_receive(ps, ifa, n); + ospf_receive_lsack(pkt, ifa, n); break; + default: - log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type); - return 1; + DROP("invalid packet type", pkt->type); }; return 1; + +drop: + LOG_PKT("Bad packet from %I via %s - %s (%u)", + sk->faddr, ifa->ifname, err_dsc, err_val); + + return 1; } /* @@ -508,7 +444,7 @@ void ospf_tx_hook(sock * sk) { struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); -// struct proto *p = (struct proto *) (ifa->oa->po); +// struct proto *p = (struct proto *) (ifa->oa->p); log(L_ERR "OSPF: TX hook called on %s", ifa->ifname); } */ @@ -517,16 +453,35 @@ void ospf_err_hook(sock * sk, int err) { struct ospf_iface *ifa= (struct ospf_iface *) (sk->data); - struct proto *p = &(ifa->oa->po->proto); - log(L_ERR "%s: Socket error on %s: %M", p->name, ifa->ifname, err); + struct ospf_proto *p = ifa->oa->po; + log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err); } void ospf_verr_hook(sock *sk, int err) { - struct proto_ospf *po = (struct proto_ospf *) (sk->data); - struct proto *p = &po->proto; - log(L_ERR "%s: Vlink socket error: %M", p->name, err); + struct ospf_proto *p = (struct ospf_proto *) (sk->data); + log(L_ERR "%s: Vlink socket error: %M", p->p.name, err); +} + +void +ospf_send_to(struct ospf_iface *ifa, ip_addr dst) +{ + sock *sk = ifa->sk; + struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; + int plen = ntohs(pkt->length); + + if (ospf_is_v2(ifa->oa->po)) + { + if (ifa->autype == OSPF_AUTH_CRYPT) + plen += OSPF_AUTH_CRYPT_SIZE; + + ospf_pkt_finalize(ifa, pkt); + } + + int done = sk_send_to(sk, plen, dst, 0); + if (!done) + log(L_WARN "OSPF: TX queue full on %s", ifa->ifname); } void @@ -542,28 +497,8 @@ ospf_send_to_agt(struct ospf_iface *ifa, u8 state) void ospf_send_to_bdr(struct ospf_iface *ifa) { - if (!ipa_equal(ifa->drip, IPA_NONE)) + if (ipa_nonzero(ifa->drip)) ospf_send_to(ifa, ifa->drip); - if (!ipa_equal(ifa->bdrip, IPA_NONE)) + if (ipa_nonzero(ifa->bdrip)) ospf_send_to(ifa, ifa->bdrip); } - -void -ospf_send_to(struct ospf_iface *ifa, ip_addr dst) -{ - sock *sk = ifa->sk; - struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf; - int len = ntohs(pkt->length); - -#ifdef OSPFv2 - if (ifa->autype == OSPF_AUTH_CRYPT) - len += OSPF_AUTH_CRYPT_SIZE; -#endif - - ospf_pkt_finalize(ifa, pkt); - - int done = sk_send_to(sk, len, dst, 0); - if (!done) - log(L_WARN "OSPF: TX queue full on %s", ifa->ifname); -} - |