⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ospf_packet.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* Create OSPF LSA instance. */      lsa = ospf_lsa_new ();      /* We may wish to put some error checking if type NSSA comes in         and area not in NSSA mode */      switch (lsah->type)        {        case OSPF_AS_EXTERNAL_LSA:#ifdef HAVE_OPAQUE_LSA        case OSPF_OPAQUE_AS_LSA:          lsa->area = NULL;          break;        case OSPF_OPAQUE_LINK_LSA:          lsa->oi = oi; /* Remember incoming interface for flooding control. */          /* Fallthrough */#endif /* HAVE_OPAQUE_LSA */        default:          lsa->area = oi->area;          break;        }      lsa->data = ospf_lsa_data_new (length);      memcpy (lsa->data, lsah, length);      if (IS_DEBUG_OSPF_EVENT)	zlog_info("LSA[Type%d:%s]: %p new LSA created with Link State Update",		  lsa->data->type, inet_ntoa (lsa->data->id), lsa);      listnode_add (lsas, lsa);    }  return lsas;}/* Cleanup Update list. */voidospf_upd_list_clean (list lsas){  listnode node;  struct ospf_lsa *lsa;  for (node = listhead (lsas); node; nextnode (node))    if ((lsa = getdata (node)) != NULL)      ospf_lsa_discard (lsa);  list_delete (lsas);}/* OSPF Link State Update message read -- RFC2328 Section 13. */voidospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,	     struct stream *s, struct ospf_interface *oi, u_int16_t size){  struct ospf_neighbor *nbr;  list lsas;#ifdef HAVE_OPAQUE_LSA  list mylsa_acks, mylsa_upds;#endif /* HAVE_OPAQUE_LSA */  listnode node, next;  struct ospf_lsa *lsa = NULL;  /* unsigned long ls_req_found = 0; */  /* Dis-assemble the stream, update each entry, re-encapsulate for flooding */  /* Increment statistics. */  oi->ls_upd_in++;  /* Check neighbor. */  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);  if (nbr == NULL)    {      zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",		 inet_ntoa (ospfh->router_id), IF_NAME (oi));      return;    }  /* Check neighbor state. */  if (nbr->state < NSM_Exchange)    {      zlog_warn ("Link State Update: Neighbor[%s] state is less than Exchange",		 inet_ntoa (ospfh->router_id));      return;    }  /* Get list of LSAs from Link State Update packet. - Also perorms Stages    * 1 (validate LSA checksum) and 2 (check for LSA consistent type)    * of section 13.    */  lsas = ospf_ls_upd_list_lsa (nbr, s, oi, size);#ifdef HAVE_OPAQUE_LSA  /*   * Prepare two kinds of lists to clean up unwanted self-originated   * Opaque-LSAs from the routing domain as soon as possible.   */  mylsa_acks = list_new (); /* Let the sender cease retransmission. */  mylsa_upds = list_new (); /* Flush target LSAs if necessary. */  /*   * If self-originated Opaque-LSAs that have flooded before restart   * are contained in the received LSUpd message, corresponding LSReq   * messages to be sent may have to be modified.   * To eliminate possible race conditions such that flushing and normal   * updating for the same LSA would take place alternately, this trick   * must be done before entering to the loop below.   */   ospf_opaque_adjust_lsreq (nbr, lsas);#endif /* HAVE_OPAQUE_LSA */#define DISCARD_LSA(L,N) {\        if (IS_DEBUG_OSPF_EVENT) \          zlog_info ("ospf_lsa_discard() in ospf_ls_upd() point %d: lsa %p Type-%d", N, lsa, (int) lsa->data->type); \        ospf_lsa_discard (L); \	continue; }  /* Process each LSA received in the one packet. */  for (node = listhead (lsas); node; node = next)    {      struct ospf_lsa *ls_ret, *current;      int ret = 1;      next = node->next;      lsa = getdata (node);#ifdef HAVE_NSSA      if (IS_DEBUG_OSPF_NSSA)	{	  char buf1[INET_ADDRSTRLEN];	  char buf2[INET_ADDRSTRLEN];	  char buf3[INET_ADDRSTRLEN];	  zlog_info("LSA Type-%d from %s, ID: %s, ADV: %s",		  lsa->data->type,		  inet_ntop (AF_INET, &ospfh->router_id,			     buf1, INET_ADDRSTRLEN),		  inet_ntop (AF_INET, &lsa->data->id,			     buf2, INET_ADDRSTRLEN),		  inet_ntop (AF_INET, &lsa->data->adv_router,			     buf3, INET_ADDRSTRLEN));	}#endif /* HAVE_NSSA */      listnode_delete (lsas, lsa); /* We don't need it in list anymore */      /* Validate Checksum - Done above by ospf_ls_upd_list_lsa() */      /* LSA Type  - Done above by ospf_ls_upd_list_lsa() */         /* Do not take in AS External LSAs if we are a stub or NSSA. */      /* Do not take in AS NSSA if this neighbor and we are not NSSA */      /* Do take in Type-7's if we are an NSSA  */        /* If we are also an ABR, later translate them to a Type-5 packet */       /* Later, an NSSA Re-fresh can Re-fresh Type-7's and an ABR will	 translate them to a separate Type-5 packet.  */      if (lsa->data->type == OSPF_AS_EXTERNAL_LSA)        /* Reject from STUB or NSSA */        if (nbr->oi->area->external_routing != OSPF_AREA_DEFAULT) 	  {	    DISCARD_LSA (lsa, 1);#ifdef HAVE_NSSA	    if (IS_DEBUG_OSPF_NSSA)	      zlog_info("Incoming External LSA Discarded: We are NSSA/STUB Area");#endif /* HAVE_NSSA */	  }#ifdef  HAVE_NSSA       if (lsa->data->type == OSPF_AS_NSSA_LSA)	if (nbr->oi->area->external_routing != OSPF_AREA_NSSA)	  {	    DISCARD_LSA (lsa,2);	    if (IS_DEBUG_OSPF_NSSA)	      zlog_info("Incoming NSSA LSA Discarded:  Not NSSA Area");	  }#endif /* HAVE_NSSA */      /* Find the LSA in the current database. */      current = ospf_lsa_lookup_by_header (oi->area, lsa->data);      /* If the LSA's LS age is equal to MaxAge, and there is currently	 no instance of the LSA in the router's link state database,	 and none of router's neighbors are in states Exchange or Loading,	 then take the following actions. */      if (IS_LSA_MAXAGE (lsa) && !current &&	  (ospf_nbr_count (oi, NSM_Exchange) +	   ospf_nbr_count (oi, NSM_Loading)) == 0)	{	  /* Response Link State Acknowledgment. */	  ospf_ls_ack_send (nbr, lsa);	  /* Discard LSA. */	  	  zlog_warn ("Link State Update: LS age is equal to MaxAge.");          DISCARD_LSA (lsa, 3);	}#ifdef HAVE_OPAQUE_LSA      if (IS_OPAQUE_LSA (lsa->data->type)      &&  IPV4_ADDR_SAME (&lsa->data->adv_router, &oi->ospf->router_id))        {          /*           * Even if initial flushing seems to be completed, there might           * be a case that self-originated LSA with MaxAge still remain           * in the routing domain.           * Just send an LSAck message to cease retransmission.           */          if (IS_LSA_MAXAGE (lsa))            {              zlog_warn ("LSA[%s]: Boomerang effect?", dump_lsa_key (lsa));              ospf_ls_ack_send (nbr, lsa);              ospf_lsa_discard (lsa);              if (current != NULL && ! IS_LSA_MAXAGE (current))                ospf_opaque_lsa_refresh_schedule (current);              continue;            }          /*           * If an instance of self-originated Opaque-LSA is not found           * in the LSDB, there are some possible cases here.           *           * 1) This node lost opaque-capability after restart.           * 2) Else, a part of opaque-type is no more supported.           * 3) Else, a part of opaque-id is no more supported.           *           * Anyway, it is still this node's responsibility to flush it.           * Otherwise, the LSA instance remains in the routing domain           * until its age reaches to MaxAge.           */          if (current == NULL)            {              if (IS_DEBUG_OSPF_EVENT)                zlog_info ("LSA[%s]: Previously originated Opaque-LSA, not found in the LSDB.", dump_lsa_key (lsa));              SET_FLAG (lsa->flags, OSPF_LSA_SELF);              listnode_add (mylsa_upds, ospf_lsa_dup  (lsa));              listnode_add (mylsa_acks, ospf_lsa_lock (lsa));              continue;            }        }#endif /* HAVE_OPAQUE_LSA */      /* (5) Find the instance of this LSA that is currently contained	 in the router's link state database.  If there is no	 database copy, or the received LSA is more recent than	 the database copy the following steps must be performed. */      if (current == NULL ||	  (ret = ospf_lsa_more_recent (current, lsa)) < 0)	{	  /* Actual flooding procedure. */	  if (ospf_flood (oi->ospf, nbr, current, lsa) < 0)  /* Trap NSSA later. */	    DISCARD_LSA (lsa, 4);	  continue;	}      /* (6) Else, If there is an instance of the LSA on the sending	 neighbor's Link state request list, an error has occurred in	 the Database Exchange process.  In this case, restart the	 Database Exchange process by generating the neighbor event	 BadLSReq for the sending neighbor and stop processing the	 Link State Update packet. */      if (ospf_ls_request_lookup (nbr, lsa))	{	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);	  zlog_warn ("LSA instance exists on Link state request list");	  /* Clean list of LSAs. */          ospf_upd_list_clean (lsas);	  /* this lsa is not on lsas list already. */	  ospf_lsa_discard (lsa);#ifdef HAVE_OPAQUE_LSA          list_delete (mylsa_acks);          list_delete (mylsa_upds);#endif /* HAVE_OPAQUE_LSA */	  return;	}      /* If the received LSA is the same instance as the database copy	 (i.e., neither one is more recent) the following two steps	 should be performed: */      if (ret == 0)	{	  /* If the LSA is listed in the Link state retransmission list	     for the receiving adjacency, the router itself is expecting	     an acknowledgment for this LSA.  The router should treat the	     received LSA as an acknowledgment by removing the LSA from	     the Link state retransmission list.  This is termed an	     "implied acknowledgment". */	  ls_ret = ospf_ls_retransmit_lookup (nbr, lsa);	  if (ls_ret != NULL)	    {	      ospf_ls_retransmit_delete (nbr, ls_ret);	      /* Delayed acknowledgment sent if advertisement received		 from Designated Router, otherwise do nothing. */	      if (oi->state == ISM_Backup)		if (NBR_IS_DR (nbr))		  listnode_add (oi->ls_ack, ospf_lsa_lock (lsa));              DISCARD_LSA (lsa, 5);	    }	  else	    /* Acknowledge the receipt of the LSA by sending a	       Link State Acknowledgment packet back out the receiving	       interface. */	    {	      ospf_ls_ack_send (nbr, lsa);	      DISCARD_LSA (lsa, 6);	    }	}      /* The database copy is more recent.  If the database copy	 has LS age equal to MaxAge and LS sequence number equal to	 MaxSequenceNumber, simply discard the received LSA without	 acknowledging it. (In this case, the LSA's LS sequence number is	 wrapping, and the MaxSequenceNumber LSA must be completely	 flushed before any new LSA instance can be introduced). */      else if (ret > 0)  /* Database copy is more recent */	{ 	  if (IS_LSA_MAXAGE (current) &&	      current->data->ls_seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))	    {	      DISCARD_LSA (lsa, 7);	    }	  /* Otherwise, as long as the database copy has not been sent in a	     Link State Update within the last MinLSArrival seconds, send the	     database copy back to the sending neighbor, encapsulated within	     a Link State Update Packet. The Link State Update Packet should	     be sent directly to the neighbor. In so doing, do not put the	     database copy of the LSA on the neighbor's link state	     retransmission list, and do not acknowledge the received (less	     recent) LSA instance. */	  else	    {	      struct timeval now;	      	      gettimeofday (&now, NULL);	      	      if (tv_cmp (tv_sub (now, current->tv_orig), 			  int2tv (OSPF_MIN_LS_ARRIVAL)) > 0)		/* Trap NSSA type later.*/		ospf_ls_upd_send_lsa (nbr, current, OSPF_SEND_PACKET_DIRECT);	      DISCARD_LSA (lsa, 8);	    }	}    }  #ifdef HAVE_OPAQUE_LSA  /*   * Now that previously originated Opaque-LSAs those which not yet   * installed into LSDB are captured, take several steps to clear   * them completely from the routing domain, before proceeding to   * origination for the current target Opaque-LSAs.   */  while (listcount (mylsa_acks) > 0)    ospf_ls_ack_send_list (oi, mylsa_acks, nbr->address.u.prefix4);  if (listcount (mylsa_upds) > 0)    ospf_opaque_self_originated_lsa_received (nbr, mylsa_upds);  list_delete (mylsa_upds);#endif /* HAVE_OPAQUE_LSA */  assert (listcount (lsas) == 0);  list_delete (lsas);}/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */voidospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,	     struct stream *s, struct ospf_interface *oi, u_int16_t size){  struct ospf_neighbor *nbr;#ifdef HAVE_OPAQUE_LSA  list opaque_acks;#endif /* HAVE_OPAQUE_LSA */  /* increment statistics. */  oi->ls_ack_in++;  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);  if (nbr == NULL)    {      zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",		 inet_ntoa (ospfh->router_id));      return;    }  if (nbr->state < NSM_Exchange)    {      zlog_warn ("Link State Acknowledgment: State is less than Exchange.");      return;    }#ifdef HAVE_OPAQUE_LSA  opaque_acks = list_new ();#endif /* HAVE_OPAQUE_LSA */  while (size >= OSPF_LSA_HEADER_SIZE)    {      struct ospf_lsa *lsa, *lsr;      lsa = ospf_lsa_new ();      lsa->data = (struct lsa_header *) STREAM_PNT (s);      /* lsah = (struct lsa_header *) STREAM_PNT (s); */      size -= OSPF_LSA_HEADER_SIZE;      stream_forward (s, OSPF_LSA_HEADER_SIZE);      if (lsa->data->type < OSPF_MIN_LSA || lsa->data->type >= OSPF_MAX_LSA)	{	  lsa->data = NULL;	  ospf_lsa_discard (lsa);	  continue;	}      lsr = ospf_ls_retransmit_lookup (nbr, lsa);      if (lsr != NULL && lsr->data->ls_seqnum == lsa->data->ls_seqnum)        {#ifdef HAVE_OPAQUE_LSA          /* Keep this LSA entry for later reference. */          if (IS_OPAQUE_LSA (lsr->data->type))            listnode_add (opaque_acks, ospf_lsa_dup (lsr));#endif /* HAVE_OPAQUE_LSA */          ospf_ls_retransmit_delete (nbr, lsr);        }      lsa->data = NULL;      ospf_lsa_discard (lsa);    }#ifdef HAVE_OPAQUE_LSA  if (listcount (opaque_acks) > 0)    ospf_opaque_ls_ack_received (nbr, opaque_acks);  list_delete (opaque_acks);  return;#endif /* HAVE_OPAQUE_LSA */}struct stream *ospf_recv_packet (int fd, struct interface **ifp){  int ret;  struct ip iph;  u_int16_t ip_len;  struct stream *ibuf;  unsigned int ifindex = 0;  struct iovec iov;  struct cmsghdr *cmsg;#if defined (IP_PKTINFO)  struct in_pktinfo *pktinfo;#elif defined (IP_RECVIF)  struct sockaddr_dl *pktinfo;#else  char *pktinfo; /* dummy */#endif  char buff [sizeof (*cmsg) + sizeof (*pktinfo)];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -