mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-03-14 02:17:04 +00:00
Temporary integrated commit (OSPF), unfinished.
This commit is contained in:
parent
1ee54a8413
commit
a7b7b2bd0f
@ -14,6 +14,9 @@
|
||||
#include "nest/route.h"
|
||||
#include "nest/attrs.h"
|
||||
|
||||
|
||||
#define IPV6 1 // XXXX temporary
|
||||
|
||||
struct f_inst { /* Instruction */
|
||||
struct f_inst *next; /* Structure is 16 bytes, anyway */
|
||||
u16 code;
|
||||
|
26
lib/ip.h
26
lib/ip.h
@ -15,13 +15,30 @@
|
||||
#include "lib/unaligned.h"
|
||||
|
||||
|
||||
#ifdef DEBUGGING
|
||||
|
||||
#define IP4_MIN_MTU 576 /* RFC 2328 A.1 */
|
||||
#define IP6_MIN_MTU 1280 /* RFC 5340 A.1 */
|
||||
|
||||
#define IP4_ALL_SPF_ROUTERS ipa_build4(224, 0, 0, 5)
|
||||
#define IP4_ALL_D_ROUTERS ipa_build4(224, 0, 0, 6)
|
||||
|
||||
#define IP6_All_NODES ipa_build6(0xFF020000, 0, 0, 1)
|
||||
#define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2)
|
||||
#define IP6_ALL_OSPF_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
|
||||
#define IP6_ALL_OSPF_D_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
|
||||
|
||||
#define IP4_NONE _MI4(0)
|
||||
#define IP6_NONE _MI6(0,0,0,0)
|
||||
#define IPA_NONE IP6_NONE
|
||||
|
||||
|
||||
/*
|
||||
* Use the structural representation when you want to make sure
|
||||
* nobody unauthorized attempts to handle ip_addr as number.
|
||||
*/
|
||||
|
||||
#ifdef DEBUGGING
|
||||
|
||||
typedef struct ip4_addr {
|
||||
u32 addr;
|
||||
} ip4_addr;
|
||||
@ -54,11 +71,6 @@ typedef ip6_addr ip_addr;
|
||||
|
||||
|
||||
|
||||
#define IPA_NONE IP6_NONE
|
||||
#define IP4_NONE _MI4(0)
|
||||
#define IP6_NONE _MI6(0,0,0,0)
|
||||
|
||||
|
||||
/*
|
||||
* ip_classify() returns either a negative number for invalid addresses
|
||||
* or scope OR'ed together with address type.
|
||||
@ -123,9 +135,11 @@ static inline ip6_addr ip6_not(ip6_addr a)
|
||||
|
||||
#define ipa_from_ip4(x) _MI6(0,0,0xffff,_I(x))
|
||||
#define ipa_from_ip6(x) x
|
||||
#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
|
||||
|
||||
#define ipa_to_ip4(x) _I3(x)
|
||||
#define ipa_to_ip6(x) x
|
||||
#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
|
||||
|
||||
#define ip4_from_u32(x) _MI4(x)
|
||||
#define ip4_to_u32(x) _I(x)
|
||||
|
11
nest/iface.c
11
nest/iface.c
@ -534,10 +534,8 @@ ifa_update(struct ifa *a)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef IPV6
|
||||
if ((i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
|
||||
log(L_ERR "Missing broadcast address for interface %s", i->name);
|
||||
#endif
|
||||
if (ipa_is_ip4(a->ip) && (i->flags & IF_BROADCAST) && !ipa_nonzero(a->brd))
|
||||
log(L_WARN "Missing broadcast address for interface %s", i->name);
|
||||
|
||||
b = mb_alloc(if_pool, sizeof(struct ifa));
|
||||
memcpy(b, a, sizeof(struct ifa));
|
||||
@ -583,10 +581,13 @@ ifa_delete(struct ifa *a)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
auto_router_id(void)
|
||||
{
|
||||
#ifndef IPV6
|
||||
// XXXX check this
|
||||
#if 0
|
||||
|
||||
struct iface *i, *j;
|
||||
|
||||
j = NULL;
|
||||
|
@ -75,12 +75,11 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
|
||||
{
|
||||
if (ipa_in_net(*a, b->prefix, b->pxlen))
|
||||
{
|
||||
#ifndef IPV6
|
||||
// XXXX what about this ?
|
||||
if ((b->pxlen < (BITS_PER_IP_ADDRESS - 1)) &&
|
||||
(ipa_equal(*a, b->prefix) || /* Network address */
|
||||
ipa_equal(*a, b->brd))) /* Broadcast */
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return b->scope;
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ ipa_item:
|
||||
ipa_el
|
||||
| ipa_ne;
|
||||
|
||||
ipa_el: IPA ';'
|
||||
ipa_el: ipa ';'
|
||||
{
|
||||
this_nbma = cfg_allocz(sizeof(struct nbma_node));
|
||||
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
|
||||
@ -344,7 +344,7 @@ ipa_el: IPA ';'
|
||||
}
|
||||
;
|
||||
|
||||
ipa_ne: IPA ELIGIBLE ';'
|
||||
ipa_ne: ipa ELIGIBLE ';'
|
||||
{
|
||||
this_nbma = cfg_allocz(sizeof(struct nbma_node));
|
||||
add_tail(&OSPF_PATT->nbma_list, NODE this_nbma);
|
||||
|
@ -9,47 +9,77 @@
|
||||
#include "ospf.h"
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct ospf_dbdes_packet
|
||||
struct ospf_dbdes2_packet
|
||||
{
|
||||
struct ospf_packet ospf_packet;
|
||||
struct ospf_packet hdr;
|
||||
union ospf_auth auth;
|
||||
|
||||
u16 iface_mtu;
|
||||
u8 options;
|
||||
union imms imms; /* I, M, MS bits */
|
||||
u8 imms; /* I, M, MS bits */
|
||||
u32 ddseq;
|
||||
|
||||
struct ospf_lsa_header lsas[];
|
||||
};
|
||||
|
||||
struct ospf_dbdes3_packet
|
||||
{
|
||||
struct ospf_packet hdr;
|
||||
|
||||
u32 options;
|
||||
u16 iface_mtu;
|
||||
u8 padding;
|
||||
u8 imms; /* I, M, MS bits */
|
||||
u32 ddseq;
|
||||
|
||||
struct ospf_lsa_header lsas[];
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
#define hton_opt(X) X
|
||||
#define ntoh_opt(X) X
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OSPFv3
|
||||
struct ospf_dbdes_packet
|
||||
{
|
||||
struct ospf_packet ospf_packet;
|
||||
u32 options;
|
||||
u16 iface_mtu;
|
||||
u8 padding;
|
||||
union imms imms; /* I, M, MS bits */
|
||||
u32 ddseq;
|
||||
};
|
||||
|
||||
#define hton_opt(X) htonl(X)
|
||||
#define ntoh_opt(X) ntohl(X)
|
||||
#endif
|
||||
|
||||
|
||||
static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||
static inline unsigned
|
||||
ospf_dbdes_hdrlen(struct proto_ospf *po)
|
||||
{
|
||||
struct ospf_packet *op = &pkt->ospf_packet;
|
||||
return ospf_is_v2(po) ?
|
||||
sizeof(struct ospf_dbdes2_packet) :
|
||||
sizeof(struct ospf_dbdes3_packet);
|
||||
}
|
||||
|
||||
ASSERT(op->type == DBDES_P);
|
||||
ospf_dump_common(p, op);
|
||||
log(L_TRACE "%s: imms %s%s%s",
|
||||
p->name, pkt->imms.bit.ms ? "MS " : "",
|
||||
pkt->imms.bit.m ? "M " : "",
|
||||
pkt->imms.bit.i ? "I " : "" );
|
||||
static void
|
||||
ospf_dbdes_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
|
||||
struct ospf_lsa_header **body, unsigned *count)
|
||||
{
|
||||
unsigned hdrlen = ospf_dbdes_hdrlen(po);
|
||||
*body = ((void *) pkt) + hdrlen;
|
||||
*count = (plen - hdrlen) / sizeof(struct ospf_lsa_header);
|
||||
}
|
||||
|
||||
static void ospf_dbdes_dump(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_lsa_header *lsas;
|
||||
unsigned i, lsa_count;
|
||||
|
||||
ASSERT(pkt->type == DBDES_P);
|
||||
ospf_dump_common(po, pkt);
|
||||
|
||||
log(L_TRACE "%s: imms %s%s%s", p->name,
|
||||
(imms & DBDES_I) ? "I " : "",
|
||||
(imms & DBDES_M) ? "M " : "",
|
||||
(imms & DBDES_MS) ? "MS" : "");
|
||||
log(L_TRACE "%s: ddseq %u", p->name, ntohl(pkt->ddseq));
|
||||
|
||||
struct ospf_lsa_header *plsa = (void *) (pkt + 1);
|
||||
@ -59,7 +89,7 @@ static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||
sizeof(struct ospf_lsa_header);
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
ospf_dump_lsahdr(p, plsa + i);
|
||||
ospf_dump_lsahdr(p, &lsas[i]);
|
||||
}
|
||||
|
||||
|
||||
@ -77,12 +107,12 @@ static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||
void
|
||||
ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
{
|
||||
struct ospf_dbdes_packet *pkt;
|
||||
struct ospf_packet *op;
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct ospf_area *oa = ifa->oa;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
struct ospf_dbdes_packet *pkt;
|
||||
struct ospf_packet *op;
|
||||
u16 length, i, j;
|
||||
|
||||
/* FIXME ??? */
|
||||
@ -92,7 +122,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
switch (n->state)
|
||||
{
|
||||
case NEIGHBOR_EXSTART: /* Send empty packets */
|
||||
n->myimms.bit.i = 1;
|
||||
n->myimms |= DBDES_I;
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
op = &pkt->ospf_packet;
|
||||
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
||||
@ -108,7 +138,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
break;
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
n->myimms.bit.i = 0;
|
||||
n->myimms &= ~DBDES_I;
|
||||
|
||||
if (next)
|
||||
{
|
||||
@ -126,7 +156,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
|
||||
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
|
||||
|
||||
if (n->myimms.bit.m)
|
||||
if (n->myimms & DBDES_M)
|
||||
{
|
||||
sn = s_get(&(n->dbsi));
|
||||
|
||||
@ -158,13 +188,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
{
|
||||
DBG("Number of LSA NOT sent: %d\n", i);
|
||||
DBG("M bit unset.\n");
|
||||
n->myimms.bit.m = 0; /* Unset more bit */
|
||||
n->myimms &= ~DBDES_M; /* Unset more bit */
|
||||
}
|
||||
|
||||
s_put(&(n->dbsi), sn);
|
||||
}
|
||||
|
||||
pkt->imms.byte = n->myimms.byte;
|
||||
pkt->imms = n->myimms;
|
||||
|
||||
length = (j - i) * sizeof(struct ospf_lsa_header) +
|
||||
sizeof(struct ospf_dbdes_packet);
|
||||
@ -191,11 +221,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
|
||||
if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
|
||||
if (n->myimms & DBDES_MS)
|
||||
tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
|
||||
|
||||
if (!n->myimms.bit.ms)
|
||||
if (!(n->myimms & DBDES_MS))
|
||||
{
|
||||
if ((n->myimms.bit.m == 0) && (n->imms.bit.m == 0) &&
|
||||
if (!(n->myimms & DBDES_M) &&
|
||||
!(n->imms & DBDES_M) &&
|
||||
(n->state == NEIGHBOR_EXCHANGE))
|
||||
{
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
@ -244,11 +276,15 @@ ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
|
||||
}
|
||||
|
||||
void
|
||||
ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
u32 rcv_ddseq, rcv_options;
|
||||
u16 rcv_iface_mtu;
|
||||
u8 rcv_imms;
|
||||
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_dbdes_packet))
|
||||
@ -257,12 +293,24 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_dbdes_packet *ps = (void *) ps_i;
|
||||
u32 ps_ddseq = ntohl(ps->ddseq);
|
||||
u32 ps_options = ntoh_opt(ps->options);
|
||||
u16 ps_iface_mtu = ntohs(ps->iface_mtu);
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
struct ospf_dbdes2_packet *ps = (void *) pkt;
|
||||
rcv_iface_mtu = ntohs(ps->iface_mtu);
|
||||
rcv_options = ps->options;
|
||||
rcv_imms = ps->imms;
|
||||
rcv_ddseq = ntohl(ps->ddseq);
|
||||
}
|
||||
else /* OSPFv3 */
|
||||
{
|
||||
struct ospf_dbdes3_packet *ps = (void *) pkt;
|
||||
rcv_options = ntohl(ps->options);
|
||||
rcv_iface_mtu = ntohs(ps->iface_mtu);
|
||||
rcv_imms = ps->imms;
|
||||
rcv_ddseq = ntohl(ps->ddseq);
|
||||
}
|
||||
|
||||
OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_dbdes_dump, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
|
||||
@ -272,56 +320,62 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
case NEIGHBOR_ATTEMPT:
|
||||
case NEIGHBOR_2WAY:
|
||||
return;
|
||||
break;
|
||||
|
||||
case NEIGHBOR_INIT:
|
||||
ospf_neigh_sm(n, INM_2WAYREC);
|
||||
if (n->state != NEIGHBOR_EXSTART)
|
||||
return;
|
||||
|
||||
case NEIGHBOR_EXSTART:
|
||||
|
||||
if ((ps_iface_mtu != ifa->iface->mtu) && (ifa->type != OSPF_IT_VLINK)
|
||||
&& (ps_iface_mtu != 0) && (ifa->iface->mtu != 0))
|
||||
if ((rcv_iface_mtu != ifa->iface->mtu) &&
|
||||
(rcv_iface_mtu != 0) &&
|
||||
(ifa->iface->mtu != 0) &&
|
||||
(ifa->type != OSPF_IT_VLINK))
|
||||
log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
|
||||
n->ip, ifa->iface->name, ps_iface_mtu, ifa->iface->mtu);
|
||||
n->ip, ifa->iface->name, rcv_iface_mtu, ifa->iface->mtu);
|
||||
|
||||
if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
|
||||
&& (n->rid > po->router_id) && (size == sizeof(struct ospf_dbdes_packet)))
|
||||
if ((rcv_imms == DBDES_IMMS) &&
|
||||
(n->rid > po->router_id) &&
|
||||
(size == sizeof(struct ospf_dbdes_packet)))
|
||||
{
|
||||
/* I'm slave! */
|
||||
n->dds = ps_ddseq;
|
||||
n->ddr = ps_ddseq;
|
||||
n->options = ps_options;
|
||||
n->myimms.bit.ms = 0;
|
||||
n->imms.byte = ps->imms.byte;
|
||||
OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
|
||||
n->dds = rcv_ddseq;
|
||||
n->ddr = rcv_ddseq;
|
||||
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_dbdes_send(n, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
|
||||
(n->rid < po->router_id) && (n->dds == ps_ddseq))
|
||||
if (!(rcv_imms & DBDES_I) &&
|
||||
!(rcv_imms & DBDES_MS) &&
|
||||
(n->rid < po->router_id) &&
|
||||
(n->dds == rcv_ddseq))
|
||||
{
|
||||
/* I'm master! */
|
||||
n->options = ps_options;
|
||||
n->ddr = ps_ddseq - 1; /* It will be set corectly a few lines down */
|
||||
n->imms.byte = ps->imms.byte;
|
||||
OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
|
||||
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
|
||||
{
|
||||
DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, n->ip,
|
||||
ps->imms.byte);
|
||||
DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
|
||||
break;
|
||||
}
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options) &&
|
||||
(ps_ddseq == n->ddr))
|
||||
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.bit.ms == 0)
|
||||
if (!(n->myimms & DBDES_MS))
|
||||
{
|
||||
/* Slave should retransmit dbdes packet */
|
||||
ospf_dbdes_send(n, 0);
|
||||
@ -329,47 +383,43 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
return;
|
||||
}
|
||||
|
||||
n->ddr = ps_ddseq;
|
||||
|
||||
if (ps->imms.bit.ms != n->imms.bit.ms) /* M/S bit differs */
|
||||
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_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ps->imms.bit.i) /* I bit is set */
|
||||
if (rcv_imms & DBDES_I) /* I bit is set */
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)",
|
||||
n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
break;
|
||||
}
|
||||
|
||||
n->imms.byte = ps->imms.byte;
|
||||
|
||||
if (ps_options != n->options) /* Options differs */
|
||||
if (rcv_options != n->options) /* Options differs */
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
|
||||
n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n->myimms.bit.ms)
|
||||
n->ddr = rcv_ddseq;
|
||||
n->imms = rcv_imms;
|
||||
|
||||
if (n->myimms & DBDES_MS)
|
||||
{
|
||||
if (ps_ddseq != n->dds) /* MASTER */
|
||||
if (rcv_ddseq != n->dds) /* MASTER */
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS,
|
||||
"dbdes - sequence mismatch neighbor %I (master)", n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
break;
|
||||
}
|
||||
n->dds++;
|
||||
DBG("Incrementing dds\n");
|
||||
ospf_dbdes_reqladd(ps, n);
|
||||
if ((n->myimms.bit.m == 0) && (ps->imms.bit.m == 0))
|
||||
if (!(n->myimms & DBDES_M) &&
|
||||
!(rcv_imms & DBDES_M))
|
||||
{
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
}
|
||||
@ -381,28 +431,28 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ps_ddseq != (n->dds + 1)) /* SLAVE */
|
||||
if (rcv_ddseq != (n->dds + 1)) /* SLAVE */
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)",
|
||||
n->ip);
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
|
||||
ospf_neigh_sm(n, INM_SEQMIS);
|
||||
break;
|
||||
}
|
||||
n->ddr = ps_ddseq;
|
||||
n->dds = ps_ddseq;
|
||||
n->ddr = rcv_ddseq;
|
||||
n->dds = rcv_ddseq;
|
||||
ospf_dbdes_reqladd(ps, n);
|
||||
ospf_dbdes_send(n, 1);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NEIGHBOR_LOADING:
|
||||
case NEIGHBOR_FULL:
|
||||
if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options)
|
||||
&& (ps_ddseq == n->ddr))
|
||||
if ((rcv_imms == n->imms) &&
|
||||
(rcv_options == n->options) &&
|
||||
(rcv_ddseq == n->ddr))
|
||||
/* Only duplicate are accepted */
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
|
||||
if (n->myimms.bit.ms == 0)
|
||||
if (!(n->myimms & DBDES_MS))
|
||||
{
|
||||
/* Slave should retransmit dbdes packet */
|
||||
ospf_dbdes_send(n, 0);
|
||||
@ -411,9 +461,8 @@ ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
else
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
|
||||
n->ip);
|
||||
DBG("PS=%u, DDR=%u, DDS=%u\n", ps_ddseq, n->ddr, n->dds);
|
||||
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;
|
||||
|
@ -9,25 +9,26 @@
|
||||
#include "ospf.h"
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct ospf_hello_packet
|
||||
struct ospf_hello2_packet
|
||||
{
|
||||
struct ospf_packet ospf_packet;
|
||||
ip_addr netmask;
|
||||
struct ospf_packet hdr;
|
||||
union ospf_auth auth;
|
||||
|
||||
u32 netmask;
|
||||
u16 helloint;
|
||||
u8 options;
|
||||
u8 priority;
|
||||
u32 deadint;
|
||||
u32 dr;
|
||||
u32 bdr;
|
||||
|
||||
u32 neighbors[];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OSPFv3
|
||||
struct ospf_hello_packet
|
||||
struct ospf_hello3_packet
|
||||
{
|
||||
struct ospf_packet ospf_packet;
|
||||
struct ospf_packet hdr;
|
||||
|
||||
u32 iface_id;
|
||||
u8 priority;
|
||||
u8 options3;
|
||||
@ -37,67 +38,100 @@ struct ospf_hello_packet
|
||||
u16 deadint;
|
||||
u32 dr;
|
||||
u32 bdr;
|
||||
|
||||
u32 neighbors[];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
ospf_hello_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n, ip_addr faddr)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
char *beg = "OSPF: Bad HELLO packet from ";
|
||||
unsigned int size, i, twoway, peers;
|
||||
u32 tmp;
|
||||
u32 *pnrid;
|
||||
unsigned int size, i, two_way;
|
||||
|
||||
size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_hello_packet))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
|
||||
return;
|
||||
}
|
||||
u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
|
||||
u8 rcv_options, rcv_priority;
|
||||
|
||||
u32 *neighbors;
|
||||
u32 neigh_count;
|
||||
|
||||
struct ospf_hello_packet *ps = (void *) ps_i;
|
||||
|
||||
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
||||
|
||||
#ifdef OSPFv2
|
||||
ip_addr mask = ps->netmask;
|
||||
ipa_ntoh(mask);
|
||||
if ((ifa->type != OSPF_IT_VLINK) &&
|
||||
(ifa->type != OSPF_IT_PTP) &&
|
||||
!ipa_equal(mask, ipa_mkmask(ifa->addr->pxlen)))
|
||||
size = ntohs(pkt->length);
|
||||
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
log(L_ERR "%s%I - netmask mismatch (%I)", beg, faddr, mask);
|
||||
return;
|
||||
struct ospf_hello2_packet *ps = (void *) pkt;
|
||||
|
||||
if (size < sizeof(struct ospf_hello2_packet))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
|
||||
return;
|
||||
}
|
||||
|
||||
rcv_iface_id = 0;
|
||||
rcv_helloint = ntohs(ps->helloint);
|
||||
rcv_deadint = ntohl(ps->deadint);
|
||||
rcv_dr = ntohl(ps->dr);
|
||||
rcv_bdr = ntohl(ps->bdr);
|
||||
rcv_options = ps->options;
|
||||
rcv_priority = ps->priority;
|
||||
|
||||
int pxlen = u32_masklen(ntohl(ps->netmask));
|
||||
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;
|
||||
}
|
||||
|
||||
neighbors = ps->neighbors;
|
||||
neigh_count = (size - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
|
||||
}
|
||||
#endif
|
||||
|
||||
tmp = ntohs(ps->helloint);
|
||||
if (tmp != ifa->helloint)
|
||||
else /* OSPFv3 */
|
||||
{
|
||||
log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, tmp);
|
||||
struct ospf_hello3_packet *ps = (void *) pkt;
|
||||
|
||||
if (size < sizeof(struct ospf_hello3_packet))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
|
||||
return;
|
||||
}
|
||||
|
||||
rcv_iface_id = ntohl(ps->iface_id);
|
||||
rcv_helloint = ntohs(ps->helloint);
|
||||
rcv_deadint = ntohs(ps->deadint);
|
||||
rcv_dr = ntohl(ps->dr);
|
||||
rcv_bdr = ntohl(ps->bdr);
|
||||
rcv_options = ps->options;
|
||||
rcv_priority = ps->priority;
|
||||
|
||||
neighbors = ps->neighbors;
|
||||
neigh_count = (size - sizeof(struct ospf_hello3_packet)) / sizeof(u32);
|
||||
}
|
||||
|
||||
if (rcv_helloint != ifa->helloint)
|
||||
{
|
||||
log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, rcv_helloint);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef OSPFv2
|
||||
tmp = ntohl(ps->deadint);
|
||||
#else /* OSPFv3 */
|
||||
tmp = ntohs(ps->deadint);
|
||||
#endif
|
||||
if (tmp != ifa->deadint)
|
||||
if (rcv_deadint != ifa->deadint)
|
||||
{
|
||||
log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, tmp);
|
||||
log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, rcv_deadint);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether bits E, N match */
|
||||
if ((ps->options ^ ifa->oa->options) & (OPT_E | OPT_N))
|
||||
if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
|
||||
{
|
||||
log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, ps->options);
|
||||
log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, rcv_options);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -115,8 +149,8 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
|
||||
if (nn && (ifa->type == OSPF_IT_NBMA) &&
|
||||
(((ps->priority == 0) && nn->eligible) ||
|
||||
((ps->priority > 0) && !nn->eligible)))
|
||||
(((rcv_priority == 0) && nn->eligible) ||
|
||||
((rcv_priority > 0) && !nn->eligible)))
|
||||
{
|
||||
log(L_ERR "Eligibility mismatch for neighbor: %I on %s",
|
||||
faddr, ifa->iface->name);
|
||||
@ -132,85 +166,67 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
|
||||
n = ospf_neighbor_new(ifa);
|
||||
|
||||
n->rid = ntohl(((struct ospf_packet *) ps)->routerid);
|
||||
n->rid = ntohl(pkt->routerid);
|
||||
n->ip = faddr;
|
||||
n->dr = ntohl(ps->dr);
|
||||
n->bdr = ntohl(ps->bdr);
|
||||
n->priority = ps->priority;
|
||||
#ifdef OSPFv3
|
||||
n->iface_id = ntohl(ps->iface_id);
|
||||
#endif
|
||||
n->dr = rcv_dr;
|
||||
n->bdr = rcv_bdr;
|
||||
n->priority = rcv_priority;
|
||||
n->iface_id = rcv_iface_id;
|
||||
}
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
|
||||
pnrid = (u32 *) ((struct ospf_hello_packet *) (ps + 1));
|
||||
|
||||
peers = (size - sizeof(struct ospf_hello_packet))/ sizeof(u32);
|
||||
|
||||
twoway = 0;
|
||||
for (i = 0; i < peers; i++)
|
||||
two_way = 0;
|
||||
for (i = 0; i < neigh_count; i++)
|
||||
{
|
||||
if (ntohl(pnrid[i]) == po->router_id)
|
||||
if (ntohl(neighbors[i]) == po->router_id)
|
||||
{
|
||||
DBG("%s: Twoway received from %I\n", p->name, faddr);
|
||||
ospf_neigh_sm(n, INM_2WAYREC);
|
||||
twoway = 1;
|
||||
two_way = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!twoway)
|
||||
if (!two_way)
|
||||
ospf_neigh_sm(n, INM_1WAYREC);
|
||||
|
||||
u32 olddr = n->dr;
|
||||
u32 oldbdr = n->bdr;
|
||||
u32 oldpriority = n->priority;
|
||||
#ifdef OSPFv3
|
||||
u32 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
|
||||
u32 old_dr = n->dr;
|
||||
u32 old_bdr = n->bdr;
|
||||
u32 old_priority = n->priority;
|
||||
u32 old_iface_id = n->iface_id;
|
||||
|
||||
n->dr = rcv_dr;
|
||||
n->bdr = rcv_bdr;
|
||||
n->priority = rcv_priority;
|
||||
n->iface_id = rcv_iface_id;
|
||||
|
||||
/* Check priority change */
|
||||
if (n->state >= NEIGHBOR_2WAY)
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
u32 neigh = ipa_to_u32(n->ip);
|
||||
#else /* OSPFv3 */
|
||||
u32 neigh = n->rid;
|
||||
#endif
|
||||
u32 n_id = ospf_is_v2(po) ? ipa_to_u32(n->ip) : n->rid;
|
||||
|
||||
if (n->priority != oldpriority)
|
||||
if (n->priority != old_priority)
|
||||
ospf_iface_sm(ifa, ISM_NEICH);
|
||||
|
||||
#ifdef OSPFv3
|
||||
if (n->iface_id != oldiface_id)
|
||||
if (n->iface_id != old_iface_id)
|
||||
ospf_iface_sm(ifa, ISM_NEICH);
|
||||
#endif
|
||||
|
||||
/* Neighbor is declaring itself ad DR and there is no BDR */
|
||||
if ((n->dr == neigh) && (n->bdr == 0)
|
||||
if ((n->dr == n_id) && (n->bdr == 0)
|
||||
&& (n->state != NEIGHBOR_FULL))
|
||||
ospf_iface_sm(ifa, ISM_BACKS);
|
||||
|
||||
/* Neighbor is declaring itself as BDR */
|
||||
if ((n->bdr == neigh) && (n->state != NEIGHBOR_FULL))
|
||||
if ((n->bdr == n_id) && (n->state != NEIGHBOR_FULL))
|
||||
ospf_iface_sm(ifa, ISM_BACKS);
|
||||
|
||||
/* Neighbor is newly declaring itself as DR or BDR */
|
||||
if (((n->dr == neigh) && (n->dr != olddr))
|
||||
|| ((n->bdr == neigh) && (n->bdr != oldbdr)))
|
||||
if (((n->dr == n_id) && (n->dr != old_dr))
|
||||
|| ((n->bdr == n_id) && (n->bdr != old_bdr)))
|
||||
ospf_iface_sm(ifa, ISM_NEICH);
|
||||
|
||||
/* Neighbor is no more declaring itself as DR or BDR */
|
||||
if (((olddr == neigh) && (n->dr != olddr))
|
||||
|| ((oldbdr == neigh) && (n->bdr != oldbdr)))
|
||||
if (((old_dr == n_id) && (n->dr != old_dr))
|
||||
|| ((old_bdr == n_id) && (n->bdr != old_bdr)))
|
||||
ospf_iface_sm(ifa, ISM_NEICH);
|
||||
}
|
||||
|
||||
@ -225,13 +241,14 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
void
|
||||
ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
|
||||
{
|
||||
struct ospf_hello_packet *pkt;
|
||||
struct ospf_packet *op;
|
||||
struct proto *p;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_packet *pkt;
|
||||
struct ospf_neighbor *neigh, *n1;
|
||||
u16 length;
|
||||
int i;
|
||||
struct nbma_node *nb;
|
||||
u32 *neighbors;
|
||||
u16 length;
|
||||
int i, max;
|
||||
|
||||
if (ifa->state <= OSPF_IS_LOOP)
|
||||
return;
|
||||
@ -239,65 +256,69 @@ ospf_hello_send(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
|
||||
if (ifa->stub)
|
||||
return; /* Don't send any packet on stub iface */
|
||||
|
||||
p = (struct proto *) (ifa->oa->po);
|
||||
DBG("%s: Hello/Poll timer fired on interface %s with IP %I\n",
|
||||
p->name, ifa->iface->name, ifa->addr->ip);
|
||||
|
||||
/* Now we should send a hello packet */
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
op = &pkt->ospf_packet;
|
||||
|
||||
/* Now fill ospf_hello header */
|
||||
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
|
||||
|
||||
#ifdef OSPFv2
|
||||
pkt->netmask = ipa_mkmask(ifa->addr->pxlen);
|
||||
ipa_hton(pkt->netmask);
|
||||
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
|
||||
pkt->netmask = IPA_NONE;
|
||||
#endif
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
struct ospf_hello2_packet *ps = (void *) pkt;
|
||||
|
||||
pkt->helloint = ntohs(ifa->helloint);
|
||||
pkt->priority = ifa->priority;
|
||||
ps->netmask = htonl(u32_mkmask(ifa->addr->pxlen));
|
||||
|
||||
#ifdef OSPFv3
|
||||
pkt->iface_id = htonl(ifa->iface->index);
|
||||
if ((ifa->type == OSPF_IT_VLINK) || (ifa->type == OSPF_IT_PTP))
|
||||
ps->netmask = 0;
|
||||
|
||||
pkt->options3 = ifa->oa->options >> 16;
|
||||
pkt->options2 = ifa->oa->options >> 8;
|
||||
#endif
|
||||
pkt->options = ifa->oa->options;
|
||||
ps->helloint = ntohs(ifa->helloint);
|
||||
ps->options = ifa->oa->options;
|
||||
ps->priority = ifa->priority;
|
||||
ps->deadint = htonl(ifa->deadint);
|
||||
ps->dr = htonl(ipa_to_u32(ifa->drip));
|
||||
ps->bdr = htonl(ipa_to_u32(ifa->bdrip));
|
||||
|
||||
#ifdef OSPFv2
|
||||
pkt->deadint = htonl(ifa->deadint);
|
||||
pkt->dr = htonl(ipa_to_u32(ifa->drip));
|
||||
pkt->bdr = htonl(ipa_to_u32(ifa->bdrip));
|
||||
#else /* OSPFv3 */
|
||||
pkt->deadint = htons(ifa->deadint);
|
||||
pkt->dr = htonl(ifa->drid);
|
||||
pkt->bdr = htonl(ifa->bdrid);
|
||||
#endif
|
||||
length = sizeof(struct ospf_hello2_packet);
|
||||
neighbors = ps->neighbors;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ospf_hello3_packet *ps = (void *) pkt;
|
||||
|
||||
ps->iface_id = htonl(ifa->iface->index);
|
||||
ps->priority = ifa->priority;
|
||||
ps->options3 = ifa->oa->options >> 16;
|
||||
ps->options2 = ifa->oa->options >> 8;
|
||||
ps->options = ifa->oa->options;
|
||||
ps->helloint = ntohs(ifa->helloint);
|
||||
ps->deadint = htons(ifa->deadint);
|
||||
ps->dr = htonl(ifa->drid);
|
||||
ps->bdr = htonl(ifa->bdrid);
|
||||
|
||||
length = sizeof(struct ospf_hello3_packet);
|
||||
neighbors = ps->neighbors;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
max = (ospf_pkt_bufsize(ifa) - length) / sizeof(u32);
|
||||
|
||||
/* Fill all neighbors */
|
||||
i = 0;
|
||||
|
||||
if (kind != OHS_SHUTDOWN)
|
||||
{
|
||||
u32 *pp = (u32 *) (((u8 *) pkt) + sizeof(struct ospf_hello_packet));
|
||||
WALK_LIST(neigh, ifa->neigh_list)
|
||||
{
|
||||
if ((i+1) * sizeof(u32) + sizeof(struct ospf_hello_packet) > ospf_pkt_bufsize(ifa))
|
||||
if (i == max)
|
||||
{
|
||||
log(L_WARN "%s: Too many neighbors on interface %s", p->name, ifa->iface->name);
|
||||
break;
|
||||
}
|
||||
*(pp + i) = htonl(neigh->rid);
|
||||
neighbors[i] = htonl(neigh->rid);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
length = sizeof(struct ospf_hello_packet) + i * sizeof(u32);
|
||||
op->length = htons(length);
|
||||
length += i * sizeof(u32);
|
||||
pkt->length = htons(length);
|
||||
|
||||
switch(ifa->type)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ static void
|
||||
wait_timer_hook(timer * timer)
|
||||
{
|
||||
struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
|
||||
ospf_iface_sm(ifa, ISM_WAITF);
|
||||
@ -172,9 +172,8 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
|
||||
static void
|
||||
ospf_iface_down(struct ospf_iface *ifa)
|
||||
{
|
||||
struct ospf_neighbor *n, *nx;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_neighbor *n, *nx;
|
||||
struct ospf_iface *iff;
|
||||
|
||||
if (ifa->type != OSPF_IT_VLINK)
|
||||
@ -232,7 +231,8 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||
void
|
||||
ospf_iface_remove(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
OSPF_TRACE(D_EVENTS, "Removing vlink to %R via area %R", ifa->vid, ifa->voa->areaid);
|
||||
|
||||
@ -261,7 +261,6 @@ void
|
||||
ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
u8 oldstate = ifa->state;
|
||||
|
||||
if (oldstate == state)
|
||||
@ -490,7 +489,7 @@ ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
|
||||
void
|
||||
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
|
||||
{
|
||||
struct proto *p = &oa->po->proto;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct iface *iface = addr ? addr->iface : NULL;
|
||||
struct pool *pool;
|
||||
|
||||
@ -511,7 +510,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
#endif
|
||||
}
|
||||
|
||||
pool = rp_new(p->pool, "OSPF Interface");
|
||||
pool = rp_new(po->proto.pool, "OSPF Interface");
|
||||
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
|
||||
ifa->iface = iface;
|
||||
ifa->addr = addr;
|
||||
@ -625,7 +624,7 @@ ospf_iface_change_timer(timer *tm, unsigned val)
|
||||
int
|
||||
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
{
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct nbma_node *nb, *nbx;
|
||||
char *ifname = (ifa->type != OSPF_IT_VLINK) ? ifa->iface->name : "vlink";
|
||||
|
||||
@ -1047,7 +1046,6 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
static void
|
||||
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_packet *op;
|
||||
struct ospf_neighbor *n;
|
||||
OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->iface->name);
|
||||
|
@ -9,29 +9,38 @@
|
||||
#include "ospf.h"
|
||||
|
||||
|
||||
/*
|
||||
struct ospf_lsack_packet
|
||||
{
|
||||
struct ospf_packet ospf_packet;
|
||||
struct ospf_lsa_header lsh[];
|
||||
struct ospf_packet hdr;
|
||||
// union ospf_auth auth;
|
||||
|
||||
struct ospf_lsa_header lsas[];
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
char *s_queue[] = { "direct", "delayed" };
|
||||
|
||||
|
||||
static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
|
||||
static void
|
||||
ospf_lsack_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
|
||||
struct ospf_lsa_header **body, unsigned *count)
|
||||
{
|
||||
struct ospf_packet *op = &pkt->ospf_packet;
|
||||
unsigned hdrlen = ospf_pkt_hdrlen(po);
|
||||
*body = ((void *) pkt) + hdrlen;
|
||||
*count = (plen - hdrlen) / sizeof(struct ospf_lsa_header);
|
||||
}
|
||||
|
||||
ASSERT(op->type == LSACK_P);
|
||||
ospf_dump_common(p, op);
|
||||
static void
|
||||
ospf_lsack_dump(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
{
|
||||
struct ospf_lsa_header *lsas;
|
||||
unsigned i, lsa_count;
|
||||
|
||||
unsigned int i, j;
|
||||
j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
|
||||
sizeof(struct ospf_lsa_header);
|
||||
ASSERT(pkt->type == LSACK_P);
|
||||
ospf_dump_common(po, pkt);
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
ospf_dump_lsahdr(p, pkt->lsh + i);
|
||||
ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
ospf_dump_lsahdr(po, lsas + i);
|
||||
}
|
||||
|
||||
|
||||
@ -42,87 +51,47 @@ static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
|
||||
*/
|
||||
|
||||
void
|
||||
ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h,
|
||||
int queue)
|
||||
ospf_lsack_enqueue(struct ospf_neighbor *n, struct ospf_lsa_header *h, int queue)
|
||||
{
|
||||
struct lsah_n *no = mb_alloc(n->pool, sizeof(struct lsah_n));
|
||||
memcpy(&no->lsa, h, sizeof(struct ospf_lsa_header));
|
||||
add_tail(&n->ackl[queue], NODE no);
|
||||
DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n", s_queue[queue],
|
||||
DBG("Adding (%s) ack for %R, ID: %R, RT: %R, Type: %u\n",
|
||||
(queue == ACKL_DIRECT) ? "direct" : "delayed",
|
||||
n->rid, ntohl(h->id), ntohl(h->rt), h->type);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
||||
static inline void
|
||||
ospf_lsack_send_one(struct ospf_neighbor *n, int queue)
|
||||
{
|
||||
struct ospf_packet *op;
|
||||
struct ospf_lsack_packet *pk;
|
||||
u16 len, i = 0;
|
||||
struct ospf_lsa_header *h;
|
||||
struct lsah_n *no;
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto *p = &n->ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct ospf_lsa_header *lsas;
|
||||
struct ospf_packet *pkt;
|
||||
struct lsah_n *no;
|
||||
unsigned i, lsa_max, length;
|
||||
|
||||
if (EMPTY_LIST(n->ackl[queue]))
|
||||
return;
|
||||
|
||||
pk = ospf_tx_buffer(ifa);
|
||||
op = &pk->ospf_packet;
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
ospf_pkt_fill_hdr(ifa, pkt, LSACK_P);
|
||||
ospf_lsack_body(po, pkt, ospf_pkt_maxsize(ifa), &lsas, &lsa_max);
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
||||
h = pk->lsh;
|
||||
|
||||
while (!EMPTY_LIST(n->ackl[queue]))
|
||||
for (i = 0; i < lsa_max && !EMPTY_LIST(n->ackl[queue]); i++)
|
||||
{
|
||||
no = (struct lsah_n *) HEAD(n->ackl[queue]);
|
||||
memcpy(h + i, &no->lsa, sizeof(struct ospf_lsa_header));
|
||||
DBG("Iter %u ID: %R, RT: %R, Type: %04x\n", i, ntohl((h + i)->id),
|
||||
ntohl((h + i)->rt), (h + i)->type);
|
||||
i++;
|
||||
memcpy(&lsas[i], &no->lsa, sizeof(struct ospf_lsa_header));
|
||||
DBG("Iter %u ID: %R, RT: %R, Type: %04x\n",
|
||||
i, ntohl(lsas[i].id), ntohl(lsas[i].rt), lsas[i].type);
|
||||
rem_node(NODE no);
|
||||
mb_free(no);
|
||||
if ((i * sizeof(struct ospf_lsa_header) +
|
||||
sizeof(struct ospf_lsack_packet)) > ospf_pkt_maxsize(n->ifa))
|
||||
{
|
||||
if (!EMPTY_LIST(n->ackl[queue]))
|
||||
{
|
||||
len =
|
||||
sizeof(struct ospf_lsack_packet) +
|
||||
i * sizeof(struct ospf_lsa_header);
|
||||
op->length = htons(len);
|
||||
DBG("Sending and continuing! Len=%u\n", len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_all(ifa);
|
||||
else if (ifa->cf->real_bcast)
|
||||
ospf_send_to_bdr(ifa);
|
||||
else
|
||||
ospf_send_to(ifa, AllDRouters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
ospf_send_to_bdr(ifa);
|
||||
}
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len = sizeof(struct ospf_lsack_packet) + i * sizeof(struct ospf_lsa_header);
|
||||
op->length = htons(len);
|
||||
DBG("Sending! Len=%u\n", len);
|
||||
length = ospf_pkt_hdrlen(po) + i * sizeof(struct ospf_lsa_header);
|
||||
pkt->length = htons(length);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsack, pk, "LSACK packet sent via %s", ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet sent via %s", ifa->iface->name);
|
||||
|
||||
/* XXXX this is very strange */
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
@ -134,37 +103,46 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
||||
}
|
||||
else
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
|
||||
/*
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
ospf_send_to_bdr(ifa);
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
||||
{
|
||||
while (!EMPTY_LIST(n->ackl[queue]))
|
||||
ospf_lsack_send_one(n, queue);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct ospf_lsa_header lsa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct ospf_lsa_header lsa, *lsas;
|
||||
struct top_hash_entry *en;
|
||||
unsigned int i, lsano;
|
||||
unsigned i, lsa_count;
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_lsack_packet))
|
||||
{
|
||||
log(L_ERR "Bad OSPF LSACK packet from %I - too short (%u B)", n->ip, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_lsack_packet *ps = (void *) ps_i;
|
||||
OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
/* No need to check length, lsack has only basic header */
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet received from %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
return;
|
||||
|
||||
lsano = (size - sizeof(struct ospf_lsack_packet)) /
|
||||
sizeof(struct ospf_lsa_header);
|
||||
for (i = 0; i < lsano; i++)
|
||||
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
|
||||
|
||||
ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
{
|
||||
ntohlsah(ps->lsh + i, &lsa);
|
||||
ntohlsah(&lsas[i], &lsa);
|
||||
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
|
||||
if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
|
||||
continue; /* pg 155 */
|
||||
|
@ -11,11 +11,9 @@
|
||||
void
|
||||
flush_lsa(struct top_hash_entry *en, struct proto_ospf *po)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
OSPF_TRACE(D_EVENTS,
|
||||
"Going to remove LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seqno: 0x%x",
|
||||
en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.age, en->lsa.sn);
|
||||
s_rem_node(SNODE en);
|
||||
if (en->lsa_body != NULL)
|
||||
mb_free(en->lsa_body);
|
||||
@ -30,7 +28,7 @@ ospf_flush_area(struct proto_ospf *po, u32 areaid)
|
||||
|
||||
WALK_SLIST_DELSAFE(en, nxt, po->lsal)
|
||||
{
|
||||
if ((LSA_SCOPE(&en->lsa) == LSA_SCOPE_AREA) && (en->domain == areaid))
|
||||
if ((LSA_SCOPE(en->lsa_type) == LSA_SCOPE_AREA) && (en->domain == areaid))
|
||||
flush_lsa(en, po);
|
||||
}
|
||||
}
|
||||
@ -53,7 +51,6 @@ ospf_flush_area(struct proto_ospf *po, u32 areaid)
|
||||
void
|
||||
ospf_age(struct proto_ospf *po)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct top_hash_entry *en, *nxt;
|
||||
int flush = can_flush_lsa(po);
|
||||
|
||||
@ -68,7 +65,7 @@ ospf_age(struct proto_ospf *po)
|
||||
if ((en->lsa.rt == po->router_id) && (en->lsa.age >= LSREFRESHTIME))
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %R, Rt: %R",
|
||||
en->lsa.type, en->lsa.id, en->lsa.rt);
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt);
|
||||
en->lsa.sn++;
|
||||
en->lsa.age = 0;
|
||||
en->inst_t = now;
|
||||
@ -95,10 +92,7 @@ void
|
||||
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
|
||||
{
|
||||
n->age = htons(h->age);
|
||||
#ifdef OSPFv2
|
||||
n->options = h->options;
|
||||
#endif
|
||||
n->type = htont(h->type);
|
||||
n->type_raw = htont(h->type_raw);
|
||||
n->id = htonl(h->id);
|
||||
n->rt = htonl(h->rt);
|
||||
n->sn = htonl(h->sn);
|
||||
@ -110,10 +104,7 @@ void
|
||||
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
|
||||
{
|
||||
h->age = ntohs(n->age);
|
||||
#ifdef OSPFv2
|
||||
h->options = n->options;
|
||||
#endif
|
||||
h->type = ntoht(n->type);
|
||||
h->type_raw = ntoht(n->type_raw);
|
||||
h->id = ntohl(n->id);
|
||||
h->rt = ntohl(n->rt);
|
||||
h->sn = ntohl(n->sn);
|
||||
@ -292,6 +283,147 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
|
||||
return CMP_SAME;
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
lsa_walk_rt2(struct ospf_lsa_rt_walk *rt)
|
||||
{
|
||||
if (rt->buf >= rt->bufend)
|
||||
return 0;
|
||||
|
||||
struct ospf_lsa_rt2_link *l = rt->buf;
|
||||
rt->buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
|
||||
|
||||
rt->type = l->type;
|
||||
rt->metric = l->metric;
|
||||
rt->id = l->id;
|
||||
rt->data = l->data;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
lsa_walk_rt3(struct ospf_lsa_rt_walk *rt)
|
||||
{
|
||||
while (rt->buf >= rt->bufend)
|
||||
{
|
||||
rt->en = ospf_hash_find_rt_next(rt->en);
|
||||
if (!rt->en)
|
||||
return 0;
|
||||
|
||||
rt->buf = rt->en->lsa_body;
|
||||
rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
|
||||
rt->buf += sizeof(struct ospf_lsa_rt);
|
||||
}
|
||||
|
||||
struct ospf_lsa_rt3_link *l = rt->buf;
|
||||
rt->buf += sizeof(struct ospf_lsa_rt3_link);
|
||||
|
||||
rt->type = l->type;
|
||||
rt->metric = l->metric;
|
||||
rt->lif = l->lif;
|
||||
rt->nif = l->nif;
|
||||
rt->id = l->id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt)
|
||||
{
|
||||
rt->ospf2 = ospf_is_v2(po);
|
||||
rt->id = rt->data = rt->lif = rt->nif = 0;
|
||||
|
||||
if (rt->ospf2)
|
||||
rt->en = act;
|
||||
else
|
||||
rt->en = ospf_hash_find_rt_first(po->gr, act->domain, act->lsa.rt);
|
||||
|
||||
rt->buf = rt->en->lsa_body;
|
||||
rt->bufend = rt->buf + rt->en->lsa.length - sizeof(struct ospf_lsa_header);
|
||||
rt->buf += sizeof(struct ospf_lsa_rt);
|
||||
}
|
||||
|
||||
int
|
||||
lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
|
||||
{
|
||||
return rt->ospf2 ? lsa_walk_rt2(rt) : lsa_walk_rt3(rt);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric)
|
||||
{
|
||||
if (ospf2)
|
||||
{
|
||||
struct ospf_lsa_sum2 *ls = en->lsa_body;
|
||||
*ip = ipa_from_u32(en->lsa.id & ls->netmask);
|
||||
*pxlen = u32_masklen(ls->netmask);
|
||||
*pxopts = 0;
|
||||
*metric = ls->metric & METRIC_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ospf_lsa_sum3_net *ls = en->lsa_body;
|
||||
u16 rest;
|
||||
lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
|
||||
*metric = ls->metric & METRIC_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options)
|
||||
{
|
||||
if (ospf2)
|
||||
{
|
||||
struct ospf_lsa_sum2 *ls = en->lsa_body;
|
||||
*drid = en->lsa.id;
|
||||
*metric = ls->metric & METRIC_MASK;
|
||||
*options = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ospf_lsa_sum3_rt *ls = en->lsa_body;
|
||||
*drid = ls->drid;
|
||||
*metric = ls->metric & METRIC_MASK;
|
||||
*options = ls->options & OPTIONS_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt)
|
||||
{
|
||||
if (ospf2)
|
||||
{
|
||||
struct ospf_lsa_ext2 *ext = en->lsa_body;
|
||||
rt->ip = ipa_from_u32(en->lsa.id & ext->netmask);
|
||||
rt->pxlen = u32_masklen(ext->netmask);
|
||||
rt->pxopts = 0;
|
||||
rt->metric = ext->metric & METRIC_MASK;
|
||||
rt->ebit = ext->metric & LSA_EXT2_EBIT;
|
||||
|
||||
rt->fbit = ip4_nonzero(ext->fwaddr);
|
||||
rt->fwaddr = ipa_from_ip4(ext->fwaddr);
|
||||
|
||||
rt->tag = ext->tag;
|
||||
rt->propagate = lsa_get_options(&en->lsa) & OPT_P;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ospf_lsa_ext3 *ext = en->lsa_body;
|
||||
u16 rest;
|
||||
u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest);
|
||||
rt->metric = ext->metric & METRIC_MASK;
|
||||
rt->ebit = ext->metric & LSA_EXT3_EBIT;
|
||||
|
||||
rt->fbit = ext->metric & LSA_EXT3_FBIT;
|
||||
if (rt->fbit)
|
||||
buf = lsa_get_ipv6_addr(buf, &rt->fwaddr);
|
||||
else
|
||||
rt->fwaddr = IPA_NONE;
|
||||
|
||||
rt->tag = (ext->metric & LSA_EXT3_TBIT) ? *buf++ : 0;
|
||||
rt->propagate = rt->pxopts & OPT_PX_P;
|
||||
}
|
||||
}
|
||||
|
||||
#define HDRLEN sizeof(struct ospf_lsa_header)
|
||||
|
||||
static int
|
||||
@ -372,16 +504,16 @@ pxlen(u32 *buf)
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_net *body)
|
||||
lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum_net) + 4))
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
|
||||
return 0;
|
||||
|
||||
u8 pxl = pxlen(body->prefix);
|
||||
if (pxl > MAX_PREFIX_LENGTH)
|
||||
return 0;
|
||||
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_net) +
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
|
||||
IPV6_PREFIX_SPACE(pxl)))
|
||||
return 0;
|
||||
|
||||
@ -390,18 +522,18 @@ lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_net *body)
|
||||
|
||||
|
||||
static int
|
||||
lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_rt *body)
|
||||
lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
|
||||
{
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_rt)))
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
|
||||
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext) + 4))
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
|
||||
return 0;
|
||||
|
||||
u8 pxl = pxlen(body->rest);
|
||||
@ -409,14 +541,14 @@ lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
|
||||
return 0;
|
||||
|
||||
int len = IPV6_PREFIX_SPACE(pxl);
|
||||
if (body->metric & LSA_EXT_FBIT) // forwardinf address
|
||||
if (body->metric & LSA_EXT3_FBIT) // forwardinf address
|
||||
len += 16;
|
||||
if (body->metric & LSA_EXT_TBIT) // route tag
|
||||
if (body->metric & LSA_EXT3_TBIT) // route tag
|
||||
len += 4;
|
||||
if (*body->rest & 0xFFFF) // referenced LS type field
|
||||
len += 4;
|
||||
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext) + len))
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext3) + len))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -492,12 +624,10 @@ lsa_validate(struct ospf_lsa_header *lsa, void *body)
|
||||
case LSA_T_EXT:
|
||||
case LSA_T_NSSA:
|
||||
return lsa_validate_ext(lsa, body);
|
||||
#ifdef OSPFv3
|
||||
case LSA_T_LINK:
|
||||
return lsa_validate_link(lsa, body);
|
||||
case LSA_T_PREFIX:
|
||||
return lsa_validate_prefix(lsa, body);
|
||||
#endif
|
||||
default:
|
||||
/* In OSPFv3, unknown LSAs are OK,
|
||||
In OSPFv2, unknown LSAs are already rejected
|
||||
|
@ -26,12 +26,25 @@ static inline void htonlsab1(void *h, u16 len) { htonlsab(h, h, len); };
|
||||
static inline void ntohlsab1(void *n, u16 len) { ntohlsab(n, n, len); };
|
||||
#endif
|
||||
|
||||
struct ospf_lsa_rt_walk {
|
||||
struct top_hash_entry *en;
|
||||
void *buf, *bufend;
|
||||
int ospf2;
|
||||
u16 type, metric;
|
||||
u32 id, data, lif, nif;
|
||||
};
|
||||
|
||||
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
|
||||
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
||||
#define CMP_NEWER 1
|
||||
#define CMP_SAME 0
|
||||
#define CMP_OLDER -1
|
||||
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
|
||||
void lsa_walk_rt_init(struct proto_ospf *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt);
|
||||
int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
|
||||
void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric);
|
||||
void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
|
||||
void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
|
||||
int lsa_validate(struct ospf_lsa_header *lsa, void *body);
|
||||
struct top_hash_entry * lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body);
|
||||
void ospf_age(struct proto_ospf *po);
|
||||
|
@ -9,47 +9,52 @@
|
||||
#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 void
|
||||
ospf_lsreq_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
|
||||
struct ospf_lsreq_header **body, unsigned *count)
|
||||
{
|
||||
struct ospf_packet *op = &pkt->ospf_packet;
|
||||
unsigned hdrlen = ospf_pkt_hdrlen(po);
|
||||
*body = ((void *) pkt) + hdrlen;
|
||||
*count = (plen - hdrlen) / sizeof(struct ospf_lsreq_header);
|
||||
}
|
||||
|
||||
ASSERT(op->type == LSREQ_P);
|
||||
ospf_dump_common(p, op);
|
||||
static void
|
||||
ospf_lsreq_dump(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
{
|
||||
struct ospf_lsreq_header *lsrs;
|
||||
unsigned 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(po, 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(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
|
||||
for (i = 0; i < lsr_count; i++)
|
||||
log(L_TRACE "%s: LSR Type: %04x, Id: %R, Rt: %R", po->proto.name,
|
||||
ntohl(lsrs[i].type), ntohl(lsrs[i].id), ntohl(lsrs[i].rt));
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsreq_send(struct ospf_neighbor *n)
|
||||
{
|
||||
snode *sn;
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
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;
|
||||
unsigned i, lsh_max, length;
|
||||
snode *sn;
|
||||
|
||||
pk = ospf_tx_buffer(n->ifa);
|
||||
op = &pk->ospf_packet;
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
|
||||
|
||||
sn = SHEAD(n->lsrql);
|
||||
if (EMPTY_SLIST(n->lsrql))
|
||||
{
|
||||
if (n->state == NEIGHBOR_LOADING)
|
||||
@ -57,81 +62,68 @@ 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(po, pkt, ospf_pkt_maxsize(ifa), &lsrs, &lsh_max);
|
||||
|
||||
for (; i > 0; i--)
|
||||
sn = SHEAD(n->lsrql);
|
||||
for (i = 0; i < lsh_max; i++)
|
||||
{
|
||||
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++;
|
||||
|
||||
lsrs[i].type = htonl(en->lsa.type);
|
||||
lsrs[i].rt = htonl(en->lsa.rt);
|
||||
lsrs[i].id = htonl(en->lsa.id);
|
||||
|
||||
if (sn == STAIL(n->lsrql))
|
||||
break;
|
||||
sn = sn->next;
|
||||
}
|
||||
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(po) + 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->iface->name);
|
||||
ospf_send_to(n->ifa, n->ip);
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet sent to %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
ospf_lsreq_receive(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;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct ospf_lsreq_header *lsrs;
|
||||
unsigned i, lsr_count;
|
||||
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_lsreq_packet *ps = (void *) ps_i;
|
||||
OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
/* No need to check length, lsreq has only basic header */
|
||||
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet received from %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
return;
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
|
||||
|
||||
lsh = ps->lsh;
|
||||
init_list(&uplist);
|
||||
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
|
||||
|
||||
lsano = (size - sizeof(struct ospf_lsreq_packet)) /
|
||||
sizeof(struct ospf_lsreq_header);
|
||||
for (i = 0; i < lsano; lsh++, i++)
|
||||
ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
|
||||
for (i = 0; i < lsr_count; i++)
|
||||
{
|
||||
u32 hid = ntohl(lsh->id);
|
||||
u32 hrt = ntohl(lsh->rt);
|
||||
u32 htype = ntohl(lsh->type);
|
||||
u32 hid = ntohl(lsrs[i].id);
|
||||
u32 hrt = ntohl(lsrs[i].rt);
|
||||
u32 htype = ntohl(lsrs[i].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);
|
||||
// XXXX check
|
||||
DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", htype, hid, hrt);
|
||||
|
||||
if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
|
||||
{
|
||||
log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
|
||||
@ -140,7 +132,14 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
rfree(upslab);
|
||||
return;
|
||||
}
|
||||
|
||||
struct l_lsr_head *llsh = sl_alloc(upslab);
|
||||
llsh->lsh.id = hid;
|
||||
llsh->lsh.rt = hrt;
|
||||
llsh->lsh.type = htype;
|
||||
add_tail(&uplist, NODE llsh);
|
||||
}
|
||||
|
||||
ospf_lsupd_send_list(n, &uplist);
|
||||
rfree(upslab);
|
||||
}
|
||||
|
@ -17,27 +17,29 @@ struct ospf_lsupd_packet
|
||||
|
||||
|
||||
/* Beware of unaligned access */
|
||||
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
|
||||
void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n)
|
||||
{
|
||||
struct ospf_lsa_header lsa;
|
||||
ntohlsah(lsa_n, &lsa);
|
||||
|
||||
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
|
||||
p->name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
|
||||
po->proto.name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
|
||||
}
|
||||
|
||||
void ospf_dump_common(struct proto *p, struct ospf_packet *op)
|
||||
void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
{
|
||||
log(L_TRACE "%s: length %d", p->name, ntohs(op->length));
|
||||
log(L_TRACE "%s: router %R", p->name, ntohl(op->routerid));
|
||||
struct proto *p = &po->proto;
|
||||
log(L_TRACE "%s: length %d", p->name, ntohs(pkt->length));
|
||||
log(L_TRACE "%s: router %R", p->name, ntohl(pkt->routerid));
|
||||
}
|
||||
|
||||
static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
|
||||
static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_packet *op = &pkt->ospf_packet;
|
||||
|
||||
ASSERT(op->type == LSUPD_P);
|
||||
ospf_dump_common(p, op);
|
||||
ospf_dump_common(po, op);
|
||||
|
||||
/* We know that ntohs(op->length) >= sizeof(struct ospf_lsa_header) */
|
||||
u8 *pbuf= (u8 *) pkt;
|
||||
@ -160,7 +162,6 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
||||
struct ospf_iface *ifa;
|
||||
struct ospf_neighbor *nn;
|
||||
struct top_hash_entry *en;
|
||||
struct proto *p = &po->proto;
|
||||
int ret, retval = 0;
|
||||
|
||||
/* pg 148 */
|
||||
@ -352,7 +353,7 @@ void /* I send all I received in LSREQ */
|
||||
ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
||||
{
|
||||
struct ospf_area *oa = n->ifa->oa;
|
||||
struct proto *p = &oa->po->proto;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct l_lsr_head *lsr;
|
||||
struct top_hash_entry *en;
|
||||
struct ospf_lsupd_packet *pkt;
|
||||
@ -487,6 +488,8 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
continue;
|
||||
}
|
||||
|
||||
u16 lsa_type = ntohs(lsa->type_raw);
|
||||
lsa_type = xxxx(lsa_type); // XXXX finish
|
||||
#ifdef OSPFv2
|
||||
/* pg 143 (2) */
|
||||
if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
|
||||
@ -496,21 +499,21 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
|
||||
/* pg 143 (3) */
|
||||
if ((lsa->type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
|
||||
if ((lsa_type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
|
||||
{
|
||||
log(L_WARN "Received External LSA in stub area from %I", n->ip);
|
||||
continue;
|
||||
}
|
||||
#else /* OSPFv3 */
|
||||
/* 4.5.1 (2) */
|
||||
if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
|
||||
if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
|
||||
{
|
||||
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 4.5.1 (3) */
|
||||
if ((LSA_SCOPE(lsa) == LSA_SCOPE_RES))
|
||||
if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_RES))
|
||||
{
|
||||
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
|
||||
continue;
|
||||
@ -520,10 +523,10 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
ntohlsah(lsa, &lsatmp);
|
||||
|
||||
DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
|
||||
lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
|
||||
lsa_type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
|
||||
|
||||
/* FIXME domain should be link id for unknown LSA types with zero Ubit */
|
||||
u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
|
||||
u32 domain = ospf_lsa_domain(lsa_type, ifa);
|
||||
lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
|
||||
|
||||
#ifdef LOCAL_DEBUG
|
||||
@ -550,7 +553,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
|
||||
#ifdef OSPFv2
|
||||
/* 13.4 - check self-originated LSAs of NET type */
|
||||
if ((!self) && (lsatmp.type == LSA_T_NET))
|
||||
if ((!self) && (lsa_type == LSA_T_NET))
|
||||
{
|
||||
struct ospf_iface *nifa;
|
||||
WALK_LIST(nifa, po->iface_list)
|
||||
@ -576,7 +579,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Received old self-originated LSA (Type: %04x, Id: %R, Rt: %R)",
|
||||
lsatmp.type, lsatmp.id, lsatmp.rt);
|
||||
lsa_type, lsatmp.id, lsatmp.rt);
|
||||
|
||||
if (lsadb)
|
||||
{
|
||||
@ -666,8 +669,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
|
||||
#ifdef OSPFv3
|
||||
/* Events 6,7 from RFC5340 4.4.3. */
|
||||
if ((lsatmp.type == LSA_T_LINK) &&
|
||||
(ifa->state == OSPF_IS_DR))
|
||||
if ((lsa_type == LSA_T_LINK) && (ifa->state == OSPF_IS_DR))
|
||||
schedule_net_lsa(ifa);
|
||||
#endif
|
||||
|
||||
@ -733,12 +735,11 @@ void
|
||||
ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
|
||||
{
|
||||
struct ospf_lsa_header *lsa = &en->lsa;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
lsa->age = LSA_MAXAGE;
|
||||
lsa->sn = LSA_MAXSEQNO;
|
||||
lsasum_calculate(lsa, en->lsa_body);
|
||||
OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
|
||||
OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
|
||||
OSPF_TRACE(D_EVENTS, "Type: %04x, Id: %R, Rt: %R", en->lsa_type, lsa->id, lsa->rt);
|
||||
ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@
|
||||
#ifndef _BIRD_OSPF_LSUPD_H_
|
||||
#define _BIRD_OSPF_LSUPD_H_
|
||||
|
||||
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n);
|
||||
void ospf_dump_common(struct proto *p, struct ospf_packet *op);
|
||||
void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n);
|
||||
void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt);
|
||||
void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
|
||||
void ospf_lsupd_receive(struct ospf_packet *ps_i,
|
||||
struct ospf_iface *ifa, struct ospf_neighbor *n);
|
||||
|
@ -123,7 +123,6 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
|
||||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
n->state = state;
|
||||
|
||||
@ -157,13 +156,10 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
|
||||
n->dds = random_u32();
|
||||
}
|
||||
n->dds++;
|
||||
n->myimms.byte = 0;
|
||||
n->myimms.bit.ms = 1;
|
||||
n->myimms.bit.m = 1;
|
||||
n->myimms.bit.i = 1;
|
||||
n->myimms = DBDES_IMMS;
|
||||
}
|
||||
if (state > NEIGHBOR_EXSTART)
|
||||
n->myimms.bit.i = 0;
|
||||
n->myimms &= ~DBDES_I;
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,7 +550,7 @@ neighbor_timer_hook(timer * timer)
|
||||
{
|
||||
struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS,
|
||||
"Inactivity timer fired on interface %s for neighbor %I.",
|
||||
@ -566,7 +562,8 @@ void
|
||||
ospf_neigh_remove(struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
u32 rid = n->rid;
|
||||
|
||||
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
|
||||
{
|
||||
@ -579,7 +576,7 @@ ospf_neigh_remove(struct ospf_neighbor *n)
|
||||
neigh_chstate(n, NEIGHBOR_DOWN);
|
||||
rem_node(NODE n);
|
||||
rfree(n->pool);
|
||||
OSPF_TRACE(D_EVENTS, "Deleting neigbor.");
|
||||
OSPF_TRACE(D_EVENTS, "Deleting neigbor %R", rid);
|
||||
}
|
||||
|
||||
void
|
||||
@ -633,7 +630,7 @@ rxmt_timer_hook(timer * timer)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((n->state == NEIGHBOR_EXCHANGE) && n->myimms.bit.ms) /* I'm master */
|
||||
if ((n->state == NEIGHBOR_EXCHANGE) && (n->myimms & DBDES_MS)) /* I'm master */
|
||||
ospf_dbdes_send(n, 0);
|
||||
|
||||
|
||||
|
@ -185,11 +185,11 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
|
||||
static void
|
||||
ospf_area_remove(struct ospf_area *oa)
|
||||
{
|
||||
struct proto *p = &oa->po->proto;
|
||||
struct proto_ospf *po = oa->po;
|
||||
OSPF_TRACE(D_EVENTS, "Removing area %R", oa->areaid);
|
||||
|
||||
/* We suppose that interfaces are already removed */
|
||||
ospf_flush_area(oa->po, oa->areaid);
|
||||
ospf_flush_area(po, oa->areaid);
|
||||
|
||||
fib_free(&oa->rtr);
|
||||
fib_free(&oa->net_fib);
|
||||
@ -198,7 +198,7 @@ ospf_area_remove(struct ospf_area *oa)
|
||||
if (oa->translator_timer)
|
||||
rfree(oa->translator_timer);
|
||||
|
||||
oa->po->areano--;
|
||||
po->areano--;
|
||||
rem_node(NODE oa);
|
||||
mb_free(oa);
|
||||
}
|
||||
@ -377,7 +377,7 @@ ospf_build_attrs(ea_list * next, struct linpool *pool, u32 m1, u32 m2,
|
||||
void
|
||||
schedule_net_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->iface->name);
|
||||
ifa->orignet = 1;
|
||||
@ -387,7 +387,7 @@ schedule_net_lsa(struct ospf_iface *ifa)
|
||||
void
|
||||
schedule_link_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
|
||||
ifa->origlink = 1;
|
||||
@ -397,7 +397,7 @@ schedule_link_lsa(struct ospf_iface *ifa)
|
||||
void
|
||||
schedule_rt_lsa(struct ospf_area *oa)
|
||||
{
|
||||
struct proto *p = &oa->po->proto;
|
||||
struct proto_ospf *po = oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling router-LSA origination for area %R", oa->areaid);
|
||||
oa->origrt = 1;
|
||||
@ -406,8 +406,6 @@ schedule_rt_lsa(struct ospf_area *oa)
|
||||
void
|
||||
schedule_rtcalc(struct proto_ospf *po)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
if (po->calcrt)
|
||||
return;
|
||||
|
||||
@ -449,11 +447,9 @@ area_disp(struct ospf_area *oa)
|
||||
/* Now try to originate network LSA's */
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
#ifdef OSPFv3
|
||||
/* Link LSA should be originated before Network LSA */
|
||||
if (ifa->origlink && (ifa->oa == oa))
|
||||
if (ospf_is_v3(po) && ifa->origlink && (ifa->oa == oa))
|
||||
update_link_lsa(ifa);
|
||||
#endif
|
||||
|
||||
if (ifa->orignet && (ifa->oa == oa))
|
||||
update_net_lsa(ifa);
|
||||
@ -945,32 +941,44 @@ fake_lsa_from_prefix_lsa(struct ospf_lsa_header *dst, struct ospf_lsa_header *sr
|
||||
|
||||
#endif
|
||||
|
||||
static int lsa_compare_ospf3; // XXXX fixme
|
||||
|
||||
static int
|
||||
lsa_compare_for_state(const void *p1, const void *p2)
|
||||
{
|
||||
struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
|
||||
struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
|
||||
struct top_hash_entry *he1 = * (struct top_hash_entry **) p1;
|
||||
struct top_hash_entry *he2 = * (struct top_hash_entry **) p2;
|
||||
struct ospf_lsa_header *lsa1 = &(he1->lsa);
|
||||
struct ospf_lsa_header *lsa2 = &(he2->lsa);
|
||||
struct ospf_lsa_header lsatmp1, lsatmp2;
|
||||
u16 lsa1_type = he1->lsa_type;
|
||||
u16 lsa2_type = he2->lsa_type;
|
||||
int px1 = 0;
|
||||
int px2 = 0;
|
||||
|
||||
if (he1->domain != he2->domain)
|
||||
return he1->domain - he2->domain;
|
||||
|
||||
#ifdef OSPFv3
|
||||
struct ospf_lsa_header lsatmp1, lsatmp2;
|
||||
if (lsa_compare_ospf3)
|
||||
{
|
||||
px1 = (lsa1_type == LSA_T_PREFIX);
|
||||
px2 = (lsa2_type == LSA_T_PREFIX);
|
||||
xxxx();
|
||||
|
||||
int px1 = (lsa1->type == LSA_T_PREFIX);
|
||||
int px2 = (lsa2->type == LSA_T_PREFIX);
|
||||
if (px1)
|
||||
{
|
||||
lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
|
||||
lsa1_type = lsa1->type;
|
||||
px1 = 1;
|
||||
}
|
||||
|
||||
if (px1)
|
||||
lsa1 = fake_lsa_from_prefix_lsa(&lsatmp1, lsa1, he1->lsa_body);
|
||||
if (px2)
|
||||
lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
|
||||
}
|
||||
|
||||
if (px2)
|
||||
lsa2 = fake_lsa_from_prefix_lsa(&lsatmp2, lsa2, he2->lsa_body);
|
||||
#endif
|
||||
|
||||
int nt1 = (lsa1->type == LSA_T_NET);
|
||||
int nt2 = (lsa2->type == LSA_T_NET);
|
||||
int nt1 = (lsa1_type == LSA_T_NET);
|
||||
int nt2 = (lsa2_type == LSA_T_NET);
|
||||
|
||||
if (nt1 != nt2)
|
||||
return nt1 - nt2;
|
||||
@ -988,10 +996,8 @@ lsa_compare_for_state(const void *p1, const void *p2)
|
||||
if (lsa1->id != lsa2->id)
|
||||
return lsa1->id - lsa2->id;
|
||||
|
||||
#ifdef OSPFv3
|
||||
if (px1 != px2)
|
||||
return px1 - px2;
|
||||
#endif
|
||||
|
||||
return lsa1->sn - lsa2->sn;
|
||||
}
|
||||
@ -1000,16 +1006,14 @@ lsa_compare_for_state(const void *p1, const void *p2)
|
||||
if (lsa1->rt != lsa2->rt)
|
||||
return lsa1->rt - lsa2->rt;
|
||||
|
||||
if (lsa1->type != lsa2->type)
|
||||
return lsa1->type - lsa2->type;
|
||||
if (lsa1_type != lsa2_type)
|
||||
return lsa1_type - lsa2_type;
|
||||
|
||||
if (lsa1->id != lsa2->id)
|
||||
return lsa1->id - lsa2->id;
|
||||
|
||||
#ifdef OSPFv3
|
||||
if (px1 != px2)
|
||||
return px1 - px2;
|
||||
#endif
|
||||
|
||||
return lsa1->sn - lsa2->sn;
|
||||
}
|
||||
@ -1042,79 +1046,77 @@ show_lsa_distance(struct top_hash_entry *he)
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int first, int verbose)
|
||||
show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int verbose)
|
||||
{
|
||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
||||
struct ospf_lsa_rt *rt = he->lsa_body;
|
||||
struct ospf_lsa_rt_link *rr = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
int max = lsa_rt_count(lsa);
|
||||
int i;
|
||||
struct ospf_lsa_rt_walk rtl;
|
||||
|
||||
if (first)
|
||||
{
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\trouter %R", he->lsa.rt);
|
||||
show_lsa_distance(he);
|
||||
}
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\trouter %R", he->lsa.rt);
|
||||
show_lsa_distance(he);
|
||||
|
||||
lsa_walk_rt_init(po, he, &rtl);
|
||||
while (lsa_walk_rt(&rtl))
|
||||
if (rtl.type == LSART_VLNK)
|
||||
cli_msg(-1016, "\t\tvlink %R metric %u", rtl.id, rtl.metric);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
if (rr[i].type == LSART_VLNK)
|
||||
cli_msg(-1016, "\t\tvlink %R metric %u", rr[i].id, rr[i].metric);
|
||||
lsa_walk_rt_init(po, he, &rtl);
|
||||
while (lsa_walk_rt(&rtl))
|
||||
if (rtl.type == LSART_PTP)
|
||||
cli_msg(-1016, "\t\trouter %R metric %u", rtl.id, rtl.metric);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
if (rr[i].type == LSART_PTP)
|
||||
cli_msg(-1016, "\t\trouter %R metric %u", rr[i].id, rr[i].metric);
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
if (rr[i].type == LSART_NET)
|
||||
lsa_walk_rt_init(po, he, &rtl);
|
||||
while (lsa_walk_rt(&rtl))
|
||||
if (rtl.type == LSART_NET)
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rr[i].id);
|
||||
|
||||
if (net_he)
|
||||
if (ospf_is_v2(po))
|
||||
{
|
||||
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
|
||||
struct ospf_lsa_net *net_ln = net_he->lsa_body;
|
||||
/* In OSPFv2, we try to find network-LSA to get prefix/pxlen */
|
||||
struct top_hash_entry *net_he = ospf_hash_find_net(po->gr, he->domain, rtl.id, 0);
|
||||
|
||||
cli_msg(-1016, "\t\tnetwork %I/%d metric %u",
|
||||
ipa_and(ipa_from_u32(net_lsa->id), net_ln->netmask),
|
||||
ipa_mklen(net_ln->netmask), rr[i].metric);
|
||||
if (net_he)
|
||||
{
|
||||
struct ospf_lsa_header *net_lsa = &(net_he->lsa);
|
||||
struct ospf_lsa_net *net_ln = net_he->lsa_body;
|
||||
|
||||
cli_msg(-1016, "\t\tnetwork %I/%d metric %u",
|
||||
ipa_from_u32(net_lsa->id & net_ln->optx),
|
||||
u32_masklen(net_ln->optx), rtl.metric);
|
||||
}
|
||||
else
|
||||
cli_msg(-1016, "\t\tnetwork [%R] metric %u", rtl.id, rtl.metric);
|
||||
}
|
||||
else
|
||||
cli_msg(-1016, "\t\tnetwork [%R] metric %u", rr[i].id, rr[i].metric);
|
||||
|
||||
#else /* OSPFv3 */
|
||||
cli_msg(-1016, "\t\tnetwork [%R-%u] metric %u", rr[i].id, rr[i].nif, rr[i].metric);
|
||||
#endif
|
||||
cli_msg(-1016, "\t\tnetwork [%R-%u] metric %u", rtl.id, rtl.nif, rtl.metric);
|
||||
}
|
||||
|
||||
#ifdef OSPFv2
|
||||
if (!verbose)
|
||||
return;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
if (rr[i].type == LSART_STUB)
|
||||
cli_msg(-1016, "\t\tstubnet %I/%d metric %u", ipa_from_u32(rr[i].id),
|
||||
ipa_mklen(ipa_from_u32(rr[i].data)), rr[i].metric);
|
||||
#endif
|
||||
if (ospf_is_v2(po) && verbose)
|
||||
{
|
||||
lsa_walk_rt_init(po, he, &rtl);
|
||||
while (lsa_walk_rt(&rtl))
|
||||
if (rtl.type == LSART_STUB)
|
||||
cli_msg(-1016, "\t\tstubnet %I/%d metric %u",
|
||||
ipa_from_u32(rtl.id), u32_masklen(rtl.data), rtl.metric);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_lsa_network(struct top_hash_entry *he)
|
||||
show_lsa_network(struct top_hash_entry *he, int ospf2)
|
||||
{
|
||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
||||
struct ospf_lsa_net *ln = he->lsa_body;
|
||||
u32 i;
|
||||
|
||||
#ifdef OSPFv2
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\tnetwork %I/%d", ipa_and(ipa_from_u32(lsa->id), ln->netmask), ipa_mklen(ln->netmask));
|
||||
cli_msg(-1016, "\t\tdr %R", lsa->rt);
|
||||
#else /* OSPFv3 */
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
|
||||
#endif
|
||||
if (ospf2)
|
||||
{
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\tnetwork %I/%d", ipa_from_u32(lsa->id & ln->optx), u32_masklen(ln->optx));
|
||||
cli_msg(-1016, "\t\tdr %R", lsa->rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
cli_msg(-1016, "");
|
||||
cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
|
||||
}
|
||||
|
||||
show_lsa_distance(he);
|
||||
|
||||
@ -1123,95 +1125,52 @@ show_lsa_network(struct top_hash_entry *he)
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_lsa_sum_net(struct top_hash_entry *he)
|
||||
show_lsa_sum_net(struct top_hash_entry *he, int ospf2)
|
||||
{
|
||||
ip_addr ip;
|
||||
int pxlen;
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct ospf_lsa_sum *ls = he->lsa_body;
|
||||
pxlen = ipa_mklen(ls->netmask);
|
||||
ip = ipa_and(ipa_from_u32(he->lsa.id), ls->netmask);
|
||||
#else /* OSPFv3 */
|
||||
u8 pxopts;
|
||||
u16 rest;
|
||||
struct ospf_lsa_sum_net *ls = he->lsa_body;
|
||||
lsa_get_ipv6_prefix(ls->prefix, &ip, &pxlen, &pxopts, &rest);
|
||||
#endif
|
||||
u32 metric;
|
||||
|
||||
cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, ls->metric);
|
||||
lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric);
|
||||
cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric);
|
||||
}
|
||||
|
||||
static inline void
|
||||
show_lsa_sum_rt(struct top_hash_entry *he)
|
||||
show_lsa_sum_rt(struct top_hash_entry *he, int ospf2)
|
||||
{
|
||||
u32 metric;
|
||||
u32 dst_rid;
|
||||
u32 options;
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct ospf_lsa_sum *ls = he->lsa_body;
|
||||
dst_rid = he->lsa.id;
|
||||
// options = 0;
|
||||
#else /* OSPFv3 */
|
||||
struct ospf_lsa_sum_rt *ls = he->lsa_body;
|
||||
dst_rid = ls->drid;
|
||||
// options = ls->options & OPTIONS_MASK;
|
||||
#endif
|
||||
|
||||
cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, ls->metric);
|
||||
lsa_parse_sum_rt(he, ospf2, &dst_rid, &metric, &options);
|
||||
cli_msg(-1016, "\t\txrouter %R metric %u", dst_rid, metric);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
show_lsa_external(struct top_hash_entry *he)
|
||||
show_lsa_external(struct top_hash_entry *he, int ospf2)
|
||||
{
|
||||
struct ospf_lsa_ext *ext = he->lsa_body;
|
||||
struct ospf_lsa_ext_local rt;
|
||||
char str_via[STD_ADDRESS_P_LENGTH + 8] = "";
|
||||
char str_tag[16] = "";
|
||||
ip_addr ip, rt_fwaddr;
|
||||
int pxlen, ebit, rt_fwaddr_valid;
|
||||
u32 rt_tag, rt_metric;
|
||||
|
||||
if (he->lsa.type == LSA_T_EXT)
|
||||
if (he->lsa_type == LSA_T_EXT)
|
||||
he->domain = 0; /* Unmark the LSA */
|
||||
|
||||
rt_metric = ext->metric & METRIC_MASK;
|
||||
ebit = ext->metric & LSA_EXT_EBIT;
|
||||
#ifdef OSPFv2
|
||||
ip = ipa_and(ipa_from_u32(he->lsa.id), ext->netmask);
|
||||
pxlen = ipa_mklen(ext->netmask);
|
||||
rt_fwaddr = ext->fwaddr;
|
||||
rt_fwaddr_valid = !ipa_equal(rt_fwaddr, IPA_NONE);
|
||||
rt_tag = ext->tag;
|
||||
#else /* OSPFv3 */
|
||||
u8 pxopts;
|
||||
u16 rest;
|
||||
u32 *buf = ext->rest;
|
||||
buf = lsa_get_ipv6_prefix(buf, &ip, &pxlen, &pxopts, &rest);
|
||||
|
||||
rt_fwaddr_valid = ext->metric & LSA_EXT_FBIT;
|
||||
if (rt_fwaddr_valid)
|
||||
buf = lsa_get_ipv6_addr(buf, &rt_fwaddr);
|
||||
else
|
||||
rt_fwaddr = IPA_NONE;
|
||||
|
||||
if (ext->metric & LSA_EXT_TBIT)
|
||||
rt_tag = *buf++;
|
||||
else
|
||||
rt_tag = 0;
|
||||
#endif
|
||||
lsa_parse_ext(he, ospf2, &rt);
|
||||
|
||||
if (rt_fwaddr_valid)
|
||||
bsprintf(str_via, " via %I", rt_fwaddr);
|
||||
if (rt.fbit)
|
||||
bsprintf(str_via, " via %I", rt.fwaddr);
|
||||
|
||||
if (rt_tag)
|
||||
bsprintf(str_tag, " tag %08x", rt_tag);
|
||||
if (rt.tag)
|
||||
bsprintf(str_tag, " tag %08x", rt.tag);
|
||||
|
||||
cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s",
|
||||
(he->lsa.type == LSA_T_NSSA) ? "nssa-ext" : "external",
|
||||
ip, pxlen, ebit ? "2" : "", rt_metric, str_via, str_tag);
|
||||
(he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external",
|
||||
rt.ip, rt.pxlen, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
|
||||
}
|
||||
|
||||
#ifdef OSPFv3
|
||||
static inline void
|
||||
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||
{
|
||||
@ -1224,7 +1183,7 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||
int i;
|
||||
|
||||
/* We check whether given prefix-LSA is related to the current node */
|
||||
if ((px->ref_type != cnode->type) || (px->ref_rt != cnode->rt))
|
||||
if ((px->ref_type != cnode->type_raw) || (px->ref_rt != cnode->rt))
|
||||
return;
|
||||
|
||||
if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
|
||||
@ -1244,13 +1203,13 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||
cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct ospf_lsa_header *cnode = NULL;
|
||||
int ospf2 = ospf_is_v2(po);
|
||||
int num = po->gr->hash_entries;
|
||||
unsigned int i, ix, j1, j2, jx;
|
||||
u32 last_area = 0xFFFFFFFF;
|
||||
@ -1274,7 +1233,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
{
|
||||
int accept;
|
||||
|
||||
switch (he->lsa.type)
|
||||
switch (he->lsa_type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
case LSA_T_NET:
|
||||
@ -1284,9 +1243,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
case LSA_T_SUM_NET:
|
||||
case LSA_T_SUM_RT:
|
||||
case LSA_T_NSSA:
|
||||
#ifdef OSPFv3
|
||||
case LSA_T_PREFIX:
|
||||
#endif
|
||||
accept = verbose;
|
||||
break;
|
||||
|
||||
@ -1339,7 +1296,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
/* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
|
||||
if (!cnode)
|
||||
{
|
||||
if (((he->lsa.type == LSA_T_RT) || (he->lsa.type == LSA_T_NET))
|
||||
if (((he->lsa_type == LSA_T_RT) || (he->lsa_type == LSA_T_NET))
|
||||
&& ((he->color == INSPF) || !reachable))
|
||||
{
|
||||
cnode = &(he->lsa);
|
||||
@ -1358,35 +1315,34 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
|
||||
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->rt));
|
||||
|
||||
switch (he->lsa.type)
|
||||
switch (he->lsa_type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
show_lsa_router(po, he, he->lsa.id == cnode->id, verbose);
|
||||
if (he->lsa.id == cnode->id)
|
||||
show_lsa_router(po, he, verbose);
|
||||
break;
|
||||
|
||||
case LSA_T_NET:
|
||||
show_lsa_network(he);
|
||||
show_lsa_network(he, ospf2);
|
||||
break;
|
||||
|
||||
case LSA_T_SUM_NET:
|
||||
if (cnode->type == LSA_T_RT)
|
||||
show_lsa_sum_net(he);
|
||||
show_lsa_sum_net(he, ospf2);
|
||||
break;
|
||||
|
||||
case LSA_T_SUM_RT:
|
||||
if (cnode->type == LSA_T_RT)
|
||||
show_lsa_sum_rt(he);
|
||||
show_lsa_sum_rt(he, ospf2);
|
||||
break;
|
||||
|
||||
#ifdef OSPFv3
|
||||
case LSA_T_PREFIX:
|
||||
show_lsa_prefix(he, cnode);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LSA_T_EXT:
|
||||
case LSA_T_NSSA:
|
||||
show_lsa_external(he);
|
||||
show_lsa_external(he, ospf2);
|
||||
break;
|
||||
|
||||
case LSA_T_PREFIX:
|
||||
show_lsa_prefix(he, cnode);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1394,13 +1350,13 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
if ((i+1 == j1)
|
||||
|| (hea[i+1]->domain != last_area)
|
||||
|| (hea[i+1]->lsa.rt != cnode->rt)
|
||||
|| (hea[i+1]->lsa.type == LSA_T_NET))
|
||||
|| (hea[i+1]->lsa_type == LSA_T_NET))
|
||||
{
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->rt))
|
||||
ix++;
|
||||
|
||||
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->rt))
|
||||
show_lsa_external(hex[ix++]);
|
||||
show_lsa_external(hex[ix++], ospf2);
|
||||
|
||||
cnode = NULL;
|
||||
}
|
||||
@ -1434,7 +1390,7 @@ ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||
last_rt = he->lsa.rt;
|
||||
}
|
||||
|
||||
show_lsa_external(he);
|
||||
show_lsa_external(he, ospf2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1449,8 +1405,8 @@ lsa_compare_for_lsadb(const void *p1, const void *p2)
|
||||
struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
|
||||
struct ospf_lsa_header *lsa1 = &(he1->lsa);
|
||||
struct ospf_lsa_header *lsa2 = &(he2->lsa);
|
||||
int sc1 = LSA_SCOPE(lsa1);
|
||||
int sc2 = LSA_SCOPE(lsa2);
|
||||
int sc1 = LSA_SCOPE(he1->lsa_type);
|
||||
int sc2 = LSA_SCOPE(he2->lsa_type);
|
||||
|
||||
if (sc1 != sc2)
|
||||
return sc2 - sc1;
|
||||
@ -1464,8 +1420,8 @@ lsa_compare_for_lsadb(const void *p1, const void *p2)
|
||||
if (lsa1->id != lsa2->id)
|
||||
return lsa1->id - lsa2->id;
|
||||
|
||||
if (lsa1->type != lsa2->type)
|
||||
return lsa1->type - lsa2->type;
|
||||
if (he1->lsa_type != he2->lsa_type)
|
||||
return he1->lsa_type - he2->lsa_type;
|
||||
|
||||
return lsa1->sn - lsa2->sn;
|
||||
}
|
||||
@ -1505,7 +1461,7 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
struct ospf_lsa_header *lsa = &(hea[i]->lsa);
|
||||
int dscope = LSA_SCOPE(lsa);
|
||||
int dscope = LSA_SCOPE(hea[i]->lsa_type);
|
||||
|
||||
if (ld->scope && (dscope != (ld->scope & 0xf000)))
|
||||
continue;
|
||||
@ -1514,6 +1470,7 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
|
||||
continue;
|
||||
|
||||
/* Ignore high nibble */
|
||||
// XXXX check
|
||||
if (ld->type && ((lsa->type & 0x0fff) != (ld->type & 0x0fff)))
|
||||
continue;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
#ifndef _BIRD_OSPF_H_
|
||||
#define _BIRD_OSPF_H_
|
||||
|
||||
#define MAXNETS 10
|
||||
|
||||
#define OSPF_MAX_PKT_SIZE 65535
|
||||
/*
|
||||
* RFC 2328 says, maximum packet size is 65535 (IP packet size
|
||||
@ -24,12 +24,14 @@
|
||||
#else
|
||||
#define OSPF_FORCE_DEBUG 0
|
||||
#endif
|
||||
#define OSPF_TRACE(flags, msg, args...) do { if ((p->debug & flags) || OSPF_FORCE_DEBUG) \
|
||||
log(L_TRACE "%s: " msg, p->name , ## args ); } while(0)
|
||||
|
||||
#define OSPF_TRACE(flags, msg, args...) \
|
||||
do { if ((po->proto.debug & flags) || OSPF_FORCE_DEBUG) \
|
||||
log(L_TRACE "%s: " msg, po->proto.name , ## args ); } while(0)
|
||||
|
||||
#define OSPF_PACKET(dumpfn, buffer, msg, args...) \
|
||||
do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
|
||||
{ log(L_TRACE "%s: " msg, p->name, ## args ); dumpfn(p, buffer); } } while(0)
|
||||
do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
|
||||
{ log(L_TRACE "%s: " msg, po->proto.name, ## args ); dumpfn(po, buffer); } } while(0)
|
||||
|
||||
|
||||
#include "nest/bird.h"
|
||||
@ -51,19 +53,11 @@ do { if ((p->debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
|
||||
|
||||
#define OSPF_PROTO 89
|
||||
|
||||
#ifndef IPV6
|
||||
#define OSPFv2 1
|
||||
#define OSPF_VERSION 2
|
||||
#define OSPF_VLINK_MTU 576 /* RFC 2328 A.1 */
|
||||
#define AllSPFRouters ipa_from_u32(0xe0000005) /* 224.0.0.5 */
|
||||
#define AllDRouters ipa_from_u32(0xe0000006) /* 224.0.0.6 */
|
||||
#else
|
||||
|
||||
// XXXX
|
||||
#define OSPFv3 1
|
||||
#define OSPF_VERSION 3
|
||||
#define OSPF_VLINK_MTU 1280 /* RFC 5340 A.1 */
|
||||
#define AllSPFRouters _MI(0xFF020000, 0, 0, 5) /* FF02::5 */
|
||||
#define AllDRouters _MI(0xFF020000, 0, 0, 6) /* FF02::6 */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define LSREFRESHTIME 1800 /* 30 minutes */
|
||||
@ -140,38 +134,45 @@ struct ospf_area_config
|
||||
};
|
||||
|
||||
|
||||
/* Option flags */
|
||||
/* Generic option flags */
|
||||
#define OPT_V6 0x01 /* OSPFv3, LSA relevant for IPv6 routing calculation */
|
||||
#define OPT_E 0x02 /* Related to AS-external LSAs */
|
||||
#define OPT_MC 0x04 /* Related to MOSPF, not used and obsolete */
|
||||
#define OPT_N 0x08 /* Related to NSSA */
|
||||
#define OPT_P 0x08 /* OSPFv2, flags P and N share position, see NSSA RFC */
|
||||
#define OPT_EA 0x10 /* OSPFv2, external attributes, not used and obsolete */
|
||||
#define OPT_R 0x10 /* OSPFv3, originator is active router */
|
||||
#define OPT_DC 0x20 /* Related to demand circuits, not used */
|
||||
|
||||
#define OPT_E 0x02
|
||||
#define OPT_N 0x08
|
||||
#define OPT_DC 0x20
|
||||
|
||||
#ifdef OSPFv2
|
||||
#define OPT_P 0x08 /* flags P and N share position, see NSSA RFC */
|
||||
#define OPT_EA 0x10
|
||||
|
||||
/* VEB flags are are stored independently in 'u16 options' */
|
||||
#define OPT_RT_B (0x01 << 8)
|
||||
#define OPT_RT_E (0x02 << 8)
|
||||
#define OPT_RT_V (0x04 << 8)
|
||||
#define OPT_RT_NT (0x10 << 8)
|
||||
#endif
|
||||
|
||||
#ifdef OSPFv3
|
||||
#define OPT_V6 0x01
|
||||
#define OPT_R 0x10
|
||||
|
||||
/* VEB flags are are stored together with options in 'u32 options' */
|
||||
/* Router-LSA VEB flags are are stored together with links (OSPFv2) or options (OSPFv3) */
|
||||
#define OPT_RT_B (0x01 << 24)
|
||||
#define OPT_RT_E (0x02 << 24)
|
||||
#define OPT_RT_V (0x04 << 24)
|
||||
#define OPT_RT_NT (0x10 << 24)
|
||||
|
||||
/* Prefix flags, specific for OSPFv3 */
|
||||
#define OPT_PX_NU 0x01
|
||||
#define OPT_PX_LA 0x02
|
||||
#define OPT_PX_P 0x08
|
||||
#define OPT_PX_DN 0x10
|
||||
#endif
|
||||
|
||||
|
||||
/* OSPF interface types */
|
||||
#define OSPF_IT_BCAST 0
|
||||
#define OSPF_IT_NBMA 1
|
||||
#define OSPF_IT_PTP 2
|
||||
#define OSPF_IT_PTMP 3
|
||||
#define OSPF_IT_VLINK 4
|
||||
#define OSPF_IT_UNDEF 5
|
||||
|
||||
/* OSPF interface states */
|
||||
#define OSPF_IS_DOWN 0 /* Not active */
|
||||
#define OSPF_IS_LOOP 1 /* Iface with no link */
|
||||
#define OSPF_IS_WAITING 2 /* Waiting for Wait timer */
|
||||
#define OSPF_IS_PTP 3 /* PTP operational */
|
||||
#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
|
||||
#define OSPF_IS_BACKUP 5 /* I'm BDR */
|
||||
#define OSPF_IS_DR 6 /* I'm DR */
|
||||
|
||||
|
||||
struct ospf_iface
|
||||
@ -197,14 +198,10 @@ struct ospf_iface
|
||||
transmit a Link State Update Packet over this
|
||||
interface. LSAs contained in the update */
|
||||
u16 helloint; /* number of seconds between hello sending */
|
||||
|
||||
#ifdef OSPFv2
|
||||
list *passwords;
|
||||
u16 autype;
|
||||
u32 csn; /* Last used crypt seq number */
|
||||
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
|
||||
#endif
|
||||
|
||||
ip_addr all_routers; /* */
|
||||
ip_addr drip; /* Designated router */
|
||||
ip_addr bdrip; /* Backup DR */
|
||||
@ -212,33 +209,15 @@ struct ospf_iface
|
||||
u32 bdrid;
|
||||
s16 rt_pos_beg; /* Position of iface in Router-LSA, begin, inclusive */
|
||||
s16 rt_pos_end; /* Position of iface in Router-LSA, end, exclusive */
|
||||
|
||||
#ifdef OSPFv3
|
||||
s16 px_pos_beg; /* Position of iface in Rt Prefix-LSA, begin, inclusive */
|
||||
s16 px_pos_end; /* Position of iface in Rt Prefix-LSA, end, exclusive */
|
||||
|
||||
u32 dr_iface_id; /* if drid is valid, this is iface_id of DR (for connecting network) */
|
||||
u8 instance_id; /* Used to differentiate between more OSPF
|
||||
instances on one interface */
|
||||
#endif
|
||||
|
||||
u8 type; /* OSPF view of type */
|
||||
#define OSPF_IT_BCAST 0
|
||||
#define OSPF_IT_NBMA 1
|
||||
#define OSPF_IT_PTP 2
|
||||
#define OSPF_IT_PTMP 3
|
||||
#define OSPF_IT_VLINK 4
|
||||
#define OSPF_IT_UNDEF 5
|
||||
u8 type; /* OSPF view of type (OSPF_IT_*) */
|
||||
u8 strictnbma; /* Can I talk with unknown neighbors? */
|
||||
u8 stub; /* Inactive interface */
|
||||
u8 state; /* Interface state machine */
|
||||
#define OSPF_IS_DOWN 0 /* Not working */
|
||||
#define OSPF_IS_LOOP 1 /* Iface with no link */
|
||||
#define OSPF_IS_WAITING 2 /* Waiting for Wait timer */
|
||||
#define OSPF_IS_PTP 3 /* PTP operational */
|
||||
#define OSPF_IS_DROTHER 4 /* I'm on BCAST or NBMA and I'm not DR */
|
||||
#define OSPF_IS_BACKUP 5 /* I'm BDR */
|
||||
#define OSPF_IS_DR 6 /* I'm DR */
|
||||
u8 state; /* Interface state machine (OSPF_IS_*) */
|
||||
timer *wait_timer; /* WAIT timer */
|
||||
timer *hello_timer; /* HELLOINT timer */
|
||||
timer *poll_timer; /* Poll Interval - for NBMA */
|
||||
@ -255,11 +234,9 @@ struct ospf_iface
|
||||
|
||||
struct top_hash_entry *net_lsa; /* Originated network LSA */
|
||||
int orignet; /* Schedule network LSA origination */
|
||||
#ifdef OSPFv3
|
||||
int origlink; /* Schedule link LSA origination */
|
||||
struct top_hash_entry *link_lsa; /* Originated link LSA */
|
||||
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
|
||||
#endif
|
||||
int fadj; /* Number of full adjacent neigh */
|
||||
list nbma_list;
|
||||
u8 priority; /* A router priority for DR election */
|
||||
@ -290,42 +267,30 @@ union ospf_auth
|
||||
|
||||
|
||||
/* Packet types */
|
||||
#define HELLO_P 1 /* Hello */
|
||||
#define DBDES_P 2 /* Database description */
|
||||
#define LSREQ_P 3 /* Link state request */
|
||||
#define LSUPD_P 4 /* Link state update */
|
||||
#define LSACK_P 5 /* Link state acknowledgement */
|
||||
#define HELLO_P 1 /* Hello */
|
||||
#define DBDES_P 2 /* Database description */
|
||||
#define LSREQ_P 3 /* Link state request */
|
||||
#define LSUPD_P 4 /* Link state update */
|
||||
#define LSACK_P 5 /* Link state acknowledgement */
|
||||
|
||||
/* Area IDs */
|
||||
#define BACKBONE 0
|
||||
#define BACKBONE 0
|
||||
|
||||
|
||||
struct immsb
|
||||
{
|
||||
#ifdef CPU_BIG_ENDIAN
|
||||
u8 padding:5;
|
||||
u8 i:1;
|
||||
u8 m:1;
|
||||
u8 ms:1;
|
||||
#else
|
||||
u8 ms:1;
|
||||
u8 m:1;
|
||||
u8 i:1;
|
||||
u8 padding:5;
|
||||
#endif
|
||||
};
|
||||
|
||||
union imms
|
||||
{
|
||||
u8 byte;
|
||||
struct immsb bit;
|
||||
};
|
||||
#define DBDES_MS 1
|
||||
#define DBDES_M 2
|
||||
#define DBDES_I 4
|
||||
#define DBDES_I 4 /* Init bit */
|
||||
#define DBDES_M 2 /* More bit */
|
||||
#define DBDES_MS 1 /* Master/Slave bit */
|
||||
#define DBDES_IMMS (DBDES_I | DBDES_M | DBDES_MS)
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
|
||||
/*
|
||||
* There is slight difference in OSPF packet header between v2 and v3
|
||||
* in vdep field. For OSPFv2, vdep is u16 authentication type and
|
||||
* ospf_header is followed by union ospf_auth. For OSPFv3, higher byte
|
||||
* of vdep is instance ID and lower byte is zero.
|
||||
*/
|
||||
|
||||
struct ospf_packet
|
||||
{
|
||||
@ -335,56 +300,19 @@ struct ospf_packet
|
||||
u32 routerid;
|
||||
u32 areaid;
|
||||
u16 checksum;
|
||||
u16 autype;
|
||||
union ospf_auth u;
|
||||
u16 vdep;
|
||||
};
|
||||
|
||||
|
||||
#else /* OSPFv3 packet descriptions */
|
||||
|
||||
struct ospf_packet
|
||||
{
|
||||
u8 version;
|
||||
u8 type;
|
||||
u16 length;
|
||||
u32 routerid;
|
||||
u32 areaid;
|
||||
u16 checksum;
|
||||
u8 instance_id;
|
||||
u8 zero;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
struct ospf_lsa_header
|
||||
{
|
||||
u16 age; /* LS Age */
|
||||
#define LSA_MAXAGE 3600 /* 1 hour */
|
||||
#define LSA_CHECKAGE 300 /* 5 minutes */
|
||||
#define LSA_MAXAGEDIFF 900 /* 15 minutes */
|
||||
|
||||
#ifdef OSPFv2
|
||||
u8 options;
|
||||
u8 type;
|
||||
|
||||
// XXXX
|
||||
/*
|
||||
#define LSA_T_RT 1
|
||||
#define LSA_T_NET 2
|
||||
#define LSA_T_SUM_NET 3
|
||||
#define LSA_T_SUM_RT 4
|
||||
#define LSA_T_EXT 5
|
||||
#define LSA_T_NSSA 7
|
||||
|
||||
#define LSA_SCOPE_AREA 0x2000
|
||||
#define LSA_SCOPE_AS 0x4000
|
||||
|
||||
#define LSA_SCOPE(lsa) (((lsa)->type == LSA_T_EXT) ? LSA_SCOPE_AS : LSA_SCOPE_AREA)
|
||||
|
||||
#else /* OSPFv3 */
|
||||
u16 type;
|
||||
*/
|
||||
|
||||
#define LSA_T_RT 0x2001
|
||||
#define LSA_T_NET 0x2002
|
||||
@ -402,91 +330,76 @@ struct ospf_lsa_header
|
||||
#define LSA_SCOPE_AS 0x4000
|
||||
#define LSA_SCOPE_RES 0x6000
|
||||
#define LSA_SCOPE_MASK 0x6000
|
||||
#define LSA_SCOPE(lsa) ((lsa) & LSA_SCOPE_MASK)
|
||||
|
||||
#define LSA_SCOPE(lsa) ((lsa)->type & LSA_SCOPE_MASK)
|
||||
#endif
|
||||
|
||||
#define LSA_MAXAGE 3600 /* 1 hour */
|
||||
#define LSA_CHECKAGE 300 /* 5 minutes */
|
||||
#define LSA_MAXAGEDIFF 900 /* 15 minutes */
|
||||
|
||||
#define LSA_INITSEQNO ((s32) 0x80000001)
|
||||
#define LSA_MAXSEQNO ((s32) 0x7fffffff)
|
||||
|
||||
|
||||
#define LSART_PTP 1
|
||||
#define LSART_NET 2
|
||||
#define LSART_STUB 3
|
||||
#define LSART_VLNK 4
|
||||
|
||||
#define LSA_SUM2_TOS 0xFF000000
|
||||
|
||||
#define LSA_EXT2_TOS 0x7F000000
|
||||
#define LSA_EXT2_EBIT 0x80000000
|
||||
|
||||
#define LSA_EXT3_EBIT 0x4000000
|
||||
#define LSA_EXT3_FBIT 0x2000000
|
||||
#define LSA_EXT3_TBIT 0x1000000
|
||||
|
||||
// XXXX remove
|
||||
#define LSA_EXT_EBIT 0x4000000
|
||||
|
||||
|
||||
struct ospf_lsa_header
|
||||
{
|
||||
u16 age; /* LS Age */
|
||||
u16 type_raw; /* Type, mixed with options on OSPFv2 */
|
||||
|
||||
u32 id;
|
||||
u32 rt; /* Advertising router */
|
||||
s32 sn; /* LS Sequence number */
|
||||
#define LSA_INITSEQNO ((s32) 0x80000001)
|
||||
#define LSA_MAXSEQNO ((s32) 0x7fffffff)
|
||||
u16 checksum;
|
||||
u16 length;
|
||||
};
|
||||
|
||||
/* In OSPFv2, options are embedded in higher half of type_raw */
|
||||
static inline u8 lsa_get_options(struct ospf_lsa_header *lsa)
|
||||
{ return lsa->type_raw >> 8; }
|
||||
|
||||
#define LSART_PTP 1
|
||||
#define LSART_NET 2
|
||||
#define LSART_STUB 3
|
||||
#define LSART_VLNK 4
|
||||
static inline void lsa_set_options(struct ospf_lsa_header *lsa, u16 options)
|
||||
{ lsa->type_raw = (lsa->type_raw & 0xff) | (options << 8); }
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
struct ospf_lsa_rt
|
||||
{
|
||||
#ifdef CPU_BIG_ENDIAN
|
||||
u16 options; /* VEB flags only */
|
||||
u16 links;
|
||||
#else
|
||||
u16 links;
|
||||
u16 options; /* VEB flags only */
|
||||
#endif
|
||||
u32 options; /* VEB flags, mixed with link count for OSPFv2 and options for OSPFv3 */
|
||||
};
|
||||
|
||||
struct ospf_lsa_rt_link
|
||||
struct ospf_lsa_rt2_link
|
||||
{
|
||||
u32 id;
|
||||
u32 data;
|
||||
#ifdef CPU_BIG_ENDIAN
|
||||
u8 type;
|
||||
u8 padding;
|
||||
u8 no_tos;
|
||||
u16 metric;
|
||||
#else
|
||||
u16 metric;
|
||||
u8 padding;
|
||||
u8 no_tos;
|
||||
u8 type;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ospf_lsa_net
|
||||
{
|
||||
ip_addr netmask;
|
||||
u32 routers[];
|
||||
};
|
||||
|
||||
struct ospf_lsa_sum
|
||||
{
|
||||
ip_addr netmask;
|
||||
u32 metric;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext
|
||||
{
|
||||
ip_addr netmask;
|
||||
u32 metric;
|
||||
ip_addr fwaddr;
|
||||
u32 tag;
|
||||
};
|
||||
|
||||
#define LSA_SUM_TOS 0xFF000000
|
||||
#define LSA_EXT_TOS 0x7F000000
|
||||
#define LSA_EXT_EBIT 0x80000000
|
||||
|
||||
/* Endianity swap for lsa->type */
|
||||
#define ntoht(x) x
|
||||
#define htont(x) x
|
||||
|
||||
|
||||
#else /* OSPFv3 */
|
||||
|
||||
struct ospf_lsa_rt
|
||||
{
|
||||
u32 options;
|
||||
};
|
||||
|
||||
struct ospf_lsa_rt_link
|
||||
struct ospf_lsa_rt3_link
|
||||
{
|
||||
#ifdef CPU_BIG_ENDIAN
|
||||
u8 type;
|
||||
@ -502,35 +415,58 @@ struct ospf_lsa_rt_link
|
||||
u32 id; /* Neighbor router ID */
|
||||
};
|
||||
|
||||
|
||||
struct ospf_lsa_net
|
||||
{
|
||||
u32 options;
|
||||
u32 optx; /* Netmask for OSPFv2, options for OSPFv3 */
|
||||
u32 routers[];
|
||||
};
|
||||
|
||||
struct ospf_lsa_sum_net
|
||||
struct ospf_lsa_sum2
|
||||
{
|
||||
ip4_addr netmask;
|
||||
u32 metric;
|
||||
};
|
||||
|
||||
struct ospf_lsa_sum3_net
|
||||
{
|
||||
u32 metric;
|
||||
u32 prefix[];
|
||||
};
|
||||
|
||||
struct ospf_lsa_sum_rt
|
||||
struct ospf_lsa_sum3_rt
|
||||
{
|
||||
u32 options;
|
||||
u32 metric;
|
||||
u32 drid;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext
|
||||
struct ospf_lsa_ext2
|
||||
{
|
||||
ip4_addr netmask;
|
||||
u32 metric;
|
||||
ip4_addr fwaddr;
|
||||
u32 tag;
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext3
|
||||
{
|
||||
u32 metric;
|
||||
u32 rest[];
|
||||
};
|
||||
|
||||
struct ospf_lsa_ext_local
|
||||
{
|
||||
ip_addr ip, fwaddr;
|
||||
int pxlen;
|
||||
u32 metric, ebit, fbit, tag, propagate;
|
||||
u8 pxopts;
|
||||
};
|
||||
|
||||
struct ospf_lsa_link
|
||||
{
|
||||
u32 options;
|
||||
ip_addr lladdr;
|
||||
ip6_addr lladdr;
|
||||
u32 pxcount;
|
||||
u32 rest[];
|
||||
};
|
||||
@ -549,9 +485,21 @@ struct ospf_lsa_prefix
|
||||
u32 rest[];
|
||||
};
|
||||
|
||||
#define LSA_EXT_EBIT 0x4000000
|
||||
#define LSA_EXT_FBIT 0x2000000
|
||||
#define LSA_EXT_TBIT 0x1000000
|
||||
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
|
||||
/* Endianity swap for lsa->type */
|
||||
#define ntoht(x) x
|
||||
#define htont(x) x
|
||||
|
||||
|
||||
#else /* OSPFv3 */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Endianity swap for lsa->type */
|
||||
#define ntoht(x) ntohs(x)
|
||||
@ -562,12 +510,6 @@ struct ospf_lsa_prefix
|
||||
#define METRIC_MASK 0x00FFFFFF
|
||||
#define OPTIONS_MASK 0x00FFFFFF
|
||||
|
||||
static inline unsigned
|
||||
lsa_rt_count(struct ospf_lsa_header *lsa)
|
||||
{
|
||||
return (lsa->length - sizeof(struct ospf_lsa_header) - sizeof(struct ospf_lsa_rt))
|
||||
/ sizeof(struct ospf_lsa_rt_link);
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
lsa_net_count(struct ospf_lsa_header *lsa)
|
||||
@ -672,10 +614,11 @@ struct ospf_neighbor
|
||||
#define NEIGHBOR_LOADING 6
|
||||
#define NEIGHBOR_FULL 7
|
||||
timer *inactim; /* Inactivity timer */
|
||||
union imms imms; /* I, M, Master/slave received */
|
||||
u8 imms; /* I, M, Master/slave received */
|
||||
u8 myimms; /* I, M Master/slave */
|
||||
u32 dds; /* DD Sequence number being sent */
|
||||
u32 ddr; /* last Dat Des packet received */
|
||||
union imms myimms; /* I, M Master/slave */
|
||||
|
||||
u32 rid; /* Router ID */
|
||||
ip_addr ip; /* IP of it's interface */
|
||||
u8 priority; /* Priority */
|
||||
@ -686,10 +629,7 @@ struct ospf_neighbor
|
||||
we use the same type to simplify handling */
|
||||
u32 dr; /* Neigbour's idea of DR */
|
||||
u32 bdr; /* Neigbour's idea of BDR */
|
||||
|
||||
#ifdef OSPFv3
|
||||
u32 iface_id; /* ID of Neighbour's iface connected to common network */
|
||||
#endif
|
||||
|
||||
siterator dbsi; /* Database summary list iterator */
|
||||
slist lsrql; /* Link state request */
|
||||
@ -808,14 +748,8 @@ struct ospf_iface_patt
|
||||
u8 check_link;
|
||||
u8 ecmp_weight;
|
||||
u8 real_bcast; /* Not really used in OSPFv3 */
|
||||
|
||||
#ifdef OSPFv2
|
||||
list *passwords;
|
||||
#endif
|
||||
|
||||
#ifdef OSPFv3
|
||||
u8 instance_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
||||
@ -826,6 +760,14 @@ void schedule_rt_lsa(struct ospf_area *oa);
|
||||
void schedule_rtcalc(struct proto_ospf *po);
|
||||
void schedule_net_lsa(struct ospf_iface *ifa);
|
||||
|
||||
static inline int ospf_is_v2(struct proto_ospf *po)
|
||||
{ return 0; } // XXXX fixme
|
||||
static inline int ospf_is_v3(struct proto_ospf *po)
|
||||
{ return 1; } // XXXX fixme
|
||||
|
||||
static inline void lsa_fix_options(struct proto_ospf *po, struct ospf_lsa_header *lsa, u8 options)
|
||||
{ if (ospf_is_v2(po)) lsa_set_options(lsa, options); }
|
||||
|
||||
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
||||
static inline struct ospf_area *ospf_main_area(struct proto_ospf *po)
|
||||
{ return (po->areano == 1) ? HEAD(po->area_list) : po->backbone; }
|
||||
@ -838,11 +780,8 @@ static inline int oa_is_nssa(struct ospf_area *oa)
|
||||
{ return oa->options & OPT_N; }
|
||||
|
||||
|
||||
#ifdef OSPFv3
|
||||
void schedule_link_lsa(struct ospf_iface *ifa);
|
||||
#else
|
||||
static inline void schedule_link_lsa(struct ospf_iface *ifa UNUSED) {}
|
||||
#endif
|
||||
|
||||
void schedule_link_lsa(struct ospf_iface *ifa); // XXXX caller ??
|
||||
|
||||
void ospf_sh_neigh(struct proto *p, char *iff);
|
||||
void ospf_sh(struct proto *p);
|
||||
|
@ -439,7 +439,7 @@ ospf_rx_hook(sock *sk, int size)
|
||||
struct ospf_neighbor *n = find_neigh(ifa, rid);
|
||||
#endif
|
||||
|
||||
if(!n && (ps->type != HELLO_P))
|
||||
if (!n && (ps->type != HELLO_P))
|
||||
{
|
||||
log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
|
||||
sk->faddr, ifa->iface->name);
|
||||
|
607
proto/ospf/rt.c
607
proto/ospf/rt.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@ struct top_hash_entry
|
||||
in intra-area routing table calculation */
|
||||
struct top_hash_entry *next; /* Next in hash chain */
|
||||
struct ospf_lsa_header lsa;
|
||||
u16 lsa_type; /* lsa.type processed and converted to common values */
|
||||
u32 domain; /* Area ID for area-wide LSAs, Iface ID for link-wide LSAs */
|
||||
// struct ospf_area *oa;
|
||||
void *lsa_body;
|
||||
@ -76,7 +77,7 @@ void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src);
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 lsa);
|
||||
struct top_hash_entry * ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif);
|
||||
|
||||
static inline struct top_hash_entry *
|
||||
ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
|
||||
@ -85,6 +86,13 @@ ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr)
|
||||
}
|
||||
|
||||
#else /* OSPFv3 */
|
||||
static inline struct top_hash_entry *
|
||||
ospf_hash_find_net(struct top_graph *f, u32 domain, u32 id, u32 nif)
|
||||
{
|
||||
return ospf_hash_find(f, domain, nif, id, LSA_T_NET);
|
||||
}
|
||||
|
||||
|
||||
struct top_hash_entry * ospf_hash_find_rt(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt_first(struct top_graph *f, u32 domain, u32 rtr);
|
||||
struct top_hash_entry * ospf_hash_find_rt_next(struct top_hash_entry *e);
|
||||
|
@ -160,7 +160,7 @@ radv_send_ra(struct radv_iface *ifa, int shutdown)
|
||||
}
|
||||
|
||||
RADV_TRACE(D_PACKETS, "Sending RA via %s", ifa->iface->name);
|
||||
sk_send_to(ifa->sk, ifa->plen, AllNodes, 0);
|
||||
sk_send_to(ifa->sk, ifa->plen, IP6_ALL_NODES, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -251,7 +251,7 @@ radv_sk_open(struct radv_iface *ifa)
|
||||
if (sk_setup_multicast(sk) < 0)
|
||||
goto err;
|
||||
|
||||
if (sk_join_group(sk, AllRouters) < 0)
|
||||
if (sk_join_group(sk, IP6_ALL_ROUTERS) < 0)
|
||||
goto err;
|
||||
|
||||
ifa->sk = sk;
|
||||
|
@ -26,9 +26,6 @@
|
||||
|
||||
#define ICMPV6_PROTO 58
|
||||
|
||||
#define AllNodes ipa_build6(0xFF020000, 0, 0, 1) /* FF02::1 */
|
||||
#define AllRouters ipa_build6(0xFF020000, 0, 0, 2) /* FF02::2 */
|
||||
|
||||
#define ICMPV6_RS 133
|
||||
#define ICMPV6_RA 134
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user