summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2010-03-02 14:32:57 -0800
committerSam Roberts <vieuxtech@gmail.com>2010-03-02 14:32:57 -0800
commit657246088b53891fd86c624b9f690c7723c28618 (patch)
tree47726cb9cc7a902778320aa52048263bc76b51c6
parentce400fec6a051a84d614eae801291c65df2c6c9e (diff)
downloadlibnet-657246088b53891fd86c624b9f690c7723c28618.tar.gz
merged icmpv6 patch in, but I believe either it or the sample/icmp6_unreach generates the cksum incorrectly (victor@inliniac.net)
-rw-r--r--.gitignore1
-rw-r--r--README.txt9
-rw-r--r--libnet/include/libnet/libnet-functions.h17
-rw-r--r--libnet/include/libnet/libnet-headers.h16
-rw-r--r--libnet/include/libnet/libnet-structures.h3
-rw-r--r--libnet/sample/Makefile.am6
-rw-r--r--libnet/sample/icmp6_unreach.c194
-rw-r--r--libnet/src/libnet_build_icmp.c42
-rw-r--r--libnet/src/libnet_checksum.c22
-rw-r--r--libnet/src/libnet_internal.c8
-rw-r--r--libnet/src/libnet_pblock.c5
-rw-r--r--unmerged/libnet-1.1.3-RC-01-ipv6.diff.gzbin2157 -> 0 bytes
12 files changed, 320 insertions, 3 deletions
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 <vieuxtech@gmail.com> 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
@@ -778,6 +778,23 @@ 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
* @param code packet code (should be 0)
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 <mike@infonexus.com>
+ * Redone from synflood example by Stefan Schlott <stefan@ploing.de>
+ *
+ * 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<sizeof(payload); i++)
+ payload[i]='A'+(i%26);
+ t = libnet_build_icmpv6_unreach (
+ ICMP6_UNREACH, /* type */
+ ICMP6_ADM_PROHIBITED, /* code */
+ 0, /* checksum */
+ payload, /* payload */
+ sizeof(payload), /* payload length */
+ l, /* libnet context */
+ t); /* libnet ptag */
+
+
+
+ if (build_ip)
+ {
+ build_ip = 0;
+ libnet_build_ipv6(0,0,
+ LIBNET_IPV6_H + LIBNET_ICMPV6_H + sizeof(payload),
+ IPPROTO_ICMP6,
+ 64,
+ src_ip,
+ dst_ip,
+ NULL,
+ 0,
+ l,
+ 0);
+ }
+ printf("%15s/%5d -> %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
--- a/unmerged/libnet-1.1.3-RC-01-ipv6.diff.gz
+++ /dev/null
Binary files differ