| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	BIRD -- OSPF | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	(c) 1999-2000 Ondrej Filip <feela@network.cz> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *	Can be freely distributed and used under the terms of the GNU GPL. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ospf.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2000-05-09 19:36:32 +00:00
										 |  |  | flush_lsa(struct top_hash_entry *en, struct ospf_area *oa) | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-06-06 02:50:49 +00:00
										 |  |  |   struct proto *p=&oa->po->proto; | 
					
						
							|  |  |  |   OSPF_TRACE(D_EVENTS, "Going to remove node Type: %u, Id: %I, Rt: %I, Age: %u", | 
					
						
							| 
									
										
										
										
											2000-06-05 02:23:20 +00:00
										 |  |  |     en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.age); | 
					
						
							| 
									
										
										
										
											2000-05-09 19:36:32 +00:00
										 |  |  |   s_rem_node(SNODE en); | 
					
						
							|  |  |  |   ospf_hash_delete(oa->gr,en); | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  | ospf_age(struct ospf_area *oa) | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-05-03 22:23:41 +00:00
										 |  |  |   struct proto *p=&oa->po->proto; | 
					
						
							| 
									
										
										
										
											2000-05-30 17:49:25 +00:00
										 |  |  |   struct proto_ospf *po=(struct proto_ospf *)p; | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |   struct top_hash_entry *en,*nxt; | 
					
						
							|  |  |  |   int flush=can_flush_lsa(oa); | 
					
						
							|  |  |  |   bird_clock_t delta=now-oa->lage; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   WALK_SLIST_DELSAFE(en,nxt,oa->lsal) | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |     if(en->lsa.age==LSA_MAXAGE) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if(flush) flush_lsa(en,oa); | 
					
						
							| 
									
										
										
										
											2000-06-02 12:34:28 +00:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-06-05 18:09:49 +00:00
										 |  |  |     if((en->lsa.rt==p->cf->global->router_id)&&(en->lsa.age>=LSREFRESHTIME)) | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-06-06 02:50:49 +00:00
										 |  |  |        OSPF_TRACE(D_EVENTS, "Refreshing my LSA: Type: %u, Id: %I, Rt: %I", | 
					
						
							|  |  |  |          en->lsa.type, en->lsa.id, en->lsa.rt); | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |        en->lsa.sn++; | 
					
						
							|  |  |  |        en->lsa.age=0; | 
					
						
							| 
									
										
										
										
											2000-06-01 12:08:14 +00:00
										 |  |  |        lsasum_calculate(&en->lsa,en->lsa_body,po); | 
					
						
							| 
									
										
										
										
											2000-06-05 18:09:49 +00:00
										 |  |  |        flood_lsa(NULL,NULL,&en->lsa,po,NULL,oa,1); | 
					
						
							|  |  |  |        continue; | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-06-04 19:21:23 +00:00
										 |  |  |     if((en->lsa.age+=delta)>=LSA_MAXAGE) | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-06-04 19:21:23 +00:00
										 |  |  |       if(flush) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         flush_lsa(en,oa); | 
					
						
							|  |  |  |         schedule_rtcalc(oa); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |       else en->lsa.age=LSA_MAXAGE; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-05-31 14:21:56 +00:00
										 |  |  |   oa->lage=now; | 
					
						
							| 
									
										
										
										
											2000-05-02 22:19:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | void | 
					
						
							|  |  |  | htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   n->age=htons(h->age); | 
					
						
							|  |  |  |   n->options=h->options; | 
					
						
							|  |  |  |   n->type=h->type; | 
					
						
							|  |  |  |   n->id=htonl(h->id); | 
					
						
							|  |  |  |   n->rt=htonl(h->rt); | 
					
						
							|  |  |  |   n->sn=htonl(h->sn); | 
					
						
							|  |  |  |   n->checksum=htons(h->checksum); | 
					
						
							|  |  |  |   n->length=htons(h->length); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   h->age=ntohs(n->age); | 
					
						
							|  |  |  |   h->options=n->options; | 
					
						
							|  |  |  |   h->type=n->type; | 
					
						
							|  |  |  |   h->id=ntohl(n->id); | 
					
						
							|  |  |  |   h->rt=ntohl(n->rt); | 
					
						
							|  |  |  |   h->sn=ntohl(n->sn); | 
					
						
							|  |  |  |   h->checksum=ntohs(n->checksum); | 
					
						
							|  |  |  |   h->length=ntohs(n->length); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | htonlsab(void *h, void *n, u8 type, u16 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unsigned int i; | 
					
						
							|  |  |  |   switch(type) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     case LSA_T_RT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_rt *hrt, *nrt; | 
					
						
							|  |  |  |       struct ospf_lsa_rt_link *hrtl,*nrtl; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       u16 links; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       nrt=n; | 
					
						
							|  |  |  |       hrt=h; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       links=hrt->links; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       nrt->VEB=hrt->VEB; | 
					
						
							|  |  |  |       nrt->padding=0; | 
					
						
							|  |  |  |       nrt->links=htons(hrt->links); | 
					
						
							|  |  |  |       nrtl=(struct ospf_lsa_rt_link *)(nrt+1); | 
					
						
							|  |  |  |       hrtl=(struct ospf_lsa_rt_link *)(hrt+1); | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       for(i=0;i<links;i++) | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |       { | 
					
						
							|  |  |  |         (nrtl+i)->id=htonl((hrtl+i)->id); | 
					
						
							|  |  |  |         (nrtl+i)->data=htonl((hrtl+i)->data); | 
					
						
							|  |  |  |         (nrtl+i)->type=(hrtl+i)->type; | 
					
						
							|  |  |  |         (nrtl+i)->notos=(hrtl+i)->notos; | 
					
						
							|  |  |  |         (nrtl+i)->metric=htons((hrtl+i)->metric); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_NET: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       u32 *hid,*nid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       nid=n; | 
					
						
							|  |  |  |       hid=h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<(len/sizeof(u32));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         *(nid+i)=htonl(*(hid+i)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_SUM_NET: | 
					
						
							|  |  |  |     case LSA_T_SUM_RT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_summ *hs, *ns; | 
					
						
							|  |  |  |       struct ospf_lsa_summ_net *hn, *nn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       hs=h; | 
					
						
							|  |  |  |       ns=n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 13:39:06 +00:00
										 |  |  |       ns->netmask=hs->netmask; | 
					
						
							|  |  |  |       ipa_hton(ns->netmask); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       hn=(struct ospf_lsa_summ_net *)(hs+1); | 
					
						
							|  |  |  |       nn=(struct ospf_lsa_summ_net *)(ns+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<((len-sizeof(struct ospf_lsa_summ))/ | 
					
						
							|  |  |  |         sizeof(struct ospf_lsa_summ_net));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         (nn+i)->tos=(hn+i)->tos; | 
					
						
							|  |  |  | 	(nn+i)->metric=htons((hn+i)->metric); | 
					
						
							|  |  |  | 	(nn+i)->padding=0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_EXT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_ext *he, *ne; | 
					
						
							|  |  |  |       struct ospf_lsa_ext_tos *ht, *nt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       he=h; | 
					
						
							|  |  |  |       ne=n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 13:39:06 +00:00
										 |  |  |       ne->netmask=he->netmask; | 
					
						
							|  |  |  |       ipa_hton(ne->netmask); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ht=(struct ospf_lsa_ext_tos *)(he+1); | 
					
						
							|  |  |  |       nt=(struct ospf_lsa_ext_tos *)(ne+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<((len-sizeof(struct ospf_lsa_ext))/ | 
					
						
							|  |  |  |         sizeof(struct ospf_lsa_ext_tos));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         (nt+i)->etos=(ht+i)->etos; | 
					
						
							|  |  |  |         (nt+i)->padding=0; | 
					
						
							|  |  |  |         (nt+i)->metric=htons((ht+i)->metric); | 
					
						
							| 
									
										
										
										
											2000-05-10 11:52:39 +00:00
										 |  |  |         (nt+i)->fwaddr=(ht+i)->fwaddr; | 
					
						
							|  |  |  |         ipa_hton((nt+i)->fwaddr); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |         (nt+i)->tag=htonl((ht+i)->tag); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-06-06 01:00:34 +00:00
										 |  |  |     default: bug("(hton): Unknown LSA"); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | ntohlsab(void *n, void *h, u8 type, u16 len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unsigned int i; | 
					
						
							|  |  |  |   switch(type) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     case LSA_T_RT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_rt *hrt, *nrt; | 
					
						
							|  |  |  |       struct ospf_lsa_rt_link *hrtl,*nrtl; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       u16 links; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       nrt=n; | 
					
						
							|  |  |  |       hrt=h; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       hrt->VEB=nrt->VEB; | 
					
						
							|  |  |  |       hrt->padding=0; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       links=hrt->links=ntohs(nrt->links); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |       nrtl=(struct ospf_lsa_rt_link *)(nrt+1); | 
					
						
							|  |  |  |       hrtl=(struct ospf_lsa_rt_link *)(hrt+1); | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |       for(i=0;i<links;i++) | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |       { | 
					
						
							|  |  |  |         (hrtl+i)->id=ntohl((nrtl+i)->id); | 
					
						
							|  |  |  |         (hrtl+i)->data=ntohl((nrtl+i)->data); | 
					
						
							|  |  |  |         (hrtl+i)->type=(nrtl+i)->type; | 
					
						
							|  |  |  |         (hrtl+i)->notos=(nrtl+i)->notos; | 
					
						
							|  |  |  |         (hrtl+i)->metric=ntohs((nrtl+i)->metric); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_NET: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       u32 *hid,*nid; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       hid=h; | 
					
						
							|  |  |  |       nid=n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<(len/sizeof(u32));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         *(hid+i)=ntohl(*(nid+i)); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_SUM_NET: | 
					
						
							|  |  |  |     case LSA_T_SUM_RT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_summ *hs, *ns; | 
					
						
							|  |  |  |       struct ospf_lsa_summ_net *hn, *nn; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       hs=h; | 
					
						
							|  |  |  |       ns=n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 13:39:06 +00:00
										 |  |  |       hs->netmask=ns->netmask; | 
					
						
							|  |  |  |       ipa_ntoh(hs->netmask); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       hn=(struct ospf_lsa_summ_net *)(hs+1); | 
					
						
							|  |  |  |       nn=(struct ospf_lsa_summ_net *)(ns+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<((len-sizeof(struct ospf_lsa_summ))/ | 
					
						
							|  |  |  |         sizeof(struct ospf_lsa_summ_net));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         (hn+i)->tos=(nn+i)->tos; | 
					
						
							|  |  |  | 	(hn+i)->metric=ntohs((nn+i)->metric); | 
					
						
							|  |  |  | 	(hn+i)->padding=0; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     case LSA_T_EXT: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       struct ospf_lsa_ext *he, *ne; | 
					
						
							|  |  |  |       struct ospf_lsa_ext_tos *ht, *nt; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       he=h; | 
					
						
							|  |  |  |       ne=n; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-30 13:39:06 +00:00
										 |  |  |       he->netmask=ne->netmask; | 
					
						
							|  |  |  |       ipa_ntoh(he->netmask); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       ht=(struct ospf_lsa_ext_tos *)(he+1); | 
					
						
							|  |  |  |       nt=(struct ospf_lsa_ext_tos *)(ne+1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for(i=0;i<((len-sizeof(struct ospf_lsa_ext))/ | 
					
						
							|  |  |  |         sizeof(struct ospf_lsa_ext_tos));i++) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         (ht+i)->etos=(nt+i)->etos; | 
					
						
							|  |  |  |         (ht+i)->padding=0; | 
					
						
							|  |  |  |         (ht+i)->metric=ntohs((nt+i)->metric); | 
					
						
							| 
									
										
										
										
											2000-05-10 11:52:39 +00:00
										 |  |  |         (ht+i)->fwaddr=(nt+i)->fwaddr; | 
					
						
							|  |  |  |         ipa_ntoh((ht+i)->fwaddr); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |         (ht+i)->tag=ntohl((nt+i)->tag); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-06-06 01:00:34 +00:00
										 |  |  |     default: bug("(ntoh): Unknown LSA"); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | #define MODX 4102		/* larges signed value without overflow */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fletcher Checksum -- Refer to RFC1008. */ | 
					
						
							|  |  |  | #define MODX                 4102
 | 
					
						
							|  |  |  | #define LSA_CHECKSUM_OFFSET    15
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* FIXME This is VERY uneficient, I have huge endianity problems */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | lsasum_calculate(struct ospf_lsa_header *h,void *body,struct proto_ospf *po) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   u16 length; | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   length=h->length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   htonlsah(h,h); | 
					
						
							| 
									
										
										
										
											2000-05-04 01:23:03 +00:00
										 |  |  |   htonlsab(body,body,h->type,length-sizeof(struct ospf_lsa_header)); | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   (void)lsasum_check(h,body,po); | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   ntohlsah(h,h); | 
					
						
							| 
									
										
										
										
											2000-05-04 01:23:03 +00:00
										 |  |  |   ntohlsab(body,body,h->type,length-sizeof(struct ospf_lsa_header)); | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Note, that this function expects that LSA is in big endianity | 
					
						
							|  |  |  |  * It also returns value in big endian | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | u16 | 
					
						
							|  |  |  | lsasum_check(struct ospf_lsa_header *h,void *body,struct proto_ospf *po) | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   u8 *sp, *ep, *p, *q, *b; | 
					
						
							|  |  |  |   int c0 = 0, c1 = 0; | 
					
						
							|  |  |  |   int x, y; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   u16 length,chsum; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   b=body; | 
					
						
							|  |  |  |   sp = (char *) &h->options; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   length=ntohs(h->length)-2; | 
					
						
							|  |  |  |   h->checksum = 0; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   for (ep = sp + length; sp < ep; sp = q) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   {		/* Actually MODX is very large, do we need the for-cyclus? */ | 
					
						
							|  |  |  |     q = sp + MODX; | 
					
						
							|  |  |  |     if (q > ep) q = ep; | 
					
						
							|  |  |  |     for (p = sp; p < q; p++) | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |       /* 
 | 
					
						
							|  |  |  |        * I count with bytes from header and than from body | 
					
						
							|  |  |  |        * but if there is no body, it's appended to header | 
					
						
							|  |  |  |        * (probably checksum in update receiving) and I go on | 
					
						
							|  |  |  |        * after header | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       if((b==NULL) || (p<(u8 *)(h+1))) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	      c0 += *p; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	      c0 += *(b+(p-sp)-sizeof(struct ospf_lsa_header)+2); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c1 += c0; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |     c0 %= 255; | 
					
						
							|  |  |  |     c1 %= 255; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   x = ((length - LSA_CHECKSUM_OFFSET) * c0 - c1) % 255; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   if (x <= 0) x += 255; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  |   y = 510 - c0 - x; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   if (y > 255) y -= 255; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   chsum= x + (y << 8); | 
					
						
							|  |  |  |   h->checksum = chsum; | 
					
						
							|  |  |  |   return chsum; | 
					
						
							| 
									
										
										
										
											2000-04-01 02:45:49 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-02 19:04:23 +00:00
										 |  |  | int | 
					
						
							|  |  |  | lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  | 			/* Return codes from point of view of l1 */ | 
					
						
							| 
									
										
										
										
											2000-04-02 19:04:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-05-31 18:21:42 +00:00
										 |  |  |   u32 sn1,sn2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sn1=l1->sn-LSA_INITSEQNO+1; | 
					
						
							|  |  |  |   sn2=l2->sn-LSA_INITSEQNO+1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if(sn1>sn2) return CMP_NEWER; | 
					
						
							|  |  |  |   if(sn1<sn2) return CMP_OLDER; | 
					
						
							| 
									
										
										
										
											2000-05-30 15:01:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-01 00:22:48 +00:00
										 |  |  |   if(l1->checksum!=l2->checksum) | 
					
						
							| 
									
										
										
										
											2000-05-30 15:01:51 +00:00
										 |  |  |     return l1->checksum<l2->checksum ? CMP_OLDER : CMP_NEWER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if((l1->age==LSA_MAXAGE)&&(l2->age!=LSA_MAXAGE)) return CMP_NEWER; | 
					
						
							|  |  |  |   if((l2->age==LSA_MAXAGE)&&(l1->age!=LSA_MAXAGE)) return CMP_OLDER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if(abs(l1->age-l2->age)>LSA_MAXAGEDIFF) | 
					
						
							|  |  |  |     return l1->age<l2->age ? CMP_NEWER : CMP_OLDER; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return CMP_SAME; | 
					
						
							| 
									
										
										
										
											2000-04-02 19:04:23 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  | /* LSA can be temporarrily, but body must be mb_alloced. */ | 
					
						
							|  |  |  | struct top_hash_entry * | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  | lsa_install_new(struct ospf_lsa_header *lsa, void *body, struct ospf_area *oa, | 
					
						
							|  |  |  |   struct proto *p) | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |   int change=0; | 
					
						
							|  |  |  |   unsigned i; | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  |   struct top_hash_entry *en; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if((en=ospf_hash_find_header(oa->gr,lsa))==NULL) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     en=ospf_hash_get_header(oa->gr,lsa); | 
					
						
							|  |  |  |     change=1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |     if((en->lsa.length!=lsa->length)||(en->lsa.options!=lsa->options)|| | 
					
						
							|  |  |  |       ((en->lsa.age==LSA_MAXAGE)||(lsa->age==LSA_MAXAGE))) change=1; | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       u8 *k=en->lsa_body,*l=body; | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |       for(i=0;i<(lsa->length-sizeof(struct ospf_lsa_header));i++) | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  |       { | 
					
						
							|  |  |  |         if(*(k+i)!=*(l+i)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  change=1; | 
					
						
							|  |  |  | 	  break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-06-05 02:23:20 +00:00
										 |  |  |     s_rem_node(SNODE en); | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-05 02:23:20 +00:00
										 |  |  |   DBG("Inst lsa: Id: %I, Rt: %I, Type: %u, Age: %u, Sum: %u, Sn: 0x%x\n", | 
					
						
							|  |  |  |     lsa->id, lsa->rt, lsa->type, lsa->age, lsa->checksum, lsa->sn); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-04 19:21:23 +00:00
										 |  |  |   s_add_tail(&oa->lsal, SNODE en); | 
					
						
							|  |  |  |   en->inst_t=now; | 
					
						
							|  |  |  |   if(en->lsa_body!=NULL) mb_free(en->lsa_body); | 
					
						
							|  |  |  |   en->lsa_body=body; | 
					
						
							|  |  |  |   memcpy(&en->lsa,lsa,sizeof(struct ospf_lsa_header)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-30 22:14:31 +00:00
										 |  |  |   if(change) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2000-06-04 19:21:23 +00:00
										 |  |  |     schedule_rtcalc(oa); | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |    | 
					
						
							|  |  |  |   return en; | 
					
						
							|  |  |  | } |