| 
									
										
										
										
											2000-03-30 20:00:42 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  *	BIRD -- OSPF | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |  *	(c) 2000--2004 Ondrej Filip <feela@network.cz> | 
					
						
							| 
									
										
										
										
											2000-03-30 20:00:42 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  *	Can be freely distributed and used under the terms of the GNU GPL. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ospf.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |  * ospf_lsupd_flood - send received or generated lsa to the neighbors | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |  * @n: neighbor than sent this lsa (or NULL if generated) | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |  * @hn: LSA header followed by lsa body in network endianity (may be NULL)  | 
					
						
							|  |  |  |  * @hh: LSA header in host endianity (must be filled) | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |  * @po: actual instance of OSPF protocol | 
					
						
							|  |  |  |  * @iff: interface which received this LSA (or NULL if LSA is generated) | 
					
						
							|  |  |  |  * @oa: ospf_area which is the LSA generated for | 
					
						
							|  |  |  |  * @rtl: add this LSA into retransmission list | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |  * return value - was the LSA flooded back? | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  | int | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | ospf_lsupd_flood(struct ospf_neighbor *n, struct ospf_lsa_header *hn, | 
					
						
							|  |  |  | 		 struct ospf_lsa_header *hh, struct ospf_iface *iff, | 
					
						
							|  |  |  | 		 struct ospf_area *oa, int rtl) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   struct ospf_iface *ifa; | 
					
						
							|  |  |  |   struct ospf_neighbor *nn; | 
					
						
							|  |  |  |   struct top_hash_entry *en; | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   struct proto_ospf *po = oa->po; | 
					
						
							|  |  |  |   struct proto *p = &po->proto; | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |   int ret, retval = 0; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* pg 148 */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   WALK_LIST(NODE ifa, po->iface_list) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (ifa->stub) | 
					
						
							|  |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2000-09-04 21:21:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (hh->type == LSA_T_EXT) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (ifa->type == OSPF_IT_VLINK) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       if (ifa->oa->stub) | 
					
						
							|  |  |  | 	continue; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (oa->areaid == BACKBONE) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((ifa->type != OSPF_IT_VLINK) && (ifa->oa != oa)) | 
					
						
							|  |  |  | 	  continue; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if (ifa->oa != oa) | 
					
						
							|  |  |  | 	  continue; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     ret = 0; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     WALK_LIST(NODE nn, ifa->neigh_list) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (nn->state < NEIGHBOR_EXCHANGE) | 
					
						
							|  |  |  | 	continue; | 
					
						
							|  |  |  |       if (nn->state < NEIGHBOR_FULL) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((en = ospf_hash_find_header(nn->lsrqh, hh)) != NULL) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	  switch (lsa_comp(hh, &en->lsa)) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 	  { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	  case CMP_OLDER: | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  case CMP_SAME: | 
					
						
							|  |  |  | 	    s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	    if (en->lsa_body != NULL) | 
					
						
							|  |  |  | 	      mb_free(en->lsa_body); | 
					
						
							|  |  |  | 	    en->lsa_body = NULL; | 
					
						
							|  |  |  | 	    DBG("Removing from lsreq list for neigh %I\n", nn->rid); | 
					
						
							|  |  |  | 	    ospf_hash_delete(nn->lsrqh, en); | 
					
						
							|  |  |  | 	    if (EMPTY_SLIST(nn->lsrql)) | 
					
						
							|  |  |  | 	      ospf_neigh_sm(nn, INM_LOADDONE); | 
					
						
							|  |  |  | 	    continue; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  case CMP_NEWER: | 
					
						
							|  |  |  | 	    s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	    if (en->lsa_body != NULL) | 
					
						
							|  |  |  | 	      mb_free(en->lsa_body); | 
					
						
							|  |  |  | 	    en->lsa_body = NULL; | 
					
						
							|  |  |  | 	    DBG("Removing from lsreq list for neigh %I\n", nn->rid); | 
					
						
							|  |  |  | 	    ospf_hash_delete(nn->lsrqh, en); | 
					
						
							|  |  |  | 	    if (EMPTY_SLIST(nn->lsrql)) | 
					
						
							|  |  |  | 	      ospf_neigh_sm(nn, INM_LOADDONE); | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  default: | 
					
						
							|  |  |  | 	    bug("Bug in lsa_comp?"); | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (nn == n) | 
					
						
							|  |  |  | 	continue; | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (rtl) | 
					
						
							| 
									
										
										
										
											2000-05-09 18:17:34 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((en = ospf_hash_find_header(nn->lsrth, hh)) == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  en = ospf_hash_get_header(nn->lsrth, hh); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	s_add_tail(&nn->lsrtl, SNODE en); | 
					
						
							|  |  |  | 	memcpy(&en->lsa, hh, sizeof(struct ospf_lsa_header)); | 
					
						
							|  |  |  | 	DBG("Adding LSA lsrt RT: %I, Id: %I, Type: %u for n: %I\n", | 
					
						
							|  |  |  | 	    en->lsa.rt, en->lsa.id, en->lsa.type, nn->ip); | 
					
						
							| 
									
										
										
										
											2000-05-09 18:17:34 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((en = ospf_hash_find_header(nn->lsrth, hh)) != NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	  if (en->lsa_body != NULL) | 
					
						
							|  |  |  | 	    mb_free(en->lsa_body); | 
					
						
							|  |  |  | 	  en->lsa_body = NULL; | 
					
						
							|  |  |  | 	  ospf_hash_delete(nn->lsrth, en); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2000-05-09 18:17:34 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       ret = 1; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-05-31 18:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (ret == 0) | 
					
						
							|  |  |  |       continue;			/* pg 150 (2) */ | 
					
						
							| 
									
										
										
										
											2000-05-31 18:21:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (ifa == iff) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if ((n->rid == iff->drid) || n->rid == iff->bdrid) | 
					
						
							|  |  |  | 	continue;		/* pg 150 (3) */ | 
					
						
							|  |  |  |       if (iff->state == OSPF_IS_BACKUP) | 
					
						
							|  |  |  | 	continue;		/* pg 150 (4) */ | 
					
						
							|  |  |  |       retval = 1; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-04-18 22:07:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       sock *sk; | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |       u16 len, age; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       struct ospf_lsupd_packet *pk; | 
					
						
							|  |  |  |       struct ospf_packet *op; | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |       struct ospf_lsa_header *lh; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (ifa->type == OSPF_IT_NBMA) | 
					
						
							|  |  |  | 	sk = ifa->ip_sk; | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  | 	sk = ifa->hello_sk;	/* FIXME is this true for PTP? */ | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       pk = (struct ospf_lsupd_packet *) sk->tbuf; | 
					
						
							|  |  |  |       op = (struct ospf_packet *) sk->tbuf; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |       ospf_pkt_fill_hdr(ifa, pk, LSUPD_P); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       pk->lsano = htonl(1); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       lh = (struct ospf_lsa_header *) (pk + 1); | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Copy LSA into the packet */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (hn) | 
					
						
							| 
									
										
										
										
											2000-04-17 20:42:42 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	memcpy(lh, hn, ntohs(hn->length)); | 
					
						
							| 
									
										
										
										
											2000-04-17 20:42:42 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	u8 *help; | 
					
						
							| 
									
										
										
										
											2000-04-17 20:42:42 +00:00
										 |  |  | 	struct top_hash_entry *en; | 
					
						
							| 
									
										
										
										
											2000-05-02 22:31:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	htonlsah(hh, lh); | 
					
						
							|  |  |  | 	help = (u8 *) (lh + 1); | 
					
						
							|  |  |  | 	en = ospf_hash_find_header(oa->gr, hh); | 
					
						
							|  |  |  | 	htonlsab(en->lsa_body, help, hh->type, hh->length | 
					
						
							|  |  |  | 		 - sizeof(struct ospf_lsa_header)); | 
					
						
							| 
									
										
										
										
											2000-04-17 20:42:42 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       len = sizeof(struct ospf_lsupd_packet) + ntohs(lh->length); | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       age = ntohs(lh->age); | 
					
						
							|  |  |  |       age += ifa->inftransdelay; | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (age > LSA_MAXAGE) | 
					
						
							|  |  |  | 	age = LSA_MAXAGE; | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |       lh->age = htons(age); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       op->length = htons(len); | 
					
						
							| 
									
										
										
										
											2000-06-06 02:16:39 +00:00
										 |  |  |       OSPF_TRACE(D_PACKETS, "LS upd flooded via %s", ifa->iface->name); | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (ifa->type == OSPF_IT_NBMA) | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR)) | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  | 	  ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  | 	  ospf_send_to_bdr(sk, ifa); | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) || | 
					
						
							|  |  |  | 	    (ifa->type == OSPF_IT_PTP)) | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  | 	  ospf_send_to(sk, AllSPFRouters, ifa); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  | 	  ospf_send_to(sk, AllDRouters, ifa); | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |   return retval; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | void				/* I send all I received in LSREQ */ | 
					
						
							|  |  |  | ospf_lsupd_send_list(struct ospf_neighbor *n, list * l) | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   struct l_lsr_head *llsh; | 
					
						
							|  |  |  |   u16 len; | 
					
						
							|  |  |  |   u32 lsano; | 
					
						
							|  |  |  |   struct top_hash_entry *en; | 
					
						
							|  |  |  |   struct ospf_lsupd_packet *pk; | 
					
						
							|  |  |  |   struct ospf_packet *op; | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   struct proto *p = &n->ifa->oa->po->proto; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |   void *pktpos; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   if (EMPTY_LIST(*l)) | 
					
						
							|  |  |  |     return; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   pk = (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf; | 
					
						
							|  |  |  |   op = (struct ospf_packet *) n->ifa->ip_sk->tbuf; | 
					
						
							| 
									
										
										
										
											2000-03-31 01:14:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   DBG("LSupd: 1st packet\n"); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |   ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P); | 
					
						
							|  |  |  |   len = sizeof(struct ospf_lsupd_packet); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   lsano = 0; | 
					
						
							|  |  |  |   pktpos = (pk + 1); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   WALK_LIST(llsh, *l) | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((en = ospf_hash_find(n->ifa->oa->gr, llsh->lsh.id, llsh->lsh.rt, | 
					
						
							|  |  |  | 			     llsh->lsh.type)) == NULL) | 
					
						
							|  |  |  |       continue;			/* Probably flushed LSA */ | 
					
						
							| 
									
										
										
										
											2000-05-09 18:20:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-08 19:14:08 +00:00
										 |  |  |     DBG("Sending ID=%I, Type=%u, RT=%I Sn: 0x%x Age: %u\n", | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	llsh->lsh.id, llsh->lsh.type, llsh->lsh.rt, en->lsa.sn, en->lsa.age); | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |     if (((u32) (len + en->lsa.length)) > ospf_pkt_maxsize(n->ifa)) | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       pk->lsano = htonl(lsano); | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |       op->length = htons(len); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |       ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa); | 
					
						
							| 
									
										
										
										
											2000-06-06 02:16:39 +00:00
										 |  |  |       OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-31 01:14:41 +00:00
										 |  |  |       DBG("LSupd: next packet\n"); | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |       ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P); | 
					
						
							|  |  |  |       len = sizeof(struct ospf_lsupd_packet); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       lsano = 0; | 
					
						
							|  |  |  |       pktpos = (pk + 1); | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     htonlsah(&(en->lsa), pktpos); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     pktpos = pktpos + sizeof(struct ospf_lsa_header); | 
					
						
							| 
									
										
										
										
											2000-05-04 01:23:03 +00:00
										 |  |  |     htonlsab(en->lsa_body, pktpos, en->lsa.type, en->lsa.length | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	     - sizeof(struct ospf_lsa_header)); | 
					
						
							|  |  |  |     pktpos = pktpos + en->lsa.length - sizeof(struct ospf_lsa_header); | 
					
						
							|  |  |  |     len += en->lsa.length; | 
					
						
							| 
									
										
										
										
											2000-03-31 01:14:41 +00:00
										 |  |  |     lsano++; | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   if (lsano > 0) | 
					
						
							| 
									
										
										
										
											2000-05-30 16:49:48 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     pk->lsano = htonl(lsano); | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |     op->length = htons(len); | 
					
						
							| 
									
										
										
										
											2000-03-31 01:14:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-06 02:16:39 +00:00
										 |  |  |     OSPF_TRACE(D_PACKETS, "LS upd sent to %I (%d LSAs)", n->ip, lsano); | 
					
						
							| 
									
										
										
										
											2004-06-26 20:15:34 +00:00
										 |  |  |     ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa); | 
					
						
							| 
									
										
										
										
											2000-05-30 16:49:48 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-03-31 00:21:41 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-03-30 20:00:42 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2004-06-04 20:41:02 +00:00
										 |  |  | ospf_lsupd_receive(struct ospf_lsupd_packet *ps, | 
					
						
							| 
									
										
										
										
											2004-06-06 19:53:52 +00:00
										 |  |  | 		   struct ospf_iface *ifa, struct ospf_neighbor *n) | 
					
						
							| 
									
										
										
										
											2000-03-30 20:00:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-06-06 19:53:52 +00:00
										 |  |  |   u32 area; | 
					
						
							|  |  |  |   struct ospf_neighbor *ntmp; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   struct ospf_lsa_header *lsa; | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |   struct ospf_area *oa; | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   struct proto_ospf *po = ifa->proto; | 
					
						
							|  |  |  |   struct proto *p = (struct proto *) po; | 
					
						
							| 
									
										
										
										
											2004-06-06 19:53:52 +00:00
										 |  |  |   unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   if (n->state < NEIGHBOR_EXCHANGE) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     OSPF_TRACE(D_PACKETS, | 
					
						
							|  |  |  | 	       "Received lsupd in lesser state than EXCHANGE from (%I)", | 
					
						
							|  |  |  | 	       n->ip); | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   if (size <= | 
					
						
							|  |  |  |       (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header))) | 
					
						
							| 
									
										
										
										
											2000-05-11 22:00:55 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |     log(L_WARN "Received lsupd from %I is too short!", n->ip); | 
					
						
							| 
									
										
										
										
											2000-05-11 22:00:55 +00:00
										 |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-06 02:16:39 +00:00
										 |  |  |   OSPF_TRACE(D_PACKETS, "Received LS upd from %I", n->ip); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |   ospf_neigh_sm(n, INM_HELLOREC);	/* Questionable */ | 
					
						
							| 
									
										
										
										
											2000-05-09 18:17:34 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   lsa = (struct ospf_lsa_header *) (ps + 1); | 
					
						
							|  |  |  |   area = htonl(ps->ospf_packet.areaid); | 
					
						
							|  |  |  |   oa = ospf_find_area((struct proto_ospf *) p, area); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   for (i = 0; i < ntohl(ps->lsano); i++, | 
					
						
							|  |  |  |        lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length))) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     struct ospf_lsa_header lsatmp; | 
					
						
							|  |  |  |     struct top_hash_entry *lsadb; | 
					
						
							| 
									
										
										
										
											2004-06-06 19:53:52 +00:00
										 |  |  |     unsigned diff = ((u8 *) lsa) - ((u8 *) ps), lenn = ntohs(lsa->length); | 
					
						
							|  |  |  |     u16 chsum; | 
					
						
							| 
									
										
										
										
											2000-05-10 15:04:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (((diff + sizeof(struct ospf_lsa_header)) >= size) | 
					
						
							|  |  |  | 	|| ((lenn + diff) > size)) | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       log(L_WARN "Received lsupd from %I is too short!", n->ip); | 
					
						
							|  |  |  |       ospf_neigh_sm(n, INM_BADLSREQ); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-05-10 15:04:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lenn <= sizeof(struct ospf_lsa_header)) | 
					
						
							|  |  |  | 	|| (lenn != (4 * (lenn / 4)))) | 
					
						
							| 
									
										
										
										
											2000-05-10 15:04:21 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       log(L_WARN "Received LSA from %I with bad length", n->ip); | 
					
						
							|  |  |  |       ospf_neigh_sm(n, INM_BADLSREQ); | 
					
						
							| 
									
										
										
										
											2000-05-10 15:04:21 +00:00
										 |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg 143 (1) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     chsum = lsa->checksum; | 
					
						
							| 
									
										
										
										
											2004-06-06 18:45:08 +00:00
										 |  |  |     if (chsum != lsasum_check(lsa, NULL)) | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       log(L_WARN "Received bad lsa checksum from %I", n->ip); | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg 143 (2) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT)) | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       log(L_WARN "Unknown LSA type from %I", n->ip); | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg 143 (3) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lsa->type == LSA_T_EXT) && oa->stub) | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       log(L_WARN "Received External LSA in stub area from %I", n->ip); | 
					
						
							| 
									
										
										
										
											2000-04-03 22:31:07 +00:00
										 |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     ntohlsah(lsa, &lsatmp); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-06-05 02:23:20 +00:00
										 |  |  |     DBG("Update Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n", | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, | 
					
						
							|  |  |  | 	lsatmp.checksum); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     lsadb = ospf_hash_find_header(oa->gr, &lsatmp); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef LOCAL_DEBUG
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (lsadb) | 
					
						
							| 
									
										
										
										
											2000-06-05 02:23:20 +00:00
										 |  |  |       DBG("I have Type: %u ID: %I RT: %I, Sn: 0x%08x Age: %u, Sum: %u\n", | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	  lsadb->lsa.type, lsadb->lsa.id, lsadb->lsa.rt, lsadb->lsa.sn, | 
					
						
							|  |  |  | 	  lsadb->lsa.age, lsadb->lsa.checksum); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg 143 (4) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(oa)) | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 17:05:24 +00:00
										 |  |  |       ospf_lsack_enqueue(n, lsa, ACKL_DIRECT); | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg 144 (5) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lsadb == NULL) || (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_NEWER)) | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       struct ospf_iface *ift = NULL; | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       void *body; | 
					
						
							|  |  |  |       struct ospf_iface *nifa; | 
					
						
							|  |  |  |       int self = (lsatmp.rt == p->cf->global->router_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       DBG("PG143(5): Received LSA is newer\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |       /* pg 145 (5f) - premature aging of self originated lsa */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if ((!self) && (lsatmp.type == LSA_T_NET)) | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	WALK_LIST(nifa, po->iface_list) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (ipa_compare(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)) == | 
					
						
							|  |  |  | 	      0) | 
					
						
							|  |  |  | 	  { | 
					
						
							|  |  |  | 	    self = 1; | 
					
						
							|  |  |  | 	    break; | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (self) | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	struct top_hash_entry *en; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  ospf_lsack_enqueue(n, lsa, ACKL_DIRECT); | 
					
						
							|  |  |  | 	  continue; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	lsatmp.age = LSA_MAXAGE; | 
					
						
							|  |  |  | 	lsatmp.sn = LSA_MAXSEQNO; | 
					
						
							|  |  |  | 	lsa->age = htons(LSA_MAXAGE); | 
					
						
							|  |  |  | 	lsa->sn = htonl(LSA_MAXSEQNO); | 
					
						
							|  |  |  | 	OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa."); | 
					
						
							|  |  |  | 	OSPF_TRACE(D_EVENTS, "Type: %d, Id: %I, Rt: %I", lsatmp.type, | 
					
						
							|  |  |  | 		   lsatmp.id, lsatmp.rt); | 
					
						
							| 
									
										
										
										
											2004-06-06 18:45:08 +00:00
										 |  |  | 	lsasum_check(lsa, (lsa + 1));	/* It also calculates chsum! */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	lsatmp.checksum = ntohs(lsa->checksum); | 
					
						
							|  |  |  | 	ospf_lsupd_flood(NULL, lsa, &lsatmp, NULL, oa, 0); | 
					
						
							|  |  |  | 	if (en = ospf_hash_find_header(oa->gr, &lsatmp)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  ospf_lsupd_flood(NULL, NULL, &en->lsa, NULL, oa, 1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	continue; | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2000-05-09 21:06:48 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       /* pg 144 (5a) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (lsadb && ((now - lsadb->inst_t) <= MINLSARRIVAL))	/* FIXME: test for flooding? */ | 
					
						
							| 
									
										
										
										
											2000-04-18 22:11:05 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	DBG("I got it in less that MINLSARRIVAL\n"); | 
					
						
							|  |  |  | 	sendreq = 0; | 
					
						
							| 
									
										
										
										
											2000-04-18 22:11:05 +00:00
										 |  |  | 	continue; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (ospf_lsupd_flood(n, lsa, &lsatmp, ifa, ifa->oa, 1) == 0) | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	DBG("Wasn't flooded back\n");	/* ps 144(5e), pg 153 */ | 
					
						
							|  |  |  | 	if (ifa->state == OSPF_IS_BACKUP) | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	  if (ifa->drid == n->rid) | 
					
						
							|  |  |  | 	    ospf_lsack_enqueue(n, lsa, ACKL_DELAY); | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	else | 
					
						
							|  |  |  | 	  ospf_lsack_enqueue(n, lsa, ACKL_DELAY); | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |       /* Remove old from all ret lists */ | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       /* pg 144 (5c) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if (lsadb) | 
					
						
							|  |  |  | 	WALK_LIST(NODE ift, po->iface_list) | 
					
						
							|  |  |  | 	  WALK_LIST(NODE ntmp, ift->neigh_list) | 
					
						
							| 
									
										
										
										
											2000-06-02 13:52:50 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	struct top_hash_entry *en; | 
					
						
							|  |  |  | 	if (ntmp->state > NEIGHBOR_EXSTART) | 
					
						
							|  |  |  | 	  if ((en = ospf_hash_find_header(ntmp->lsrth, &lsadb->lsa)) != NULL) | 
					
						
							|  |  |  | 	  { | 
					
						
							|  |  |  | 	    s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	    if (en->lsa_body != NULL) | 
					
						
							|  |  |  | 	      mb_free(en->lsa_body); | 
					
						
							|  |  |  | 	    en->lsa_body = NULL; | 
					
						
							|  |  |  | 	    ospf_hash_delete(ntmp->lsrth, en); | 
					
						
							|  |  |  | 	  } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO) | 
					
						
							|  |  |  | 	  && lsadb && can_flush_lsa(oa)) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  | 	flush_lsa(lsadb, oa); | 
					
						
							| 
									
										
										
										
											2004-06-06 16:00:09 +00:00
										 |  |  | 	schedule_rtcalc(po); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	continue; | 
					
						
							|  |  |  |       }				/* FIXME lsack? */ | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       /* pg 144 (5d) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       body = | 
					
						
							|  |  |  | 	mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header)); | 
					
						
							|  |  |  |       ntohlsab(lsa + 1, body, lsatmp.type, | 
					
						
							|  |  |  | 	       lsatmp.length - sizeof(struct ospf_lsa_header)); | 
					
						
							|  |  |  |       lsadb = lsa_install_new(&lsatmp, body, oa); | 
					
						
							| 
									
										
										
										
											2000-04-04 22:27:19 +00:00
										 |  |  |       DBG("New LSA installed in DB\n"); | 
					
						
							| 
									
										
										
										
											2000-04-04 15:55:55 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |     /* FIXME pg145 (6) */ | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg145 (7) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_SAME) | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       struct top_hash_entry *en; | 
					
						
							| 
									
										
										
										
											2004-06-04 14:03:30 +00:00
										 |  |  |       DBG("PG145(7) Got the same LSA\n"); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       if ((en = ospf_hash_find_header(n->lsrth, &lsadb->lsa)) != NULL) | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	/* pg145 (7a) */ | 
					
						
							|  |  |  | 	s_rem_node(SNODE en); | 
					
						
							|  |  |  | 	if (en->lsa_body != NULL) | 
					
						
							|  |  |  | 	  mb_free(en->lsa_body); | 
					
						
							|  |  |  | 	en->lsa_body = NULL; | 
					
						
							|  |  |  | 	ospf_hash_delete(n->lsrth, en); | 
					
						
							|  |  |  | 	if (ifa->state == OSPF_IS_BACKUP) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	  if (n->rid == ifa->drid) | 
					
						
							|  |  |  | 	    ospf_lsack_enqueue(n, lsa, ACKL_DELAY); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |       { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	/* pg145 (7b) */ | 
					
						
							|  |  |  | 	ospf_lsack_enqueue(n, lsa, ACKL_DIRECT); | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-06-04 20:41:02 +00:00
										 |  |  |       sendreq = 0; | 
					
						
							| 
									
										
										
										
											2000-04-18 21:40:11 +00:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     /* pg145 (8) */ | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     if ((lsadb->lsa.age == LSA_MAXAGE) && (lsadb->lsa.sn == LSA_MAXSEQNO)) | 
					
						
							| 
									
										
										
										
											2000-04-18 01:06:16 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-04-04 00:32:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     { | 
					
						
							|  |  |  |       list l; | 
					
						
							| 
									
										
										
										
											2000-05-30 15:05:47 +00:00
										 |  |  |       struct l_lsr_head ll; | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |       init_list(&l); | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |       ll.lsh.id = lsadb->lsa.id; | 
					
						
							|  |  |  |       ll.lsh.rt = lsadb->lsa.rt; | 
					
						
							|  |  |  |       ll.lsh.type = lsadb->lsa.type; | 
					
						
							|  |  |  |       add_tail(&l, NODE & ll); | 
					
						
							|  |  |  |       ospf_lsupd_send_list(n, &l); | 
					
						
							| 
									
										
										
										
											2000-04-05 00:51:25 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2000-04-02 20:41:33 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2004-06-04 12:53:10 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 16:30:04 +00:00
										 |  |  |   /* Send direct LSAs */ | 
					
						
							|  |  |  |   ospf_lsack_send(n, ACKL_DIRECT); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   if (sendreq && (n->state == NEIGHBOR_LOADING)) | 
					
						
							| 
									
										
										
										
											2000-06-02 09:53:26 +00:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |     ospf_lsreq_send(n);		/* Ask for another part of neighbor's database */ | 
					
						
							| 
									
										
										
										
											2000-06-02 09:53:26 +00:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2000-03-30 20:00:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2000-05-27 15:36:02 +00:00
										 |  |  | void | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | ospf_lsupd_flush_nlsa(struct top_hash_entry *en, struct ospf_area *oa) | 
					
						
							| 
									
										
										
										
											2000-05-27 15:36:02 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   struct ospf_lsa_header *lsa = &en->lsa; | 
					
						
							|  |  |  |   struct proto_ospf *po = oa->po; | 
					
						
							|  |  |  |   struct proto *p = &po->proto; | 
					
						
							| 
									
										
										
										
											2000-05-27 15:36:02 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  |   lsa->age = LSA_MAXAGE; | 
					
						
							|  |  |  |   lsa->sn = LSA_MAXSEQNO; | 
					
						
							| 
									
										
										
										
											2004-06-06 18:45:08 +00:00
										 |  |  |   lsasum_calculate(lsa, en->lsa_body); | 
					
						
							| 
									
										
										
										
											2000-06-06 02:16:39 +00:00
										 |  |  |   OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!"); | 
					
						
							|  |  |  |   OSPF_TRACE(D_EVENTS, "Type: %d, Id: %I, Rt: %I", lsa->type, | 
					
						
							| 
									
										
										
										
											2004-06-04 21:05:43 +00:00
										 |  |  | 	     lsa->id, lsa->rt); | 
					
						
							|  |  |  |   ospf_lsupd_flood(NULL, NULL, lsa, NULL, oa, 0); | 
					
						
							| 
									
										
										
										
											2000-05-27 15:36:02 +00:00
										 |  |  | } |