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

📄 ospf_packet.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* Lookup received LSA, then add LS request list. */      find = ospf_lsa_lookup_by_header (oi->area, lsah);      if (!find || ospf_lsa_more_recent (find, new) < 0)	{	  ospf_ls_request_add (nbr, new);	  ospf_lsa_discard (new);	}      else	{	  /* Received LSA is not recent. */	  if (IS_DEBUG_OSPF_EVENT)	    zlog_info ("Packet [DD:RECV]: LSA received Type %d, "		       "ID %s is not recent.", lsah->type, inet_ntoa (lsah->id));	  ospf_lsa_discard (new);	  continue;	}    }  /* Master */  if (IS_SET_DD_MS (nbr->dd_flags))    {      nbr->dd_seqnum++;      /* Entire DD packet sent. */      if (!IS_SET_DD_M (dd->flags) && !IS_SET_DD_M (nbr->dd_flags))	OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);      else	/* Send new DD packet. */	ospf_db_desc_send (nbr);    }  /* Slave */  else    {      nbr->dd_seqnum = ntohl (dd->dd_seqnum);      /* When master's more flags is not set. */      if (!IS_SET_DD_M (dd->flags) && ospf_db_summary_isempty (nbr))	{	  nbr->dd_flags &= ~(OSPF_DD_FLAG_M);	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_ExchangeDone);	}      /* Send DD pakcet in reply. */      ospf_db_desc_send (nbr);    }  /* Save received neighbor values from DD. */  ospf_db_desc_save_current (nbr, dd);}intospf_db_desc_is_dup (struct ospf_db_desc *dd, struct ospf_neighbor *nbr){  /* Is DD duplicated? */  if (dd->options == nbr->last_recv.options &&      dd->flags == nbr->last_recv.flags &&      dd->dd_seqnum == htonl (nbr->last_recv.dd_seqnum))    return 1;  return 0;}/* OSPF Database Description message read -- RFC2328 Section 10.6. */voidospf_db_desc (struct ip *iph, struct ospf_header *ospfh,	      struct stream *s, struct ospf_interface *oi, u_int16_t size){  struct ospf_db_desc *dd;  struct ospf_neighbor *nbr;  /* Increment statistics. */  oi->db_desc_in++;  dd = (struct ospf_db_desc *) STREAM_PNT (s);  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);  if (nbr == NULL)    {      zlog_warn ("Packet[DD]: Unknown Neighbor %s",		 inet_ntoa (ospfh->router_id));      return;    }  /* Check MTU. */  if (ntohs (dd->mtu) > oi->ifp->mtu)    {      zlog_warn ("Packet[DD]: MTU is larger than [%s]'s MTU", IF_NAME (oi));      return;    }#ifdef REJECT_IF_TBIT_ON  if (CHECK_FLAG (dd->options, OSPF_OPTION_T))    {      /*       * In Hello protocol, optional capability must have checked       * to prevent this T-bit enabled router be my neighbor.       */      zlog_warn ("Packet[DD]: Neighbor %s: T-bit on?", inet_ntoa (nbr->router_id));      return;    }#endif /* REJECT_IF_TBIT_ON */#ifdef HAVE_OPAQUE_LSA  if (CHECK_FLAG (dd->options, OSPF_OPTION_O)      && !CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))    {      /*       * This node is not configured to handle O-bit, for now.       * Clear it to ignore unsupported capability proposed by neighbor.       */      UNSET_FLAG (dd->options, OSPF_OPTION_O);    }#endif /* HAVE_OPAQUE_LSA */  /* Process DD packet by neighbor status. */  switch (nbr->state)    {    case NSM_Down:    case NSM_Attempt:    case NSM_TwoWay:      zlog_warn ("Packet[DD]: Neighbor state is %s, packet discarded.",		 LOOKUP (ospf_nsm_state_msg, nbr->state));      break;    case NSM_Init:      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived);      /* If the new state is ExStart, the processing of the current	 packet should then continue in this new state by falling	 through to case ExStart below.  */      if (nbr->state != NSM_ExStart)	break;    case NSM_ExStart:      /* Initial DBD */      if ((IS_SET_DD_ALL (dd->flags) == OSPF_DD_FLAG_ALL) &&	  (size == OSPF_DB_DESC_MIN_SIZE))	{	  if (IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) > 0)	    {	      /* We're Slave---obey */	      zlog_warn ("Packet[DD]: Negotiation done (Slave).");	      nbr->dd_seqnum = ntohl (dd->dd_seqnum);	      nbr->dd_flags &= ~(OSPF_DD_FLAG_MS|OSPF_DD_FLAG_I); /* Reset I/MS */	    }	  else	    {	      /* We're Master, ignore the initial DBD from Slave */	      zlog_warn ("Packet[DD]: Initial DBD from Slave, ignoring.");	      break;	    }	}      /* Ack from the Slave */      else if (!IS_SET_DD_MS (dd->flags) && !IS_SET_DD_I (dd->flags) &&	       ntohl (dd->dd_seqnum) == nbr->dd_seqnum &&	       IPV4_ADDR_CMP (&nbr->router_id, &oi->ospf->router_id) < 0)	{	  zlog_warn ("Packet[DD]: Negotiation done (Master).");	  nbr->dd_flags &= ~OSPF_DD_FLAG_I;	}      else	{	  zlog_warn ("Packet[DD]: Negotiation fails.");	  break;	}            /* This is where the real Options are saved */      nbr->options = dd->options;#ifdef HAVE_OPAQUE_LSA      if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE))        {          if (IS_DEBUG_OSPF_EVENT)            zlog_info ("Neighbor[%s] is %sOpaque-capable.",		       inet_ntoa (nbr->router_id),		       CHECK_FLAG (nbr->options, OSPF_OPTION_O) ? "" : "NOT ");          if (! CHECK_FLAG (nbr->options, OSPF_OPTION_O)          &&  IPV4_ADDR_SAME (&DR (oi), &nbr->address.u.prefix4))            {              zlog_warn ("DR-neighbor[%s] is NOT opaque-capable; Opaque-LSAs cannot be reliably advertised in this network.", inet_ntoa (nbr->router_id));              /* This situation is undesirable, but not a real error. */            }        }#endif /* HAVE_OPAQUE_LSA */      OSPF_NSM_EVENT_EXECUTE (nbr, NSM_NegotiationDone);      /* continue processing rest of packet. */      ospf_db_desc_proc (s, oi, nbr, dd, size);      break;    case NSM_Exchange:      if (ospf_db_desc_is_dup (dd, nbr))	{	  if (IS_SET_DD_MS (nbr->dd_flags))	    /* Master: discard duplicated DD packet. */	    zlog_warn ("Packet[DD] (Master): packet duplicated.");	  else	    /* Slave: cause to retransmit the last Database Description. */	    {	      zlog_warn ("Packet[DD] [Slave]: packet duplicated.");	      ospf_db_desc_resend (nbr);	    }	  break;	}      /* Otherwise DD packet should be checked. */      /* Check Master/Slave bit mismatch */      if (IS_SET_DD_MS (dd->flags) != IS_SET_DD_MS (nbr->last_recv.flags))	{	  zlog_warn ("Packet[DD]: MS-bit mismatch.");	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);	  if (IS_DEBUG_OSPF_EVENT)	    zlog_info ("Packet[DD]: dd->flags=%d, nbr->dd_flags=%d",		       dd->flags, nbr->dd_flags);	  break;	}      /* Check initialize bit is set. */      if (IS_SET_DD_I (dd->flags))	{	  zlog_warn ("Packet[DD]: I-bit set.");	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);	  break;	}      /* Check DD Options. */      if (dd->options != nbr->options)	{#ifdef ORIGINAL_CODING	  /* Save the new options for debugging */	  nbr->options = dd->options;#endif /* ORIGINAL_CODING */	  zlog_warn ("Packet[DD]: options mismatch.");	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);	  break;	}      /* Check DD sequence number. */      if ((IS_SET_DD_MS (nbr->dd_flags) &&	   ntohl (dd->dd_seqnum) != nbr->dd_seqnum) ||	  (!IS_SET_DD_MS (nbr->dd_flags) &&	   ntohl (dd->dd_seqnum) != nbr->dd_seqnum + 1))	{	  zlog_warn ("Pakcet[DD]: sequence number mismatch.");	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);	  break;	}      /* Continue processing rest of packet. */      ospf_db_desc_proc (s, oi, nbr, dd, size);      break;    case NSM_Loading:    case NSM_Full:      if (ospf_db_desc_is_dup (dd, nbr))	{	  if (IS_SET_DD_MS (nbr->dd_flags))	    {	      /* Master should discard duplicate DD packet. */	      zlog_warn ("Pakcet[DD]: duplicated, packet discarded.");	      break;	    }	  else	    {	      struct timeval t, now;	      gettimeofday (&now, NULL);	      t = tv_sub (now, nbr->last_send_ts);	      if (tv_cmp (t, int2tv (nbr->v_inactivity)) < 0)		{		  /* In states Loading and Full the slave must resend		     its last Database Description packet in response to		     duplicate Database Description packets received		     from the master.  For this reason the slave must		     wait RouterDeadInterval seconds before freeing the		     last Database Description packet.  Reception of a		     Database Description packet from the master after		     this interval will generate a SeqNumberMismatch		     neighbor event. RFC2328 Section 10.8 */		  ospf_db_desc_resend (nbr);		  break;		}	    }	}      OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);      break;    default:      zlog_warn ("Packet[DD]: NSM illegal status.");      break;    }}#define OSPF_LSA_KEY_SIZE       12 /* type(4) + id(4) + ar(4) *//* OSPF Link State Request Read -- RFC2328 Section 10.7. */voidospf_ls_req (struct ip *iph, struct ospf_header *ospfh,	     struct stream *s, struct ospf_interface *oi, u_int16_t size){  struct ospf_neighbor *nbr;  u_int32_t ls_type;  struct in_addr ls_id;  struct in_addr adv_router;  struct ospf_lsa *find;  list ls_upd;  int length;  /* Increment statistics. */  oi->ls_req_in++;  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);  if (nbr == NULL)    {      zlog_warn ("Link State Request: Unknown Neighbor %s.",		 inet_ntoa (ospfh->router_id));      return;    }  /* Neighbor State should be Exchange or later. */  if (nbr->state != NSM_Exchange &&      nbr->state != NSM_Loading &&      nbr->state != NSM_Full)    {      zlog_warn ("Link State Request: Neighbor state is %s, packet discarded.",		 LOOKUP (ospf_nsm_state_msg, nbr->state));      return;    }  /* Send Link State Update for ALL requested LSAs. */  ls_upd = list_new ();  length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;  while (size >= OSPF_LSA_KEY_SIZE)    {      /* Get one slice of Link State Request. */      ls_type = stream_getl (s);      ls_id.s_addr = stream_get_ipv4 (s);      adv_router.s_addr = stream_get_ipv4 (s);      /* Verify LSA type. */      if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA)	{	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);	  list_delete (ls_upd);	  return;	}      /* Search proper LSA in LSDB. */      find = ospf_lsa_lookup (oi->area, ls_type, ls_id, adv_router);      if (find == NULL)	{	  OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_BadLSReq);	  list_delete (ls_upd);	  return;	}      /* Packet overflows MTU size, send immediatly. */      if (length + ntohs (find->data->length) > OSPF_PACKET_MAX (oi))	{	  if (oi->type == OSPF_IFTYPE_NBMA)	    ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);	  else	    ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);	  /* Only remove list contents.  Keep ls_upd. */	  list_delete_all_node (ls_upd);	  length = OSPF_HEADER_SIZE + OSPF_LS_UPD_MIN_SIZE;	}      /* Append LSA to update list. */      listnode_add (ls_upd, find);      length += ntohs (find->data->length);      size -= OSPF_LSA_KEY_SIZE;    }  /* Send rest of Link State Update. */  if (listcount (ls_upd) > 0)    {      if (oi->type == OSPF_IFTYPE_NBMA)	ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_DIRECT);      else	ospf_ls_upd_send (nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT);      list_delete (ls_upd);    }  else    list_free (ls_upd);}/* Get the list of LSAs from Link State Update packet.   And process some validation -- RFC2328 Section 13. (1)-(2). */static listospf_ls_upd_list_lsa (struct ospf_neighbor *nbr, struct stream *s,                      struct ospf_interface *oi, size_t size){  u_int16_t count, sum;  u_int32_t length;  struct lsa_header *lsah;  struct ospf_lsa *lsa;  list lsas;  lsas = list_new ();  count = stream_getl (s);  size -= OSPF_LS_UPD_MIN_SIZE; /* # LSAs */  for (; size >= OSPF_LSA_HEADER_SIZE && count > 0;       size -= length, stream_forward (s, length), count--)    {      lsah = (struct lsa_header *) STREAM_PNT (s);      length = ntohs (lsah->length);      if (length > size)	{	  zlog_warn ("Link State Update: LSA length exceeds packet size.");	  break;	}      /* Validate the LSA's LS checksum. */      sum = lsah->checksum;      if (sum != ospf_lsa_checksum (lsah))	{	  zlog_warn ("Link State Update: LSA checksum error %x, %x.",		     sum, lsah->checksum);	  continue;	}      /* Examine the LSA's LS type. */      if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA)	{	  zlog_warn ("Link State Update: Unknown LS type %d", lsah->type);	  continue;	}      /*       * What if the received LSA's age is greater than MaxAge?       * Treat it as a MaxAge case -- endo.       */      if (ntohs (lsah->ls_age) > OSPF_LSA_MAXAGE)        lsah->ls_age = htons (OSPF_LSA_MAXAGE);#ifdef HAVE_OPAQUE_LSA      if (CHECK_FLAG (nbr->options, OSPF_OPTION_O))        {#ifdef STRICT_OBIT_USAGE_CHECK	  if ((IS_OPAQUE_LSA(lsah->type) &&               ! CHECK_FLAG (lsah->options, OSPF_OPTION_O))	  ||  (! IS_OPAQUE_LSA(lsah->type) &&               CHECK_FLAG (lsah->options, OSPF_OPTION_O)))            {              /*               * This neighbor must know the exact usage of O-bit;               * the bit will be set in Type-9,10,11 LSAs only.               */              zlog_warn ("LSA[Type%d:%s]: O-bit abuse?", lsah->type, inet_ntoa (lsah->id));              continue;            }#endif /* STRICT_OBIT_USAGE_CHECK */          /* Do not take in AS External Opaque-LSAs if we are a stub. */          if (lsah->type == OSPF_OPAQUE_AS_LSA	      && nbr->oi->area->external_routing != OSPF_AREA_DEFAULT)             {              if (IS_DEBUG_OSPF_EVENT)                zlog_info ("LSA[Type%d:%s]: We are a stub, don't take this LSA.", lsah->type, inet_ntoa (lsah->id));              continue;            }        }      else if (IS_OPAQUE_LSA(lsah->type))        {          zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id));          continue;        }#endif /* HAVE_OPAQUE_LSA */

⌨️ 快捷键说明

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