📄 igmp_snoop.c
字号:
/* Main routine of igmp_snoop. */
/***************************************************************************************************
* Func: igmp_snoop_main
*Main routine of igmp_snoop
****************************************************************************************************/
int igmp_snoop_main (int argc, char **argv)
{
/*struct thread thread;*/
/* Prepare master thread. */
/* igmp_snoop_master = thread_make_master ();*/
/* thread_add_read (igmp_snoop_master, igmp_snoop_msg_read,NULL, (int)IgmpSnoopMsgQId); why should i convert the IgmpSnoopMsgQId into int */
/*
thread_add_timer (igmp_snoop_master, igmp_snoop_update, NULL,
(unsigned long)IgmpSnoopMsgQId ? 2 : update_timer);
*/
/*semGive (semIgmpSnoopSyncCLI); */
/* Execute each thread. */
/* while (thread_fetch (igmp_snoop_master, &thread))
thread_call (&thread); */
/* Not reached. */
/* exit (0);*/
int ret;
TIMERMSG_S msgbuf;
int fromlen, len;
ROUTER_V1_TIME_OUT_TIMER = 400*1000;
GROUP_MEMEBER_SHIP_INTERVAL = 260*1000;
GROUP_V1_MEMEBER_SHIP_INTERVAL = 260*1000;
ROUTER_TIME_OUT_TIMER = 260*1000;
ROUTER_GENERAL_QUERY_INTERVAL = 125*1000;
host_time_milli_flag = 1;
router_time_milli_flag = 1;
/* IgmpSnoopMsgQId = (MSG_Q_ID)THREAD_FD (t); */
/* Add myself to tne next event */
/* thread_add_read(igmp_snoop_master, igmp_snoop_msg_read, NULL, (int)IgmpSnoopMsgQId); */ /*here is the same as above*/
memset (&msgbuf, 0, sizeof (TIMERMSG_S));
/*
bzero ((char *)igmp_snoop_router_list, sizeof (struct igmp_snoop_router_entry));
bzero ((char *)igmp_snoop_mac_list, sizeof (struct igmp_snoop_mac_group));
*/
/* fromlen = sizeof(struct igmp_snoop_pkt_msg) ;*/
while(1)
{
len = msgQReceive(IgmpSnoopMsgQId, (char *)&msgbuf, sizeof(msgbuf), WAIT_FOREVER);
if (len < 0)
{
zlog_info ("msgQReceive failed: %s", strerror (errno));
}
else
{
igmp_snoop_process_msg(&msgbuf);
}
}
/*process the received msg*/
/*igmp_snoop_process_msg(&msgbuf);*/
}
/***************************************************************************************************
* Func: igmp_snoop_msg_read()
*This function reads the messages from the msg queue.
*Input:
*Output:OK -the packet is normally disposed
* ERROR - meets error when processing the packet
****************************************************************************************************/
int igmp_snoop_msg_read(struct thread *t)
{
int ret;
TIMERMSG_S msgbuf;
int fromlen, len;
IgmpSnoopMsgQId = (MSG_Q_ID)THREAD_FD (t);
/* Add myself to tne next event */
thread_add_read(igmp_snoop_master, igmp_snoop_msg_read, NULL, (int)IgmpSnoopMsgQId); /*here is the same as above*/
memset (&msgbuf, 0, sizeof (TIMERMSG_S));
fromlen = sizeof(struct igmp_snoop_pkt_msg);
len = msgQReceive(IgmpSnoopMsgQId, (char *)&msgbuf, sizeof(msgbuf), WAIT_FOREVER);
if (len < 0)
{
zlog_info ("msgQReceive failed: %s", strerror (errno));
return len;
}
/*process the received msg*/
igmp_snoop_process_msg(&msgbuf);
}
/***************************************************************************************************
* Func: igmp_snoop_process_msg
*This function processes the msg received from msg queue.
*Input: msg - the msg received from msg queue
*Output:OK -the msg is normally processed
* ERROR - meets error when processing the msg
****************************************************************************************************/
int igmp_snoop_process_msg_false(TIMERMSG_S *msg)
{
struct igmp_snoop_pkt_msg *igmp_rec_pkt_msg;
char *vlanpkt;
igmp_rec_pkt_msg = (struct igmp_snoop_pkt_msg *)msg->parg;
switch (msg->source_id)
{
case TASK_TIMER_NOTIFY:
switch(igmp_rec_pkt_msg->time_out_type)
{
case ROUTER_TIME_OUT:
kfree(igmp_rec_pkt_msg);
break;
case GROUP_TIME_OUT:
kfree(igmp_rec_pkt_msg);
break;
case ROUTER_V1_TIME_OUT:
kfree(igmp_rec_pkt_msg);
break;
case GROUP_V1_TIME_OUT: /*the igmpv1 host of the group is timeout*/
kfree(igmp_rec_pkt_msg);
break;
case OTHER_ROUTER_TIME_OUT:
kfree(igmp_rec_pkt_msg);
break;
case GENERAL_QEURY_10S_TIMEOUT: /* the every timer(10s) for group */
kfree(igmp_rec_pkt_msg);
break;
}
break;
case IGMP_SNOOP_RECV_PKT:
vlanpkt = igmp_rec_pkt_msg->pkt;
kfree(igmp_rec_pkt_msg);
kfree(vlanpkt);
break;
default:
syslog(LOG_INFO,"there is error with the msg");
break;
}
}
/***************************************************************************************************
* Func: igmp_snoop_process_msg
*This function processes the msg received from msg queue.
*Input: msg - the msg received from msg queue
*Output:OK -the msg is normally processed
* ERROR - meets error when processing the msg
****************************************************************************************************/
int igmp_snoop_process_msg(TIMERMSG_S *msg)
{
struct igmp_snoop_pkt_msg *igmp_rec_pkt_msg;
igmp_rec_pkt_msg = (struct igmp_snoop_pkt_msg *)msg->parg;
switch (msg->source_id)
{
case TASK_TIMER_NOTIFY:
switch(igmp_rec_pkt_msg->time_out_type)
{
case ROUTER_TIME_OUT:
router_port_timeout_process(msg);
break;
case GROUP_TIME_OUT:
group_port_timeout_process(msg);
break;
case ROUTER_V1_TIME_OUT:
router_v1_timeout_process(msg);
break;
case GROUP_V1_TIME_OUT: /*the igmpv1 host of the group is timeout*/
group_v1_timeout_process(msg);
break;
case OTHER_ROUTER_TIME_OUT:
other_router_port_timeout_process(msg);
break;
case GENERAL_QEURY_10S_TIMEOUT: /* the every timer(10s) for group */
general_query_10s_timeout_process(msg);
break;
}
break;
case IGMP_SNOOP_RECV_PKT:
#ifdef _FLEX_HAMMER_
igmp_snoop_pkt_process_flex(msg);
#endif
#ifdef _U_24_IGMPSNOOPING_
igmp_snoop_pkt_process(msg);
#endif
break;
default:
syslog(LOG_INFO,"there is error with the msg");
break;
}
}
void u24_recv_igmp(unsigned short portno,unsigned char* pkt,int len)
{
}
/***************************************************************************************************
* Func: igmp_snoop_recv
*This function is called by the lower function when it received a pkt. this function just
* makes a copy for the pkt ,and send msg to the msgqueque.
*Input: port_no - the port_no from which received this packet
* pkt - the received packet
* len - the length of the packet
* VID - the vlan id to which the port_no belongs
*Output:OK -the packet is normally processed
* ERROR - meets error when processing the packet
****************************************************************************************************/
int igmp_snoop_recv(int port_no, char *pkt, int len, int VID)
{
unsigned char *pktbuf;
struct igmp_snoop_pkt_msg * rec_pkt_msg;
TIMERMSG_S * msg;
int rnet,msg_num;
if (igmp_snoop_tid == 0 )
return;
msg_num = msgQNumMsgs(IgmpSnoopMsgQId);
if(12 <= msg_num )
return;
msg = (TIMERMSG_S *)kmalloc(sizeof(TIMERMSG_S) , IGMP_SNOOPING_MOD_ID);
if(NULL == msg)
return NULL;
bzero ((char *)msg, sizeof (TIMERMSG_S));
rec_pkt_msg = (struct igmp_snoop_pkt_msg *)kmalloc(sizeof(struct igmp_snoop_pkt_msg) , IGMP_SNOOPING_MOD_ID);
if(NULL == rec_pkt_msg)
return NULL;
bzero ((char *)rec_pkt_msg, sizeof (struct igmp_snoop_pkt_msg));
pktbuf = (unsigned char *)kmalloc(len , IGMP_SNOOPING_MOD_ID);
if(NULL == pktbuf)
return NULL;
bzero ((char *)pktbuf, len);
memcpy(pktbuf,pkt,len);
/*memcpy(pktbuf+2,pkt,len);*/
rec_pkt_msg->port_no = port_no;
rec_pkt_msg->len = len;
rec_pkt_msg->pkt = pktbuf;
rec_pkt_msg->VID = VID;
msg->source_id = IGMP_SNOOP_RECV_PKT;
msg->timer_id = 0; /*should choose an impossible value temporarily 0*/
msg->func = 0;
msg->parg = (char *)rec_pkt_msg;
rnet = (int)msgQSend(IgmpSnoopMsgQId, (char *)msg, sizeof(TIMERMSG_S), NO_WAIT, MSG_PRI_NORMAL);
kfree(msg);
msg = NULL;
if (rnet ==0 )
{ syslog(LOG_INFO,"return ok");
return OK;
}
else
{
syslog(LOG_INFO, "return error");
kfree(pktbuf);
pktbuf = NULL;
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
return ERROR;
}
/* kfree(rec_pkt_msg);
rec_pkt_msg = NULL;*/
/*kfree(pktbuf);
pktbuf = NULL;*/
}
/***************************************************************************************************
* Func: igmp_snoop_pkt_process_flex
*This function processes the received IGMP packet.
*Input: msg - the msg received from msg queue
*Output:OK -the packet is normally processed
* ERROR - meets error when processing the packet
****************************************************************************************************/
int igmp_snoop_pkt_process_flex(TIMERMSG_S *msg)
{
/*how to get the igmphdr from the pkt, and if there is many igmp datagrams in the pkt,what to do*/
/*unsigned char * buf;
buf = (unsigned char *)kmalloc(len+2 , IGMP_SNOOPING_MOD_ID);
if(NULL == buf)
return NULL;
memcpy(buf,&port_no,2);
memcpy(buf+2,pkt,len);*/
struct igmp_snoop_pkt_msg *rec_pkt_msg;
struct iphdr *iph;
struct igmphdr *ih;
short port_no;
char *vlanpkt,*pkt;
short VID ,new_vid;
int len, ihl ,check_rnet,res,res_vlan_index;
long timer;
int tag_flag = 0;
unsigned int group_addr;
unsigned char enaddr[6], saenaddr[6],daenaddr[6];
__u32 daddr, saddr;
struct vlanhdr *veth;
struct _vlanentry * vlan_for_new_vid;
/*for 802.1q*/
unsigned char vlanhdr_for_send[4] ,vid_tag_pad[4];
short ih_type;
char iph_proto;
struct igmp_snoop_group *igmp_snoop_group_to_join, *igmp_snoop_group_to_find;
struct igmp_snoop_router_entry *igmp_snoop_router_to_find;
struct igmp_snoop_mac_group *igmp_snoop_mac_to_find;
rec_pkt_msg = (struct igmp_snoop_pkt_msg *)msg->parg;
port_no = rec_pkt_msg->port_no;
vlanpkt = rec_pkt_msg->pkt;
VID = rec_pkt_msg->VID;
len = rec_pkt_msg->len;
/*check if the dest macaddr and the group_addr and the dest ipaddr match*/
check_rnet = igmp_pkt_check_flex(vlanpkt,len);
if (check_rnet != 0)
{
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
kfree(vlanpkt);
vlanpkt = NULL;
return;
}
veth = (struct vlanhdr *)vlanpkt;
memcpy((char*)saenaddr,(char*)(veth->v_source),ETH_ALEN);
memcpy((unsigned char*)daenaddr,(unsigned char *)(veth->v_dest),ETH_ALEN);
/*get the 802.1q*/
memcpy((char*)vlanhdr_for_send, (char*)vlanpkt + ETH_ALEN*2 , 4);
vid_tag_pad[0] = 0x81;
vid_tag_pad[1] = 0x00;
if (! memcmp(vlanpkt + ETH_ALEN*2, vid_tag_pad,2) )
{
memcpy(vid_tag_pad + 2,vlanpkt + ETH_ALEN*2 +2 ,2);
memcpy((char*)&new_vid,(char*)(vid_tag_pad+2),2);
/* new_vid = ntohs(new_vid);*/
new_vid &= 0x0fff;
vlan_for_new_vid = vlan_get_by_VID(new_vid);
if ( NULL == vlan_for_new_vid)
{
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
kfree(vlanpkt);
vlanpkt = NULL;
return;
}
else
{
res = vlan_port_relation(port_no,vlan_for_new_vid);
if (res == 0)
{
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
kfree(vlanpkt);
vlanpkt = NULL;
return;
}
}
VID = new_vid;
tag_flag = 1;
}
/*before here,the vlanpkt includes the vlanhdr,now we change it to pkt*/
len = len - sizeof(struct vlanhdr);
pkt = (char *)kmalloc(len , IGMP_SNOOPING_MOD_ID);
if(NULL == pkt)
return NULL;
bzero ((char *)pkt, len);
memcpy(pkt,vlanpkt + sizeof(struct vlanhdr),len);
kfree(rec_pkt_msg->pkt);
rec_pkt_msg->pkt = pkt;
iph = (struct iphdr *)pkt;
#ifdef _FLEX_HAMMER_
iph_proto = ntohs(iph->protocol);
if(iph_proto == 2)
{
ihl = ntohs(iph->ihl);
ih = (struct igmphdr *)(pkt + ihl * 4);
ih_type = ntohs(ih->type);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -