0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-14 10:27:03 +00:00

Temporary integrated commit (OSPF), unfinished.

This commit is contained in:
Ondrej Zajicek 2012-08-05 22:32:06 +02:00
parent 1ee54a8413
commit a7b7b2bd0f
23 changed files with 1590 additions and 1615 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;

View File

@ -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