From 657246088b53891fd86c624b9f690c7723c28618 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Tue, 2 Mar 2010 14:32:57 -0800 Subject: merged icmpv6 patch in, but I believe either it or the sample/icmp6_unreach generates the cksum incorrectly (victor@inliniac.net) --- .gitignore | 1 + README.txt | 9 ++ libnet/include/libnet/libnet-functions.h | 17 +++ libnet/include/libnet/libnet-headers.h | 16 +++ libnet/include/libnet/libnet-structures.h | 3 + libnet/sample/Makefile.am | 6 +- libnet/sample/icmp6_unreach.c | 194 ++++++++++++++++++++++++++++++ libnet/src/libnet_build_icmp.c | 42 +++++++ libnet/src/libnet_checksum.c | 22 ++++ libnet/src/libnet_internal.c | 8 +- libnet/src/libnet_pblock.c | 5 + unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz | Bin 2157 -> 0 bytes 12 files changed, 320 insertions(+), 3 deletions(-) create mode 100644 libnet/sample/icmp6_unreach.c delete mode 100644 unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz diff --git a/.gitignore b/.gitignore index 29dd775..cf63220 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ libnet/sample/get_addr libnet/sample/gre libnet/sample/hsrp libnet/sample/icmp6_echoreq +libnet/sample/icmp6_unreach libnet/sample/icmp_echo_cq libnet/sample/icmp_redirect libnet/sample/icmp_timeexceed diff --git a/README.txt b/README.txt index 9ade012..69e3381 100644 --- a/README.txt +++ b/README.txt @@ -10,6 +10,15 @@ I forked from packetfactory.net and am maintaining and rereleasing libnet. Contact Sam Roberts if you have bugs or patches to contribute. +Todo: + +- redo error handling in net binding +- cross-target patches +- icmpv6 patches: cksum is wrong +- cksum bug? generally, I don't trust the checksums are correct +- unit test framework + + In progress: - lua bindings, to libnet, libpcap, and libnfq: these will allow construction, diff --git a/libnet/include/libnet/libnet-functions.h b/libnet/include/libnet/libnet-functions.h index 667905c..47efe08 100644 --- a/libnet/include/libnet/libnet-functions.h +++ b/libnet/include/libnet/libnet-functions.h @@ -777,6 +777,23 @@ libnet_build_icmpv4_timestamp(uint8_t type, uint8_t code, uint16_t sum, uint16_t id, uint16_t seq, n_time otime, n_time rtime, n_time ttime, const uint8_t* payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag); +/** + * Builds an IP version 6 RFC 4443 Internet Control Message Protocol (ICMP) + * unreachable header. The IP header that caused the error message should be + * built by a previous call to libnet_build_ipv6(). + * @param type type of ICMP packet (should be ICMP6_UNREACH) + * @param code code of ICMP packet (should be one of the 5 unreachable codes) + * @param sum checksum (0 for libnet to autofill) + * @param payload optional payload or NULL + * @param payload_s payload length or 0 + * @param l pointer to a libnet context + * @param ptag protocol tag to modify an existing header, 0 to build a new one + * @return protocol tag value on success, -1 on error + */ +libnet_ptag_t +libnet_build_icmpv6_unreach(u_int8_t type, u_int8_t code, u_int16_t sum, +u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag); + /** * Builds an RFC 1112 Internet Group Memebership Protocol (IGMP) header. * @param type packet type diff --git a/libnet/include/libnet/libnet-headers.h b/libnet/include/libnet/libnet-headers.h index 6f5e521..0345f02 100644 --- a/libnet/include/libnet/libnet-headers.h +++ b/libnet/include/libnet/libnet-headers.h @@ -64,6 +64,7 @@ #define LIBNET_ICMPV4_REDIRECT_H 0x08 /**< ICMP_REDIRECT header: 8 bytes */ #define LIBNET_ICMPV4_TS_H 0x14 /**< ICMP_TIMESTAMP headr:20 bytes */ #define LIBNET_ICMPV6_H 0x08 /**< ICMP6 header base: 8 bytes */ +#define LIBNET_ICMPV6_UNREACH_H 0x08 /**< ICMP6 unreach base: 8 bytes */ #define LIBNET_IGMP_H 0x08 /**< IGMP header: 8 bytes */ #define LIBNET_IPV4_H 0x14 /**< IPv4 header: 20 bytes */ #define LIBNET_IPV6_H 0x28 /**< IPv6 header: 40 bytes */ @@ -841,6 +842,21 @@ struct libnet_icmpv6_hdr #define ICMP6_PARAMPROB 4 #endif uint8_t icmp_code; /* ICMP code */ +#ifndef ICMP6_NOROUTE +#define ICMP6_NOROUTE 0 +#endif +#ifndef ICMP6_ADM_PROHIBITED +#define ICMP6_ADM_PROHIBITED 1 +#endif +#ifndef ICMP6_NOT_NEIGHBOUR +#define ICMP6_NOT_NEIGHBOUR 2 +#endif +#ifndef ICMP6_ADDR_UNREACH +#define ICMP6_ADDR_UNREACH 3 +#endif +#ifndef ICMP6_PORT_UNREACH +#define ICMP6_PORT_UNREACH 4 +#endif uint16_t icmp_sum; /* ICMP Checksum */ uint16_t id; /* ICMP id */ uint16_t seq; /* ICMP sequence number */ diff --git a/libnet/include/libnet/libnet-structures.h b/libnet/include/libnet/libnet-structures.h index cb1697e..c7ed88e 100644 --- a/libnet/include/libnet/libnet-structures.h +++ b/libnet/include/libnet/libnet-structures.h @@ -158,6 +158,9 @@ struct libnet_protocol_block #define LIBNET_PBLOCK_IPV6_HBHOPTS_H 0x3e /* IPv6 hop/hop opts header */ #define LIBNET_PBLOCK_SEBEK_H 0x3f /* Sebek header */ #define LIBNET_PBLOCK_HSRP_H 0x40 /* HSRP header */ +#define LIBNET_PBLOCK_ICMPV6_H 0x41 /* ICMPv6 header */ +#define LIBNET_PBLOCK_ICMPV6_UNREACH_H 0x42 /* ICMPv6 unreach header */ + uint8_t flags; /* control flags */ #define LIBNET_PBLOCK_DO_CHECKSUM 0x01 /* needs a checksum */ libnet_ptag_t ptag; /* protocol block tag */ diff --git a/libnet/sample/Makefile.am b/libnet/sample/Makefile.am index aa4181b..4e9474f 100644 --- a/libnet/sample/Makefile.am +++ b/libnet/sample/Makefile.am @@ -10,7 +10,10 @@ include $(top_srcdir)/Makefile.am.common samples = arp cdp dhcp_discover get_addr icmp_timestamp icmp_unreach \ ieee isl ntp ospf_hello ospf_lsa ping_of_death stp synflood \ - tcp1 tcp2 udp1 udp2 synflood6 icmp6_echoreq icmp_echo_cq \ + tcp1 tcp2 udp1 udp2 synflood6 \ + icmp6_echoreq \ + icmp6_unreach \ + icmp_echo_cq \ smurf dot1x dns rpc_tcp rpc_udp mpls icmp_timeexceed \ fddi_tcp1 fddi_tcp2 tring_tcp1 tring_tcp2 icmp_redirect \ bgp4_hdr bgp4_open bgp4_update bgp4_notification gre \ @@ -54,6 +57,7 @@ tftp_SOURCES = tftp.c udp1_SOURCES = udp1.c udp2_SOURCES = udp2.c icmp6_echoreq_SOURCES = icmp6_echoreq.c +icmp6_unreach_SOURCES = icmp6_unreach.c smurf_SOURCES = smurf.c synflood6_SOURCES = synflood6.c synflood6_frag_SOURCES = synflood6_frag.c diff --git a/libnet/sample/icmp6_unreach.c b/libnet/sample/icmp6_unreach.c new file mode 100644 index 0000000..aff6064 --- /dev/null +++ b/libnet/sample/icmp6_unreach.c @@ -0,0 +1,194 @@ +/* + * $Id: icmp6_unreach.c,v 1.1.1.1 2003/06/26 21:55:10 route Exp $ + * + * Poseidon++ (c) 1996 - 2002 Mike D. Schiffman + * Redone from synflood example by Stefan Schlott + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#if (HAVE_CONFIG_H) +#include "../include/config.h" +#endif +#include "./libnet_test.h" + +struct t_pack +{ + struct libnet_ipv6_hdr ip; + struct libnet_tcp_hdr tcp; +}; + + +int +main(int argc, char **argv) +{ + struct libnet_in6_addr dst_ip; + struct libnet_in6_addr src_ip; + u_short dst_prt = 0; + u_short src_prt = 0; + libnet_t *l; + libnet_ptag_t t; + char *cp; + char errbuf[LIBNET_ERRBUF_SIZE]; + int i, c, packet_amt, burst_int, burst_amt, build_ip; + char srcname[100],dstname[100]; + + packet_amt = 0; + burst_int = 0; + burst_amt = 1; + + printf("libnet 1.1 unreach/admin prohibited request ICMP6[raw]\n"); + + /* + * Initialize the library. Root priviledges are required. + */ + l = libnet_init( + LIBNET_RAW6, /* injection type */ + NULL, /* network interface */ + errbuf); /* error buffer */ + + if (l == NULL) + { + fprintf(stderr, "libnet_init() failed: %s", errbuf); + exit(EXIT_FAILURE); + } + + while((c = getopt(argc, argv, "t:a:i:b:")) != EOF) + { + switch (c) + { + case 't': + if (!(cp = strrchr(optarg, '/'))) + { + usage(argv[0]); + exit(EXIT_FAILURE); + } + *cp++ = 0; + dst_prt = (u_short)atoi(cp); + dst_ip = libnet_name2addr6(l, optarg, 1); + if (strncmp((char*)&dst_ip,(char*)&in6addr_error,sizeof(in6addr_error))==0) + { + fprintf(stderr, "Bad IP6 address: %s\n", optarg); + exit(EXIT_FAILURE); + } + break; + case 'a': + packet_amt = atoi(optarg); + break; + case 'i': + burst_int = atoi(optarg); + break; + case 'b': + burst_amt = atoi(optarg); + break; + default: + usage(argv[0]); + exit(EXIT_FAILURE); + } + } + + if (!dst_prt || strncmp((char*)&dst_ip,(char*)&in6addr_error,sizeof(in6addr_error))==0 || !packet_amt) + { + usage(argv[0]); + exit(EXIT_FAILURE); + } + + + + libnet_seed_prand(l); + libnet_addr2name6_r(src_ip,1,srcname,sizeof(srcname)); + libnet_addr2name6_r(dst_ip,1,dstname,sizeof(dstname)); + + for(t = LIBNET_PTAG_INITIALIZER, build_ip = 1; burst_amt--;) + { + for (i = 0; i < packet_amt; i++) + { + uint8_t payload[56]; + int i; + for (i=0; i %15s/%5d\n", + srcname, + ntohs(src_prt), + dstname, + dst_prt); + c = libnet_write(l); + if (c == -1) + { + fprintf(stderr, "libnet_write: %s\n", libnet_geterror(l)); + } +#if !(__WIN32__) + usleep(250); +#else + Sleep(250); +#endif + + } +#if !(__WIN32__) + sleep(burst_int); +#else + Sleep(burst_int * 1000); +#endif + } + exit(EXIT_SUCCESS); +} + + +void +usage(char *nomenclature) +{ + fprintf(stderr, + "\n\nusage: %s -t -a [-i -b]\n" + "\t-t target, (ip6:address/port, e.g. ::1/23)\n" + "\t-a number of packets to send per burst\n" + "\t-i packet burst sending interval (defaults to 0)\n" + "\t-b number packet bursts to send (defaults to 1)\n" , nomenclature); +} + + +/* EOF */ diff --git a/libnet/src/libnet_build_icmp.c b/libnet/src/libnet_build_icmp.c index 12ed3fb..72e1fd6 100644 --- a/libnet/src/libnet_build_icmp.c +++ b/libnet/src/libnet_build_icmp.c @@ -395,4 +395,46 @@ bad: return (-1); } + +libnet_ptag_t +libnet_build_icmpv6_unreach(u_int8_t type, u_int8_t code, u_int16_t sum, +u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) +{ + u_int32_t n, h; + libnet_pblock_t *p; + struct libnet_icmpv6_hdr icmp_hdr; + + if (l == NULL) + { + return (-1); + } + + n = LIBNET_ICMPV6_UNREACH_H + payload_s; /* size of memory block */ + + /* + * Find the existing protocol block if a ptag is specified, or create + * a new one. + */ + p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_UNREACH_H); + if (p == NULL) + { + return (-1); + } + + memset(&icmp_hdr, 0, sizeof(icmp_hdr)); + icmp_hdr.icmp_type = type; /* packet type */ + icmp_hdr.icmp_code = code; /* packet code */ + icmp_hdr.icmp_sum = (sum ? htons(sum) : 0); /* checksum */ + icmp_hdr.id = 0; /* must be 0 */ + icmp_hdr.seq = 0; /* must be 0 */ + + LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV6_UNREACH_H); + + return (ptag ? ptag : libnet_pblock_update(l, p, h, + LIBNET_PBLOCK_ICMPV6_UNREACH_H)); +bad: + libnet_pblock_delete(l, p); + return (-1); +} + /* EOF */ diff --git a/libnet/src/libnet_checksum.c b/libnet/src/libnet_checksum.c index c1efd17..de1cda0 100644 --- a/libnet/src/libnet_checksum.c +++ b/libnet/src/libnet_checksum.c @@ -294,6 +294,9 @@ libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const u CHECK_IP_PAYLOAD_SIZE(); icmph_p->icmp_sum = 0; + /* Hm, is this valid? Is the checksum algorithm for ICMPv6 encapsulated in IPv4 + * actually defined? + */ if (is_ipv6) { sum = libnet_in_cksum((uint16_t *)&ip6h_p->ip_src, 32); @@ -303,6 +306,25 @@ libnet_do_checksum(libnet_t *l, uint8_t *iphdr, int protocol, int h_len, const u icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); break; } + case IPPROTO_ICMPV6: + { + struct libnet_icmpv6_hdr *icmph_p = + (struct libnet_icmpv6_hdr *)(iphdr + ip_hl); + + h_len = end - (uint8_t*) icmph_p; /* ignore h_len, sum the packet we've coalesced */ + + CHECK_IP_PAYLOAD_SIZE(); + + icmph_p->icmp_sum = 0; + if (is_ipv6) + { + sum = libnet_in_cksum((u_int16_t *)&ip6h_p->ip_src, 32); + sum += ntohs(IPPROTO_ICMP6 + h_len); + } + sum += libnet_in_cksum((u_int16_t *)icmph_p, h_len); + icmph_p->icmp_sum = LIBNET_CKSUM_CARRY(sum); + break; + } case IPPROTO_IGMP: { struct libnet_igmp_hdr *igmph_p = diff --git a/libnet/src/libnet_internal.c b/libnet/src/libnet_internal.c index c45b3b5..fc481ce 100644 --- a/libnet/src/libnet_internal.c +++ b/libnet/src/libnet_internal.c @@ -174,7 +174,7 @@ libnet_diag_dump_pblock_type(uint8_t type) { switch (type) { - /* below text can be regenerated using map-pblock-typs */ + /* below text can be regenerated using ./map-pblock-types */ case LIBNET_PBLOCK_ARP_H: return ("arp"); case LIBNET_PBLOCK_DHCPV4_H: @@ -303,7 +303,11 @@ libnet_diag_dump_pblock_type(uint8_t type) return ("sebek"); case LIBNET_PBLOCK_HSRP_H: return ("hsrp"); + case LIBNET_PBLOCK_ICMPV6_H: + return ("icmpv6"); + case LIBNET_PBLOCK_ICMPV6_UNREACH_H: + return ("icmpv6_unreach"); } return ("unrecognized pblock"); } -/* EOF */ + diff --git a/libnet/src/libnet_pblock.c b/libnet/src/libnet_pblock.c index 2b9913a..7218f21 100644 --- a/libnet/src/libnet_pblock.c +++ b/libnet/src/libnet_pblock.c @@ -575,10 +575,15 @@ libnet_pblock_p2p(uint8_t type) case LIBNET_PBLOCK_ICMPV4_REDIRECT_H: case LIBNET_PBLOCK_ICMPV4_TS_H: return (IPPROTO_ICMP); + case LIBNET_PBLOCK_ICMPV6_H: + case LIBNET_PBLOCK_ICMPV6_UNREACH_H: + return (IPPROTO_ICMPV6); case LIBNET_PBLOCK_IGMP_H: return (IPPROTO_IGMP); case LIBNET_PBLOCK_IPV4_H: return (IPPROTO_IP); + case LIBNET_PBLOCK_IPV6_H: + return (IPPROTO_IPV6); case LIBNET_ISL_H: return (LIBNET_PROTO_ISL); case LIBNET_PBLOCK_OSPF_H: diff --git a/unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz b/unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz deleted file mode 100644 index 129ab06..0000000 Binary files a/unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz and /dev/null differ -- cgit v1.2.1