📄 igmp_snoop.c
字号:
daddr = ntohl(iph->daddr);
/* ih = (struct igmphdr *)pkt;*/
}
#endif
#ifdef _U_24_IGMPSNOOPING_
iph_proto = iph->protocol;
if(iph_proto == 2)
{
ihl = iph->ihl;
ih = (struct igmphdr *)(pkt + ihl * 4);
ih_type = ih->type;
/* ih = (struct igmphdr *)pkt;*/
daddr = iph->daddr;
}
#endif
/*first we should check if the destination address is from
*0xe0000002(PIM V1 HELLO) ,0xe0000004(DVMRP probes) ,0xe0000005(0xe0000006)(MOSPF messages)
* 0xe000000d(PIM V2 hello)
*/
/*addr = ntohl(iph->saddr);*/
/*THER_MAP_IP_MULTICAST(&saddr, saenaddr); */
#ifdef _FLEX_HAMMER_
if ((daddr == 0xe0000002) || (daddr == 0xe0000004) ||(daddr == 0xe0000005) || \
(daddr == 0xe0000006) ||(daddr == 0xe000000d ))
{
IGMP_ETHER_MAP_IP_MULTICAST(&daddr, enaddr);
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
igmp_other_router_pkt_process(VID,port_no, pkt , len,enaddr,saenaddr,daenaddr);
send_query(VID,pkt,len,port_no,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
kfree(pkt);
pkt = NULL;
}
#endif
#ifdef _U_24_IGMPSNOOPING_
if ((daddr == 0x020000e0) || (daddr == 0x040000e0) ||(daddr == 0x050000e0) || \
(daddr == 0x060000e0) ||(daddr == 0x0d0000e0 ))
{
IGMP_ETHER_MAP_IP_MULTICAST(&daddr, enaddr);
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
igmp_other_router_pkt_process(VID,port_no, pkt , len,enaddr,saenaddr,daenaddr);
send_query(VID,pkt,len,port_no,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
kfree(pkt);
pkt = NULL;
}
#endif
else if (iph_proto == 2)
{
#ifdef _FLEX_HAMMER_
timer = ntohs(ih->code);
group_addr = ntohl(ih->group);
#endif
#ifdef _U_24_IGMPSNOOPING_
timer = ih->code;
group_addr = ih->group;
#endif
timer = timer*(1000/IGMP_TIMER_SCALE);
IGMP_ETHER_MAP_IP_MULTICAST(&group_addr, enaddr);
switch(ih_type)
{
case IGMP_MEMBERSHIP_QUERY: /*embership query */
{
/* int port_no_to_send = 0;*/
/* int i = 0;*/
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
igmp_memebership_query_process(port_no, timer ,VID);
send_query(VID,pkt,len,port_no,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
kfree(pkt);
pkt = NULL;
break;
}
case IGMP_V1_MEMBERSHIP_REPORT: /* Ver. 1 membership report */
{
int send_general_report ,i,port_no_to_send;
struct igmp_snoop_mac_group *igmp_snoop_mac_to_join = igmp_snoop_mac_find(VID,enaddr);
kfree(rec_pkt_msg);
rec_pkt_msg =NULL;
if (igmp_snoop_mac_to_join != NULL)
{
igmp_snoop_group_to_join = igmp_snoop_group_find(igmp_snoop_mac_to_join, group_addr);
if (igmp_snoop_group_to_join != NULL)
send_general_report = igmp_snoop_group_to_join->send_general_report;
}
else
{
send_general_report = TRUE;
}
igmp_memebership_report_process(port_no,ih_type, VID, enaddr, group_addr );
/*if the send_general_report is true ,then we should send the ports of this group*/
if (send_general_report == TRUE)
{
/*send the reports to ports of the group*/
igmp_snoop_mac_to_find = igmp_snoop_mac_find(VID, enaddr);
if ( NULL == igmp_snoop_mac_to_find)
{
kfree(pkt);
pkt =NULL;
return NULL;
}
igmp_snoop_group_to_find = igmp_snoop_group_find(igmp_snoop_mac_to_find, group_addr );
if ( NULL == igmp_snoop_group_to_find)
{
kfree(pkt);
pkt =NULL;
return NULL;
}
for (i = 0; i < MAXPortNum; i ++)
{
port_no_to_send = igmp_snoop_group_to_find->port_no_list[i];
if ((port_no_to_send >0) && (port_no_to_send != port_no))
igmp_snoop_send(VID,port_no_to_send, pkt, len,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
}
/*should be changed ,if the 10s timer is on*/
/* igmp_snoop_group_to_find->send_general_report = TRUE;*/
igmp_snoop_group_to_find->send_general_report = FALSE;
}
kfree(pkt);
pkt =NULL;
break;
}
case IGMP_V2_MEMBERSHIP_REPORT: /* Ver. 2 membership report */
{
int send_general_report,i;
int port_no_to_send = 0;
struct igmp_snoop_router_entry *p;
struct igmp_snoop_mac_group *igmp_snoop_mac_to_join = igmp_snoop_mac_find(VID,enaddr);
kfree(rec_pkt_msg);
rec_pkt_msg =NULL;
if (igmp_snoop_mac_to_join != NULL)
{
igmp_snoop_group_to_join = igmp_snoop_group_find(igmp_snoop_mac_to_join, group_addr);
if (igmp_snoop_group_to_join != NULL)
send_general_report = igmp_snoop_group_to_join->send_general_report;
}
else
{
send_general_report = TRUE;
}
igmp_memebership_report_process(port_no,ih_type, VID, enaddr, group_addr );
/*if the send_general_report is true ,then we should send the pkt to router ports*/
if (send_general_report == TRUE)
{
/*send the reports to ports of the group*/
igmp_snoop_mac_to_find = igmp_snoop_mac_find(VID, enaddr);
if ( NULL == igmp_snoop_mac_to_find)
{
kfree(pkt);
pkt =NULL;
return NULL;
}
igmp_snoop_group_to_find = igmp_snoop_group_find(igmp_snoop_mac_to_find, group_addr );
if ( NULL == igmp_snoop_group_to_find)
{
kfree(pkt);
pkt =NULL;
return NULL;
}
for (i = 0; i < MAXPortNum; i ++)
{
port_no_to_send = igmp_snoop_group_to_find->port_no_list[i];
if ((port_no_to_send >0) && (port_no_to_send != port_no))
{
p = igmp_snoop_router_find(port_no_to_send,VID);
if ((p == NULL) ||((p != NULL)&& (p->router_v1flag == FALSE)))
igmp_snoop_send(VID,port_no_to_send, pkt, len,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
}
}
/*should be changed ,if the 10s timer is on*/
/* igmp_snoop_group_to_find->send_general_report = TRUE; */
igmp_snoop_group_to_find->send_general_report = FALSE;
}
kfree(pkt);
pkt =NULL;
/* send_general_report = FALSE;*/
break;
}
case IGMP_V2_LEAVE_GROUP: /* Leave-group message */
{
int port_no_to_send = 0,i;
int send_to_router_or_not = TRUE;
struct igmp_snoop_router_entry *p;
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
/*first we should check if the group has IGMPV1 host*/
igmp_snoop_mac_to_find = igmp_snoop_mac_find(VID, enaddr);
if(igmp_snoop_mac_to_find == NULL)
{
kfree(pkt);
pkt = NULL;
break;
}
igmp_snoop_group_to_find = igmp_snoop_group_find(igmp_snoop_mac_to_find, group_addr );
if(igmp_snoop_group_to_find == NULL)
{
kfree(pkt);
pkt = NULL;
break;
}
for (port_no_to_send = 0; port_no_to_send < MAXPortNum; port_no_to_send ++)
{
if (igmp_snoop_group_to_find->host_v1flag[port_no_to_send] == TRUE)
{
port_no_to_send = MAXPortNum;
send_to_router_or_not = FALSE;
}
}
/*if the group doesn't have IGMPV1 host ,the report should be sent to the routers*/
if (send_to_router_or_not == TRUE)
{
/*send the reports to ports of the group*/
igmp_snoop_mac_to_find = igmp_snoop_mac_find(VID, enaddr);
igmp_snoop_group_to_find = igmp_snoop_group_find(igmp_snoop_mac_to_find, group_addr );
for (i = 0; i < MAXPortNum; i ++)
{
port_no_to_send = igmp_snoop_group_to_find->port_no_list[i];
if ((port_no_to_send >0) && (port_no_to_send != port_no))
{
/*only the IGMPV2 routers can receive the leave group report*/
p = igmp_snoop_router_find(port_no_to_send, VID);
if ((p == NULL) || ((p !=NULL) &&(p->router_v1flag == FALSE)))
igmp_snoop_send(VID,port_no_to_send, pkt, len,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
}
}
}
kfree(pkt);
pkt = NULL;
break;
}
}
}
}
/***************************************************************************************************
* Func: igmp_snoop_pkt_process
*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(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;
/*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(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);
#ifdef _U_24_IGMPSNOOPING_
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;
if ( -1 ==getvlanindexbyvid(new_vid))
{
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
kfree(vlanpkt);
vlanpkt = NULL;
return;
}
else
{
res_vlan_index = getvlanindexbyvid(new_vid);
res = getportinfoinvlan(port_no,res_vlan_index);
if (res == 0)
{
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
kfree(vlanpkt);
vlanpkt = NULL;
return;
}
}
VID = new_vid;
tag_flag = 1;
}
#endif
/*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);
daddr = ntohl(iph->daddr);
/* ih = (struct igmphdr *)pkt;*/
}
#endif
#ifdef _U_24_IGMPSNOOPING_
iph_proto = iph->protocol;
if(iph_proto == 2)
{
ihl = iph->ihl;
ih = (struct igmphdr *)(pkt + ihl * 4);
ih_type = ih->type;
/* ih = (struct igmphdr *)pkt;*/
daddr = iph->daddr;
}
#endif
/*first we should check if the destination address is from
*0xe0000002(PIM V1 HELLO) ,0xe0000004(DVMRP probes) ,0xe0000005(0xe0000006)(MOSPF messages)
* 0xe000000d(PIM V2 hello)
*/
/*addr = ntohl(iph->saddr);*/
/*THER_MAP_IP_MULTICAST(&saddr, saenaddr); */
#ifdef _FLEX_HAMMER_
if ((daddr == 0xe0000002) || (daddr == 0xe0000004) ||(daddr == 0xe0000005) || \
(daddr == 0xe0000006) ||(daddr == 0xe000000d ))
{
IGMP_ETHER_MAP_IP_MULTICAST(&daddr, enaddr);
kfree(rec_pkt_msg);
rec_pkt_msg = NULL;
igmp_other_router_pkt_process(VID,port_no, pkt , len,enaddr,saenaddr,daenaddr);
send_query(VID,pkt,len,port_no,enaddr,saenaddr,daenaddr,vlanhdr_for_send,tag_flag);
kfree(pkt);
pkt = NULL;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -