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

📄 ospfh_packet.c

📁 实现禁位自动排列在禁位中具体实现了此方法所以这是一个创新很有应用价值在VC平台上调试通过
💻 C
字号:
/*   The receiving and sending of the ospfh packet  */


#include "ospfh.h"
#include "ospfh_patch.h"


struct ospf_packet *
ospf_packet_new (size_t size)
{
  struct ospf_packet *new;

  new = XCALLOC (MTYPE_OSPF_PACKET, sizeof (struct ospf_packet));
  new->s = stream_new (size);
  new->next=NULL;
  new->length=0;

  return new;
}

struct ospf_fifo *
ospf_fifo_new ()
{
  struct ospf_fifo *new;

  new = XCALLOC (MTYPE_OSPF_FIFO, sizeof (struct ospf_fifo));
  new->head=NULL;
  new->tail=NULL;
  new->count=0;
  return new;
}


void
ospf_fifo_push (struct ospf_fifo *fifo, struct ospf_packet *op)
{
  if (fifo->tail)
    fifo->tail->next = op;
  else
    fifo->head = op;

  fifo->tail = op;

  fifo->count++;
}


/* Delete first packet from fifo. */
struct ospf_packet *
ospf_fifo_pop (struct ospf_fifo *fifo)
{
  struct ospf_packet *op;

  op = fifo->head;

  if (op)
    {
      fifo->head = op->next;

      if (fifo->head == NULL)
	fifo->tail = NULL;

      fifo->count--;
    }

  return op;
}

void
ospf_packet_free (struct ospf_packet *op)
{
  if (op->s)
    stream_free (op->s);

  XFREE (MTYPE_OSPF_PACKET, op);

  op = NULL;
}

void
ospf_packet_delete (struct ospf *top)
{
  struct ospf_packet *op;
  
  op = ospf_fifo_pop (top->outbuf);

  if (op)
    ospf_packet_free (op);
}


struct ospf_packet *
ospf_fifo_head (struct ospf_fifo *fifo)
{
  return fifo->head;
}

//以上几个函数是完成对一个数据包的最基本操作。



//下面这个函数完成IP包头的填写和发送
int
ospfh_write_and_send (struct thread *thread)
{
  struct ospf_packet *op;
  u_char type;
  int ret;
  int flags = 0;
  struct ospf *top;
  struct thread_master *master;
  struct sockaddr_in addr_in;
  struct ip ipHeader;
  char * szSendBuf;
  int len;
//  struct listnode *node_temp;


  top = THREAD_ARG (thread);
  top->t_write = NULL;
  master=top->master;

  /* Get one packet from queue. */
  op = ospf_fifo_head (top->outbuf);

  /* Get the OSPF packet type. */  //是否能够实现指向Type字段?
  stream_set_getp (op->s, 1);
  type = stream_getc (op->s);

	
 


  //填充IP首部 
  ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); 
  ipHeader.tos=0; 
  ipHeader.total_len = htons(sizeof(ipHeader)+op->length);
  ipHeader.ident=htons(0);
  ipHeader.frag_and_flags=htons(0); 
  ipHeader.ttl = OSPF_IP_TTL;
  ipHeader.proto=IPPROTO_OSPFIGP;
  ipHeader.checksum=htons(0); 

//以下这一段是根据不同类型包添加不同的IP地址,添加后调用写线程执行该段程序
 if      (type==OSPF_MSG_LS_UPD)    
 {
	 ipHeader.destIP.s_addr=inet_addr(BROADCAST_ADDRESS); 
	 ipHeader.sourceIP=top->self_rc_id;
	 printf("Prepare to send a update  packet.\n");
 }
 else if (type==OSPF_MSG_LS_ACK)       {ipHeader.destIP.s_addr=inet_addr(BROADCAST_ADDRESS); ipHeader.sourceIP=top->self_rc_id; printf("Prepare to send a ack  packet.\n");}
 else if (type==OSPF_MSG_LS_FEED_UP)   {ipHeader.destIP=top->ip_address; ipHeader.sourceIP=top->self_rc_id; printf("Prepare to send a feed_up  packet.\n");}
 else if (type==OSPF_MSG_LS_FEED_DOWN) {ipHeader.destIP=top->ip_address; ipHeader.sourceIP=top->self_rc_id; printf("Prepare to send a feed_down packet.\n");}
 else  NULL; 
 
   addr_in.sin_family=AF_INET; 
   addr_in.sin_port=htons(0); 
   addr_in.sin_addr=ipHeader.destIP; 
 
  szSendBuf=(char *)XMALLOC(MTYPE_LINK_LIST,MAX_PACKET);
  memcpy(szSendBuf, &ipHeader, sizeof(ipHeader));
  memcpy(szSendBuf+sizeof(ipHeader), op->s->data, op->length); 

  
  //send the packet
  len =sizeof(ipHeader)+op->length;
  
  ret=sendto(top->fd, szSendBuf, sizeof(ipHeader)+op->length, 0 , (struct sockaddr*)&addr_in, sizeof(addr_in)); 

  if (ret==SOCKET_ERROR) 
  { 
      printf("send error!:%d\n",WSAGetLastError()); 
      return 0; 
  } 
  else 
     printf("send ok!\n");
 

  /* Now delete packet from queue. */
  ospf_packet_delete (top);

  if (!list_isempty (top->outbuf))
    top->t_write =                                              

	thread_add_write (master, ospfh_write_and_send, top, top->fd);

  XFREE(MTYPE_LINK_LIST,szSendBuf);

  return 0;

}


//下面这个函数完成IP包的接收
struct stream *
ospf_recv_packet (int fd)
{
  int ret;
  struct ip iph;
  u_int16_t ip_len;
  struct stream *ibuf;
  unsigned int ifindex = 0;
  char * recvbuf;
  recvbuf = (char *)XMALLOC(MTYPE_LINK_LIST,MAX_PACKET);
  
  //recieve the header

   ret = recvfrom (fd, recvbuf, MAX_PACKET, MSG_PEEK, NULL, NULL);

  iph= * (struct ip*)recvbuf;

  ip_len =ntohs(iph.total_len);

  free(recvbuf);

  ibuf = stream_new (ip_len);

  //recieve the packet
  ret = recvfrom (fd, ibuf->data, ip_len, 0, NULL, NULL);
  

  if (ret != ip_len)
    {
      printf ("ospf_recv_packet short read. "
		 "ip_len %d bytes read %d", ip_len, ret);
      stream_free (ibuf);
      return NULL;
    }
  
  return ibuf;
}


//下面这个函数完成收到IP包后的一系列处理

int
ospf_read (struct thread *thread)
{
int i=0;
  int nbrnum;
  struct stream *ibuf;
  struct ospf *top;
  struct ip *iph;
  struct ospf_header *ospfh;
  struct thread_master *master;
  u_int16_t length=0;
  struct list *nbr_list;
  struct in_addr  nbr_id_temp;
  struct listnode *node;
  struct ospf_lsa *lsa;



  /* first of all get interface pointer. */
  top = THREAD_ARG (thread);
  top->t_read = NULL;
  master=top->master;
  top->t_read = thread_add_read (master, ospf_read, top, thread->u.fd);
  nbr_list=top->nbrlist;
  nbrnum=nbr_list->count;

 /* read OSPF packet. */
  ibuf = ospf_recv_packet (thread->u.fd);
  if (ibuf == NULL)
    return -1;
  
  iph = (struct ip *) STREAM_DATA (ibuf); 




  for(i=0;i<1;i++)
  {   
	  
	  if((iph->sourceIP.s_addr==top->uplayer_rc_id.s_addr)&&(iph->destIP.s_addr==top->ip_address.s_addr))
	{printf("receive a feed_down packet.\n");
	break;
	}
	if((iph->sourceIP.s_addr==top->downlayer_rc_id.s_addr)&&(iph->destIP.s_addr==top->ip_address.s_addr))
	{ printf("receive a feed_up packet.\n");
	break;}

    if (nbrnum)
    {
	 for (node =nbr_list->head; node;  node = node->next)
     {
         if (nbrnum)
		 {
		   nbrnum--;
           nbr_id_temp=((struct ospf_neighbor *)(node->data))->nbr_id;
			if((iph->sourceIP.s_addr==nbr_id_temp.s_addr)&&(iph->destIP.s_addr==inet_addr(BROADCAST_ADDRESS)))
			 {  //   printf("receive a flood packet.\n");
			break;
			}
		 }
	if(node==nbr_list->tail)
		{//printf("The received packet is not for me.\n");
         stream_free(ibuf);
		return 0;
		}
	 }
    
	}


}
  

  /* Adjust size to message length. */
  stream_forward (ibuf, sizeof(struct ip));
  
  /* Get ospf packet header. */
  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);


  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_LS_UPD:
        {printf("receive a update packet.\n");
		ospf_ls_upd (iph, ospfh, ibuf, length,top);}

      break;
    case OSPF_MSG_LS_ACK:
		{	printf("receive a ack packet.\n");
		ospf_ls_ack (iph, ospfh, ibuf,top,length);}
      break;
    case OSPF_MSG_LS_FEED_UP:
		{
			if (iph->sourceIP.s_addr==top->uplayer_rc_id.s_addr)
		{
             stream_free (ibuf);
              return 0;
		}
		else  ospfh_feed_up_receive(top);
        break;
		}
    case OSPF_MSG_LS_FEED_DOWN:
		{
			if (iph->sourceIP.s_addr==top->downlayer_rc_id.s_addr)
		{
             stream_free (ibuf);
              return 0;
		}
		else  ospfh_feed_down_receive (top,ibuf);
      break;
        }
    default:
      break;
    }

  stream_free (ibuf);
  return 0;
}
///////////////////////////////////////////////////////////////
//将ospf包头填充的函数原型也放在这个模块中写了,其他函数调用就是

/* Make OSPF header. */
//去掉了原来形参接口部分,此程序把一个lsa当作一个stream来处理的
void
ospf_make_header (int type,struct ospf *ospf, struct stream *s) //ospf头的填充,checksum和auth字段除外
{
  struct ospf_header *ospfh;

  ospfh = (struct ospf_header *)(s->data);
  ospfh->version = (u_char) OSPF_VERSION;
  ospfh->type = (u_char) type;
  ospfh->router_id=ospf->self_rc_id;
  ospfh->checksum = htons(0);
  ospfh->area_id.s_addr =DEFALT_RC_ID;
   ospfh->auth_type =0 ;

  memset (ospfh->u.auth_data, 0, OSPF_AUTH_SIMPLE_SIZE);//Sets buffers to a specified character.

  ospf_output_forward (s, OSPF_HEADER_SIZE);//
}



void
ospf_output_forward (struct stream *s, int size)
{
  s->putp += size;
}

//去掉了原来形参接口部分,程序体无改动
void                                    
ospf_fill_header (struct stream *s, u_int16_t length)//填充checksum和auth字段
{
  struct ospf_header *ospfh;

  ospfh = (struct ospf_header *) (s->data);

  /* Fill length. */
    ospfh->length =htons(length);
    ospfh->checksum =htons(0);

 }//end ospf_fill_header()

int			
in_cksum(ptr, nbytes)                      //checksum计算
register u_short	*ptr;
register int		nbytes;
{
	register long		sum;		/* assumes long == 32 bits */
	u_short			oddbyte;
	register long	answer;		/* assumes u_short == 16 bits */

	/*
	 * Our algorithm is simple, using a 32-bit accumulator (sum),
	 * we add sequential 16-bit words to it, and at the end, fold back
	 * all the carry bits from the top 16 bits into the lower 16 bits.
	 */

	sum = 0;
	while (nbytes > 1)  {
		sum += *ptr++;
		nbytes -= 2;
	}

				/* mop up an odd byte, if necessary */
	if (nbytes == 1) {
		oddbyte = 0;		/* make sure top half is zero */
		*((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
		sum += oddbyte;
	}

	/*
	 * Add back carry outs from top 16 bits to low 16 bits.
	 */

	sum  = (sum >> 16) + (sum & 0xffff);	/* add high-16 to low-16 */
	sum += (sum >> 16);			/* add carry */
	answer = ~sum;		/* ones-complement, then truncate to 16 bits */
	return(answer);
}

//end in_cksum()

⌨️ 快捷键说明

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