summaryrefslogtreecommitdiffstats
path: root/proto/ospf/hello.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/hello.c')
-rw-r--r--proto/ospf/hello.c137
1 files changed, 106 insertions, 31 deletions
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index 45b6b61..7eeee3b 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -8,12 +8,46 @@
#include "ospf.h"
+
+#ifdef OSPFv2
+struct ospf_hello_packet
+{
+ struct ospf_packet ospf_packet;
+ ip_addr netmask;
+ u16 helloint;
+ u8 options;
+ u8 priority;
+ u32 deadint;
+ u32 dr;
+ u32 bdr;
+};
+#endif
+
+
+#ifdef OSPFv3
+struct ospf_hello_packet
+{
+ struct ospf_packet ospf_packet;
+ u32 iface_id;
+ u8 priority;
+ u8 options3;
+ u8 options2;
+ u8 options;
+ u16 helloint;
+ u16 deadint;
+ u32 dr;
+ u32 bdr;
+};
+#endif
+
+
void
-ospf_hello_receive(struct ospf_hello_packet *ps,
- struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr)
+ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ struct ospf_neighbor *n, ip_addr faddr)
{
+ struct ospf_hello_packet *ps = (void *) ps_i;
u32 *pnrid;
- ip_addr olddr, oldbdr;
+ u32 olddr, oldbdr, oldiface_id, tmp;
ip_addr mask;
char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
struct proto *p = (struct proto *) ifa->oa->po;
@@ -21,9 +55,10 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
+
+#ifdef OSPFv2
mask = ps->netmask;
ipa_ntoh(mask);
-
if (ifa->type != OSPF_IT_VLINK)
{
char *msg = L_WARN "Received HELLO packet %s (%I) is inconsistent "
@@ -50,24 +85,30 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
return;
}
}
+#endif
- if (ntohs(ps->helloint) != ifa->helloint)
+ tmp = ntohs(ps->helloint);
+ if (tmp != ifa->helloint)
{
- log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec,
- ntohs(ps->helloint));
+ log(L_ERR "%s%I%shello interval mismatch (%d).", beg, faddr, rec, tmp);
return;
}
- if (ntohl(ps->deadint) != ifa->dead)
+#ifdef OSPFv2
+ tmp = ntohl(ps->deadint);
+#else /* OSPFv3 */
+ tmp = ntohs(ps->deadint);
+#endif
+ if (tmp != ifa->dead)
{
- log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec,
- ntohl(ps->deadint));
+ log(L_ERR "%s%I%sdead interval mismatch (%d).", beg, faddr, rec, tmp);
return;
}
- if (ps->options != ifa->oa->opt.byte)
+ tmp = !(ps->options & OPT_E);
+ if (tmp != ifa->oa->stub)
{
- log(L_ERR "%s%I%soptions mismatch (0x%x).", beg, faddr, rec, ps->options);
+ log(L_ERR "%s%I%sstub area flag mismatch (%d).", beg, faddr, rec, tmp);
return;
}
@@ -111,12 +152,12 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
n->ip = faddr;
- n->dr = ps->dr;
- ipa_ntoh(n->dr);
- n->bdr = ps->bdr;
- ipa_ntoh(n->bdr);
+ n->dr = ntohl(ps->dr);
+ n->bdr = ntohl(ps->bdr);
n->priority = ps->priority;
- n->options = ps->options;
+#ifdef OSPFv3
+ n->iface_id = ntohl(ps->iface_id);
+#endif
}
ospf_neigh_sm(n, INM_HELLOREC);
@@ -140,35 +181,54 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
ospf_neigh_sm(n, INM_1WAYREC);
olddr = n->dr;
- n->dr = ipa_ntoh(ps->dr);
oldbdr = n->bdr;
- n->bdr = ipa_ntoh(ps->bdr);
oldpriority = n->priority;
+#ifdef OSPFv3
+ oldiface_id = n->iface_id;
+#endif
+
+ n->dr = ntohl(ps->dr);
+ n->bdr = ntohl(ps->bdr);
n->priority = ps->priority;
+#ifdef OSPFv3
+ n->iface_id = ntohl(ps->iface_id);
+#endif
+
/* Check priority change */
if (n->state >= NEIGHBOR_2WAY)
{
+#ifdef OSPFv2
+ u32 rid = n->ip;
+#else /* OSPFv3 */
+ u32 rid = p->cf->global->router_id;
+#endif
+
if (n->priority != oldpriority)
ospf_iface_sm(ifa, ISM_NEICH);
+#ifdef OSPFv3
+ if (n->iface_id != oldiface_id)
+ ospf_iface_sm(ifa, ISM_NEICH);
+#endif
+
/* Router is declaring itself ad DR and there is no BDR */
- if (ipa_equal(n->ip, n->dr) && (ipa_to_u32(n->bdr) == 0)
+ if ((rid == n->dr) && (n->bdr == 0)
&& (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is declaring itself as BDR */
- if (ipa_equal(n->ip, n->bdr) && (n->state != NEIGHBOR_FULL))
+ if ((rid == n->bdr) && (n->state != NEIGHBOR_FULL))
ospf_iface_sm(ifa, ISM_BACKS);
/* Neighbor is newly declaring itself as DR or BDR */
- if ((ipa_equal(n->ip, n->dr) && (!ipa_equal(n->dr, olddr)))
- || (ipa_equal(n->ip, n->bdr) && (!ipa_equal(n->bdr, oldbdr))))
+ if (((rid == n->dr) && (n->dr != olddr))
+ || ((rid == n->bdr) && (n->bdr != oldbdr)))
ospf_iface_sm(ifa, ISM_NEICH);
/* Neighbor is no more declaring itself as DR or BDR */
- if ((ipa_equal(n->ip, olddr) && (!ipa_equal(n->dr, olddr)))
- || (ipa_equal(n->ip, oldbdr) && (!ipa_equal(n->bdr, oldbdr))))
+ if (((rid == olddr) && (n->dr != olddr))
+ || ((rid == oldbdr) && (n->bdr != oldbdr)))
ospf_iface_sm(ifa, ISM_NEICH);
}
@@ -181,7 +241,7 @@ ospf_hello_receive(struct ospf_hello_packet *ps,
}
void
-ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
+ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
{
struct ospf_iface *ifa;
struct ospf_hello_packet *pkt;
@@ -223,18 +283,33 @@ ospf_hello_send(timer * timer, int poll, struct ospf_neighbor *dirn)
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
+#ifdef OSPFv2
pkt->netmask = ipa_mkmask(ifa->iface->addr->pxlen);
ipa_hton(pkt->netmask);
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
pkt->netmask = IPA_NONE;
+#endif
+
pkt->helloint = ntohs(ifa->helloint);
- pkt->options = ifa->oa->opt.byte;
pkt->priority = ifa->priority;
+
+#ifdef OSPFv3
+ pkt->iface_id = htonl(ifa->iface->index);
+
+ pkt->options3 = ifa->oa->options >> 16;
+ pkt->options2 = ifa->oa->options >> 8;
+#endif
+ pkt->options = ifa->oa->options;
+
+#ifdef OSPFv2
pkt->deadint = htonl(ifa->dead);
- pkt->dr = ifa->drip;
- ipa_hton(pkt->dr);
- pkt->bdr = ifa->bdrip;
- ipa_hton(pkt->bdr);
+ pkt->dr = htonl(ipa_to_u32(ifa->drip));
+ pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
+#else /* OSPFv3 */
+ pkt->deadint = htons(ifa->dead);
+ pkt->dr = htonl(ifa->drid);
+ pkt->bdr = htonl(ifa->bdrid);
+#endif
/* Fill all neighbors */
i = 0;