summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsomeone <sickmind@lavabit.com>2012-02-22 15:42:48 -0800
committerSam Roberts <vieuxtech@gmail.com>2012-03-01 09:06:10 -0800
commit434b33d1b06f39125a2d8fa841b0b7d31d85a687 (patch)
tree4afafcd7f97af428ead6c9d8952feeca4e5c35b7
parentb973ab894c2f2281802c7fd9f1dd055877934c5b (diff)
downloadlibnet-434b33d1b06f39125a2d8fa841b0b7d31d85a687.tar.gz
Support building ICMPv6 packets.
Support for building base ICMPv6 header (type/code), as well as echo requests, neighbour solicitation, and neighbour advertisement.
-rw-r--r--libnet/include/libnet/libnet-functions.h69
-rw-r--r--libnet/include/libnet/libnet-headers.h63
-rw-r--r--libnet/include/libnet/libnet-macros.h2
-rw-r--r--libnet/include/libnet/libnet-structures.h4
-rw-r--r--libnet/src/libnet_build_icmp.c164
5 files changed, 273 insertions, 29 deletions
diff --git a/libnet/include/libnet/libnet-functions.h b/libnet/include/libnet/libnet-functions.h
index 49a968f..f2d4226 100644
--- a/libnet/include/libnet/libnet-functions.h
+++ b/libnet/include/libnet/libnet-functions.h
@@ -777,6 +777,22 @@ libnet_build_icmpv4_timestamp(uint8_t type, uint8_t code, uint16_t sum,
uint16_t id, uint16_t seq, uint32_t otime, uint32_t rtime, uint32_t ttime,
const uint8_t* payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
+/*
+ * Builds an ICMPv6 header
+ * @param type type of ICMPv6 packet
+ * @param code code of ICMP packet
+ * @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
+ * See definitions of types and codes (ICMP6_*) in struct libnet_icmpv6_hdr.
+ * @return protocol tag value on success, -1 on error
+ */
+libnet_ptag_t libnet_build_icmpv6(uint8_t type, uint8_t code, uint16_t sum,
+ 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
@@ -795,6 +811,59 @@ libnet_build_icmpv6_unreach(uint8_t type, uint8_t code, uint16_t sum,
uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
/**
+ * Builds ICMPv6 echo header
+ * @param id echo id number
+ * @param seq echo sequence number
+ * @param data optional payload or NULL
+ * @param datalen 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_echo(uint16_t id, uint16_t seq,
+ uint8_t *data, uint32_t datalen,
+ libnet_t *l, libnet_ptag_t ptag);
+
+/**
+ * Builds ICMPv6 Neighbor Solicitation header
+ * @param tgt target ipv6 address
+ * @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_nsol(struct libnet_in6_addr tgt,
+ libnet_t* l, libnet_ptag_t ptag);
+
+/**
+ * Builds ICMPv6 Neighbor Advertisement header
+ * @param flags neighbor advertisement flags
+ * @param tgt target ipv6 address
+ * @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_nadv(uint32_t flags,
+ struct libnet_in6_addr tgt,
+ libnet_t* l, libnet_ptag_t ptag);
+
+/**
+ * Builds ICMPv6 NDP link-layer address option
+ * @param type address type (ICMPV6_NDPOPT_SLLA for source, ICMPV6_NDPOPT_TLLA for target)
+ * @param len addess length in 8-byte chunks FIXME builder should calculate len if it is zero
+ * @param mac hardware address
+ * @param maclen hardware address length FIXME builder doesn't pad to 8-byte boundaries, if caller doesn't, option is invalid
+ * @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_ndp_lla(uint8_t type, uint8_t len,
+ uint8_t* mac, uint32_t maclen,
+ libnet_t* l, libnet_ptag_t ptag);
+
+/**
* Builds an RFC 1112 Internet Group Memebership Protocol (IGMP) header.
* @param type packet type
* @param reserved (should be 0 for IGMPv1)
diff --git a/libnet/include/libnet/libnet-headers.h b/libnet/include/libnet/libnet-headers.h
index b126e39..2e01541 100644
--- a/libnet/include/libnet/libnet-headers.h
+++ b/libnet/include/libnet/libnet-headers.h
@@ -63,8 +63,11 @@
#define LIBNET_ICMPV4_TIMXCEED_H 0x08 /**< ICMP_TIMXCEED header: 8 bytes */
#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_H 0x04 /**< ICMP6 header base: 4 bytes */
#define LIBNET_ICMPV6_UNREACH_H 0x08 /**< ICMP6 unreach base: 8 bytes */
+#define LIBNET_ICMPV6_ECHO_H 0x04 /**< ICMP6 echo header: 4 bytes */
+#define LIBNET_ICMPV6_NDP_NSA_H 0x14 /**< ICMP6 NDP header: 20 bytes */
+#define LIBNET_ICMPV6_NDP_OPT_H 0x02 /**< ICMP6 ndp options: 2 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 */
@@ -502,6 +505,7 @@ struct libnet_ethernet_hdr
#ifndef ETHERTYPE_IP
#define ETHERTYPE_IP 0x0800 /* IP protocol */
#endif
+#define ETHERTYPE_IPV6 0x86dd /* IPv6 protocol */
#ifndef ETHERTYPE_ARP
#define ETHERTYPE_ARP 0x0806 /* addr. resolution protocol */
#endif
@@ -816,53 +820,56 @@ struct libnet_ipv6_hbhopts_hdr
/*
* ICMP6 header
* Internet Control Message Protocol v6
- * Base header size: 8 bytes
+ * Base header size: 4 bytes
*/
-#ifndef IPPROTO_ICMP6
#define IPPROTO_ICMP6 0x3a
-#endif
struct libnet_icmpv6_hdr
{
uint8_t icmp_type; /* ICMP type */
-#ifndef ICMP6_ECHO
#define ICMP6_ECHO 128
-#endif
-#ifndef ICMP6_ECHOREPLY
#define ICMP6_ECHOREPLY 129
-#endif
-#ifndef ICMP6_UNREACH
+#define ICMP6_ROUTERSOL 133
+#define ICMP6_ROUTERADV 134
+#define ICMP6_NEIGHSOL 135
+#define ICMP6_NEIGHADV 136
+
#define ICMP6_UNREACH 1
-#endif
-#ifndef ICMP6_PKTTOOBIG
#define ICMP6_PKTTOOBIG 2
-#endif
-#ifndef ICMP6_TIMXCEED
#define ICMP6_TIMXCEED 3
-#endif
-#ifndef ICMP6_PARAMPROB
#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 */
};
+/* All of this stuff follows base ICMPv6 header */
+
+struct libnet_icmpv6_echo {
+ uint16_t id;
+ uint16_t seq;
+};
+
+struct libnet_icmpv6_ndp_nsa {
+ uint32_t flags;
+#define NDP_FL_ROUTER (1 << 31)
+#define NDP_FL_SOLICITED (1 << 30)
+#define NDP_FL_OVERRIDE (1 << 29)
+ struct libnet_in6_addr tgt_addr;
+};
+
+struct libnet_icmpv6_ndp_opt {
+ uint8_t type;
+#define ICMPV6_NDPOPT_SLLA 1
+#define ICMPV6_NDPOPT_TLLA 2
+#define ICMPV6_NDPOPT_PREFIX 3
+#define ICMPV6_NDPOPT_REDHDR 4
+#define ICMPV6_NDPOPT_MTU 5
+ uint8_t len;
+};
/*
diff --git a/libnet/include/libnet/libnet-macros.h b/libnet/include/libnet/libnet-macros.h
index afd9029..817a2b1 100644
--- a/libnet/include/libnet/libnet-macros.h
+++ b/libnet/include/libnet/libnet-macros.h
@@ -166,7 +166,7 @@ if (payload_s) \
#ifdef IFF_LOOPBACK
#define LIBNET_ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
#else
-#define LIBNET_ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
+#define LIBNET_ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo") == 0)
#endif
/* advanced mode check */
diff --git a/libnet/include/libnet/libnet-structures.h b/libnet/include/libnet/libnet-structures.h
index 912c321..831999e 100644
--- a/libnet/include/libnet/libnet-structures.h
+++ b/libnet/include/libnet/libnet-structures.h
@@ -160,6 +160,10 @@ struct libnet_protocol_block
#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 */
+#define LIBNET_PBLOCK_ICMPV6_NDNSOL_H 0x43 /* ICMPv6 neighbor solicitation header */
+#define LIBNET_PBLOCK_ICMPV6_NDNADV_H 0x44 /* ICMPv6 neighbor adv header */
+#define LIBNET_PBLOCK_ICMPV6_NDPOPT_H 0x45 /* ICMPv6 NDP option */
+#define LIBNET_PBLOCK_ICMPV6_ECHO_H 0x46 /* ICMPv6 echo header */
uint8_t flags; /* control flags */
#define LIBNET_PBLOCK_DO_CHECKSUM 0x01 /* needs a checksum */
diff --git a/libnet/src/libnet_build_icmp.c b/libnet/src/libnet_build_icmp.c
index d46590f..4034ff9 100644
--- a/libnet/src/libnet_build_icmp.c
+++ b/libnet/src/libnet_build_icmp.c
@@ -404,6 +404,8 @@ uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
libnet_pblock_t *p;
struct libnet_icmpv6_hdr icmp_hdr;
+#if 0
+
if (l == NULL)
{
return (-1);
@@ -434,7 +436,169 @@ uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
LIBNET_PBLOCK_ICMPV6_UNREACH_H));
bad:
libnet_pblock_delete(l, p);
+#endif
return (-1);
}
+libnet_ptag_t libnet_build_icmpv6(uint8_t type, uint8_t code, uint16_t sum,
+ uint8_t* payload, uint32_t payload_s,
+ libnet_t* l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_hdr icmp_hdr;
+ libnet_pblock_t* p;
+ uint32_t n;
+
+ if(l == NULL)
+ return -1;
+
+ n = payload_s + LIBNET_ICMPV6_H;
+
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_H);
+ if(p == NULL)
+ return -1;
+
+ memset(&icmp_hdr, 0, sizeof(icmp_hdr));
+ icmp_hdr.icmp_type = type;
+ icmp_hdr.icmp_code = code;
+ icmp_hdr.icmp_sum = (sum ? htons(sum) : 0);
+
+ LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV6_H);
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_H));
+
+bad:
+ libnet_pblock_delete(l, p);
+ return -1;
+}
+
+libnet_ptag_t libnet_build_icmpv6_echo(uint16_t id, uint16_t seq,
+ uint8_t *data, uint32_t datalen,
+ libnet_t *l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_echo echo;
+ libnet_pblock_t *p;
+ uint32_t n;
+
+ if(l == NULL)
+ return -1;
+
+ n = LIBNET_ICMPV6_ECHO_H;
+
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_ECHO_H);
+ if(p == NULL)
+ return -1;
+
+ memset(&echo, 0, sizeof(echo));
+ echo.id = id;
+ echo.seq = seq;
+ if(libnet_pblock_append(l, p, &echo, n) == -1)
+ goto bad;
+
+ return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_ECHO_H);
+
+bad:
+ libnet_pblock_delete(l, p);
+ return -1;
+}
+
+
+libnet_ptag_t libnet_build_icmpv6_nsol(struct libnet_in6_addr tgt,
+ libnet_t* l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_ndp_nsa na;
+ uint32_t n;
+ libnet_pblock_t* p;
+
+ if(l == NULL)
+ return -1;
+
+ n = LIBNET_ICMPV6_NDP_NSA_H;
+
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDNSOL_H);
+ if(p == NULL)
+ return -1;
+
+ memset(&na, 0, sizeof(na));
+ na.tgt_addr = tgt;
+ if(libnet_pblock_append(l, p, &na, n) == -1)
+ goto bad;
+
+ return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDNSOL_H);
+
+bad:
+ libnet_pblock_delete(l, p);
+ return -1;
+}
+
+
+libnet_ptag_t libnet_build_icmpv6_nadv(uint32_t flags,
+ struct libnet_in6_addr tgt,
+ libnet_t* l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_ndp_nsa na;
+ uint32_t n;
+ libnet_pblock_t* p;
+
+ if(l == NULL)
+ return -1;
+
+ n = LIBNET_ICMPV6_NDP_NSA_H;
+
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDNADV_H);
+ if(p == NULL)
+ return -1;
+
+ memset(&na, 0, sizeof(na));
+ na.flags = htonl(flags);
+ na.tgt_addr = tgt;
+ if(libnet_pblock_append(l, p, &na, n) == -1)
+ goto bad;
+
+ return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDNADV_H);
+
+bad:
+ libnet_pblock_delete(l, p);
+ return -1;
+}
+
+libnet_ptag_t libnet_build_icmpv6_ndp_lla(uint8_t type, uint8_t len,
+ uint8_t* mac, uint32_t maclen,
+ libnet_t* l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_ndp_opt no;
+ uint32_t n;
+ libnet_pblock_t* p;
+
+ if(l == NULL)
+ return -1;
+
+ if(!mac)
+ maclen = 0;
+
+ if(len == 0)
+ len = (LIBNET_PBLOCK_ICMPV6_NDPOPT_H + maclen);
+
+ n = LIBNET_ICMPV6_NDP_OPT_H + maclen;
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDPOPT_H);
+ if(p == NULL)
+ return -1;
+ memset(&no, 0, sizeof(no));
+ no.type = type;
+ no.len = len;
+
+ if(libnet_pblock_append(l, p, &no, LIBNET_ICMPV6_NDP_OPT_H) == -1)
+ goto bad;
+
+ if(mac != NULL) {
+ if(libnet_pblock_append(l, p, mac, maclen) == -1)
+ goto bad;
+ }
+
+ return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDPOPT_H);
+
+bad:
+ libnet_pblock_delete(l, p);
+ return -1;
+}
+
/* EOF */