summaryrefslogtreecommitdiff
path: root/proto/ospf/lsreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/lsreq.c')
-rw-r--r--proto/ospf/lsreq.c174
1 files changed, 87 insertions, 87 deletions
diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c
index 15854ce7..8888f88e 100644
--- a/proto/ospf/lsreq.c
+++ b/proto/ospf/lsreq.c
@@ -2,6 +2,8 @@
* BIRD -- OSPF
*
* (c) 2000--2004 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.
*/
@@ -9,47 +11,55 @@
#include "ospf.h"
+/*
struct ospf_lsreq_packet
{
- struct ospf_packet ospf_packet;
- struct ospf_lsreq_header lsh[];
+ struct ospf_packet hdr;
+ // union ospf_auth auth;
+
+ struct ospf_lsreq_header lsrs[];
};
+*/
-static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
+static inline void
+ospf_lsreq_body(struct ospf_proto *p, struct ospf_packet *pkt,
+ struct ospf_lsreq_header **body, uint *count)
{
- struct ospf_packet *op = &pkt->ospf_packet;
+ uint plen = ntohs(pkt->length);
+ uint hlen = ospf_pkt_hdrlen(p);
+
+ *body = ((void *) pkt) + hlen;
+ *count = (plen - hlen) / sizeof(struct ospf_lsreq_header);
+}
- ASSERT(op->type == LSREQ_P);
- ospf_dump_common(p, op);
+static void
+ospf_dump_lsreq(struct ospf_proto *p, struct ospf_packet *pkt)
+{
+ struct ospf_lsreq_header *lsrs;
+ uint i, lsr_count;
- unsigned int i, j;
- j = (ntohs(op->length) - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
+ ASSERT(pkt->type == LSREQ_P);
+ ospf_dump_common(p, pkt);
- for (i = 0; i < j; i++)
- log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", p->name,
- htonl(pkt->lsh[i].type), htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt));
+ ospf_lsreq_body(p, pkt, &lsrs, &lsr_count);
+ for (i = 0; i < lsr_count; i++)
+ log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", p->p.name,
+ ntohl(lsrs[i].type), ntohl(lsrs[i].id), ntohl(lsrs[i].rt));
}
+
void
-ospf_lsreq_send(struct ospf_neighbor *n)
+ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n)
{
- snode *sn;
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_lsreq_header *lsrs;
struct top_hash_entry *en;
- struct ospf_lsreq_packet *pk;
- struct ospf_packet *op;
- struct ospf_lsreq_header *lsh;
- u16 length;
- int i, j;
- struct proto *p = &n->ifa->oa->po->proto;
+ struct ospf_packet *pkt;
+ uint i, lsr_max, length;
- pk = ospf_tx_buffer(n->ifa);
- op = &pk->ospf_packet;
+ /* RFC 2328 10.9 */
- ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
-
- sn = SHEAD(n->lsrql);
if (EMPTY_SLIST(n->lsrql))
{
if (n->state == NEIGHBOR_LOADING)
@@ -57,90 +67,80 @@ ospf_lsreq_send(struct ospf_neighbor *n)
return;
}
- i = j = (ospf_pkt_maxsize(n->ifa) - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
- lsh = pk->lsh;
+ pkt = ospf_tx_buffer(ifa);
+ ospf_pkt_fill_hdr(ifa, pkt, LSREQ_P);
+ ospf_lsreq_body(p, pkt, &lsrs, &lsr_max);
+
+ // for (i = 0; i < lsr_max; i++)
- for (; i > 0; i--)
+ i = 0;
+ WALK_SLIST(en, n->lsrql)
{
- en = (struct top_hash_entry *) sn;
- lsh->type = htonl(en->lsa.type);
- lsh->rt = htonl(en->lsa.rt);
- lsh->id = htonl(en->lsa.id);
- DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
- i, en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
- lsh++;
- if (sn == STAIL(n->lsrql))
+ if (i == lsr_max)
break;
- sn = sn->next;
+
+ DBG("Requesting %uth LSA: Type: %04u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
+ i, en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
+
+ u32 etype = lsa_get_etype(&en->lsa, p);
+ lsrs[i].type = htonl(etype);
+ lsrs[i].rt = htonl(en->lsa.rt);
+ lsrs[i].id = htonl(en->lsa.id);
+ i++;
}
- if (i != 0)
- i--;
- length =
- sizeof(struct ospf_lsreq_packet) + (j -
- i) * sizeof(struct ospf_lsreq_header);
- op->length = htons(length);
+ length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header);
+ pkt->length = htons(length);
- OSPF_PACKET(ospf_dump_lsreq, pk, "LSREQ packet sent to %I via %s", n->ip, n->ifa->ifname);
- ospf_send_to(n->ifa, n->ip);
+ OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to %I via %s", n->ip, ifa->ifname);
+ ospf_send_to(ifa, n->ip);
}
+
void
-ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
- struct ospf_area *oa = ifa->oa;
- struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
- struct ospf_lsreq_header *lsh;
- struct l_lsr_head *llsh;
- list uplist;
- slab *upslab;
- int i, lsano;
-
- unsigned int size = ntohs(ps_i->length);
- if (size < sizeof(struct ospf_lsreq_packet))
- {
- log(L_ERR "Bad OSPF LSREQ packet from %I - too short (%u B)", n->ip, size);
- return;
- }
+ struct ospf_proto *p = ifa->oa->po;
+ struct ospf_lsreq_header *lsrs;
+ uint i, lsr_count;
- struct ospf_lsreq_packet *ps = (void *) ps_i;
- OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->ifname);
+ /* RFC 2328 10.7 */
+
+ /* 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);
if (n->state < NEIGHBOR_EXCHANGE)
return;
- ospf_neigh_sm(n, INM_HELLOREC);
+ ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
+
+ ospf_lsreq_body(p, pkt, &lsrs, &lsr_count);
- lsh = ps->lsh;
- init_list(&uplist);
- upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
+ struct top_hash_entry *en, *entries[lsr_count];
- lsano = (size - sizeof(struct ospf_lsreq_packet)) /
- sizeof(struct ospf_lsreq_header);
- for (i = 0; i < lsano; lsh++, i++)
+ for (i = 0; i < lsr_count; i++)
{
- u32 hid = ntohl(lsh->id);
- u32 hrt = ntohl(lsh->rt);
- u32 htype = ntohl(lsh->type);
- u32 dom = ospf_lsa_domain(htype, ifa);
- DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", lsh->type, hid, hrt);
- llsh = sl_alloc(upslab);
- llsh->lsh.id = hid;
- llsh->lsh.rt = hrt;
- llsh->lsh.type = htype;
- add_tail(&uplist, NODE llsh);
- if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
+ u32 id, rt, type, domain;
+
+ id = ntohl(lsrs[i].id);
+ rt = ntohl(lsrs[i].rt);
+ lsa_get_type_domain_(ntohl(lsrs[i].type), ifa, &type, &domain);
+
+ DBG("Processing requested LSA: Type: %04x, Id: %R, Rt: %R\n", type, id, rt);
+
+ en = ospf_hash_find(p->gr, domain, id, rt, type);
+ if (!en)
{
- log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
- n->ip, htype, hid, hrt);
+ 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);
ospf_neigh_sm(n, INM_BADLSREQ);
- rfree(upslab);
return;
}
+
+ entries[i] = en;
}
- ospf_lsupd_send_list(n, &uplist);
- rfree(upslab);
+
+ ospf_send_lsupd(p, entries, lsr_count, n);
}