📄 ospfh_packet.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 + -