/* * BIRD -- OSPF * * (c) 1999 Ondrej Filip * * 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->mtuname, 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; } }