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

📄 ospf_packet.c

📁 router source code for the ospdf.
💻 C
📖 第 1 页 / 共 5 页
字号:
  struct msghdr msgh = {NULL, 0, &iov, 1, buff,			sizeof (*cmsg) + sizeof (*pktinfo), 0};      ret = recvfrom (fd, (void *)&iph, sizeof (iph), MSG_PEEK, NULL, 0);    if (ret != sizeof (iph))    {      zlog_warn ("ospf_recv_packet packet smaller than ip header");      return NULL;    }#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)  ip_len = iph.ip_len;#else  ip_len = ntohs (iph.ip_len);#endif#if !defined(GNU_LINUX)  /*   * Kernel network code touches incoming IP header parameters,   * before protocol specific processing.   *   *   1) Convert byteorder to host representation.   *      --> ip_len, ip_id, ip_off   *   *   2) Adjust ip_len to strip IP header size!   *      --> If user process receives entire IP packet via RAW   *          socket, it must consider adding IP header size to   *          the "ip_len" field of "ip" structure.   *   * For more details, see <netinet/ip_input.c>.   */  ip_len = ip_len + (iph.ip_hl << 2);#endif    ibuf = stream_new (ip_len);  iov.iov_base = STREAM_DATA (ibuf);  iov.iov_len = ip_len;  ret = recvmsg (fd, &msgh, 0);    cmsg = CMSG_FIRSTHDR (&msgh);    if (cmsg != NULL && //cmsg->cmsg_len == sizeof (*pktinfo) &&      cmsg->cmsg_level == IPPROTO_IP &&#if defined (IP_PKTINFO)      cmsg->cmsg_type == IP_PKTINFO#elif defined (IP_RECVIF)      cmsg->cmsg_type == IP_RECVIF#else      0#endif      )    {#if defined (IP_PKTINFO)      pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);      ifindex = pktinfo->ipi_ifindex;#elif defined (IP_RECVIF)      pktinfo = (struct sockaddr_dl *)CMSG_DATA(cmsg);      ifindex = pktinfo->sdl_index;#else      ifindex = 0;#endif    }    *ifp = if_lookup_by_index (ifindex);  if (ret != ip_len)    {      zlog_warn ("ospf_recv_packet short read. "		 "ip_len %d bytes read %d", ip_len, ret);      stream_free (ibuf);      return NULL;    }    return ibuf;}struct ospf_interface *ospf_associate_packet_vl (struct ospf *ospf,			  struct interface *ifp, struct ospf_interface *oi,			  struct ip *iph, struct ospf_header *ospfh){  struct ospf_interface *rcv_oi;  struct ospf_vl_data *vl_data;  struct ospf_area *vl_area;  listnode node;  if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||      !OSPF_IS_AREA_BACKBONE (ospfh))    return oi;  if ((rcv_oi = oi) == NULL)    {     if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, ifp,						 iph->ip_dst)) == NULL)       return NULL;    }  for (node = listhead (ospf->vlinks); node; nextnode (node))    {      if ((vl_data = getdata (node)) == NULL)	continue;            vl_area = ospf_area_lookup_by_area_id (ospf, vl_data->vl_area_id);      if (!vl_area)	continue;            if (OSPF_AREA_SAME (&vl_area, &rcv_oi->area) &&	  IPV4_ADDR_SAME (&vl_data->vl_peer, &ospfh->router_id))	{	  if (IS_DEBUG_OSPF_EVENT)	    zlog_info ("associating packet with %s",		       IF_NAME (vl_data->vl_oi));	  if (! CHECK_FLAG (vl_data->vl_oi->ifp->flags, IFF_UP))	    {	      if (IS_DEBUG_OSPF_EVENT)		zlog_info ("This VL is not up yet, sorry");	      return NULL;	    }	  	  return vl_data->vl_oi;	}    }  if (IS_DEBUG_OSPF_EVENT)    zlog_info ("couldn't find any VL to associate the packet with");    return oi;}intospf_check_area_id (struct ospf_interface *oi, struct ospf_header *ospfh){  /* Check match the Area ID of the receiving interface. */  if (OSPF_AREA_SAME (&oi->area, &ospfh))    return 1;  return 0;}/* Unbound socket will accept any Raw IP packets if proto is matched.   To prevent it, compare src IP address and i/f address with masking   i/f network mask. */intospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src){  struct in_addr mask, me, him;  if (oi->type == OSPF_IFTYPE_POINTOPOINT ||      oi->type == OSPF_IFTYPE_VIRTUALLINK)    return 1;  masklen2ip (oi->address->prefixlen, &mask);  me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;  him.s_addr = ip_src.s_addr & mask.s_addr; if (IPV4_ADDR_SAME (&me, &him))   return 1; return 0;}intospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,		 struct ospf_header *ospfh){  int ret = 0;  struct crypt_key *ck;  switch (ntohs (ospfh->auth_type))    {    case OSPF_AUTH_NULL:      ret = 1;      break;    case OSPF_AUTH_SIMPLE:      if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))	ret = 1;      else	ret = 0;      break;    case OSPF_AUTH_CRYPTOGRAPHIC:      if ((ck = getdata (OSPF_IF_PARAM (oi,auth_crypt)->tail)) == NULL)	{	  ret = 0;	  break;	}            /* This is very basic, the digest processing is elsewhere */      if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE &&           ospfh->u.crypt.key_id == ck->key_id &&          ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))        ret = 1;      else        ret = 0;      break;    default:      ret = 0;      break;    }  return ret;}intospf_check_sum (struct ospf_header *ospfh){  u_int32_t ret;  u_int16_t sum;  int in_cksum (void *ptr, int nbytes);  /* clear auth_data for checksum. */  memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);  /* keep checksum and clear. */  sum = ospfh->checksum;  memset (&ospfh->checksum, 0, sizeof (u_int16_t));  /* calculate checksum. */  ret = in_cksum (ospfh, ntohs (ospfh->length));  if (ret != sum)    {      zlog_info ("ospf_check_sum(): checksum mismatch, my %X, his %X",		 ret, sum);      return 0;    }  return 1;}/* OSPF Header verification. */intospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,		    struct ip *iph, struct ospf_header *ospfh){  /* check version. */  if (ospfh->version != OSPF_VERSION)    {      zlog_warn ("interface %s: ospf_read version number mismatch.",		 IF_NAME (oi));      return -1;    }  /* Check Area ID. */  if (!ospf_check_area_id (oi, ospfh))    {      zlog_warn ("interface %s: ospf_read invalid Area ID %s.",		 IF_NAME (oi), inet_ntoa (ospfh->area_id));      return -1;    }  /* Check network mask, Silently discarded. */  if (! ospf_check_network_mask (oi, iph->ip_src))    {      zlog_warn ("interface %s: ospf_read network address is not same [%s]",		 IF_NAME (oi), inet_ntoa (iph->ip_src));      return -1;    }  /* Check authentication. */  if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))    {      zlog_warn ("interface %s: ospf_read authentication type mismatch.",		 IF_NAME (oi));      return -1;    }  if (! ospf_check_auth (oi, ibuf, ospfh))    {      zlog_warn ("interface %s: ospf_read authentication failed.",		 IF_NAME (oi));      return -1;    }  /* if check sum is invalid, packet is discarded. */  if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)    {      if (! ospf_check_sum (ospfh))	{	  zlog_warn ("interface %s: ospf_read packet checksum error %s",		     IF_NAME (oi), inet_ntoa (ospfh->router_id));	  return -1;	}    }  else    {      if (ospfh->checksum != 0)	return -1;      if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)	{	  zlog_warn ("interface %s: ospf_read md5 authentication failed.",		     IF_NAME (oi));	  return -1;	}    }  return 0;}/* Starting point of packet process function. */intospf_read (struct thread *thread){  int ret;  struct stream *ibuf;  struct ospf *ospf;  struct ospf_interface *oi;  struct ip *iph;  struct ospf_header *ospfh;  u_int16_t length;  struct interface *ifp;  /* first of all get interface pointer. */  ospf = THREAD_ARG (thread);  ospf->t_read = NULL;  /* read OSPF packet. */  ibuf = ospf_recv_packet (ospf->fd, &ifp);  if (ibuf == NULL)    return -1;    iph = (struct ip *) STREAM_DATA (ibuf);  /* prepare for next packet. */  ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);  /* IP Header dump. */  /*  if (ospf_debug_packet & OSPF_DEBUG_RECV)    ospf_ip_header_dump (ibuf);  */  /* Self-originated packet should be discarded silently. */  if (ospf_if_lookup_by_local_addr (ospf, NULL, iph->ip_src))    {      stream_free (ibuf);      return 0;    }  /* Adjust size to message length. */  stream_forward (ibuf, iph->ip_hl * 4);    /* Get ospf packet header. */  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);  /* associate packet with ospf interface */  oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);  if (ifp && oi && oi->ifp != ifp)    {      zlog_warn ("Packet from [%s] received on wrong link %s",		 inet_ntoa (iph->ip_src), ifp->name);       stream_free (ibuf);      return 0;    }    if ((oi = ospf_associate_packet_vl (ospf, ifp, oi, iph, ospfh)) == NULL)    {      stream_free (ibuf);      return 0;    }  /*   * If the received packet is destined for AllDRouters, the packet   * should be accepted only if the received ospf interface state is   * either DR or Backup -- endo.   */  if (iph->ip_dst.s_addr == htonl (OSPF_ALLDROUTERS)  && (oi->state != ISM_DR && oi->state != ISM_Backup))    {      zlog_info ("Packet for AllDRouters from [%s] via [%s] (ISM: %s)",                 inet_ntoa (iph->ip_src), IF_NAME (oi),                 LOOKUP (ospf_ism_state_msg, oi->state));      stream_free (ibuf);      return 0;    }  /* Show debug receiving packet. */  if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))    {      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))	{	  zlog_info ("-----------------------------------------------------");	  ospf_packet_dump (ibuf);	}      zlog_info ("%s received from [%s] via [%s]",		 ospf_packet_type_str[ospfh->type],		 inet_ntoa (ospfh->router_id), IF_NAME (oi));      zlog_info (" src [%s],", inet_ntoa (iph->ip_src));      zlog_info (" dst [%s]", inet_ntoa (iph->ip_dst));      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, DETAIL))	zlog_info ("-----------------------------------------------------");    }  /* Some header verification. */  ret = ospf_verify_header (ibuf, oi, iph, ospfh);  if (ret < 0)    {      stream_free (ibuf);      return ret;    }  stream_forward (ibuf, OSPF_HEADER_SIZE);  /* Adjust size to message length. */  length = ntohs (ospfh->length) - OSPF_HEADER_SIZE;  /* Read rest of the packet and call each sort of packet routine. */  switch (ospfh->type)    {    case OSPF_MSG_HELLO:      ospf_hello (iph, ospfh, ibuf, oi, length);      break;    case OSPF_MSG_DB_DESC:      ospf_db_desc (iph, ospfh, ibuf, oi, length);      break;    case OSPF_MSG_LS_REQ:      ospf_ls_req (iph, ospfh, ibuf, oi, length);      break;    case OSPF_MSG_LS_UPD:      ospf_ls_upd (iph, ospfh, ibuf, oi, length);      break;    case OSPF_MSG_LS_ACK:      ospf_ls_ack (iph, ospfh, ibuf, oi, length);      break;    default:      zlog (NULL, LOG_WARNING,	    "interface %s: OSPF packet header type %d is illegal",	    IF_NAME (oi), ospfh->type);      break;    }  stream_free (ibuf);  return 0;}/* Make OSPF header. */voidospf_make_header (int type, struct ospf_interface *oi, struct stream *s){  struct ospf_header *ospfh;  ospfh = (struct ospf_header *) STREAM_DATA (s);  ospfh->version = (u_char) OSPF_VERSION;  ospfh->type = (u_char) type;  ospfh->router_id = oi->ospf->router_id;  ospfh->checksum = 0;  ospfh->area_id = oi->area->area_id;  ospfh->auth_type = htons (ospf_auth_type (oi));  memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);  ospf_output_forward (s, OSPF_HEADER_SIZE);}/* Make Authentication Data. */intospf_make_auth (struct ospf_interface *oi, struct ospf_header *ospfh){  struct crypt_key *ck;  switch (ospf_auth_type (oi))    {    case OSPF_AUTH_NULL:      /* memset (ospfh->u.auth_data, 0, sizeof (ospfh->u.auth_data)); */      break;    case OSPF_AUTH

⌨️ 快捷键说明

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