204 lines
4.6 KiB
C
204 lines
4.6 KiB
C
|
/*
|
||
|
* BIRD -- OSPF
|
||
|
*
|
||
|
* (c) 1999 Ondrej Filip <feela@network.cz>
|
||
|
*
|
||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||
|
*/
|
||
|
|
||
|
#include "ospf.h"
|
||
|
|
||
|
void
|
||
|
ospf_dbdes_tx(struct ospf_neighbor *n)
|
||
|
{
|
||
|
struct ospf_dbdes_packet *pkt;
|
||
|
struct ospf_packet *op;
|
||
|
struct ospf_iface *ifa;
|
||
|
u16 length;
|
||
|
struct proto *p;
|
||
|
|
||
|
ifa=n->ifa;
|
||
|
|
||
|
p=(struct proto *)(ifa->proto);
|
||
|
|
||
|
switch(n->state)
|
||
|
{
|
||
|
case NEIGHBOR_EXSTART: /* Send empty packets */
|
||
|
pkt=(struct ospf_dbdes_packet *)(ifa->ip_sk->tbuf);
|
||
|
op=(struct ospf_packet *)pkt;
|
||
|
|
||
|
fill_ospf_pkt_hdr(ifa, pkt, DBDES);
|
||
|
pkt->iface_mtu= ((struct iface *)ifa)->mtu;
|
||
|
pkt->options= ifa->options;
|
||
|
pkt->imms=n->myimms;
|
||
|
pkt->ddseq=n->dds;
|
||
|
length=sizeof(struct ospf_dbdes_packet);
|
||
|
op->length=htons(length);
|
||
|
ospf_pkt_finalize(ifa, op);
|
||
|
sk_send_to(ifa->ip_sk,length, n->ip, OSPF_PROTO);
|
||
|
debug("%s: DB_DES sent for %u.\n", p->name, n->rid);
|
||
|
|
||
|
/*case NEIGHBOR_EXCHANGE: */
|
||
|
default: /* Ignore it */
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
rxmt_timer_hook(timer *timer)
|
||
|
{
|
||
|
struct ospf_iface *ifa;
|
||
|
struct proto *p;
|
||
|
struct ospf_neighbor *n;
|
||
|
|
||
|
ifa=(struct ospf_iface *)timer->data;
|
||
|
p=(struct proto *)(ifa->proto);
|
||
|
debug("%s: RXMT timer fired on interface %s.\n",
|
||
|
p->name, ifa->iface->name);
|
||
|
WALK_LIST (n, ifa->neigh_list) /* Try to send db_des */
|
||
|
{
|
||
|
ospf_dbdes_tx(n);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ospf_dbdes_rx(struct ospf_dbdes_packet *ps, struct proto *p,
|
||
|
struct ospf_iface *ifa, u16 size)
|
||
|
{
|
||
|
u32 nrid, myrid;
|
||
|
struct ospf_neighbor *n;
|
||
|
u8 i;
|
||
|
|
||
|
nrid=ntohl(((struct ospf_packet *)ps)->routerid);
|
||
|
|
||
|
myrid=p->cf->global->router_id;
|
||
|
|
||
|
if((n=find_neigh(ifa, nrid))==NULL)
|
||
|
{
|
||
|
debug("%s: Received dbdes from unknown neigbor! (%u)\n", p->name,
|
||
|
nrid);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
if(ifa->iface->mtu<size)
|
||
|
{
|
||
|
debug("%s: Received dbdes larger than MTU from (%u)!\n", p->name, nrid);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
switch(n->state)
|
||
|
{
|
||
|
case NEIGHBOR_DOWN:
|
||
|
case NEIGHBOR_ATTEMPT:
|
||
|
case NEIGHBOR_2WAY:
|
||
|
debug("%s: Received dbdes from %u in bad state. (%u)\n", p->name, nrid);
|
||
|
return;
|
||
|
break;
|
||
|
case NEIGHBOR_INIT:
|
||
|
ospf_neigh_sm(n, INM_2WAYREC);
|
||
|
if(n->state!=NEIGHBOR_EXSTART) return;
|
||
|
case NEIGHBOR_EXSTART:
|
||
|
if(ps->imms==(DBDES_I|DBDES_M|DBDES_MS) && (n->rid > myrid) &&
|
||
|
(size == sizeof(struct ospf_dbdes_packet)))
|
||
|
{
|
||
|
/* I'm slave! */
|
||
|
n->dds=ps->ddseq;
|
||
|
n->options=ps->options;
|
||
|
n->myimms=(n->myimms && DBDES_M);
|
||
|
n->ddr=ps->ddseq;
|
||
|
n->imms=ps->imms;
|
||
|
debug("%s: I'm slave to %u. \n", p->name, nrid);
|
||
|
ospf_neigh_sm(n, INM_NEGDONE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(((ps->imms & (DBDES_I|DBDES_MS))== 0) && (n->rid < myrid) &&
|
||
|
(n->dds == ps->ddseq))
|
||
|
{
|
||
|
/* I'm master! */
|
||
|
n->options=ps->options;
|
||
|
n->ddr=ps->ddseq;
|
||
|
n->imms=ps->imms;
|
||
|
debug("%s: I'm master to %u. \n", p->name, nrid);
|
||
|
ospf_neigh_sm(n, INM_NEGDONE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
debug("%s: Nothing happend to %u (imms=%u)", p->name, nrid,
|
||
|
ps->imms);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break; /* I should probably continue processing packet */
|
||
|
|
||
|
case NEIGHBOR_EXCHANGE:
|
||
|
if((ps->imms==n->imms) && (ps->options=n->options) &&
|
||
|
(ps->ddseq==n->dds))
|
||
|
{
|
||
|
/* Duplicate packet */
|
||
|
debug("%s: Received duplicate dbdes from (%u)!\n", p->name, nrid);
|
||
|
if(!IAMMASTER(n->imms))
|
||
|
{
|
||
|
ospf_dbdes_tx(n);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(IAMMASTER(ps->imms)!=IAMMASTER(n->myimms)) /* M/S bit differs */
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(INISET(ps->imms)) /* I bit is set */
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(ps->options!=n->options) /* Options differs */
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(IAMMASTER(n->myimms))
|
||
|
{
|
||
|
if(ps->ddseq!=n->dds)
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(ps->ddseq!=(n->dds+1))
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* FIXME: Packet accepted, go on */
|
||
|
|
||
|
break;
|
||
|
case NEIGHBOR_LOADING:
|
||
|
case NEIGHBOR_FULL:
|
||
|
if((ps->imms==n->imms) && (ps->options=n->options) &&
|
||
|
(ps->ddseq==n->dds)) /* Only duplicate are accepted */
|
||
|
{
|
||
|
debug("%s: Received duplicate dbdes from (%u)!\n", p->name, nrid);
|
||
|
return;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ospf_neigh_sm(n, INM_SEQMIS);
|
||
|
}
|
||
|
break;
|
||
|
defaut:
|
||
|
die("%s: Received dbdes from %u in unknown state. (%u)\n", p->name, nrid);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|