diff options
Diffstat (limited to 'proto/ospf/packet.c')
-rw-r--r-- | proto/ospf/packet.c | 584 |
1 files changed, 285 insertions, 299 deletions
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 1240b05c..96351178 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,232 +15,215 @@ 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; + } + password_cpy(auth->password, passwd->password, sizeof(union ospf_auth)); - /* 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++; + + 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]; + password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE); - 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"); + 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) { - struct proto_ospf *po = ifa->oa->po; - struct proto *p = &po->proto; + struct ospf_proto *p = ifa->oa->po; + union ospf_auth *auth = (void *) (pkt + 1); struct password_item *pass = NULL, *ptmp; - void *tail; - char md5sum[OSPF_AUTH_CRYPT_SIZE]; char password[OSPF_AUTH_CRYPT_SIZE]; - struct MD5Context ctxt; + uint plen = ntohs(pkt->length); + u8 autype = pkt->autype; - if (pkt->autype != htons(ifa->autype)) + if (autype != ifa->autype) { - OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype)); + OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype); return 0; } - 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)); + case OSPF_AUTH_NONE: + return 1; - 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_SIMPLE: + pass = password_find(ifa->passwords, 1); + if (!pass) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found"); + return 0; + } - 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; - } + password_cpy(password, pass->password, sizeof(union ospf_auth)); + if (memcmp(auth->password, password, sizeof(union ospf_auth))) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords"); + return 0; + } + return 1; - tail = ((void *)pkt) + ntohs(pkt->length); + case OSPF_AUTH_CRYPT: + if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest"); + return 0; + } - 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; - } - } + if (plen + OSPF_AUTH_CRYPT_SIZE > size) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)", + plen + OSPF_AUTH_CRYPT_SIZE, size); + return 0; + } - if (!pass) + if (n) + { + u32 rcv_csn = ntohl(auth->md5.csn); + if(rcv_csn < n->csn) { - OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found"); - return 0; + OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn); + return 0; } - 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; - } + n->csn = rcv_csn; + } - 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)) + if (ifa->passwords) + { + WALK_LIST(ptmp, *(ifa->passwords)) { - OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest"); - return 0; + if (auth->md5.keyid != ptmp->id) continue; + if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue; + pass = ptmp; + break; } - return 1; - break; - default: - OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); + } + + if (!pass) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found"); return 0; - } -} + } -#else + void *tail = ((void *) pkt) + plen; + char md5sum[OSPF_AUTH_CRYPT_SIZE]; + password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE); -/* OSPFv3 authentication not yet supported */ + struct MD5Context ctxt; + MD5Init(&ctxt); + MD5Update(&ctxt, (char *) pkt, plen); + MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); + MD5Final(md5sum, &ctxt); -static inline void -ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) -{ } + if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE)) + { + OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest"); + return 0; + } + return 1; -static int -ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size) -{ return 1; } - -#endif + default: + OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); + return 0; + } +} /** @@ -266,43 +251,44 @@ 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; - 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 */ + 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; - /* 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 + /* Ignore my own broadcast packets */ + if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip)) + return 1; + } + else + { + /* 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); + } /* Second, we check packet size, checksum, and the protocol version */ - struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); + struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); - if (ps == NULL) + if (pkt == NULL) { log(L_ERR "%s%I - bad IP header", mesg, sk->faddr); return 1; @@ -314,13 +300,13 @@ ospf_rx_hook(sock *sk, int size) return 1; } - if ((unsigned) size < sizeof(struct ospf_packet)) + if ((uint) size < sizeof(struct ospf_packet)) { log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size); return 1; } - uint plen = ntohs(ps->length); + 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); @@ -348,89 +334,101 @@ ospf_rx_hook(sock *sk, int size) return 1; } - if (ps->version != OSPF_VERSION) + if (pkt->version != ospf_get_version(p)) { - log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version); + log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version); return 1; } -#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))) + if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) { - log(L_ERR "%s%I - bad checksum", mesg, sk->faddr); - return 1; - } -#endif + uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth); + uint blen = plen - hlen; + void *body = ((void *) pkt) + hlen; + if (! ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) + { + log(L_ERR "%s%I - bad checksum", mesg, sk->faddr); + return 1; + } + } /* 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) { + /* Matching area ID */ + + if (instance_id != ifa->instance_id) + return 1; + /* It is real iface, source should be local (in OSPFv2) */ -#ifdef OSPFv2 - if (!src_local) + if (ospf_is_v2(p) && !src_local) + { + log(L_ERR "%s%I - strange source address for %s", mesg, sk->faddr, ifa->ifname); 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; + goto found; } - else + else if ((areaid == 0) && !dst_mcast) { - /* Some vlink? */ - struct ospf_iface *iff = NULL; + /* Backbone area ID and possible vlink packet */ + + if ((p->areano == 1) || !oa_is_ext(ifa->oa)) + return 1; - WALK_LIST(iff, po->iface_list) + struct ospf_iface *iff = NULL; + WALK_LIST(iff, p->iface_list) { 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 */ + + if (instance_id != ifa->instance_id) + return 1; + + log(L_ERR "%s%I - area does not match (%R vs %R)", + mesg, sk->faddr, areaid, ifa->oa->areaid); return 1; } + 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) + if (rid == p->router_id) { log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr); return 1; @@ -442,62 +440,51 @@ ospf_rx_hook(sock *sk, int size) return 1; } -#ifdef OSPFv2 /* In OSPFv2, neighbors are identified by either IP or Router ID, base 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); return 1; } - if (!ospf_pkt_checkauth(n, ifa, ps, size)) + if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, size)) { log(L_ERR "%s%I - authentication failed", mesg, sk->faddr); 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); + log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type); return 1; }; return 1; @@ -508,7 +495,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 +504,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 +548,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); -} - |