summaryrefslogtreecommitdiff
path: root/proto/ospf
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf')
-rw-r--r--proto/ospf/iface.c20
-rw-r--r--proto/ospf/lsalib.c63
-rw-r--r--proto/ospf/lsupd.c25
-rw-r--r--proto/ospf/neighbor.c3
-rw-r--r--proto/ospf/ospf.h8
-rw-r--r--proto/ospf/rt.c17
-rw-r--r--proto/ospf/topology.c25
7 files changed, 137 insertions, 24 deletions
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index cae36ad3..c902a878 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -67,7 +67,13 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
ipsk = sk_new(p->pool);
ipsk->type = SK_IP;
ipsk->dport = OSPF_PROTO;
+
+#ifdef OSPFv2
ipsk->saddr = ifa->iface->addr->ip;
+#else /* OSPFv3 */
+ ipsk->saddr = ifa->lladdr;
+#endif
+
ipsk->tos = IP_PREC_INTERNET_CONTROL;
ipsk->ttl = 1;
if (ifa->type == OSPF_IT_VLINK)
@@ -135,7 +141,13 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
ifa->dr_sk->type = SK_IP_MC;
ifa->dr_sk->sport = 0;
ifa->dr_sk->dport = OSPF_PROTO;
+
+#ifdef OSPFv2
ifa->dr_sk->saddr = AllDRouters;
+#else /* OSPFv3 */
+ ifa->dr_sk->saddr = ifa->lladdr;
+#endif
+
ifa->dr_sk->daddr = AllDRouters;
ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
ifa->dr_sk->ttl = 1;
@@ -308,7 +320,13 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
mcsk->type = SK_IP_MC;
mcsk->sport = 0;
mcsk->dport = OSPF_PROTO;
- mcsk->saddr = AllSPFRouters;
+
+#ifdef OSPFv2
+ mcsk->saddr = AllDRouters;
+#else /* OSPFv3 */
+ mcsk->saddr = ifa->lladdr;
+#endif
+
mcsk->daddr = AllSPFRouters;
mcsk->tos = IP_PREC_INTERNET_CONTROL;
mcsk->ttl = 1;
diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c
index 4cbabcc1..3bc5986c 100644
--- a/proto/ospf/lsalib.c
+++ b/proto/ospf/lsalib.c
@@ -99,7 +99,7 @@ htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
#ifdef OSPFv2
n->options = h->options;
#endif
- n->type = h->type;
+ n->type = htont(h->type);
n->id = htonl(h->id);
n->rt = htonl(h->rt);
n->sn = htonl(h->sn);
@@ -114,7 +114,7 @@ ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
#ifdef OSPFv2
h->options = n->options;
#endif
- h->type = n->type;
+ h->type = ntoht(n->type);
h->id = ntohl(n->id);
h->rt = ntohl(n->rt);
h->sn = ntohl(n->sn);
@@ -143,7 +143,7 @@ htonlsab(void *h, void *n, u16 type, u16 len)
nrt->links = htons(hrt->links);
links = hrt->links;
#else /* OSPFv3 */
- hrt->options = htonl(nrt->options);
+ nrt->options = htonl(hrt->options);
links = (len - sizeof(struct ospf_lsa_rt)) /
sizeof(struct ospf_lsa_rt_link);
#endif
@@ -173,6 +173,10 @@ htonlsab(void *h, void *n, u16 type, u16 len)
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
+#ifdef OSPFv3
+ case LSA_T_LINK:
+ case LSA_T_PREFIX:
+#endif
{
u32 *hid, *nid;
@@ -241,6 +245,10 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
+#ifdef OSPFv3
+ case LSA_T_LINK:
+ case LSA_T_PREFIX:
+#endif
{
u32 *hid, *nid;
@@ -258,6 +266,35 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
}
};
+void
+buf_dump(const char *hdr, const byte *buf, int blen)
+{
+ char b2[1024];
+ char *bp;
+ int first = 1;
+ int i;
+
+ const char *lhdr = hdr;
+
+ bp = b2;
+ for(i = 0; i < blen; i++)
+ {
+ if ((i > 0) && ((i % 16) == 0))
+ {
+ *bp = 0;
+ log(L_WARN "%s\t%s", lhdr, b2);
+ lhdr = "";
+ bp = b2;
+ }
+
+ bp += snprintf(bp, 1022, "%02x ", buf[i]);
+
+ }
+
+ *bp = 0;
+ log(L_WARN "%s\t%s", lhdr, b2);
+}
+
#define MODX 4102 /* larges signed value without overflow */
/* Fletcher Checksum -- Refer to RFC1008. */
@@ -268,17 +305,25 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
void
lsasum_calculate(struct ospf_lsa_header *h, void *body)
{
- u16 length;
-
- length = h->length;
+ u16 length = h->length;
+ u16 type = h->type;
+ log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
htonlsah(h, h);
- htonlsab(body, body, h->type, length - sizeof(struct ospf_lsa_header));
+
+ htonlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
+
+ char buf[1024];
+ memcpy(buf, h, sizeof(struct ospf_lsa_header));
+ memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header));
+ buf_dump("CALC", buf, length);
(void) lsasum_check(h, body);
+ log(L_WARN "Checksum result %4x", h->checksum);
+
ntohlsah(h, h);
- ntohlsab(body, body, h->type, length - sizeof(struct ospf_lsa_header));
+ ntohlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
}
/*
@@ -294,7 +339,7 @@ lsasum_check(struct ospf_lsa_header *h, void *body)
u16 length;
b = body;
- sp = (char *) &h;
+ sp = (char *) h;
sp += 2; /* Skip Age field */
length = ntohs(h->length) - 2;
h->checksum = 0;
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index efaafe86..72861bd5 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -78,13 +78,32 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
#else /* OSPFv3 */
+static int
+unknown_lsa_type(struct ospf_lsa_header *lsa)
+{
+ switch (lsa->type)
+ {
+ case LSA_T_RT:
+ case LSA_T_NET:
+ case LSA_T_SUM_NET:
+ case LSA_T_SUM_RT:
+ case LSA_T_EXT:
+ case LSA_T_LINK:
+ case LSA_T_PREFIX:
+ return 0;
+
+ default:
+ return 1;
+ }
+}
+
int
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
{
u32 scope = LSA_SCOPE(lsa);
/* 4.5.2 (Case 2) */
- if (unknown_type(lsa) && !(lsa->type & LSA_UBIT))
+ if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
scope = LSA_SCOPE_LINK;
switch (scope)
@@ -444,9 +463,11 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
/* pg 143 (1) */
chsum = lsa->checksum;
+ log(L_WARN "Checking rcv %R %R %d (len %d)", ntohl(lsa->id), ntohl(lsa->rt), ntoht(lsa->type), ntohs(lsa->length));
+ buf_dump("RCV", lsa, ntohs(lsa->length));
if (chsum != lsasum_check(lsa, NULL))
{
- log(L_WARN "Received bad lsa checksum from %I", n->ip);
+ log(L_WARN "Received bad lsa checksum from %I: %x %x", n->ip, chsum, lsa->checksum);
continue;
}
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index 374da636..78476541 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -451,12 +451,13 @@ bdr_election(struct ospf_iface *ifa)
me.state = NEIGHBOR_2WAY;
me.rid = myid;
me.priority = ifa->priority;
- me.ip = ifa->iface->addr->ip;
#ifdef OSPFv2
+ me.ip = ifa->iface->addr->ip;
me.dr = ipa_to_u32(ifa->drip);
me.bdr = ipa_to_u32(ifa->bdrip);
#else /* OSPFv3 */
+ me.ip = ifa->lladdr;
me.dr = ifa->drid;
me.bdr = ifa->bdrid;
me.iface_id = ifa->iface->index;
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index da0104de..c1d5de76 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -424,6 +424,10 @@ struct ospf_lsa_ext
#define LSA_EXT_EBIT 0x80000000
+/* Endianity swap for lsa->type */
+#define ntoht(x) x
+#define htont(x) x
+
#else /* OSPFv3 */
@@ -488,6 +492,10 @@ struct ospf_lsa_prefix
#define LSA_EXT_FBIT 0x2000000
#define LSA_EXT_TBIT 0x1000000
+/* Endianity swap for lsa->type */
+#define ntoht(x) ntohs(x)
+#define htont(x) htons(x)
+
#endif
#define METRIC_MASK 0x00FFFFFF
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 677ce5b4..27bd2266 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -312,7 +312,7 @@ ospf_rt_spfa(struct ospf_area *oa)
nf.ar = act;
nf.nh = act->nh;
nf.ifa = act->nhi;
- ri_install(po, ipa_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL);
+ ri_install(po, ipa_from_rid(act->lsa.rt), MAX_PREFIX_LENGTH, ORT_ROUTER, &nf, NULL);
}
rr = (struct ospf_lsa_rt_link *) (rt + 1);
@@ -582,7 +582,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
#endif
ip = ipa_from_rid(dst_rid);
- pxlen = 32;
+ pxlen = MAX_PREFIX_LENGTH;
metric = ls->metric & METRIC_MASK;
options |= ORTA_ASBR;
type = ORT_ROUTER;
@@ -595,7 +595,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
abrip = ipa_from_rid(en->lsa.rt);
- abr = fib_find(&oa->rtr, &abrip, 32);
+ abr = fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH);
if (!abr) continue;
nf.type = re->n.type;
@@ -691,7 +691,7 @@ ospf_rt_sum(struct ospf_area *oa)
#endif
ip = ipa_from_rid(dst_rid);
- pxlen = 32;
+ pxlen = MAX_PREFIX_LENGTH;
metric = ls->metric & METRIC_MASK;
options |= ORTA_ASBR;
type = ORT_ROUTER;
@@ -703,7 +703,7 @@ ospf_rt_sum(struct ospf_area *oa)
/* Page 169 (4) */
abrip = ipa_from_rid(en->lsa.rt);
- if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
+ if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH))) continue;
if (abr->n.metric1 == LSINFINITY) continue;
if (!(abr->n.options & ORTA_ABR)) continue;
@@ -891,7 +891,7 @@ ospf_ext_spf(struct proto_ospf *po)
nf1 = NULL;
WALK_LIST(atmp, po->area_list)
{
- nfh = fib_find(&atmp->rtr, &rtid, 32);
+ nfh = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH);
if (nfh == NULL) continue;
if (nf1 == NULL) nf1 = nfh;
else if (ri_better(po, &nfh->n, NULL, &nf1->n, NULL, po->rfc1583)) nf1 = nfh;
@@ -915,7 +915,7 @@ ospf_ext_spf(struct proto_ospf *po)
}
else
{
- nf2 = fib_route(&po->rtf, rt_fwaddr, 32);
+ nf2 = fib_route(&po->rtf, rt_fwaddr, MAX_PREFIX_LENGTH);
if (!nf2)
{
@@ -923,7 +923,6 @@ ospf_ext_spf(struct proto_ospf *po)
continue;
}
-
if ((nn = neigh_find(p, &rt_fwaddr, 0)) != NULL)
{
nh = rt_fwaddr;
@@ -1179,7 +1178,7 @@ again1:
int found = 0;
struct ospf_iface *ifa;
struct top_hash_entry *en;
- OSPF_TRACE(D_EVENTS, "Trying to find correct next hop");
+ OSPF_TRACE(D_EVENTS, "Trying to find correct next hop %I/%d via %I", nf->fn.prefix, nf->fn.pxlen, nf->n.nh);
WALK_LIST(ifa, po->iface_list)
{
if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 360e3627..82630104 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -22,6 +22,7 @@
void originate_prefix_rt_lsa(struct ospf_area *oa);
void originate_prefix_net_lsa(struct ospf_iface *ifa);
+void flush_prefix_net_lsa(struct ospf_iface *ifa);
#ifdef OSPFv2
#define ipa_to_rid(x) _I(x)
@@ -557,8 +558,6 @@ flush_net_lsa(struct ospf_iface *ifa)
ifa->net_lsa->lsa.age = LSA_MAXAGE;
lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
-
-
flush_lsa(ifa->net_lsa, po);
ifa->net_lsa = NULL;
}
@@ -1215,6 +1214,28 @@ originate_prefix_net_lsa(struct ospf_iface *ifa)
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
}
+void
+flush_prefix_net_lsa(struct ospf_iface *ifa)
+{
+ struct proto_ospf *po = ifa->oa->po;
+ struct proto *p = &po->proto;
+ struct top_hash_entry *en = ifa->pxn_lsa;
+ u32 dom = ifa->oa->areaid;
+
+ if (en == NULL)
+ return;
+
+ OSPF_TRACE(D_EVENTS, "Flushing Net Prefix lsa for iface \"%s\".",
+ ifa->iface->name);
+ en->lsa.sn += 1;
+ en->lsa.age = LSA_MAXAGE;
+ lsasum_calculate(&en->lsa, en->lsa_body);
+ ospf_lsupd_flood(po, NULL, NULL, &en->lsa, dom, 0);
+ flush_lsa(en, po);
+ ifa->pxn_lsa = NULL;
+}
+
+
#endif