diff --git a/src/ipg_types.h b/src/ipg_types.h index 9047feb..95c7f72 100644 --- a/src/ipg_types.h +++ b/src/ipg_types.h @@ -2,31 +2,30 @@ #ifndef IGP_TYPES_H #define IGP_TYPES_H -#define IPOPT_RA 148 /* router alert */ +#define IPOPT_RA 148 /* router alert */ #define IGMP_V3_MEMBERSHIP_REPORT 0x22 #include /* Structure to represent IGMP extra information */ typedef struct { - u_int8_t igmp_version; - char *igmp_tag; - u_int8_t igmp_type; /* IGMP type */ - u_int8_t igmp_code; /* routing code */ - char *igmp_dst; - int group_override_dst; + u_int8_t igmp_version; + char *igmp_tag; + u_int8_t igmp_type; /* IGMP type */ + u_int8_t igmp_code; /* routing code */ + char *igmp_dst; + int group_override_dst; } ipg_igmp_extra_t; typedef struct { - char *device; - char *igmp_type_version; // Combined type and version - char *igmp_group; - char *source_ip_port; // Combined source IP and port - char *destination_ip_port; // Combined destination IP and port - int delay_between_packets; // Optional, can be 0 if not specified + char *device; + char *igmp_type_version; // Combined type and version + char *igmp_group; + char *source_ip_port; // Combined source IP and port + char *destination_ip_port; // Combined destination IP and port + int delay_between_packets; // Optional, can be 0 if not specified } ipg_cmdline_options_t; extern ipg_igmp_extra_t g_igmp_pkts[]; -#endif /* IGP_TYPES_H */ - +#endif /* IGP_TYPES_H */ diff --git a/src/main.c b/src/main.c index 1e013df..0eacaea 100644 --- a/src/main.c +++ b/src/main.c @@ -5,10 +5,10 @@ #include /* missing type definitions (depending on system) */ -typedef unsigned char unchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; +typedef unsigned char unchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; #include #include @@ -17,356 +17,358 @@ typedef unsigned long ulong; /* global table of IGMP packet types*/ ipg_igmp_extra_t g_igmp_pkts[] = { - /* name, type (or version+type), code */ - { 1, "query", 0x11, 0, "224.0.0.1", 0 }, - { 1, "report", 0x12, 0, "224.0.0.1", 1 }, - { 1, "dvmrp", 0x13, 0, "224.0.0.1", 0 }, - { 2, "query", 0x11, 1, "224.0.0.1", 0 }, - { 2, "report", 0x16, 1, "224.0.0.2", 1 }, - { 2, "leave", 0x17, 1, "224.0.0.2", 0 }, - { 3, "report", 0x22, 1, "224.0.0.22", 0 }, + /* name, type (or version+type), code */ + {1, "query", 0x11, 0, "224.0.0.1", 0}, + {1, "report", 0x12, 0, "224.0.0.1", 1}, + {1, "dvmrp", 0x13, 0, "224.0.0.1", 0}, + {2, "query", 0x11, 1, "224.0.0.1", 0}, + {2, "report", 0x16, 1, "224.0.0.2", 1}, + {2, "leave", 0x17, 1, "224.0.0.2", 0}, + {3, "report", 0x22, 1, "224.0.0.22", 0}, - /* Note: end of list (please keep) */ - { 0, 0, 0, 0, 0, 0 }, + /* Note: end of list (please keep) */ + {0, 0, 0, 0, 0, 0}, }; void usage(char *); -ipg_igmp_extra_t * igmp_packet_type_find(u_int8_t igmp_version, char *igmp_request) { - ipg_igmp_extra_t *pkt_ptr; +ipg_igmp_extra_t *igmp_packet_type_find(u_int8_t igmp_version, + char *igmp_request) +{ + ipg_igmp_extra_t *pkt_ptr; - pkt_ptr = g_igmp_pkts; - while(pkt_ptr->igmp_version || pkt_ptr->igmp_tag){ - // if ((strcasecmp(pkt_ptr->igmp_tag, optarg) == 0) - if ((strcasecmp(pkt_ptr->igmp_tag, igmp_request) == 0) - && (igmp_version == pkt_ptr->igmp_version)){ - return pkt_ptr; - } - pkt_ptr++; - } - return NULL; + pkt_ptr = g_igmp_pkts; + while (pkt_ptr->igmp_version || pkt_ptr->igmp_tag) { + // if ((strcasecmp(pkt_ptr->igmp_tag, optarg) == 0) + if ((strcasecmp(pkt_ptr->igmp_tag, igmp_request) == 0) + && (igmp_version == pkt_ptr->igmp_version)) { + return pkt_ptr; + } + pkt_ptr++; + } + return NULL; } int main(int argc, char **argv) { - u_int32_t ip_src = 0; - u_int32_t ip_dst = 0; - u_int32_t igmp_group = 0; - char *igmp_group_str = NULL; - char *ip_src_str = NULL; - char *ip_dst_str = NULL; - u_char igmp_type = 0; - u_char igmp_code = 0; - ipg_igmp_extra_t *pkt_ptr; - int igmp_override; + u_int32_t ip_src = 0; + u_int32_t ip_dst = 0; + u_int32_t igmp_group = 0; + char *igmp_group_str = NULL; + char *ip_src_str = NULL; + char *ip_dst_str = NULL; + u_char igmp_type = 0; + u_char igmp_code = 0; + ipg_igmp_extra_t *pkt_ptr; + int igmp_override; - /* ports */ - u_short src_prt = 3141; - u_short dst_prt = 5926; + /* ports */ + u_short src_prt = 3141; + u_short dst_prt = 5926; - /* igmp stuff */ - u_int8_t igmp_version = 0; + /* igmp stuff */ + u_int8_t igmp_version = 0; - int ip_src_test = 1; - int ip_dst_test = 1; - int igmp_group_test =1; + int ip_src_test = 1; + int ip_dst_test = 1; + int igmp_group_test = 1; - /* libnet stuff */ - char neterr[LIBNET_ERRBUF_SIZE]; - libnet_ptag_t ptag; - libnet_t *netcontext = NULL; + /* libnet stuff */ + char neterr[LIBNET_ERRBUF_SIZE]; + libnet_ptag_t ptag; + libnet_t *netcontext = NULL; - /* misc */ - char *device = "eth0"; - int c; - char *cp = NULL; + /* misc */ + char *device = "eth0"; + int c; + char *cp = NULL; - printf("IGMP packet generator\n\n"); - printf("Detected options:\n"); + printf("IGMP packet generator\n\n"); + printf("Detected options:\n"); - /* Parsing command line */ - while((c = getopt(argc, argv, "i:t:g:d:s:")) != EOF) - { - switch (c) - { - case 'i': - printf(" Net interface = [%s]\n",optarg); - device = optarg; - break; + /* Parsing command line */ + while ((c = getopt(argc, argv, "i:t:g:d:s:")) != EOF) { + switch (c) { + case 'i': + printf(" Net interface = [%s]\n", optarg); + device = optarg; + break; - case 't': - if (!(cp = strrchr(optarg, '.'))) { - usage(argv[0]); - exit(1); - } - *cp++ = 0; + case 't': + if (!(cp = strrchr(optarg, '.'))) { + usage(argv[0]); + exit(1); + } + *cp++ = 0; - igmp_version = (u_short)atoi(optarg); + igmp_version = (u_short) atoi(optarg); - pkt_ptr = igmp_packet_type_find(igmp_version, cp); - if (!pkt_ptr) { - printf("ERROR: Packet type %d.%s not found!\n", igmp_version, cp); - usage(argv[0]); - exit(1); - } + pkt_ptr = igmp_packet_type_find(igmp_version, cp); + if (!pkt_ptr) { + printf("ERROR: Packet type %d.%s not found!\n", + igmp_version, cp); + usage(argv[0]); + exit(1); + } - igmp_type = pkt_ptr->igmp_type; - igmp_code = pkt_ptr->igmp_code; - ip_dst_str = pkt_ptr->igmp_dst; - igmp_override = pkt_ptr->group_override_dst; - printf(" Packet = [%s] version [%d]\n", pkt_ptr->igmp_tag, igmp_version); - break; + igmp_type = pkt_ptr->igmp_type; + igmp_code = pkt_ptr->igmp_code; + ip_dst_str = pkt_ptr->igmp_dst; + igmp_override = pkt_ptr->group_override_dst; + printf(" Packet = [%s] version [%d]\n", + pkt_ptr->igmp_tag, igmp_version); + break; - case 'g': - // Group argument handling logic - printf(" Group = [%s]\n", optarg); - igmp_group_str = optarg; - break; + case 'g': + // Group argument handling logic + printf(" Group = [%s]\n", optarg); + igmp_group_str = optarg; + break; - case 'n': - // delay between packets in sec - break; + case 'n': + // delay between packets in sec + break; - case 'd': - /* - * We expect the input to be of the form `ip.ip.ip.ip:port`. We - * point cp to the last dot of the IP address/port string and - * then seperate them with a NULL byte. The optarg now points to - * just the IP address, and cp points to the port. - */ + case 'd': + /* + * We expect the input to be of the form `ip.ip.ip.ip:port`. We + * point cp to the last dot of the IP address/port string and + * then seperate them with a NULL byte. The optarg now points to + * just the IP address, and cp points to the port. + */ - if ((cp = strrchr(optarg, ':'))) - { - *cp++ = 0; - dst_prt = (u_short)atoi(cp); - } else { - dst_prt = 0; - } - ip_dst_str = strdup(optarg); - printf(" Destination = ip [%s] port [%d]\n", ip_dst_str, dst_prt); - break; + if ((cp = strrchr(optarg, ':'))) { + *cp++ = 0; + dst_prt = (u_short) atoi(cp); + } else { + dst_prt = 0; + } + ip_dst_str = strdup(optarg); + printf(" Destination = ip [%s] port [%d]\n", + ip_dst_str, dst_prt); + break; - case 's': - if ((cp = strrchr(optarg, ':'))) - { - *cp++ = 0; - src_prt = (u_short)atoi(cp); - } else { - src_prt = 0; - } - ip_src_str = strdup(optarg); - printf(" Source = ip [%s] port [%d]\n", ip_src_str, src_prt); - break; + case 's': + if ((cp = strrchr(optarg, ':'))) { + *cp++ = 0; + src_prt = (u_short) atoi(cp); + } else { + src_prt = 0; + } + ip_src_str = strdup(optarg); + printf(" Source = ip [%s] port [%d]\n", ip_src_str, + src_prt); + break; - default: - usage(argv[0]); - exit(1); - } - } + default: + usage(argv[0]); + exit(1); + } + } - if (!igmp_group_str) - { - usage(argv[0]); - fprintf(stderr, "ERROR: missing destination IGMP group\n"); - exit(EXIT_FAILURE); - } + if (!igmp_group_str) { + usage(argv[0]); + fprintf(stderr, "ERROR: missing destination IGMP group\n"); + exit(EXIT_FAILURE); + } - if (!device) - { - usage(argv[0]); - fprintf(stderr, "ERROR: missing device\n"); - exit(EXIT_FAILURE); - } + if (!device) { + usage(argv[0]); + fprintf(stderr, "ERROR: missing device\n"); + exit(EXIT_FAILURE); + } - printf("done\n"); + printf("done\n"); - /* Memory initialization */ - printf("Initializing libnet context...\n"); - netcontext = libnet_init(LIBNET_RAW4, device, neterr); - if (!netcontext) { - fprintf(stderr, "%s\n", neterr); - exit(1); - } - libnet_clear_packet(netcontext); + /* Memory initialization */ + printf("Initializing libnet context...\n"); + netcontext = libnet_init(LIBNET_RAW4, device, neterr); + if (!netcontext) { + fprintf(stderr, "%s\n", neterr); + exit(1); + } + libnet_clear_packet(netcontext); - if (!ip_src_str) { - ip_src = libnet_get_ipaddr4(netcontext); - ip_src_str = libnet_addr2name4(ip_src, LIBNET_DONT_RESOLVE); - } + if (!ip_src_str) { + ip_src = libnet_get_ipaddr4(netcontext); + ip_src_str = libnet_addr2name4(ip_src, LIBNET_DONT_RESOLVE); + } - printf("Packet construction...\n"); + printf("Packet construction...\n"); - /* Packet construction: IGMP */ - printf(" Building IGMP content...\n"); - ptag = libnet_build_igmp( - igmp_type, // IGMP type - igmp_code, // IGMP code - 0, // checksum - 0, // group address - NULL, // payload - 0, // payload size - netcontext, // libnet context - 0 // ptag - ); - if (ptag == -1) { - fprintf(stderr, "Error building IGMP header: %s\n", libnet_geterror(netcontext)); - libnet_destroy(netcontext); - exit(EXIT_FAILURE); - } + /* Packet construction: IGMP */ + printf(" Building IGMP content...\n"); + ptag = libnet_build_igmp(igmp_type, // IGMP type + igmp_code, // IGMP code + 0, // checksum + 0, // group address + NULL, // payload + 0, // payload size + netcontext, // libnet context + 0 // ptag + ); + if (ptag == -1) { + fprintf(stderr, "Error building IGMP header: %s\n", + libnet_geterror(netcontext)); + libnet_destroy(netcontext); + exit(EXIT_FAILURE); + } - printf(" done\n"); + printf(" done\n"); - /* Send packet */ - if (libnet_write(netcontext) == -1) { - fprintf(stderr, "Error sending packet: %s\n", libnet_geterror(netcontext)); - } else { - printf("Packet sent successfully.\n"); - } + /* Send packet */ + if (libnet_write(netcontext) == -1) { + fprintf(stderr, "Error sending packet: %s\n", + libnet_geterror(netcontext)); + } else { + printf("Packet sent successfully.\n"); + } - printf("Packet construction...\n"); + printf("Packet construction...\n"); - /* - * Packet construction : IGMP - */ - printf(" Building IGMP content...\n"); + /* + * Packet construction : IGMP + */ + printf(" Building IGMP content...\n"); - // Override dest with group info when needed - if (igmp_override) { - ip_dst_str = igmp_group_str; - } + // Override dest with group info when needed + if (igmp_override) { + ip_dst_str = igmp_group_str; + } - switch ( igmp_type ) { - case 0x11: // IGMP_MEMBERSHIP_QUERY - if (igmp_version == 2){ - // group specific - } else if (igmp_version == 1) { - // general - igmp_group = 0; - igmp_group_str = "0.0.0.0"; - igmp_group_test = 0; - } - // DST = 224.0.0.1 - //igmp_group = 0; - //igmp_group_test = 0; - break; - case 0x12: // - default: - break; - } + switch (igmp_type) { + case 0x11: // IGMP_MEMBERSHIP_QUERY + if (igmp_version == 2) { + // group specific + } else if (igmp_version == 1) { + // general + igmp_group = 0; + igmp_group_str = "0.0.0.0"; + igmp_group_test = 0; + } + // DST = 224.0.0.1 + //igmp_group = 0; + //igmp_group_test = 0; + break; + case 0x12: // + default: + break; + } - if (ip_src_test - && !(ip_src = libnet_name2addr4(netcontext, ip_src_str, LIBNET_RESOLVE))) - { - fprintf(stderr,"Bad source IP address: %s\n", ip_src_str); - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - exit(1); - } + if (ip_src_test + && !(ip_src = + libnet_name2addr4(netcontext, ip_src_str, LIBNET_RESOLVE))) { + fprintf(stderr, "Bad source IP address: %s\n", ip_src_str); + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + exit(1); + } - if (ip_dst_test - && !(ip_dst = libnet_name2addr4(netcontext, ip_dst_str, LIBNET_RESOLVE))) - { - fprintf(stderr,"Bad destination IP address: %s\n", ip_dst_str); - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - exit(1); - } + if (ip_dst_test + && !(ip_dst = + libnet_name2addr4(netcontext, ip_dst_str, LIBNET_RESOLVE))) { + fprintf(stderr, "Bad destination IP address: %s\n", ip_dst_str); + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + exit(1); + } - if (igmp_group_test && !(igmp_group = libnet_name2addr4(netcontext, igmp_group_str, LIBNET_RESOLVE))) - { - fprintf(stderr,"Bad group IP address: %s\n", optarg); - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - exit(1); - } + if (igmp_group_test + && !(igmp_group = + libnet_name2addr4(netcontext, igmp_group_str, LIBNET_RESOLVE))) + { + fprintf(stderr, "Bad group IP address: %s\n", optarg); + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + exit(1); + } - printf(" IP SRC IP = %s\n", ip_src_str); - printf(" IP DEST IP = %s\n", ip_dst_str); - printf(" IGMP TYPE = 0x%02x\n", igmp_type); - printf(" IGMP CODE = 0x%02x\n", igmp_code); - printf(" IGMP GROUP = %s\n", igmp_group_str); - printf(" GROUP TEST = %d\n", igmp_group_test); + printf(" IP SRC IP = %s\n", ip_src_str); + printf(" IP DEST IP = %s\n", ip_dst_str); + printf(" IGMP TYPE = 0x%02x\n", igmp_type); + printf(" IGMP CODE = 0x%02x\n", igmp_code); + printf(" IGMP GROUP = %s\n", igmp_group_str); + printf(" GROUP TEST = %d\n", igmp_group_test); - /* - int test = 1; - if ( *(char *) test == 1) { - // little endian - printf("little endian\n"); - } else { - // big endian - printf("big endian\n"); - } - */ + /* + int test = 1; + if ( *(char *) test == 1) { + // little endian + printf("little endian\n"); + } else { + // big endian + printf("big endian\n"); + } + */ - ptag = libnet_build_igmp( - igmp_type, // IGMP type - igmp_code, // IGMP code or TTL - 0, // checksum - htonl(igmp_group), // ip addr - NULL, // Ptr to packet data (or null) - 0, // Packet payload length - netcontext, // Ptr to libnet context - 0); // Build a new packet header - if (ptag < 0) - { - fprintf(stderr, "Error while building IGMP header data (err %d)\n", ptag); - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - exit(1); - } + ptag = libnet_build_igmp(igmp_type, // IGMP type + igmp_code, // IGMP code or TTL + 0, // checksum + htonl(igmp_group), // ip addr + NULL, // Ptr to packet data (or null) + 0, // Packet payload length + netcontext, // Ptr to libnet context + 0); // Build a new packet header + if (ptag < 0) { + fprintf(stderr, + "Error while building IGMP header data (err %d)\n", + ptag); + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + exit(1); + } + u_int8_t ipopt[2]; + ipopt[0] = IPOPT_RA; + ipopt[1] = 4; + ptag = libnet_build_ipv4_options(ipopt, // options + 2, // options_s (length of option string) + netcontext, // libnet context + 0 // ptag + ); + if (ptag < 0) { + fprintf(stderr, + "Error while building IPv4 options data (err %d)\n", + ptag); + } - u_int8_t ipopt[2]; - ipopt[0] = IPOPT_RA; - ipopt[1] = 4; - ptag = libnet_build_ipv4_options( - ipopt, // options - 2, // options_s (length of option string) - netcontext, // libnet context - 0 // ptag - ); - if (ptag < 0) - { - fprintf(stderr, "Error while building IPv4 options data (err %d)\n", ptag); - } + ptag = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_IGMP_H, // pkg size + data + 0, // IP tos + getpid(), // IP ID + IP_DF, // frag flags and offset + 1, // TTL + IPPROTO_IGMP, // transport protocol + 0, // checksum + ip_src, // source IP + ip_dst, // destination IP + NULL, // payload (none) + 0, // payload length + netcontext, // libnet context + 0 // build a new header + ); + if (ptag < 0) { + fprintf(stderr, + "Error while building IPv4 header data (err %d)\n", + ptag); + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + exit(1); + } - ptag = libnet_build_ipv4(LIBNET_IPV4_H + LIBNET_IGMP_H, // pkg size + data - 0, // IP tos - getpid(), // IP ID - IP_DF, // frag flags and offset - 1, // TTL - IPPROTO_IGMP, // transport protocol - 0, // checksum - ip_src, // source IP - ip_dst, // destination IP - NULL, // payload (none) - 0, // payload length - netcontext, // libnet context - 0 // build a new header - ); - if (ptag < 0) - { - fprintf(stderr, "Error while building IPv4 header data (err %d)\n", ptag); - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - exit(1); - } + printf(" done\n"); //IGMP content - printf(" done\n"); //IGMP content + c = libnet_write(netcontext); + if (c < 0) { + fprintf(stderr, "%s\n", libnet_geterror(netcontext)); + } else { + printf + ("construction and injection completed, wrote all %d bytes\n", + c); + } - c = libnet_write(netcontext); - if (c < 0) - { - fprintf(stderr,"%s\n", libnet_geterror(netcontext)); - } - else - { - printf("construction and injection completed, wrote all %d bytes\n", c); - } + /* + * Free packet memory. + */ + libnet_diag_dump_pblock(netcontext); + libnet_destroy(netcontext); + exit(0); - /* - * Free packet memory. - */ - libnet_diag_dump_pblock(netcontext); - libnet_destroy(netcontext); - exit(0); - - return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS); + return (c == -1 ? EXIT_FAILURE : EXIT_SUCCESS); } // vim: ts=4 sts=4 sw=4 et diff --git a/src/usage.c b/src/usage.c index b1f6212..ba15041 100644 --- a/src/usage.c +++ b/src/usage.c @@ -7,24 +7,30 @@ void usage(const char *name) { - ipg_igmp_extra_t *pkt_ptr; + ipg_igmp_extra_t *pkt_ptr; - fprintf(stderr, "Usage: %s [options]\n", basename(name)); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -i Specify the network interface (e.g., eth0)\n"); - fprintf(stderr, " -t Specify the IGMP packet type and version (e.g., 1.query)\n"); - fprintf(stderr, " -g Specify the destination IGMP group (e.g., 224.0.0.1)\n"); - fprintf(stderr, " -s Specify the source IP and port (e.g., 192.168.1.1:1234)\n"); - fprintf(stderr, " -d Specify the destination IP and port (e.g., 224.0.0.2:5678)\n"); - fprintf(stderr, " -n Specify delay between packets in seconds (optional)\n"); + fprintf(stderr, "Usage: %s [options]\n", basename(name)); + fprintf(stderr, "\nOptions:\n"); + fprintf(stderr, + " -i Specify the network interface (e.g., eth0)\n"); + fprintf(stderr, + " -t Specify the IGMP packet type and version (e.g., 1.query)\n"); + fprintf(stderr, + " -g Specify the destination IGMP group (e.g., 224.0.0.1)\n"); + fprintf(stderr, + " -s Specify the source IP and port (e.g., 192.168.1.1:1234)\n"); + fprintf(stderr, + " -d Specify the destination IP and port (e.g., 224.0.0.2:5678)\n"); + fprintf(stderr, + " -n Specify delay between packets in seconds (optional)\n"); - fprintf(stderr, "\nAvailable IGMP packet types:\n"); + fprintf(stderr, "\nAvailable IGMP packet types:\n"); - pkt_ptr = g_igmp_pkts; - while(pkt_ptr->igmp_version || pkt_ptr->igmp_tag){ - fprintf(stderr," - %d.%s\n", pkt_ptr->igmp_version, pkt_ptr->igmp_tag); - pkt_ptr++; - } - fprintf(stderr, "\n"); + pkt_ptr = g_igmp_pkts; + while (pkt_ptr->igmp_version || pkt_ptr->igmp_tag) { + fprintf(stderr, " - %d.%s\n", pkt_ptr->igmp_version, + pkt_ptr->igmp_tag); + pkt_ptr++; + } + fprintf(stderr, "\n"); } -