diff options
Diffstat (limited to 'main/common/igmp.c')
-rw-r--r-- | main/common/igmp.c | 284 |
1 files changed, 145 insertions, 139 deletions
diff --git a/main/common/igmp.c b/main/common/igmp.c index 213d1cb..1c4fd44 100644 --- a/main/common/igmp.c +++ b/main/common/igmp.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -40,161 +40,167 @@ int SendIGMP(int type,uchar *groupip); char *IgmpHelp[] = { - "IGMP interface", + "IGMP interface", #if INCLUDE_VERBOSEHELP - "{operation} [args]", - "Operations...", - " join {IP}", - " leave {IP}", + "{operation} [args]", + "Operations...", + " join {IP}", + " leave {IP}", #endif - 0, + 0, }; int Igmp(int argc,char *argv[]) { - int opt, verbose = 0; - uchar binip[8]; - char *operation, *ipadd; - - while ((opt=getopt(argc,argv,"v")) != -1) { - switch(opt) { - case 'v': - verbose = 1; - break; - default: - return(CMD_PARAM_ERROR); - } - } - - if (argc != optind + 2) - return(CMD_PARAM_ERROR); - - operation = argv[optind]; - ipadd = argv[optind+1]; - - /* Convert IP address to binary: */ - if (IpToBin(ipadd,binip) < 0) - return(CMD_SUCCESS); - - /* If time or echo, do the common up-front stuff here... */ - if (!strcmp(operation,"join")) { - SendIGMP(IGMPTYPE_JOIN,binip); - } - else if (!strcmp(operation,"leave")) { - SendIGMP(IGMPTYPE_LEAVE,binip); - } - else { - printf("Unrecognized IGMP op: %s\n",operation); - return(CMD_FAILURE); - } - return(CMD_SUCCESS); + int opt, verbose = 0; + uchar binip[8]; + char *operation, *ipadd; + + while((opt=getopt(argc,argv,"v")) != -1) { + switch(opt) { + case 'v': + verbose = 1; + break; + default: + return(CMD_PARAM_ERROR); + } + } + + if(argc != optind + 2) { + return(CMD_PARAM_ERROR); + } + + operation = argv[optind]; + ipadd = argv[optind+1]; + + /* Convert IP address to binary: */ + if(IpToBin(ipadd,binip) < 0) { + return(CMD_SUCCESS); + } + + /* If time or echo, do the common up-front stuff here... */ + if(!strcmp(operation,"join")) { + SendIGMP(IGMPTYPE_JOIN,binip); + } else if(!strcmp(operation,"leave")) { + SendIGMP(IGMPTYPE_LEAVE,binip); + } else { + printf("Unrecognized IGMP op: %s\n",operation); + return(CMD_FAILURE); + } + return(CMD_SUCCESS); } int SendIGMP(int type,uchar *groupip) { - int i; - ushort *sp; - struct ip *ti; - struct Igmphdr *tigmp; - struct ether_header *te; - ulong csum, *router_alert_opt; - - /* Retrieve an ethernet buffer from the driver and populate the */ - /* ethernet level of packet: */ - te = (struct ether_header *) getXmitBuffer(); - - /* Source MAC is this target's MAC address... - */ - memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); - /* Destination MAC is multicast, so it is derived from the - * group IP address... - * The upper 24 bits are 0x01005e. - * For JOIN, the lower 24 bits are masked with the groupIP and 0x7fffff. - * For LEAVE, the message is sent to the All_Routers_Multicast_Group - * (224.0.0.2), so the lower three bytes are 0,0,2. - */ - te->ether_dhost.ether_addr_octet[0] = 0x01; - te->ether_dhost.ether_addr_octet[1] = 0x00; - te->ether_dhost.ether_addr_octet[2] = 0x5e; - - if (type == IGMPTYPE_LEAVE) { - te->ether_dhost.ether_addr_octet[3] = 0x00; - te->ether_dhost.ether_addr_octet[4] = 0x00; - te->ether_dhost.ether_addr_octet[5] = 0x02; - } - else { - te->ether_dhost.ether_addr_octet[3] = groupip[1] & 0x7f; - te->ether_dhost.ether_addr_octet[4] = groupip[2]; - te->ether_dhost.ether_addr_octet[5] = groupip[3]; - } - te->ether_type = ecs(ETHERTYPE_IP); - - /* Move to the IP portion of the packet and populate it appropriately: */ - ti = (struct ip *) (te + 1); - ti->ip_vhl = ((IP_VER<<4) | ((sizeof(struct ip)+sizeof(ulong)) >> 2)); - ti->ip_tos = 0; - ti->ip_len = sizeof(struct ip) + sizeof(ulong) + sizeof(struct Igmphdr); - ti->ip_id = ipId(); - ti->ip_off = 0; - ti->ip_ttl = 1; - ti->ip_p = IP_IGMP; - memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); - if (type == IGMPTYPE_LEAVE) - ti->ip_dst.s_addr = ALL_MULTICAST_ROUTERS; - else - memcpy((char *)&ti->ip_dst.s_addr,(char *)groupip,4); - - self_ecs(ti->ip_len); - self_ecs(ti->ip_off); - self_ecs(ti->ip_id); - - router_alert_opt = (ulong *)(ti+1); - *router_alert_opt = 0x94040000; /* see RFC2113 */ - - ipChksum(ti); /* Compute csum of ip hdr */ - - /* Move to the IGMP portion of the packet and populate it appropriately: */ - tigmp = (struct Igmphdr *)(router_alert_opt+1); - tigmp->type = type; - tigmp->mrt = 0; - tigmp->csum = 0; - memcpy((char *)&tigmp->group,(char *)groupip,4); - - /* Calculate checksum of IGMP portion of the header. - * This uses the same method as is used with ipChksum()... - */ - sp = (ushort *)tigmp; - csum = 0; - for (i=0;i<4;i++,sp++) { - csum += *sp; - if (csum & 0x80000000) - csum = (csum & 0xffff) + (csum >> 16); - } - while(csum >> 16) - csum = (csum & 0xffff) + (csum >> 16); - tigmp->csum = ~csum; - - sendBuffer(IGMP_JOINRQSTSIZE); - return(0); + int i; + ushort *sp; + struct ip *ti; + struct Igmphdr *tigmp; + struct ether_header *te; + ulong csum, *router_alert_opt; + + /* Retrieve an ethernet buffer from the driver and populate the */ + /* ethernet level of packet: */ + te = (struct ether_header *) getXmitBuffer(); + + /* Source MAC is this target's MAC address... + */ + memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6); + /* Destination MAC is multicast, so it is derived from the + * group IP address... + * The upper 24 bits are 0x01005e. + * For JOIN, the lower 24 bits are masked with the groupIP and 0x7fffff. + * For LEAVE, the message is sent to the All_Routers_Multicast_Group + * (224.0.0.2), so the lower three bytes are 0,0,2. + */ + te->ether_dhost.ether_addr_octet[0] = 0x01; + te->ether_dhost.ether_addr_octet[1] = 0x00; + te->ether_dhost.ether_addr_octet[2] = 0x5e; + + if(type == IGMPTYPE_LEAVE) { + te->ether_dhost.ether_addr_octet[3] = 0x00; + te->ether_dhost.ether_addr_octet[4] = 0x00; + te->ether_dhost.ether_addr_octet[5] = 0x02; + } else { + te->ether_dhost.ether_addr_octet[3] = groupip[1] & 0x7f; + te->ether_dhost.ether_addr_octet[4] = groupip[2]; + te->ether_dhost.ether_addr_octet[5] = groupip[3]; + } + te->ether_type = ecs(ETHERTYPE_IP); + + /* Move to the IP portion of the packet and populate it appropriately: */ + ti = (struct ip *)(te + 1); + ti->ip_vhl = ((IP_VER<<4) | ((sizeof(struct ip)+sizeof(ulong)) >> 2)); + ti->ip_tos = 0; + ti->ip_len = sizeof(struct ip) + sizeof(ulong) + sizeof(struct Igmphdr); + ti->ip_id = ipId(); + ti->ip_off = 0; + ti->ip_ttl = 1; + ti->ip_p = IP_IGMP; + memcpy((char *)&ti->ip_src.s_addr,(char *)BinIpAddr,4); + if(type == IGMPTYPE_LEAVE) { + ti->ip_dst.s_addr = ALL_MULTICAST_ROUTERS; + } else { + memcpy((char *)&ti->ip_dst.s_addr,(char *)groupip,4); + } + + self_ecs(ti->ip_len); + self_ecs(ti->ip_off); + self_ecs(ti->ip_id); + + router_alert_opt = (ulong *)(ti+1); + *router_alert_opt = 0x94040000; /* see RFC2113 */ + + ipChksum(ti); /* Compute csum of ip hdr */ + + /* Move to the IGMP portion of the packet and populate it appropriately: */ + tigmp = (struct Igmphdr *)(router_alert_opt+1); + tigmp->type = type; + tigmp->mrt = 0; + tigmp->csum = 0; + memcpy((char *)&tigmp->group,(char *)groupip,4); + + /* Calculate checksum of IGMP portion of the header. + * This uses the same method as is used with ipChksum()... + */ + sp = (ushort *)tigmp; + csum = 0; + for(i=0; i<4; i++,sp++) { + csum += *sp; + if(csum & 0x80000000) { + csum = (csum & 0xffff) + (csum >> 16); + } + } + while(csum >> 16) { + csum = (csum & 0xffff) + (csum >> 16); + } + tigmp->csum = ~csum; + + sendBuffer(IGMP_JOINRQSTSIZE); + return(0); } int MacIsMulticast(uchar *mac) { - if (*mac != 0x01) - return(0); - mac++; - if (*mac != 0x00) - return(0); - mac++; - if (*mac != 0x5e) - return(0); - mac++; - if (*mac & 0x80) - return(0); - return(1); + if(*mac != 0x01) { + return(0); + } + mac++; + if(*mac != 0x00) { + return(0); + } + mac++; + if(*mac != 0x5e) { + return(0); + } + mac++; + if(*mac & 0x80) { + return(0); + } + return(1); } #endif |