From 6f542884d002d55d517a50dd9892068e95400b25 Mon Sep 17 00:00:00 2001 From: Vadim Kochan Date: Mon, 2 Mar 2015 13:16:55 +0200 Subject: mz: Add igmp v1/v2 packet type crafting support Signed-off-by: Vadim Kochan Signed-off-by: Tobias Klauser --- staging/layer3.c | 18 ++++------ staging/layer4.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++ staging/mausezahn.c | 28 +++++++++++++-- staging/mz.h | 38 ++++++++++---------- 4 files changed, 153 insertions(+), 32 deletions(-) diff --git a/staging/layer3.c b/staging/layer3.c index 3eca55d..0b17db1 100644 --- a/staging/layer3.c +++ b/staging/layer3.c @@ -154,17 +154,14 @@ libnet_ptag_t create_ip_packet (libnet_t *l) tx.ip_frag = 0; // Flags and Offset !!! tx.ip_sum = 0; // default: automatically calculate checksum tx.ip_tos = 0; - tx.ip_ttl = 255; - // temporary variables unsigned int dummy; size_t len; char *s; - T = tx.packet_mode; // >0 means automatic L2 creation - + if ( (getarg(tx.arg_string,"help", NULL)==1) && (mode==IP) ) { if (mz_port) @@ -284,13 +281,12 @@ libnet_ptag_t create_ip_packet (libnet_t *l) { tx.ip_frag |= 0x8000; } - - - if (getarg(tx.arg_string,"ttl", argval)==1) - { - tx.ip_ttl = (u_int8_t) str2int(argval); - } - + + if (getarg(tx.arg_string, "ttl", argval) == 1) + tx.ip_ttl = (u_int8_t)str2int(argval); + else if (tx.ip_ttl == 0) + tx.ip_ttl = 255; + if (getarg(tx.arg_string,"proto", argval)==1) { tx.ip_proto = (u_int8_t) str2int(argval); diff --git a/staging/layer4.c b/staging/layer4.c index a4431a1..8ccf80c 100644 --- a/staging/layer4.c +++ b/staging/layer4.c @@ -136,7 +136,32 @@ "| Of course all Ethernet fields can also be accessed.\n"\ "|\n" +#define MZ_IGMP_HELP \ + "| IGMP type: Send raw IGMP packets.\n" \ + "|\n" \ + "| Parameters Values Explanation \n" \ + "| ---------- ------------------------------------ -------------------\n" \ + "| v,ver 1-2 version\n" \ + "| t,type packet type:\n" \ + "| q,qry,query - memberhsip query\n" \ + "| j,join - join group\n" \ + "| l,lv,leave - leave group\n" \ + "| resp_time max response time (v2 only)\n" \ + "| igmp_sum checksum (optional)\n" \ + "| g,group group ipv4 address\n" \ + "\n" +int print_packet_help(char *help) +{ + if (mz_port) { + cli_print(gcli, "%s", help); + } else { + fprintf(stderr,"\n" MAUSEZAHN_VERSION "\n%s", help); + exit(0); + } + + return -1; +} // Note: If another function specified tx.udp_payload then it must also // set tx.udp_payload_s AND tx.udp_len = tx.udp_payload_s + 8 @@ -884,3 +909,79 @@ libnet_ptag_t create_tcp_packet (libnet_t *l) return t; } + +libnet_ptag_t create_igmp_packet(libnet_t *l) +{ + libnet_ptag_t t; + char argval[MAX_PAYLOAD_SIZE]; + int ver = 2; + uint8_t type = IGMP_MEMBERSHIP_QUERY; + uint8_t resp_time = 10; + uint16_t sum = 0; + uint32_t group = 0; + + if ((getarg(tx.arg_string, "help", NULL) == 1) && (mode == IGMP)) + return print_packet_help(MZ_IGMP_HELP); + + if (getarg(tx.arg_string, "ver", argval) == 1 || + getarg(tx.arg_string, "v", argval) == 1) { + + ver = str2int(argval); + if (ver == 1) + resp_time = 0; + } + + if (getarg(tx.arg_string, "type", argval) == 1 || + getarg(tx.arg_string, "t", argval) == 1) { + + if (strcmp("j", argval) == 0 || strcmp("join", argval) == 0) { + + if (ver == 1) + type = IGMP_V1_MEMBERSHIP_REPORT; + else if (ver == 2) + type = IGMP_V2_MEMBERSHIP_REPORT; + + } else if (strcmp("l", argval) == 0 || strcmp("lv", argval) == 0 || + strcmp("leave", argval) == 0) { + + type = IGMP_LEAVE_GROUP; + } + } + + if (getarg(tx.arg_string, "resp_time", argval) == 1) + resp_time = (uint8_t)str2int(argval); + + if (getarg(tx.arg_string, "igmp_sum", argval) == 1) + sum = (uint16_t)str2int(argval); + + if (getarg(tx.arg_string, "group", argval) == 1 || + getarg(tx.arg_string, "g", argval) == 1) { + + group = str2ip32_rev(argval); + } + + if (type == IGMP_LEAVE_GROUP) { + tx.ip_dst = str2ip32_rev("224.0.0.2"); + } else if (type == IGMP_MEMBERSHIP_QUERY) { + if (ver == 1 || group == 0) + tx.ip_dst = str2ip32_rev("224.0.0.1"); + else if (ver == 2 && group != 0) + tx.ip_dst = group; + } else if (type == IGMP_V1_MEMBERSHIP_REPORT || + type == IGMP_V2_MEMBERSHIP_REPORT) { + + tx.ip_dst = group; + } + + if (getarg(tx.arg_string, "ttl", argval) == 0) + tx.ip_ttl = 1; + + t = libnet_build_igmp(type, resp_time, sum, group, NULL, 0, l, 0); + if (t == -1) { + fprintf(stderr, " mz/create_igmp_packet: Can't build IGMP header: %s\n", + libnet_geterror(l)); + exit (0); + } + + return t; +} diff --git a/staging/mausezahn.c b/staging/mausezahn.c index c06a1d8..5051bcb 100644 --- a/staging/mausezahn.c +++ b/staging/mausezahn.c @@ -281,6 +281,7 @@ int reset(void) tx.ip_dst_stop = 0; tx.ip_dst_isrange = 0; + tx.ip_ttl = 0; tx.ip_len = 0; tx.ip_payload[0]= '\0'; tx.ip_payload_s = 0; @@ -361,6 +362,7 @@ static void print_packet_types(void) "| udp ... sends UDP datagrams\n" "| tcp ... sends TCP segments\n" "| icmp ... sends ICMP messages\n" + "| igmp ... sends IGMP messages\n" "| dns ... sends DNS messages\n" "| rtp ... sends RTP datagrams\n" "| syslog ... sends Syslog messages\n" @@ -814,6 +816,9 @@ int getopts (int argc, char *argv[]) else if (strcmp(packet_type,"syslog")==0) { mode = SYSLOG; } + else if (strcmp(packet_type, "igmp") == 0) { + mode = IGMP; + } else if (strcmp(packet_type,"lldp")==0) { mode = LLDP; tx.packet_mode=0; // create whole frame by ourself @@ -928,9 +933,9 @@ int main(int argc, char **argv) else send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly break; - + case TCP: - tx.ip_proto = 6; + tx.ip_proto = 6; l = get_link_context(); t4 = create_tcp_packet(l); // t4 can be used for later header changes t3 = create_ip_packet(l); // t3 can be used for later header changes @@ -942,7 +947,24 @@ int main(int argc, char **argv) else send_frame (l, t3, t4); // NOTE: send_frame also destroys context finaly break; - + + case IGMP: + tx.ip_proto = 2; + l = get_link_context(); + t4 = create_igmp_packet(l); + /* t3 can be used for later header changes */ + t3 = create_ip_packet(l); + if (!quiet) + complexity(); + + /* Ethernet manipulation features does NOT use ARP to determine eth_dst + * */ + if (tx.packet_mode == 0) + t2 = create_eth_frame(l, t3, t4); // t2 can be used for later header changes + else + send_frame(l, t3, t4); // NOTE: send_frame also destroys context finaly + break; + case DNS: tx.ip_proto = 17; l = get_link_context(); diff --git a/staging/mz.h b/staging/mz.h index ade4da3..339be31 100644 --- a/staging/mz.h +++ b/staging/mz.h @@ -256,20 +256,21 @@ struct struct_rtp { enum operating_modes { - BYTE_STREAM, - ARP, - BPDU, - IP, - ICMP, - ICMP6, - UDP, - TCP, - DNS, - CDP, - RTP, - RX_RTP, - SYSLOG, - LLDP + BYTE_STREAM, + ARP, + BPDU, + IP, + ICMP, + ICMP6, + UDP, + TCP, + DNS, + CDP, + RTP, + RX_RTP, + SYSLOG, + LLDP, + IGMP } mode; @@ -561,10 +562,11 @@ int send_frame (libnet_t *l, libnet_ptag_t t3, libnet_ptag_t t4); // Prototypes: Layer 4 // // ************************************ -libnet_ptag_t create_udp_packet (libnet_t *l); -libnet_ptag_t create_icmp_packet (libnet_t *l); -libnet_ptag_t create_icmp6_packet (libnet_t *l); -libnet_ptag_t create_tcp_packet (libnet_t *l); +libnet_ptag_t create_udp_packet(libnet_t *l); +libnet_ptag_t create_icmp_packet(libnet_t *l); +libnet_ptag_t create_icmp6_packet(libnet_t *l); +libnet_ptag_t create_tcp_packet(libnet_t *l); +libnet_ptag_t create_igmp_packet(libnet_t *l); // ************************************ -- cgit v1.2.3-54-g00ecf