From a7a7372aa7c527619ee527e3b37013f9fb87d618 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 18 Jul 2014 18:24:12 +0200 Subject: Temporary integrated OSPF commit. --- nest/locks.c | 10 ++++++---- nest/locks.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'nest') diff --git a/nest/locks.c b/nest/locks.c index 7044d6a9..c74f2f45 100644 --- a/nest/locks.c +++ b/nest/locks.c @@ -22,10 +22,11 @@ * or some other non-shareable resource, it asks the core to lock it and it doesn't * use the resource until it's notified that it has acquired the lock. * - * Object locks are represented by &object_lock structures which are in turn a kind of - * resource. Lockable resources are uniquely determined by resource type + * Object locks are represented by &object_lock structures which are in turn a + * kind of resource. Lockable resources are uniquely determined by resource type * (%OBJLOCK_UDP for a UDP port etc.), IP address (usually a broadcast or - * multicast address the port is bound to), port number and interface. + * multicast address the port is bound to), port number, interface and optional + * instance ID. */ #undef LOCAL_DEBUG @@ -45,6 +46,7 @@ olock_same(struct object_lock *x, struct object_lock *y) x->type == y->type && x->iface == y->iface && x->port == y->port && + x->inst == y->inst && ipa_equal(x->addr, y->addr); } @@ -88,7 +90,7 @@ olock_dump(resource *r) struct object_lock *l = (struct object_lock *) r; static char *olock_states[] = { "free", "locked", "waiting", "event" }; - debug("(%d:%s:%I:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->port, olock_states[l->state]); + debug("(%d:%s:%I:%d:%d) [%s]\n", l->type, (l->iface ? l->iface->name : "?"), l->addr, l->port, l->inst, olock_states[l->state]); if (!EMPTY_LIST(l->waiters)) debug(" [wanted]\n"); } diff --git a/nest/locks.h b/nest/locks.h index 892d3c6b..3d58c8ed 100644 --- a/nest/locks.h +++ b/nest/locks.h @@ -26,9 +26,10 @@ struct object_lock { resource r; ip_addr addr; /* Identification of a object: IP address */ - unsigned int type; /* ... object type (OBJLOCK_xxx) */ + uint type; /* ... object type (OBJLOCK_xxx) */ + uint port; /* ... port number */ + uint inst; /* ... instance ID */ struct iface *iface; /* ... interface */ - unsigned int port; /* ... port number */ void (*hook)(struct object_lock *); /* Called when the lock succeeds */ void *data; /* User data */ /* ... internal to lock manager, don't touch ... */ -- cgit v1.2.3 From f8fefde318c6248ad94e7b6d60155deed9ab8eed Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Fri, 24 Oct 2014 10:27:21 +0200 Subject: Refactoring of OSPF messages. --- nest/password.c | 15 +- nest/password.h | 9 +- proto/ospf/dbdes.c | 230 +++++++++++-------------- proto/ospf/hello.c | 78 ++++----- proto/ospf/iface.c | 71 ++++---- proto/ospf/lsack.c | 5 +- proto/ospf/lsreq.c | 12 +- proto/ospf/lsupd.c | 96 +++++------ proto/ospf/neighbor.c | 455 +++++++++++++++++++++++++------------------------- proto/ospf/ospf.c | 5 +- proto/ospf/ospf.h | 40 ++++- proto/ospf/packet.c | 213 +++++++++-------------- proto/ospf/rt.c | 8 +- proto/ospf/topology.c | 4 +- proto/rip/auth.c | 6 +- 15 files changed, 591 insertions(+), 656 deletions(-) (limited to 'nest') diff --git a/nest/password.c b/nest/password.c index 179939e2..21e42e0e 100644 --- a/nest/password.c +++ b/nest/password.c @@ -36,9 +36,18 @@ password_find(list *l, int first_fit) return pf; } -void password_cpy(char *dst, char *src, int size) +struct password_item * +password_find_by_id(list *l, int id) { - bzero(dst, size); - memcpy(dst, src, (strlen(src) < (unsigned) size ? strlen(src) : (unsigned) size)); + struct password_item *pi; + + if (!l) + return NULL; + + WALK_LIST(pi, *l) + if ((pi->id == id) && (pi->accfrom <= now_real) && (now_real < pi->accto)) + return pi; + + return NULL; } diff --git a/nest/password.h b/nest/password.h index 726af733..cd120d70 100644 --- a/nest/password.h +++ b/nest/password.h @@ -23,6 +23,13 @@ struct password_item { extern struct password_item *last_password_item; struct password_item *password_find(list *l, int first_fit); -void password_cpy(char *dst, char *src, int size); +struct password_item *password_find_by_id(list *l, int id); + +static inline int password_verify(struct password_item *p1, char *p2, uint size) +{ + char buf[size]; + strncpy(buf, p1->password, size); + return !memcmp(buf, p2, size); +} #endif diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index 2b076157..88c87164 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -98,7 +98,7 @@ ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt) static void -ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body) +ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) { struct ospf_iface *ifa = n->ifa; struct ospf_packet *pkt; @@ -106,6 +106,7 @@ ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body) u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu; + /* Update DBDES buffer */ if (n->ldd_bsize != ifa->tx_length) { mb_free(n->ldd_buffer); @@ -136,7 +137,8 @@ ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body) length = sizeof(struct ospf_dbdes3_packet); } - if (body && (n->myimms & DBDES_M)) + /* Prepare DBDES body */ + if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M)) { struct ospf_lsa_header *lsas; struct top_hash_entry *en; @@ -182,7 +184,7 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) struct ospf_iface *ifa = n->ifa; OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer, - "DBDES packet sent to %I via %s", n->ip, ifa->ifname); + "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname); sk_set_tbuf(ifa->sk, n->ldd_buffer); ospf_send_to(ifa, n->ip); sk_set_tbuf(ifa->sk, NULL); @@ -191,7 +193,6 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) /** * ospf_send_dbdes - transmit database description packet * @n: neighbor - * @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0) * * Sending of a database description packet is described in 10.8 of RFC 2328. * Reception of each packet is acknowledged in the sequence number of another. @@ -200,104 +201,78 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) * of the buffer. */ void -ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next) +ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) { /* RFC 2328 10.8 */ + ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE)); + if (n->ifa->oa->rt == NULL) return; - switch (n->state) - { - case NEIGHBOR_EXSTART: - n->myimms |= DBDES_I; - - /* Send empty packets */ - ospf_prepare_dbdes(p, n, 0); - ospf_do_send_dbdes(p, n); - break; - - case NEIGHBOR_EXCHANGE: - n->myimms &= ~DBDES_I; - - if (next) - ospf_prepare_dbdes(p, n, 1); - - /* Send prepared packet */ - ospf_do_send_dbdes(p, n); + ospf_prepare_dbdes(p, n); + ospf_do_send_dbdes(p, n); - /* Master should restart RXMT timer for each DBDES exchange */ - if (n->myimms & DBDES_MS) - tm_start(n->rxmt_timer, n->ifa->rxmtint); + if (n->state == NEIGHBOR_EXSTART) + return; - if (!(n->myimms & DBDES_MS)) - if (!(n->myimms & DBDES_M) && - !(n->imms & DBDES_M)) - ospf_neigh_sm(n, INM_EXDONE); - break; + /* Master should restart RXMT timer for each DBDES exchange */ + if (n->myimms & DBDES_MS) + tm_start(n->rxmt_timer, n->ifa->rxmtint); - case NEIGHBOR_LOADING: - case NEIGHBOR_FULL: + if (!(n->myimms & DBDES_MS)) + if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) + ospf_neigh_sm(n, INM_EXDONE); +} - if (!n->ldd_buffer) - { - OSPF_TRACE(D_PACKETS, "No DBDES packet for repeating"); - ospf_neigh_sm(n, INM_KILLNBR); - return; - } +void +ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n) +{ + ASSERT(n->state > NEIGHBOR_EXSTART); - /* Send last packet */ - ospf_do_send_dbdes(p, n); - break; + if (!n->ldd_buffer) + { + log(L_WARN "%s: No DBDES packet for retransmit", p->p.name); + ospf_neigh_sm(n, INM_SEQMIS); + return; } -} + /* Send last packet */ + ospf_do_send_dbdes(p, n); +} static int ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n) { struct ospf_iface *ifa = n->ifa; - struct ospf_lsa_header *lsas; + struct ospf_lsa_header *lsas, lsa; + struct top_hash_entry *en, *req; + const char *err_dsc = NULL; + u32 lsa_type, lsa_domain; uint i, lsa_count; ospf_dbdes_body(p, pkt, &lsas, &lsa_count); for (i = 0; i < lsa_count; i++) { - struct top_hash_entry *en, *req; - struct ospf_lsa_header lsa; - u32 lsa_type, lsa_domain; - lsa_ntoh_hdr(lsas + i, &lsa); lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); /* RFC 2328 10.6 and RFC 5340 4.2.2 */ if (!lsa_type) - { - log(L_WARN "%s: Bad DBDES from %I - LSA of unknown type", p->p.name, n->ip); - goto err; - } + DROP1("LSA of unknown type"); if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) - { - log(L_WARN "%s: Bad DBDES from %I - LSA with AS scope in stub area", p->p.name, n->ip); - goto err; - } + DROP1("LSA with AS scope in stub area"); /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) - { - log(L_WARN "%s: Bad DBDES from %I - rt-summary-LSA in stub area", p->p.name, n->ip); - goto err; - } + DROP1("rt-summary-LSA in stub area"); /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */ if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) - { - log(L_WARN "%s: Bad DBDES from %I - LSA with invalid scope", p->p.name, n->ip); - goto err; - } + DROP1("LSA with invalid scope"); en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER)) @@ -314,7 +289,10 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne return 0; - err: +drop: + LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt); + LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc); + ospf_neigh_sm(n, INM_SEQMIS); return -1; } @@ -324,21 +302,19 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n) { struct ospf_proto *p = ifa->oa->po; + const char *err_dsc = NULL; u32 rcv_ddseq, rcv_options; u16 rcv_iface_mtu; u8 rcv_imms; - uint plen; + uint plen, err_val = 0, err_seqmis = 0; /* RFC 2328 10.6 */ plen = ntohs(pkt->length); if (plen < ospf_dbdes_hdrlen(p)) - { - log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen); - return; - } + DROP("too short", plen); - OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from %I via %s", n->ip, ifa->ifname); + OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname); ospf_neigh_sm(n, INM_HELLOREC); @@ -364,6 +340,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, case NEIGHBOR_DOWN: case NEIGHBOR_ATTEMPT: case NEIGHBOR_2WAY: + OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart"); return; case NEIGHBOR_INIT: @@ -376,8 +353,8 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, (rcv_iface_mtu != ifa->iface->mtu) && (rcv_iface_mtu != 0) && (ifa->iface->mtu != 0)) - log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)", - n->ip, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu); + LOG_PKT_WARN("MTU mismatch with nbr %R on %s (remote %d, local %d)", + n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu); if ((rcv_imms == DBDES_IMMS) && (n->rid > p->router_id) && @@ -389,9 +366,8 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, n->options = rcv_options; n->myimms &= ~DBDES_MS; n->imms = rcv_imms; - OSPF_TRACE(D_PACKETS, "I'm slave to %I", n->ip); ospf_neigh_sm(n, INM_NEGDONE); - ospf_send_dbdes(p, n, 1); + ospf_send_dbdes(p, n); break; } @@ -404,7 +380,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, n->options = rcv_options; n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */ n->imms = rcv_imms; - OSPF_TRACE(D_PACKETS, "I'm master to %I", n->ip); ospf_neigh_sm(n, INM_NEGDONE); } else @@ -417,49 +392,29 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, if ((rcv_imms == n->imms) && (rcv_options == n->options) && (rcv_ddseq == n->ddr)) - { - /* Duplicate packet */ - OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip); - if (!(n->myimms & DBDES_MS)) - { - /* Slave should retransmit dbdes packet */ - ospf_send_dbdes(p, n, 0); - } - return; - } + goto duplicate; - if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) /* M/S bit differs */ - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip); - ospf_neigh_sm(n, INM_SEQMIS); - break; - } + /* Do INM_SEQMIS during packet error */ + err_seqmis = 1; - if (rcv_imms & DBDES_I) /* I bit is set */ - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip); - ospf_neigh_sm(n, INM_SEQMIS); - break; - } + if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) + DROP("MS-bit mismatch", rcv_imms); - if (rcv_options != n->options) /* Options differs */ - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip); - ospf_neigh_sm(n, INM_SEQMIS); - break; - } + if (rcv_imms & DBDES_I) + DROP("I-bit mismatch", rcv_imms); + + if (rcv_options != n->options) + DROP("options mismatch", rcv_options); n->ddr = rcv_ddseq; n->imms = rcv_imms; if (n->myimms & DBDES_MS) { - if (rcv_ddseq != n->dds) /* MASTER */ - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip); - ospf_neigh_sm(n, INM_SEQMIS); - break; - } + /* MASTER */ + + if (rcv_ddseq != n->dds) + DROP("DD sequence number mismatch", rcv_ddseq); n->dds++; @@ -469,16 +424,14 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M)) ospf_neigh_sm(n, INM_EXDONE); else - ospf_send_dbdes(p, n, 1); + ospf_send_dbdes(p, n); } else { - if (rcv_ddseq != (n->dds + 1)) /* SLAVE */ - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip); - ospf_neigh_sm(n, INM_SEQMIS); - break; - } + /* SLAVE */ + + if (rcv_ddseq != (n->dds + 1)) + DROP("DD sequence number mismatch", rcv_ddseq); n->ddr = rcv_ddseq; n->dds = rcv_ddseq; @@ -486,7 +439,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, if (ospf_process_dbdes(p, pkt, n) < 0) return; - ospf_send_dbdes(p, n, 1); + ospf_send_dbdes(p, n); } break; @@ -495,25 +448,30 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, if ((rcv_imms == n->imms) && (rcv_options == n->options) && (rcv_ddseq == n->ddr)) - { - /* Duplicate packet */ - OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip); - if (!(n->myimms & DBDES_MS)) - { - /* Slave should retransmit dbdes packet */ - ospf_send_dbdes(p, n, 0); - } - return; - } - else - { - OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)", n->ip); - DBG("PS=%u, DDR=%u, DDS=%u\n", rcv_ddseq, n->ddr, n->dds); - ospf_neigh_sm(n, INM_SEQMIS); - } - break; + goto duplicate; + + err_seqmis = 1; + + DROP("too late for DD exchange", n->state); default: - bug("Received dbdes from %I in undefined state.", n->ip); + bug("Undefined interface state"); } + return; + +duplicate: + OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate"); + + /* Slave should retransmit DBDES packet */ + if (!(n->myimms & DBDES_MS)) + ospf_rxmt_dbdes(p, n); + return; + +drop: + LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", + n->rid, ifa->ifname, err_dsc, err_val); + + if (err_seqmis) + ospf_neigh_sm(n, INM_SEQMIS); + return; } diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 3aeb9f9a..e8b1c702 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -114,7 +114,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn) { if (i == max) { - log(L_WARN "%s: Too many neighbors on interface %s", p->p.name, ifa->ifname); + log(L_WARN "%s: Too many neighbors on %s", p->p.name, ifa->ifname); break; } neighbors[i] = htonl(neigh->rid); @@ -188,16 +188,21 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr) { struct ospf_proto *p = ifa->oa->po; - char *beg = "OSPF: Bad HELLO packet from "; + const char *err_dsc = NULL; u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr; u8 rcv_options, rcv_priority; u32 *neighbors; u32 neigh_count; - uint plen, i; + uint plen, i, err_val = 0; /* RFC 2328 10.5 */ - OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s", faddr, ifa->ifname); + /* + * We may not yet havethe associate neighbor, so we use Router ID from the + * packet instead of one from the neighbor structure for log messages. + */ + u32 rcv_rid = ntohl(pkt->routerid); + OSPF_TRACE(D_PACKETS, "HELLO packet received from nbr %R on %s", rcv_rid, ifa->ifname); plen = ntohs(pkt->length); @@ -206,10 +211,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_hello2_packet *ps = (void *) pkt; if (plen < sizeof(struct ospf_hello2_packet)) - { - log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen); - return; - } + DROP("too short", plen); rcv_iface_id = 0; rcv_helloint = ntohs(ps->helloint); @@ -223,10 +225,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, if ((ifa->type != OSPF_IT_VLINK) && (ifa->type != OSPF_IT_PTP) && (pxlen != ifa->addr->pxlen)) - { - log(L_ERR "%s%I - prefix length mismatch (%d)", beg, faddr, pxlen); - return; - } + DROP("prefix length mismatch", pxlen); neighbors = ps->neighbors; neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32); @@ -236,10 +235,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_hello3_packet *ps = (void *) pkt; if (plen < sizeof(struct ospf_hello3_packet)) - { - log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen); - return; - } + DROP("too short", plen); rcv_iface_id = ntohl(ps->iface_id); rcv_helloint = ntohs(ps->helloint); @@ -254,23 +250,14 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, } if (rcv_helloint != ifa->helloint) - { - log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, rcv_helloint); - return; - } + DROP("hello interval mismatch", rcv_helloint); if (rcv_deadint != ifa->deadint) - { - log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, rcv_deadint); - return; - } + DROP("dead interval mismatch", rcv_deadint); /* Check whether bits E, N match */ if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N)) - { - log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, rcv_options); - return; - } + DROP("area type mismatch", rcv_options); /* Check consistency of existing neighbor entry */ if (n) @@ -279,11 +266,11 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) { /* Neighbor identified by IP address; Router ID may change */ - if (n->rid != ntohl(pkt->routerid)) + if (n->rid != rcv_rid) { - OSPF_TRACE(D_EVENTS, "Neighbor %I has changed Router ID from %R to %R", - n->ip, n->rid, ntohl(pkt->routerid)); - ospf_neigh_remove(n); + OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R", + n->rid, ifa->ifname, rcv_rid); + ospf_neigh_sm(n, INM_KILLNBR); n = NULL; } } @@ -292,7 +279,8 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, /* Neighbor identified by Router ID; IP address may change */ if (!ipa_equal(faddr, n->ip)) { - OSPF_TRACE(D_EVENTS, "Neighbor address changed from %I to %I", n->ip, faddr); + OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed IP address to %I", + n->rid, ifa->ifname, n->ip, faddr); n->ip = faddr; } } @@ -305,28 +293,26 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct nbma_node *nn = find_nbma_node(ifa, faddr); if (!nn && ifa->strictnbma) - { - log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname); - return; - } + DROP1("new neighbor denied"); if (nn && (ifa->type == OSPF_IT_NBMA) && (((rcv_priority == 0) && nn->eligible) || ((rcv_priority > 0) && !nn->eligible))) - { - log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname); - return; - } + DROP("eligibility mismatch", rcv_priority); if (nn) nn->found = 1; } + // XXXX format + // "ospf1: New neighbor found: 192.168.1.1/fe80:1234:1234:1234:1234 on eth0"; + // "ospf1: New neighbor found: 192.168.1.1 on eth0 at fe80:1234:1234:1234:1234"; + // "ospf1: Neighbor 192.168.1.1 on eth0 found, IP adress fe80:1234:1234:1234:1234"; OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname); n = ospf_neighbor_new(ifa); - n->rid = ntohl(pkt->routerid); + n->rid = rcv_rid; n->ip = faddr; n->dr = rcv_dr; n->bdr = rcv_bdr; @@ -367,7 +353,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, ospf_neigh_sm(n, INM_1WAYREC); return; - found_self: +found_self: ospf_neigh_sm(n, INM_2WAYREC); @@ -400,4 +386,10 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, ((n->bdr != n_id) && (old_bdr == n_id))) ospf_iface_sm(ifa, ISM_NEICH); } + + return; + +drop: + LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)", + rcv_rid, ifa->ifname, err_dsc, err_val); } diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 892e8a77..e14f09cb 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -11,15 +11,16 @@ #include "ospf.h" -char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother", - "backup", "dr" +const char *ospf_is_names[] = { + "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR" }; -char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen", - "neighbor change", "loop indicated", "unloop indicated", "interface down" +const char *ospf_ism_names[] = { + "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange", + "LoopInd", "UnloopInd", "InterfaceDown" }; -char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" }; +const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" }; static void @@ -40,7 +41,7 @@ wait_timer_hook(timer * timer) struct ospf_iface *ifa = (struct ospf_iface *) timer->data; struct ospf_proto *p = ifa->oa->po; - OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s", ifa->ifname); + OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname); ospf_iface_sm(ifa, ISM_WAITF); } @@ -240,10 +241,7 @@ ospf_iface_down(struct ospf_iface *ifa) } WALK_LIST_DELSAFE(n, nx, ifa->neigh_list) - { - OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); - ospf_neigh_remove(n); - } + ospf_neigh_sm(n, INM_KILLNBR); if (ifa->hello_timer) tm_stop(ifa->hello_timer); @@ -311,8 +309,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) if (state == oldstate) return; - OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s", - ifa->ifname, ospf_is[oldstate], ospf_is[state]); + OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s", + ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]); ifa->state = state; @@ -351,7 +349,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) void ospf_iface_sm(struct ospf_iface *ifa, int event) { - DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism[event]); + DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]); switch (event) { @@ -613,7 +611,8 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i continue; if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) - log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip); + log(L_WARN "%s: Configured neighbor address (%I) should be link-local", + p->p.name, nb->ip); add_nbma_node(ifa, nb, 0); } @@ -726,7 +725,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* HELLO TIMER */ if (ifa->helloint != new->helloint) { - OSPF_TRACE(D_EVENTS, "Changing hello interval on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d", ifname, ifa->helloint, new->helloint); ifa->helloint = new->helloint; @@ -736,7 +735,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* RXMT TIMER */ if (ifa->rxmtint != new->rxmtint) { - OSPF_TRACE(D_EVENTS, "Changing retransmit interval on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d", ifname, ifa->rxmtint, new->rxmtint); ifa->rxmtint = new->rxmtint; @@ -745,7 +744,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* POLL TIMER */ if (ifa->pollint != new->pollint) { - OSPF_TRACE(D_EVENTS, "Changing poll interval on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d", ifname, ifa->pollint, new->pollint); ifa->pollint = new->pollint; @@ -755,7 +754,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* WAIT TIMER */ if (ifa->waitint != new->waitint) { - OSPF_TRACE(D_EVENTS, "Changing wait interval on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d", ifname, ifa->waitint, new->waitint); ifa->waitint = new->waitint; @@ -766,7 +765,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* DEAD TIMER */ if (ifa->deadint != new->deadint) { - OSPF_TRACE(D_EVENTS, "Changing dead interval on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d", ifname, ifa->deadint, new->deadint); ifa->deadint = new->deadint; } @@ -774,7 +773,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* INFTRANS */ if (ifa->inftransdelay != new->inftransdelay) { - OSPF_TRACE(D_EVENTS, "Changing transmit delay on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d", ifname, ifa->inftransdelay, new->inftransdelay); ifa->inftransdelay = new->inftransdelay; } @@ -782,7 +781,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* AUTHENTICATION */ if (ifa->autype != new->autype) { - OSPF_TRACE(D_EVENTS, "Changing authentication type on interface %s", ifname); + OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname); ifa->autype = new->autype; } @@ -797,7 +796,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* COST */ if (ifa->cost != new->cost) { - OSPF_TRACE(D_EVENTS, "Changing cost on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d", ifname, ifa->cost, new->cost); ifa->cost = new->cost; @@ -806,7 +805,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* PRIORITY */ if (ifa->priority != new->priority) { - OSPF_TRACE(D_EVENTS, "Changing priority on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d", ifname, ifa->priority, new->priority); ifa->priority = new->priority; @@ -816,7 +815,8 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* STRICT NBMA */ if (ifa->strictnbma != new->strictnbma) { - OSPF_TRACE(D_EVENTS, "Changing NBMA strictness on interface %s", ifname); + OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d", + ifname, ifa->strictnbma, new->strictnbma); ifa->strictnbma = new->strictnbma; } @@ -830,14 +830,14 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) { if (nb->eligible != nb2->eligible) { - OSPF_TRACE(D_EVENTS, "Changing eligibility of neighbor %I on interface %s", + OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s", nb->ip, ifname); nb->eligible = nb2->eligible; } } else { - OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on interface %s", + OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s", nb->ip, ifname); rem_node(NODE nb); mb_free(nb); @@ -852,11 +852,12 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) continue; if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) - log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip); + log(L_WARN "%s: Configured neighbor address (%I) should be link-local", + p->p.name, nb->ip); if (! find_nbma_node(ifa, nb->ip)) { - OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on interface %s", + OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s", nb->ip, ifname); add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip)); } @@ -867,7 +868,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* TX LENGTH */ if (old->tx_length != new->tx_length) { - OSPF_TRACE(D_EVENTS, "Changing TX length on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d", ifname, old->tx_length, new->tx_length); /* ifa cannot be vlink */ @@ -878,7 +879,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* RX BUFFER */ if (old->rx_buffer != new->rx_buffer) { - OSPF_TRACE(D_EVENTS, "Changing buffer size on interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d", ifname, old->rx_buffer, new->rx_buffer); /* ifa cannot be vlink */ @@ -896,7 +897,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* LINK */ if (ifa->check_link != new->check_link) { - OSPF_TRACE(D_EVENTS, "%s link check on interface %s", + OSPF_TRACE(D_EVENTS, "%s link check for %s", new->check_link ? "Enabling" : "Disabling", ifname); ifa->check_link = new->check_link; @@ -908,7 +909,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* ECMP weight */ if (ifa->ecmp_weight != new->ecmp_weight) { - OSPF_TRACE(D_EVENTS, "Changing ECMP weight of interface %s from %d to %d", + OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d", ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1); ifa->ecmp_weight = new->ecmp_weight; } @@ -927,7 +928,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new) /* BFD */ if (ifa->bfd != new->bfd) { - OSPF_TRACE(D_EVENTS, "%s BFD on interface %s", + OSPF_TRACE(D_EVENTS, "%s BFD for %s", new->bfd ? "Enabling" : "Disabling", ifname); ifa->bfd = new->bfd; @@ -1197,7 +1198,7 @@ ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa) { /* ifa is not vlink */ - OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->ifname); + OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d", ifa->iface->mtu); ifa->tx_length = ifa_tx_length(ifa); @@ -1285,7 +1286,7 @@ ospf_iface_info(struct ospf_iface *ifa) cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more); cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); } - cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : ""); + cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : ""); cli_msg(-1015, "\tPriority: %u", ifa->priority); cli_msg(-1015, "\tCost: %u", ifa->cost); if (ifa->oa->po->ecmp) diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c index 5cac3f69..e590817e 100644 --- a/proto/ospf/lsack.c +++ b/proto/ospf/lsack.c @@ -140,10 +140,13 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa, /* No need to check length, lsack has only basic header */ - OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from %I via %s", n->ip, ifa->ifname); + OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from nbr %R on %s", n->rid, ifa->ifname); if (n->state < NEIGHBOR_EXCHANGE) + { + OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange"); return; + } ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c index a6c0cf24..067ad79b 100644 --- a/proto/ospf/lsreq.c +++ b/proto/ospf/lsreq.c @@ -93,7 +93,7 @@ ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n) length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header); pkt->length = htons(length); - OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to %I via %s", n->ip, ifa->ifname); + OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to nbr %R on %s", n->rid, ifa->ifname); ospf_send_to(ifa, n->ip); } @@ -110,10 +110,13 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa, /* No need to check length, lsreq has only basic header */ - OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet received from %I via %s", n->ip, ifa->ifname); + OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet received from nbr %R on %s", n->rid, ifa->ifname); if (n->state < NEIGHBOR_EXCHANGE) + { + OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange"); return; + } ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ @@ -134,8 +137,9 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa, en = ospf_hash_find(p->gr, domain, id, rt, type); if (!en) { - log(L_WARN "%s: Received LSREQ from %I for missing LSA (Type: %04x, Id: %R, Rt: %R)", - p->p.name, n->ip, type, id, rt); + LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt); + LOG_LSA2(" received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname); + ospf_neigh_sm(n, INM_BADLSREQ); return; } diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 13ae54d1..0aa45f6a 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -338,7 +338,7 @@ ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa { i++; continue; } OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), - "LSUPD packet sent to %I via %s", n->ip, ifa->ifname); + "LSUPD packet sent to nbr %R on %s", n->rid, ifa->ifname); ospf_send_to(ifa, n->ip); } @@ -396,24 +396,22 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n) { struct ospf_proto *p = ifa->oa->po; - - /* RFC 2328 13. */ - + const char *err_dsc = NULL; + uint plen, err_val = 0; int skip_lsreq = 0; n->want_lsreq = 0; - uint plen = ntohs(pkt->length); + /* RFC 2328 13. */ + + plen = ntohs(pkt->length); if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header))) - { - log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen); - return; - } + DROP("too short", plen); - OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->ifname); + OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname); if (n->state < NEIGHBOR_EXCHANGE) { - OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", n->ip); + OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange"); return; } @@ -429,33 +427,18 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, u32 lsa_len, lsa_type, lsa_domain; if (offset > bound) - { - log(L_WARN "%s: Received LSUPD from %I is too short", p->p.name, n->ip); - ospf_neigh_sm(n, INM_BADLSREQ); - return; - } + DROP("too short", plen); /* LSA header in network order */ lsa_n = ((void *) pkt) + offset; lsa_len = ntohs(lsa_n->length); offset += lsa_len; - if ((offset > plen) || ((lsa_len % 4) != 0) || - (lsa_len <= sizeof(struct ospf_lsa_header))) - { - log(L_WARN "%s: Received LSA from %I with bad length", p->p.name, n->ip); - ospf_neigh_sm(n, INM_BADLSREQ); - return; - } + if (offset > plen) + DROP("too short", plen); - /* RFC 2328 13. (1) - validate LSA checksum */ - u16 chsum = lsa_n->checksum; - if (chsum != lsasum_check(lsa_n, NULL)) - { - log(L_WARN "%s: Received LSA from %I with bad checksum: %x %x", - p->p.name, n->ip, chsum, lsa_n->checksum); - continue; - } + if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header))) + DROP("invalid LSA length", lsa_len); /* LSA header in host order */ lsa_ntoh_hdr(lsa_n, &lsa); @@ -464,33 +447,25 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n", lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum); + /* RFC 2328 13. (1) - validate LSA checksum */ + if (lsa_n->checksum != lsasum_check(lsa_n, NULL)) + SKIP("invalid checksum"); + /* RFC 2328 13. (2) */ if (!lsa_type) - { - log(L_WARN "%s: Received unknown LSA type from %I", p->p.name, n->ip); - continue; - } + SKIP("unknown type"); /* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */ if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) - { - log(L_WARN "%s: Received LSA with AS scope in stub area from %I", p->p.name, n->ip); - continue; - } + SKIP("AS scope in stub area"); /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) - { - log(L_WARN "%s: Received rt-summary-LSA in stub area from %I", p->p.name, n->ip); - continue; - } + SKIP("rt-summary-LSA in stub area"); /* RFC 5340 4.5.1 (3) */ if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) - { - log(L_WARN "%s: Received LSA with invalid scope from %I", p->p.name, n->ip); - continue; - } + SKIP("invalid scope"); /* Find local copy of LSA in link state database */ en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); @@ -528,9 +503,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, if (lsa_validate(&lsa, lsa_type, ospf_is_v2(p), body) == 0) { - log(L_WARN "%s: Received invalid LSA from %I", p->p.name, n->ip); mb_free(body); - continue; + SKIP("invalid body"); } /* 13. (5f) - handle self-originated LSAs, see also 13.4. */ @@ -542,8 +516,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, continue; } - /* 13. (5c) - remove old LSA from all retransmission lists */ - /* + /* 13. (5c) - remove old LSA from all retransmission lists + * * We only need to remove it from the retransmission list of the neighbor * that send us the new LSA. The old LSA is automatically replaced in * retransmission lists by the new LSA. @@ -561,8 +535,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, WALK_LIST(ifi, p->iface_list) WALK_LIST(ni, ifi->neigh_list) - if (ni->state > NEIGHBOR_EXSTART) - ospf_lsa_lsrt_down(en, ni); + if (ni->state > NEIGHBOR_EXSTART) + ospf_lsa_lsrt_down(en, ni); #endif /* 13. (5d) - install new LSA into database */ @@ -615,7 +589,13 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, /* Send newer local copy back to neighbor */ /* FIXME - check for MinLSArrival ? */ ospf_send_lsupd(p, &en, 1, n); + + continue; } + + skip: + LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt); + LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc); } /* Send direct LSACKs */ @@ -630,4 +610,14 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa, */ if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq) ospf_send_lsreq(p, n); + + return; + +drop: + LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", + n->rid, ifa->ifname, err_dsc, err_val); + + // XXXX realy? + ospf_neigh_sm(n, INM_SEQMIS); + return; } diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index ee1e8d0f..c75b1b93 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -10,24 +10,19 @@ #include "ospf.h" -char *ospf_ns[] = { " down", - " attempt", - " init", - " 2way", - " exstart", - "exchange", - " loading", - " full" + +const char *ospf_ns_names[] = { + "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full" }; -const char *ospf_inm[] = - { "hello received", "neighbor start", "2-way received", - "negotiation done", "exstart done", "bad ls request", "load done", - "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor", - "inactivity timer", "line down" +const char *ospf_inm_names[] = { + "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone", + "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived", + "KillNbr", "InactivityTimer", "LLDown" }; -static void neigh_chstate(struct ospf_neighbor *n, u8 state); + +static int can_do_adj(struct ospf_neighbor *n); static void neighbor_timer_hook(timer * timer); static void rxmt_timer_hook(timer * timer); static void ackd_timer_hook(timer * t); @@ -113,8 +108,29 @@ ospf_neighbor_new(struct ospf_iface *ifa) return (n); } +static void +ospf_neigh_down(struct ospf_neighbor *n) +{ + struct ospf_iface *ifa = n->ifa; + struct ospf_proto *p = ifa->oa->po; + + if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)) + { + struct nbma_node *nn = find_nbma_node(ifa, n->ip); + if (nn) + nn->found = 0; + } + + s_get(&(n->dbsi)); + release_lsrtl(p, n); + rem_node(NODE n); + rfree(n->pool); + + OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", n->rid, ifa->ifname); +} + /** - * neigh_chstate - handles changes related to new or lod state of neighbor + * ospf_neigh_chstate - handles changes related to new or lod state of neighbor * @n: OSPF neighbor * @state: new state * @@ -122,7 +138,7 @@ ospf_neighbor_new(struct ospf_iface *ifa) * starts rxmt timers, call interface state machine etc. */ static void -neigh_chstate(struct ospf_neighbor *n, u8 state) +ospf_neigh_chstate(struct ospf_neighbor *n, u8 state) { struct ospf_iface *ifa = n->ifa; struct ospf_proto *p = ifa->oa->po; @@ -132,16 +148,11 @@ neigh_chstate(struct ospf_neighbor *n, u8 state) if (state == old_state) return; - OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from %s to %s", - n->ip, ospf_ns[old_state], ospf_ns[state]); + OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s", + n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]); n->state = state; - if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY)) - ospf_iface_sm(ifa, ISM_NEICH); - if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY)) - ospf_iface_sm(ifa, ISM_NEICH); - /* Increase number of partial adjacencies */ if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING)) p->padj++; @@ -181,145 +192,12 @@ neigh_chstate(struct ospf_neighbor *n, u8 state) if (state > NEIGHBOR_EXSTART) n->myimms &= ~DBDES_I; -} -static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n) -{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; } - -static struct ospf_neighbor * -elect_bdr(struct ospf_proto *p, list nl) -{ - struct ospf_neighbor *neigh, *n1, *n2; - u32 nid; - - n1 = NULL; - n2 = NULL; - WALK_LIST(neigh, nl) /* First try those decl. themselves */ - { - nid = neigh_get_id(p, neigh); - - if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */ - if (neigh->priority > 0) /* Eligible */ - if (neigh->dr != nid) /* And not decl. itself DR */ - { - if (neigh->bdr == nid) /* Declaring BDR */ - { - if (n1 != NULL) - { - if (neigh->priority > n1->priority) - n1 = neigh; - else if (neigh->priority == n1->priority) - if (neigh->rid > n1->rid) - n1 = neigh; - } - else - { - n1 = neigh; - } - } - else /* And NOT declaring BDR */ - { - if (n2 != NULL) - { - if (neigh->priority > n2->priority) - n2 = neigh; - else if (neigh->priority == n2->priority) - if (neigh->rid > n2->rid) - n2 = neigh; - } - else - { - n2 = neigh; - } - } - } - } - if (n1 == NULL) - n1 = n2; - - return (n1); -} - -static struct ospf_neighbor * -elect_dr(struct ospf_proto *p, list nl) -{ - struct ospf_neighbor *neigh, *n; - u32 nid; - - n = NULL; - WALK_LIST(neigh, nl) /* And now DR */ - { - nid = neigh_get_id(p, neigh); - - if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */ - if (neigh->priority > 0) /* Eligible */ - if (neigh->dr == nid) /* And declaring itself DR */ - { - if (n != NULL) - { - if (neigh->priority > n->priority) - n = neigh; - else if (neigh->priority == n->priority) - if (neigh->rid > n->rid) - n = neigh; - } - else - { - n = neigh; - } - } - } - - return (n); -} - -static int -can_do_adj(struct ospf_neighbor *n) -{ - struct ospf_iface *ifa = n->ifa; - struct ospf_proto *p = ifa->oa->po; - int i = 0; - - switch (ifa->type) - { - case OSPF_IT_PTP: - case OSPF_IT_PTMP: - case OSPF_IT_VLINK: - i = 1; - break; - case OSPF_IT_BCAST: - case OSPF_IT_NBMA: - switch (ifa->state) - { - case OSPF_IS_DOWN: - case OSPF_IS_LOOP: - bug("%s: Iface %s in down state?", p->p.name, ifa->ifname); - break; - case OSPF_IS_WAITING: - DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname); - break; - case OSPF_IS_DROTHER: - if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid)) - && (n->state >= NEIGHBOR_2WAY)) - i = 1; - break; - case OSPF_IS_PTP: - case OSPF_IS_BACKUP: - case OSPF_IS_DR: - if (n->state >= NEIGHBOR_2WAY) - i = 1; - break; - default: - bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname); - break; - } - break; - default: - bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname); - break; - } - DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i); - return i; + /* Generate NeighborChange event if needed, see RFC 2328 9.2 */ + if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY)) + ospf_iface_sm(ifa, ISM_NEICH); + if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY)) + ospf_iface_sm(ifa, ISM_NEICH); } /** @@ -339,20 +217,19 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) { struct ospf_proto *p = n->ifa->oa->po; - DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip, - ospf_inm[event]); + DBG("Neighbor state machine for %R on %s, event %s\n", + n->rid, n->ifa->ifname, ospf_inm_names[event]); switch (event) { case INM_START: - neigh_chstate(n, NEIGHBOR_ATTEMPT); + ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT); /* NBMA are used different way */ break; case INM_HELLOREC: - if ((n->state == NEIGHBOR_DOWN) || - (n->state == NEIGHBOR_ATTEMPT)) - neigh_chstate(n, NEIGHBOR_INIT); + if (n->state < NEIGHBOR_INIT) + ospf_neigh_chstate(n, NEIGHBOR_INIT); /* Restart inactivity timer */ tm_start(n->inactim, n->ifa->deadint); @@ -360,15 +237,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) case INM_2WAYREC: if (n->state < NEIGHBOR_2WAY) - neigh_chstate(n, NEIGHBOR_2WAY); + ospf_neigh_chstate(n, NEIGHBOR_2WAY); if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n)) - neigh_chstate(n, NEIGHBOR_EXSTART); + ospf_neigh_chstate(n, NEIGHBOR_EXSTART); break; case INM_NEGDONE: if (n->state == NEIGHBOR_EXSTART) { - neigh_chstate(n, NEIGHBOR_EXCHANGE); + ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE); /* Reset DB summary list iterator */ s_get(&(n->dbsi)); @@ -385,11 +262,11 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) break; case INM_EXDONE: - neigh_chstate(n, NEIGHBOR_LOADING); + ospf_neigh_chstate(n, NEIGHBOR_LOADING); break; case INM_LOADDONE: - neigh_chstate(n, NEIGHBOR_FULL); + ospf_neigh_chstate(n, NEIGHBOR_FULL); break; case INM_ADJOK: @@ -399,15 +276,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) /* Can In build adjacency? */ if (can_do_adj(n)) { - neigh_chstate(n, NEIGHBOR_EXSTART); + ospf_neigh_chstate(n, NEIGHBOR_EXSTART); } break; default: if (n->state >= NEIGHBOR_EXSTART) if (!can_do_adj(n)) { - reset_lists(p,n); - neigh_chstate(n, NEIGHBOR_2WAY); + reset_lists(p, n); + ospf_neigh_chstate(n, NEIGHBOR_2WAY); } break; } @@ -418,20 +295,21 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) if (n->state >= NEIGHBOR_EXCHANGE) { reset_lists(p, n); - neigh_chstate(n, NEIGHBOR_EXSTART); + ospf_neigh_chstate(n, NEIGHBOR_EXSTART); } break; case INM_KILLNBR: case INM_LLDOWN: case INM_INACTTIM: - reset_lists(p, n); - neigh_chstate(n, NEIGHBOR_DOWN); + /* No need for reset_lists() */ + ospf_neigh_chstate(n, NEIGHBOR_DOWN); + ospf_neigh_down(n); break; case INM_1WAYREC: reset_lists(p, n); - neigh_chstate(n, NEIGHBOR_INIT); + ospf_neigh_chstate(n, NEIGHBOR_INIT); break; default: @@ -440,14 +318,156 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event) } } +static int +can_do_adj(struct ospf_neighbor *n) +{ + struct ospf_iface *ifa = n->ifa; + struct ospf_proto *p = ifa->oa->po; + int i = 0; + + switch (ifa->type) + { + case OSPF_IT_PTP: + case OSPF_IT_PTMP: + case OSPF_IT_VLINK: + i = 1; + break; + case OSPF_IT_BCAST: + case OSPF_IT_NBMA: + switch (ifa->state) + { + case OSPF_IS_DOWN: + case OSPF_IS_LOOP: + bug("%s: Iface %s in down state?", p->p.name, ifa->ifname); + break; + case OSPF_IS_WAITING: + DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname); + break; + case OSPF_IS_DROTHER: + if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid)) + && (n->state >= NEIGHBOR_2WAY)) + i = 1; + break; + case OSPF_IS_PTP: + case OSPF_IS_BACKUP: + case OSPF_IS_DR: + if (n->state >= NEIGHBOR_2WAY) + i = 1; + break; + default: + bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname); + break; + } + break; + default: + bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname); + break; + } + DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i); + return i; +} + + +static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n) +{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; } + +static struct ospf_neighbor * +elect_bdr(struct ospf_proto *p, list nl) +{ + struct ospf_neighbor *neigh, *n1, *n2; + u32 nid; + + n1 = NULL; + n2 = NULL; + WALK_LIST(neigh, nl) /* First try those decl. themselves */ + { + nid = neigh_get_id(p, neigh); + + if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */ + if (neigh->priority > 0) /* Eligible */ + if (neigh->dr != nid) /* And not decl. itself DR */ + { + if (neigh->bdr == nid) /* Declaring BDR */ + { + if (n1 != NULL) + { + if (neigh->priority > n1->priority) + n1 = neigh; + else if (neigh->priority == n1->priority) + if (neigh->rid > n1->rid) + n1 = neigh; + } + else + { + n1 = neigh; + } + } + else /* And NOT declaring BDR */ + { + if (n2 != NULL) + { + if (neigh->priority > n2->priority) + n2 = neigh; + else if (neigh->priority == n2->priority) + if (neigh->rid > n2->rid) + n2 = neigh; + } + else + { + n2 = neigh; + } + } + } + } + if (n1 == NULL) + n1 = n2; + + return (n1); +} + +static struct ospf_neighbor * +elect_dr(struct ospf_proto *p, list nl) +{ + struct ospf_neighbor *neigh, *n; + u32 nid; + + n = NULL; + WALK_LIST(neigh, nl) /* And now DR */ + { + nid = neigh_get_id(p, neigh); + + if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */ + if (neigh->priority > 0) /* Eligible */ + if (neigh->dr == nid) /* And declaring itself DR */ + { + if (n != NULL) + { + if (neigh->priority > n->priority) + n = neigh; + else if (neigh->priority == n->priority) + if (neigh->rid > n->rid) + n = neigh; + } + else + { + n = neigh; + } + } + } + + return (n); +} + /** * ospf_dr_election - (Backup) Designed Router election * @ifa: actual interface * * When the wait timer fires, it is time to elect (Backup) Designated Router. - * Structure describing me is added to this list so every electing router - * has the same list. Backup Designated Router is elected before Designated - * Router. This process is described in 9.4 of RFC 2328. + * Structure describing me is added to this list so every electing router has + * the same list. Backup Designated Router is elected before Designated + * Router. This process is described in 9.4 of RFC 2328. The function is + * supposed to be called only from ospf_iface_sm() as a part of the interface + * state machine. */ void ospf_dr_election(struct ospf_iface *ifa) @@ -506,6 +526,7 @@ ospf_dr_election(struct ospf_iface *ifa) DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid); + /* We are part of the interface state machine */ if (ifa->drid == myid) ospf_iface_chstate(ifa, OSPF_IS_DR); else if (ifa->bdrid == myid) @@ -544,39 +565,15 @@ find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip) return NULL; } -/* Neighbor is inactive for a long time. Remove it. */ static void neighbor_timer_hook(timer * timer) { struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data; - struct ospf_iface *ifa = n->ifa; - struct ospf_proto *p = ifa->oa->po; - - OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I", - ifa->ifname, n->ip); - ospf_neigh_remove(n); -} - -void -ospf_neigh_remove(struct ospf_neighbor *n) -{ - struct ospf_iface *ifa = n->ifa; - struct ospf_proto *p = ifa->oa->po; - - if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP)) - { - struct nbma_node *nn = find_nbma_node(ifa, n->ip); - if (nn) - nn->found = 0; - } - - neigh_chstate(n, NEIGHBOR_DOWN); + struct ospf_proto *p = n->ifa->oa->po; - s_get(&(n->dbsi)); - release_lsrtl(p, n); - rem_node(NODE n); - rfree(n->pool); - OSPF_TRACE(D_EVENTS, "Deleting neigbor %R", n->rid); + OSPF_TRACE(D_EVENTS, "Inactivity timer expired for neighbor %R on %s", + n->rid, n->ifa->ifname); + ospf_neigh_sm(n, INM_INACTTIM); } static void @@ -587,8 +584,9 @@ ospf_neigh_bfd_hook(struct bfd_request *req) if (req->down) { - OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s", n->ip, n->ifa->ifname); - ospf_neigh_remove(n); + OSPF_TRACE(D_EVENTS, "BFD session down for neighbor %R on %s", + n->rid, n->ifa->ifname); + ospf_neigh_sm(n, INM_INACTTIM); } } @@ -611,7 +609,7 @@ void ospf_sh_neigh_info(struct ospf_neighbor *n) { struct ospf_iface *ifa = n->ifa; - char *pos = "other"; + char *pos = "ptp "; char etime[6]; int exp, sec, min; @@ -627,16 +625,18 @@ ospf_sh_neigh_info(struct ospf_neighbor *n) bsprintf(etime, "%02u:%02u", min, sec); } - if (n->rid == ifa->drid) - pos = "dr "; - else if (n->rid == ifa->bdrid) - pos = "bdr "; - else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) || - (n->ifa->type == OSPF_IT_VLINK)) - pos = "ptp "; + if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA)) + { + if (n->rid == ifa->drid) + pos = "dr "; + else if (n->rid == ifa->bdrid) + pos = "bdr "; + else + pos = "other"; + } cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority, - ospf_ns[n->state], pos, etime, ifa->ifname, n->ip); + ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip); } static void @@ -645,18 +645,18 @@ rxmt_timer_hook(timer *t) struct ospf_neighbor *n = t->data; struct ospf_proto *p = n->ifa->oa->po; - DBG("%s: RXMT timer fired on interface %s for neigh %I\n", + DBG("%s: RXMT timer fired on %s for neigh %I\n", p->p.name, n->ifa->ifname, n->ip); switch (n->state) { case NEIGHBOR_EXSTART: - ospf_send_dbdes(p, n, 1); + ospf_send_dbdes(p, n); return; case NEIGHBOR_EXCHANGE: - if (n->myimms & DBDES_MS) - ospf_send_dbdes(p, n, 0); + if (n->myimms & DBDES_MS) + ospf_rxmt_dbdes(p, n); case NEIGHBOR_LOADING: ospf_send_lsreq(p, n); return; @@ -666,9 +666,6 @@ rxmt_timer_hook(timer *t) if (!EMPTY_SLIST(n->lsrtl)) ospf_rxmt_lsupd(p, n); return; - - default: - return; } } @@ -678,7 +675,7 @@ ackd_timer_hook(timer *t) struct ospf_neighbor *n = t->data; struct ospf_proto *p = n->ifa->oa->po; - DBG("%s: ACKD timer fired on interface %s for neigh %I\n", + DBG("%s: ACKD timer fired on %s for neigh %I\n", p->p.name, n->ifa->ifname, n->ip); ospf_send_lsack(p, n, ACKL_DELAY); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 470a8633..01e53922 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -252,6 +252,9 @@ ospf_start(struct proto *P) p->gr = ospf_top_new(p, P->pool); s_init_list(&(p->lsal)); + p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 }; + p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 }; + WALK_LIST(ac, c->area_list) ospf_area_add(p, ac); @@ -742,7 +745,7 @@ ospf_sh(struct proto *P) } cli_msg(-1014, "%s:", p->p.name); - cli_msg(-1014, "RFC1583 compatibility: %s", (p->rfc1583 ? "enable" : "disabled")); + cli_msg(-1014, "RFC1583 compatibility: %s", (p->rfc1583 ? "enabled" : "disabled")); cli_msg(-1014, "Stub router: %s", (p->stub_router ? "Yes" : "No")); cli_msg(-1014, "RT scheduler tick: %d", p->tick); cli_msg(-1014, "Number of areas: %u", p->areano); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index f464a3ed..6df5df08 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -73,12 +73,28 @@ // FIXME: MAX_PREFIX_LENGTH #define OSPF_TRACE(flags, msg, args...) \ -do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \ - log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) + do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \ + log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) #define OSPF_PACKET(dumpfn, buffer, msg, args...) \ -do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \ - { log(L_TRACE "%s: " msg, p->p.name, ## args ); dumpfn(p, buffer); } } while(0) + do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \ + { log(L_TRACE "%s: " msg, p->p.name, ## args ); dumpfn(p, buffer); } } while(0) + +#define LOG_PKT(msg, args...) \ + log_rl(&p->log_pkt_tbf, L_REMOTE "%s: " msg, p->p.name, args) + +#define LOG_PKT_AUTH(msg, args...) \ + log_rl(&p->log_pkt_tbf, L_AUTH "%s: " msg, p->p.name, args) + +#define LOG_PKT_WARN(msg, args...) \ + log_rl(&p->log_pkt_tbf, L_WARN "%s: " msg, p->p.name, args) + +#define LOG_LSA1(msg, args...) \ + log_rl(&p->log_lsa_tbf, L_REMOTE "%s: " msg, p->p.name, args) + +#define LOG_LSA2(msg, args...) \ + do { if (! p->log_lsa_tbf.mark) \ + log(L_REMOTE "%s: " msg, p->p.name, args); } while(0) #define OSPF_PROTO 89 @@ -248,6 +264,8 @@ struct ospf_proto sock *vlink_sk; /* IP socket used for vlink TX */ u32 router_id; u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */ + struct tbf log_pkt_tbf; /* TBF for packet messages */ + struct tbf log_lsa_tbf; /* TBF for LSA messages */ }; struct ospf_area @@ -283,7 +301,7 @@ struct ospf_iface pool *pool; sock *sk; /* IP socket */ - list neigh_list; /* List of neigbours (struct ospf_neighbor) */ + list neigh_list; /* List of neighbors (struct ospf_neighbor) */ u32 cost; /* Cost of iface */ u32 waitint; /* number of sec before changing state from wait */ u32 rxmtint; /* number of seconds between LSA retransmissions */ @@ -368,8 +386,8 @@ struct ospf_neighbor /* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in OSPFv3, we use the same type to simplify handling */ - u32 dr; /* Neigbour's idea of DR */ - u32 bdr; /* Neigbour's idea of BDR */ + u32 dr; /* Neighbor's idea of DR */ + u32 bdr; /* Neighbor's idea of BDR */ u32 iface_id; /* ID of Neighbour's iface connected to common network */ /* Database summary list iterator, controls initial dbdes exchange. @@ -890,7 +908,6 @@ void ospf_neigh_sm(struct ospf_neighbor *n, int event); void ospf_dr_election(struct ospf_iface *ifa); struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid); struct ospf_neighbor *find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip); -void ospf_neigh_remove(struct ospf_neighbor *n); void ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd); void ospf_sh_neigh_info(struct ospf_neighbor *n); @@ -916,6 +933,10 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa) ospf_send_to_bdr(ifa); } +#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0) +#define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0) +#define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0) + static inline uint ospf_pkt_hdrlen(struct ospf_proto *p) { return ospf_is_v2(p) ? (sizeof(struct ospf_packet) + sizeof(union ospf_auth)) : sizeof(struct ospf_packet); } @@ -931,7 +952,8 @@ void ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dir void ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr); /* dbdes.c */ -void ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next); +void ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n); +void ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n); void ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n); /* lsreq.c */ diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index d64d7d6b..2814712d 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -66,7 +66,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) log(L_ERR "No suitable password found for authentication"); return; } - password_cpy(auth->password, passwd->password, sizeof(union ospf_auth)); + strncpy(auth->password, passwd->password, sizeof(auth->password)); case OSPF_AUTH_NONE: { @@ -106,7 +106,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) void *tail = ((void *) pkt) + plen; char password[OSPF_AUTH_CRYPT_SIZE]; - password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE); + strncpy(password, passwd->password, sizeof(password)); struct MD5Context ctxt; MD5Init(&ctxt); @@ -120,23 +120,22 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt) } } + /* 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 ospf_proto *p = ifa->oa->po; union ospf_auth *auth = (void *) (pkt + 1); - struct password_item *pass = NULL, *ptmp; - char password[OSPF_AUTH_CRYPT_SIZE]; + struct password_item *pass = NULL; + const char *err_dsc = NULL; + uint err_val = 0; uint plen = ntohs(pkt->length); u8 autype = pkt->autype; if (autype != ifa->autype) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype); - return 0; - } + DROP("authentication method mismatch", autype); switch (autype) { @@ -146,85 +145,65 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_ case OSPF_AUTH_SIMPLE: pass = password_find(ifa->passwords, 1); if (!pass) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found"); - return 0; - } + DROP1("no password found"); + + if (!password_verify(pass, auth->password, sizeof(auth->password))) + DROP("wrong password", pass->id); - 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; 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 (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 (n) - { - u32 rcv_csn = ntohl(auth->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; - } + DROP("invalid MD5 digest length", auth->md5.len); - n->csn = rcv_csn; - } + if (plen + OSPF_AUTH_CRYPT_SIZE > len) + DROP("length mismatch", len); - if (ifa->passwords) + u32 rcv_csn = ntohl(auth->md5.csn); + if (n && (rcv_csn < n->csn)) + // DROP("lower sequence number", rcv_csn); { - WALK_LIST(ptmp, *(ifa->passwords)) - { - if (auth->md5.keyid != ptmp->id) continue; - if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue; - pass = ptmp; - break; - } + /* 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; } + pass = password_find_by_id(ifa->passwords, auth->md5.keyid); if (!pass) - { - OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found"); - return 0; - } + DROP("no suitable password found", auth->md5.keyid); void *tail = ((void *) pkt) + plen; + char passwd[OSPF_AUTH_CRYPT_SIZE]; char md5sum[OSPF_AUTH_CRYPT_SIZE]; - password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE); + + strncpy(passwd, pass->password, OSPF_AUTH_CRYPT_SIZE); struct MD5Context ctxt; MD5Init(&ctxt); MD5Update(&ctxt, (char *) pkt, plen); - MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); + MD5Update(&ctxt, passwd, 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; - } + DROP("wrong MD5 digest", pass->id); + + if (n) + n->csn = rcv_csn; + return 1; default: - OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); - return 0; + 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 @@ -236,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; @@ -252,6 +228,8 @@ ospf_rx_hook(sock *sk, int size) /* Initially, the packet is associated with the 'master' iface */ struct ospf_iface *ifa = sk->data; struct ospf_proto *p = ifa->oa->po; + const char *err_dsc = NULL; + uint err_val = 0; int src_local, dst_local, dst_mcast; src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); @@ -282,41 +260,31 @@ ospf_rx_hook(sock *sk, int size) * 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); + LOG_PKT_WARN("Multicast packet received from not-link-local %I via %s", + sk->faddr, ifa->ifname); } - /* Second, we check packet size, checksum, and the protocol version */ - struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); + /* Second, we check packet length, checksum, and the protocol version */ + struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &len); if (pkt == NULL) - { - log(L_ERR "%s%I - bad IP header", mesg, sk->faddr); - return 1; - } + 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 ((uint) 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); + + 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; @@ -325,20 +293,11 @@ 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 (pkt->version != ospf_get_version(p)) - { - log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version); - return 1; - } + if (plen > len) + DROP("length mismatch", plen); if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) { @@ -346,11 +305,8 @@ ospf_rx_hook(sock *sk, int size) 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; - } + if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) + DROP1("invalid checksum"); } /* Third, we resolve associated iface and handle vlinks. */ @@ -368,10 +324,7 @@ ospf_rx_hook(sock *sk, int size) /* It is real iface, source should be local (in OSPFv2) */ if (ospf_is_v2(p) && !src_local) - { - log(L_ERR "%s%I - strange source address for %s", mesg, sk->faddr, ifa->ifname); - return 1; - } + DROP1("strange source address"); goto found; } @@ -415,13 +368,11 @@ ospf_rx_hook(sock *sk, int size) 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; + DROP("area mismatch", areaid); } - found: +found: if (ifa->stub) /* This shouldn't happen */ return 1; @@ -429,18 +380,12 @@ ospf_rx_hook(sock *sk, int size) return 1; if (rid == p->router_id) - { - log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr); - return 1; - } + 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"); - /* 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 (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) @@ -450,16 +395,15 @@ ospf_rx_hook(sock *sk, int size) 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); + // XXXX format + OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown neighbor %R on %s (%I)", + rid, ifa->ifname, sk->faddr); return 1; } - if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, 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; - } switch (pkt->type) { @@ -484,10 +428,15 @@ ospf_rx_hook(sock *sk, int size) break; default: - log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->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; } /* diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 16453b87..08f90b49 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -1204,7 +1204,7 @@ ospf_check_vlinks(struct ospf_proto *p) || (ifa->vifa != nhi) || !ipa_equal(ifa->vip, tmp->lb)) { - OSPF_TRACE(D_EVENTS, "Vlink peer %R found", tmp->lsa.id); + OSPF_TRACE(D_EVENTS, "Vlink peer %R found", ifa->vid); ospf_iface_sm(ifa, ISM_DOWN); ifa->vifa = nhi; ifa->addr = nhi->addr; @@ -1831,7 +1831,7 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en, bad: /* Probably bug or some race condition, we log it */ - log(L_ERR "Unexpected case in next hop calculation"); + log(L_ERR "%s: Unexpected case in next hop calculation", p->p.name); return NULL; } @@ -1875,8 +1875,8 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par, struct mpnh *nhs = calc_next_hop(oa, en, par, pos); if (!nhs) { - log(L_WARN "Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)", - en->lsa_type, en->lsa.id, en->lsa.rt); + log(L_WARN "%s: Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)", + p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); return; } diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 4e3da0de..15ba013a 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -758,7 +758,7 @@ prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa) break; default: - log("Unknown interface type %s", ifa->ifname); + log(L_BUG "OSPF: Unknown interface type"); break; } @@ -855,7 +855,7 @@ prepare_rt3_lsa_body(struct ospf_proto *p, struct ospf_area *oa) break; default: - log("Unknown interface type %s", ifa->ifname); + log(L_BUG "OSPF: Unknown interface type"); break; } diff --git a/proto/rip/auth.c b/proto/rip/auth.c index b7b0611e..5634547a 100644 --- a/proto/rip/auth.c +++ b/proto/rip/auth.c @@ -95,7 +95,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru } memcpy(md5sum_packet, tail->md5, 16); - password_cpy(tail->md5, pass->password, 16); + strncpy(tail->md5, pass->password, 16); MD5Init(&ctxt); MD5Update(&ctxt, (char *) packet, ntohs(block->packetlen) + sizeof(struct rip_block_auth) ); @@ -131,7 +131,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru block->mustbeFFFF = 0xffff; switch (P_CF->authtype) { case AT_PLAINTEXT: - password_cpy( (char *) (&block->packetlen), passwd->password, 16); + strncpy( (char *) (&block->packetlen), passwd->password, 16); return PACKETLEN(num); case AT_MD5: { @@ -156,7 +156,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru tail->mustbeFFFF = 0xffff; tail->mustbe0001 = 0x0100; - password_cpy(tail->md5, passwd->password, 16); + strncpy(tail->md5, passwd->password, 16); MD5Init(&ctxt); MD5Update(&ctxt, (char *) packet, PACKETLEN(num) + sizeof(struct rip_md5_tail)); MD5Final(tail->md5, &ctxt); -- cgit v1.2.3 From f92e6ab364d50900bc9104af4539f6ea42b25c43 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 3 Nov 2014 20:35:58 +0100 Subject: Changes order of iface/addr/neigh event hooks. Now the order is: Up -> iface, addr, neigh Down -> neigh, addr, iface It fixes the case when an iface appears, related static routes are activated and exported to OSPF before the iface notification and therefore forwarding addresses are not encoded in generated external LSAs. --- nest/iface.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'nest') diff --git a/nest/iface.c b/nest/iface.c index 298698a7..4d73c2a4 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -150,7 +150,7 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a) } static void -ifa_notify_change_dep(unsigned c, struct ifa *a) +ifa_notify_change_(unsigned c, struct ifa *a) { struct proto *p; @@ -163,8 +163,13 @@ ifa_notify_change_dep(unsigned c, struct ifa *a) static inline void ifa_notify_change(unsigned c, struct ifa *a) { - neigh_ifa_update(a); - ifa_notify_change_dep(c, a); + if (c & IF_CHANGE_DOWN) + neigh_ifa_update(a); + + ifa_notify_change_(c, a); + + if (c & IF_CHANGE_UP) + neigh_ifa_update(a); } static inline void @@ -201,14 +206,14 @@ if_notify_change(unsigned c, struct iface *i) if_dump(i); #endif - if (c & IF_CHANGE_UP) - neigh_if_up(i); + if (c & IF_CHANGE_DOWN) + neigh_if_down(i); if (c & IF_CHANGE_DOWN) WALK_LIST(a, i->addrs) { a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS); - ifa_notify_change_dep(IF_CHANGE_DOWN, a); + ifa_notify_change_(IF_CHANGE_DOWN, a); } WALK_LIST(p, active_proto_list) @@ -218,14 +223,14 @@ if_notify_change(unsigned c, struct iface *i) WALK_LIST(a, i->addrs) { a->flags = (i->flags & ~IA_FLAGS) | (a->flags & IA_FLAGS); - ifa_notify_change_dep(IF_CHANGE_UP, a); + ifa_notify_change_(IF_CHANGE_UP, a); } + if (c & IF_CHANGE_UP) + neigh_if_up(i); + if ((c & (IF_CHANGE_UP | IF_CHANGE_DOWN | IF_CHANGE_LINK)) == IF_CHANGE_LINK) neigh_if_link(i); - - if (c & IF_CHANGE_DOWN) - neigh_if_down(i); } static unsigned @@ -251,8 +256,8 @@ if_change_flags(struct iface *i, unsigned flags) } /** - * if_delete - remove interface - * @old: interface + * if_delete - remove interface + * @old: interface * * This function is called by the low-level platform dependent code * whenever it notices an interface disappears. It is just a shorthand @@ -676,7 +681,7 @@ iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a) if ((a->flags & IA_PEER) && ipa_in_net(a->opposite, p->prefix, p->pxlen)) return pos; - + continue; } -- cgit v1.2.3