📄 igmp_snoop.c
字号:
#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;
}
}
}
}
igmp_pkt_check_flex(char *vlanpkt ,int len)
{
char dest_macaddr[6],dest_ipaddr_mac[6],group_addr_mac[6];
unsigned long dest_ipaddr,ihl,iph_proto;
unsigned long group_addr;
struct iphdr *iph;
char *pkt;
struct igmphdr *ih;
int ip_checksum,igmp_checksum;
memcpy(dest_macaddr, vlanpkt, ETH_ALEN);
len = len - sizeof(struct vlanhdr);
pkt = (char *)kmalloc(len , IGMP_SNOOPING_MOD_ID);
if(NULL == pkt)
return ERROR;
bzero ((char *)pkt, len);
memcpy(pkt,vlanpkt + sizeof(struct vlanhdr),len);
iph = (struct iphdr *)pkt;
iph_proto = ntohs(iph->protocol);
if(iph_proto != 2)
{
kfree(pkt);
return ERROR;
}
dest_ipaddr = ntohl(iph->daddr);
ihl = ntohs(iph->ihl);
ih = (struct igmphdr *)(pkt + ihl * 4);
/*add for the checksum*/
bzero ((char*)&(iph->check), sizeof (u_int16_t));
bzero ((char*)&(ih->csum), sizeof (u_int16_t));
ip_checksum = hos_in_cksum(pkt,(ntohs(iph->ihl) * 4));
igmp_checksum = hos_in_cksum((char *)ih,8);
/*end for the checksum*/
group_addr = ntohl(ih->group);
IGMP_ETHER_MAP_IP_MULTICAST(&dest_ipaddr, dest_ipaddr_mac);
if (memcmp((char *)dest_ipaddr_mac,(char *)dest_macaddr,6))
{
kfree(pkt);
return ERROR;
}
if (group_addr != 0)
{
IGMP_ETHER_MAP_IP_MULTICAST(&group_addr, group_addr_mac);
if (memcmp((char *)dest_ipaddr_mac,(char *)group_addr_mac,6))
{
kfree(pkt);
return ERROR;
}
}
kfree(pkt);
return OK;
}
igmp_pkt_check(char *vlanpkt ,int len)
{
char dest_macaddr[6],dest_ipaddr_mac[6],group_addr_mac[6];
unsigned long dest_ipaddr,ihl,iph_proto;
unsigned long group_addr;
struct iphdr *iph;
char *pkt;
struct igmphdr *ih;
memcpy(dest_macaddr, vlanpkt, ETH_ALEN);
len = len - sizeof(struct vlanhdr);
pkt = (char *)kmalloc(len , IGMP_SNOOPING_MOD_ID);
if(NULL == pkt)
return ERROR;
bzero ((char *)pkt, len);
memcpy(pkt,vlanpkt + sizeof(struct vlanhdr),len);
iph = (struct iphdr *)pkt;
iph_proto = iph->protocol;
if(iph_proto != 2)
{
kfree(pkt);
return ERROR;
}
dest_ipaddr = iph->daddr;
ihl = iph->ihl;
ih = (struct igmphdr *)(pkt + ihl * 4);
group_addr = ih->group;
IGMP_ETHER_MAP_IP_MULTICAST(&dest_ipaddr, dest_ipaddr_mac);
if (memcmp((char *)dest_ipaddr_mac,(char *)dest_macaddr,6))
{
kfree(pkt);
return ERROR;
}
if (group_addr != 0)
{
IGMP_ETHER_MAP_IP_MULTICAST(&group_addr, group_addr_mac);
if (memcmp((char *)dest_ipaddr_mac,(char *)group_addr_mac,6))
{
kfree(pkt);
return ERROR;
}
}
kfree(pkt);
return OK;
}
/***************************************************************************************************
* Func: igmp_other_router_pkt_process
*This function processes the other router packet.
*Input: port_no - the port no from which the packet is received
*Output: OK -the packet is normally processed
* ERROR - meets error when processing the packet
****************************************************************************************************/
int igmp_other_router_pkt_process(short VID,short port_no, char *pkt ,int len ,unsigned char enaddr[6],unsigned char saenaddr[6],unsigned char daenaddr[6])
{
int router_port_no = 0;
int del_timer_return;
long timer;
struct igmp_snoop_pkt_msg *igmp_snoop_pkt_msg;
struct igmp_snoop_router_entry *p = igmp_snoop_router_list;
struct igmp_snoop_router_entry *igmp_snoop_router_entry_to_find = igmp_snoop_router_find(port_no,VID);
igmp_snoop_pkt_msg = (struct igmp_snoop_pkt_msg *)kmalloc(sizeof (struct igmp_snoop_pkt_msg) , IGMP_SNOOPING_MOD_ID);
if(NULL == igmp_snoop_pkt_msg)
return NULL;
bzero((char*)igmp_snoop_pkt_msg,sizeof(struct igmp_snoop_pkt_msg));
igmp_snoop_pkt_msg->port_no = port_no;
igmp_snoop_pkt_msg->time_out_type = OTHER_ROUTER_TIME_OUT;
igmp_snoop_pkt_msg->VID = VID;
timer = 400000 ; /*temporary*/
if (igmp_snoop_router_entry_to_find != NULL)
{
del_timer_return = hos_deltimer(igmp_snoop_router_entry_to_find->timer_id);
if(ERROR == del_timer_return)
{
kfree(igmp_snoop_pkt_msg);
return ERROR;
}
igmp_snoop_router_entry_to_find->router_timer = ROUTER_TIME_OUT_TIMER;/* temporary*/
/* hos_deltimer(igmp_snoop_router_entry_to_find->timer_id);*/
igmp_snoop_router_entry_to_find->timer_id = 0;
kfree(igmp_snoop_router_entry_to_find ->rec_pkt_msg);
igmp_snoop_router_entry_to_find ->rec_pkt_msg = NULL;
igmp_snoop_router_entry_to_find->timer_id = hos_timerout_byqueue((unsigned long)IgmpSnoopMsgQId, ROUTER_TIME_OUT_TIMER, NULL, (char *) igmp_snoop_pkt_msg);
}
else
{ /*on the port there is no router,so we should first add a port in the router list*/
igmp_snoop_router_entry_to_find = igmp_snoop_router_add(port_no,timer,VID);
igmp_snoop_router_entry_to_find->timer_id = hos_timerout_byqueue((unsigned long)IgmpSnoopMsgQId, ROUTER_TIME_OUT_TIMER, NULL, (char *) igmp_snoop_pkt_msg);
}
igmp_snoop_router_entry_to_find->rec_pkt_msg = igmp_snoop_pkt_msg;
igmp_snoop_router_entry_to_find->router_timer = ROUTER_TIME_OUT_TIMER;
}
/***************************************************************************************************
* Func: igmp_memebership_query_process
*This function processes the received igmp_memebership_query packet.
*Input: port_no - the port_no from which received this packet
* timer - the lifetime of router(maybe 120s)
*Output:OK -the packet is normally disposed
* ERROR - meets error when processing the packet
****************************************************************************************************/
int igmp_memebership_query_process(int port_no, long timer, int VID )
{
struct igmp_snoop_router_entry *igmp_snoop_router_entry_to_find = igmp_snoop_router_find(port_no,VID);
/* char *router_parg = "router";*/
struct igmp_snoop_pkt_msg *igmp_snoop_pkt_msg, *igmp_snoop_pktv1_msg;
struct st_timer *p_timer_to_del;
int del_timer_return;
/*now we create a igmp_snoop_pkt_msg*/
igmp_snoop_pkt_msg = (struct igmp_snoop_pkt_msg *)kmalloc(sizeof (struct igmp_snoop_pkt_msg) , IGMP_SNOOPING_MOD_ID);
if(NULL == igmp_snoop_pkt_msg)
return NULL;
bzero ((char *)igmp_snoop_pkt_msg, sizeof (struct igmp_snoop_pkt_msg));
if(igmp_snoop_pkt_msg == NULL)
{
syslog(LOG_INFO,"No free momory for new igmp_snoop_pkt_msg");
return ERROR;
/* return 0;*/
}
igmp_snoop_pkt_msg->port_no = port_no;
igmp_snoop_pkt_msg->time_out_type = ROUTER_TIME_OUT;
igmp_snoop_pkt_msg->VID = VID;
if (igmp_snoop_router_entry_to_find != NULL)
{
del_timer_return = hos_deltimer(igmp_snoop_router_entry_to_find->timer_id);
if(ERROR == del_timer_return)
{
kfree(igmp_snoop_pkt_msg);
return ERROR;
}
/* hos_deltimer(igmp_snoop_router_entry_to_find->timer_id);*/
igmp_snoop_router_entry_to_find->timer_id = 0;
kfree(igmp_snoop_router_entry_to_find->rec_pkt_msg);
igmp_snoop_router_entry_to_find->rec_pkt_msg = NULL;
/*it is a router v1 query,so we should create a new router v1 type timer and v1 msg*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -