summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2011-11-20 13:23:15 +0000
committerSam Roberts <vieuxtech@gmail.com>2012-03-05 13:32:22 -0800
commit29e72f7ad1ecf82a8fb5c33786dfe6b4cad4ac9b (patch)
treecf25322e3aee3aa86e1edabb25f5f1bb33bae8b1
parent508502b8eef27ca194e57f6144d9ad43809154a9 (diff)
downloadlibnet-29e72f7ad1ecf82a8fb5c33786dfe6b4cad4ac9b.tar.gz
Reworked icmpv6 patch to parallel the form of icmpv4 support.
Use same calling sequences, identifier names modelled on <netinet/icmp6.h>, etc.
-rw-r--r--libnet/include/libnet/libnet-functions.h89
-rw-r--r--libnet/include/libnet/libnet-headers.h129
-rw-r--r--libnet/include/libnet/libnet-structures.h10
-rw-r--r--libnet/src/libnet_build_icmp.c266
-rw-r--r--libnet/src/libnet_internal.c6
-rw-r--r--libnet/src/libnet_pblock.c10
6 files changed, 306 insertions, 204 deletions
diff --git a/libnet/include/libnet/libnet-functions.h b/libnet/include/libnet/libnet-functions.h
index f2d4226..4d9c057 100644
--- a/libnet/include/libnet/libnet-functions.h
+++ b/libnet/include/libnet/libnet-functions.h
@@ -777,28 +777,29 @@ 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)
+/**
+ * Builds an IP version 6 RFC 4443 Internet Control Message Protocol (ICMP)
+ * echo or echo reply header.
+ * @param type type of ICMP packet (should be ICMP6_ECHO_REQUEST or ICMP6_ECHO_REPLY)
+ * @param code code of ICMP packet (should be zero)
+ * @param id echo id number
+ * @param seq echo sequence number
* @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);
+libnet_ptag_t libnet_build_icmpv6_echo(uint8_t type, uint8_t code, uint16_t
+ sum, uint16_t id, uint16_t seq, 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 type type of ICMP packet (should be ICMP6_DST_UNREACH)
+ * @param code code of ICMP packet (should be one of the 5 ICMP6_DST_UNREACH_* codes)
* @param sum checksum (0 for libnet to autofill)
* @param payload optional payload or NULL
* @param payload_s payload length or 0
@@ -811,57 +812,53 @@ 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
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * NDP neighbour solicitation header. Could be used with
+ * libnet_build_icmpv6_ndp_opt() and ICMPV6_NDP_OPT_SLLA.
+ * @param type type of ICMP packet (should be ND_NEIGHBOR_SOLICIT)
+ * @param code code of ICMP packet (should be zero)
+ * @param sum checksum (0 for libnet to autofill)
+ * @param target target ipv6 address
+ * @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_nsol(struct libnet_in6_addr tgt,
- libnet_t* l, libnet_ptag_t ptag);
+libnet_ptag_t libnet_build_icmpv6_ndp_nsol(uint8_t type, uint8_t code,
+ uint16_t sum, struct libnet_in6_addr target, uint8_t *payload, uint32_t
+ payload_s, libnet_t* l, libnet_ptag_t ptag);
/**
- * Builds ICMPv6 Neighbor Advertisement header
- * @param flags neighbor advertisement flags
- * @param tgt target ipv6 address
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * NDP neighbour advertisement header. Could be used with
+ * libnet_build_icmpv6_ndp_opt() and ND_OPT_TARGET_LINKADDR.
+ * @param type type of ICMP packet (should be ND_NEIGHBOR_ADVERT)
+ * @param code code of ICMP packet (should be zero)
+ * @param sum checksum (0 for libnet to autofill)
+ * @param flags should be a bitwise or of any applicable ND_NA_FLAG_* flags
+ * @param target target ipv6 address
+ * @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_nadv(uint32_t flags,
- struct libnet_in6_addr tgt,
- libnet_t* l, libnet_ptag_t ptag);
+libnet_ptag_t libnet_build_icmpv6_ndp_nadv(uint8_t type, uint8_t code,
+ uint16_t sum, uint32_t flags, struct libnet_in6_addr target, uint8_t
+ *payload, uint32_t payload_s, 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
+ * Builds ICMPv6 NDP options.
+ * @param type one of ND_OPT_* types
+ * @param option option data
+ * @param option_s size of option data (will be padded out to an 8-byte boundary)
* @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);
+libnet_ptag_t libnet_build_icmpv6_ndp_opt(uint8_t type, uint8_t* option,
+ uint32_t option_s, libnet_t* l, libnet_ptag_t ptag);
/**
* Builds an RFC 1112 Internet Group Memebership Protocol (IGMP) header.
diff --git a/libnet/include/libnet/libnet-headers.h b/libnet/include/libnet/libnet-headers.h
index 2e01541..3b908d7 100644
--- a/libnet/include/libnet/libnet-headers.h
+++ b/libnet/include/libnet/libnet-headers.h
@@ -63,11 +63,9 @@
#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 0x04 /**< ICMP6 header base: 4 bytes */
+#define LIBNET_ICMPV6_COMMON_H 0x04 /**< ICMP6 header base: 4 bytes */
+#define LIBNET_ICMPV6_H 0x08 /**< ICMP6 header base: 8 bytes (unused, for backwards compatibility) */
#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 */
@@ -822,52 +820,139 @@ struct libnet_ipv6_hbhopts_hdr
* Internet Control Message Protocol v6
* Base header size: 4 bytes
*/
-#define IPPROTO_ICMP6 0x3a
+#ifndef IPPROTO_ICMPV6
+#define IPPROTO_ICMPV6 58
+#endif
struct libnet_icmpv6_hdr
{
uint8_t icmp_type; /* ICMP type */
+/* Don't define if <netinet/icmp6.h> has defined them. */
+#ifndef ICMP6_ECHO_REQUEST
+#define ICMP6_ECHO_REQUEST 128
+#endif
+#ifndef ICMP6_ECHO_REPLY
+#define ICMP6_ECHO_REPLY 129
+#endif
+#ifndef ICMP6_DST_UNREACH
+#define ICMP6_DST_UNREACH 1
+#endif
+#ifndef ICMP6_PACKET_TOO_BIG
+#define ICMP6_PACKET_TOO_BIG 2
+#endif
+#ifndef ICMP6_TIME_EXCEEDED
+#define ICMP6_TIME_EXCEEDED 3
+#endif
+#ifndef ICMP6_PARAM_PROB
+#define ICMP6_PARAM_PROB 4
+#endif
+
+#ifndef ND_ROUTER_SOLICIT
+#define ND_ROUTER_SOLICIT 133
+#endif
+#ifndef ND_ROUTER_ADVERT
+#define ND_ROUTER_ADVERT 134
+#endif
+#ifndef ND_NEIGHBOR_SOLICIT
+#define ND_NEIGHBOR_SOLICIT 135
+#endif
+#ifndef ND_NEIGHBOR_ADVERT
+#define ND_NEIGHBOR_ADVERT 136
+#endif
+
+ uint8_t icmp_code; /* ICMP code */
+#ifndef ICMP6_DST_UNREACH_NOROUTE
+#define ICMP6_DST_UNREACH_NOROUTE 0
+#endif
+#ifndef ICMP6_DST_UNREACH_ADMIN
+#define ICMP6_DST_UNREACH_ADMIN 1
+#endif
+#ifndef ICMP6_DST_UNREACH_BEYONDSCOPE
+#define ICMP6_DST_UNREACH_BEYONDSCOPE 2
+#endif
+#ifndef ICMP6_DST_UNREACH_ADDR
+#define ICMP6_DST_UNREACH_ADDR 3
+#endif
+#ifndef ICMP6_DST_UNREACH_NOPORT
+#define ICMP6_DST_UNREACH_NOPORT 4
+#endif
+ uint16_t icmp_sum; /* ICMP Checksum */
+
+ /* This is confusing: id/seq are used only for echo req/reply, but must
+ * exist in struct for backwards compatibility. */
+ uint16_t id; /* ICMP id (unused, for backwards compatibility) */
+ uint16_t seq; /* ICMP sequence number (unused, for backwards compatibility) */
+
+ /* Non-standard names, for libnet backwards compatibility, don't use. */
+ /* ipproto: */
+#define IPPROTO_ICMP6 58
+ /* types: */
#define ICMP6_ECHO 128
#define ICMP6_ECHOREPLY 129
-#define ICMP6_ROUTERSOL 133
-#define ICMP6_ROUTERADV 134
-#define ICMP6_NEIGHSOL 135
-#define ICMP6_NEIGHADV 136
-
#define ICMP6_UNREACH 1
#define ICMP6_PKTTOOBIG 2
#define ICMP6_TIMXCEED 3
#define ICMP6_PARAMPROB 4
- uint8_t icmp_code; /* ICMP code */
+ /* codes: */
#define ICMP6_NOROUTE 0
#define ICMP6_ADM_PROHIBITED 1
#define ICMP6_NOT_NEIGHBOUR 2
#define ICMP6_ADDR_UNREACH 3
#define ICMP6_PORT_UNREACH 4
- uint16_t icmp_sum; /* ICMP Checksum */
};
/* All of this stuff follows base ICMPv6 header */
+struct libnet_icmpv6_unreach {
+ uint32_t unused;
+};
+
struct libnet_icmpv6_echo {
uint16_t id;
uint16_t seq;
};
-struct libnet_icmpv6_ndp_nsa {
+struct libnet_icmpv6_ndp_nsol {
+ uint32_t reserved;
+ struct libnet_in6_addr target_addr;
+};
+
+struct libnet_icmpv6_ndp_nadv {
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;
+#ifndef ND_NA_FLAG_ROUTER
+#define ND_NA_FLAG_ROUTER 0x80000000
+#endif
+#ifndef ND_NA_FLAG_SOLICITED
+#define ND_NA_FLAG_SOLICITED 0x40000000
+#endif
+#ifndef ND_NA_FLAG_OVERRIDE
+#define ND_NA_FLAG_OVERRIDE 0x20000000
+#endif
+ struct libnet_in6_addr target_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
+#ifndef ND_OPT_SOURCE_LINKADDR
+#define ND_OPT_SOURCE_LINKADDR 1
+#endif
+#ifndef ND_OPT_TARGET_LINKADDR
+#define ND_OPT_TARGET_LINKADDR 2
+#endif
+#ifndef ND_OPT_PREFIX_INFORMATION
+#define ND_OPT_PREFIX_INFORMATION 3
+#endif
+#ifndef ND_OPT_REDIRECTED_HEADER
+#define ND_OPT_REDIRECTED_HEADER 4
+#endif
+#ifndef ND_OPT_MTU
+#define ND_OPT_MTU 5
+#endif
+#ifndef ND_OPT_RTR_ADV_INTERVAL
+#define ND_OPT_RTR_ADV_INTERVAL 7
+#endif
+#ifndef ND_OPT_HOME_AGENT_INFO
+#define ND_OPT_HOME_AGENT_INFO 8
+#endif
uint8_t len;
};
diff --git a/libnet/include/libnet/libnet-structures.h b/libnet/include/libnet/libnet-structures.h
index 831999e..bd7b55b 100644
--- a/libnet/include/libnet/libnet-structures.h
+++ b/libnet/include/libnet/libnet-structures.h
@@ -158,12 +158,12 @@ 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 */
-#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_H 0x41 /* ICMPv6 header (unused) */
#define LIBNET_PBLOCK_ICMPV6_ECHO_H 0x46 /* ICMPv6 echo header */
+#define LIBNET_PBLOCK_ICMPV6_UNREACH_H 0x42 /* ICMPv6 unreach header */
+#define LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H 0x43 /* ICMPv6 NDP neighbor solicitation header */
+#define LIBNET_PBLOCK_ICMPV6_NDP_NADV_H 0x44 /* ICMPv6 NDP neighbor advertisement header */
+#define LIBNET_PBLOCK_ICMPV6_NDP_OPT_H 0x45 /* ICMPv6 NDP option */
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 4034ff9..e9590d3 100644
--- a/libnet/src/libnet_build_icmp.c
+++ b/libnet/src/libnet_build_icmp.c
@@ -39,6 +39,8 @@
#include "../include/win32/libnet.h"
#endif
+#include <assert.h>
+
/* some common cruft for completing ICMP error packets */
#define LIBNET_BUILD_ICMP_ERR_FINISH(len) \
do \
@@ -397,208 +399,210 @@ bad:
libnet_ptag_t
-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)
+libnet_build_icmpv6_common(
+ uint8_t type, uint8_t code, uint16_t sum,
+ const void* specific, uint32_t specific_s, uint8_t pblock_type,
+ uint8_t *payload, uint32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag
+ )
{
uint32_t n;
libnet_pblock_t *p;
struct libnet_icmpv6_hdr icmp_hdr;
-#if 0
-
if (l == NULL)
{
return (-1);
}
- n = LIBNET_ICMPV6_UNREACH_H + payload_s; /* size of memory block */
+ n = sizeof(icmp_hdr) + specific_s + payload_s;
+
+ p = libnet_pblock_probe(l, ptag, n, pblock_type);
- /*
- * 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 */
+ icmp_hdr.icmp_type = type;
+ icmp_hdr.icmp_code = code;
+ icmp_hdr.icmp_sum = htons(sum);
+
+ if (libnet_pblock_append(l, p, (uint8_t *)&icmp_hdr, LIBNET_ICMPV6_COMMON_H) < 0)
+ {
+ goto bad;
+ }
+
+ if (libnet_pblock_append(l, p, specific, specific_s) < 0)
+ {
+ goto bad;
+ }
+
+ if (libnet_pblock_append(l, p, payload, payload_s) < 0)
+ {
+ goto bad;
+ }
+
+ if (sum == 0)
+ {
+ libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
+ }
- LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV6_UNREACH_H);
+ return ptag ? ptag : libnet_pblock_update(l, p, 0, pblock_type);
- return (ptag ? ptag : libnet_pblock_update(l, p, 0,
- LIBNET_PBLOCK_ICMPV6_UNREACH_H));
bad:
libnet_pblock_delete(l, p);
-#endif
- return (-1);
+
+ 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);
+ return libnet_build_icmpv6_common(
+ type, code, sum,
+ NULL, 0, LIBNET_PBLOCK_ICMPV6_UNREACH_H,
+ payload, payload_s,
+ l, ptag);
+}
- LIBNET_BUILD_ICMP_ERR_FINISH(LIBNET_ICMPV6_H);
+libnet_ptag_t
+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
+ )
+{
+ struct libnet_icmpv6_unreach specific;
- return (ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_H));
+ memset(&specific, 0, sizeof(specific));
-bad:
- libnet_pblock_delete(l, p);
- return -1;
+ return libnet_build_icmpv6_common(
+ type, code, sum,
+ &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_UNREACH_H,
+ payload, payload_s,
+ l, ptag);
}
-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)
+libnet_ptag_t
+libnet_build_icmpv6_echo(
+ uint8_t type, uint8_t code, uint16_t sum,
+ uint16_t id, uint16_t seq,
+ uint8_t *payload, uint32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag
+ )
{
- struct libnet_icmpv6_echo echo;
- libnet_pblock_t *p;
- uint32_t n;
+ struct libnet_icmpv6_echo specific;
- if(l == NULL)
- return -1;
+ memset(&specific, 0, sizeof(specific));
+ specific.id = htons(id);
+ specific.seq = htons(seq);
- n = LIBNET_ICMPV6_ECHO_H;
+ return libnet_build_icmpv6_common(
+ type, code, sum,
+ &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_ECHO_H,
+ payload, payload_s,
+ l, ptag);
+}
- 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;
+libnet_ptag_t libnet_build_icmpv6_ndp_nsol(
+ uint8_t type, uint8_t code, uint16_t sum,
+ struct libnet_in6_addr target,
+ uint8_t *payload, uint32_t payload_s,
+ libnet_t* l, libnet_ptag_t ptag)
+{
+ struct libnet_icmpv6_ndp_nsol specific;
- return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_ECHO_H);
+ memset(&specific, 0, sizeof(specific));
+ specific.reserved = 0;
+ specific.target_addr = target;
-bad:
- libnet_pblock_delete(l, p);
- return -1;
+ return libnet_build_icmpv6_common(
+ type, code, sum,
+ &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H,
+ payload, payload_s,
+ l, ptag);
}
-libnet_ptag_t libnet_build_icmpv6_nsol(struct libnet_in6_addr tgt,
- libnet_t* l, libnet_ptag_t ptag)
+libnet_ptag_t libnet_build_icmpv6_ndp_nadv(
+ uint8_t type, uint8_t code, uint16_t sum,
+ uint32_t flags, struct libnet_in6_addr target,
+ uint8_t *payload, uint32_t payload_s,
+ 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;
+ struct libnet_icmpv6_ndp_nadv specific;
- n = LIBNET_ICMPV6_NDP_NSA_H;
+ memset(&specific, 0, sizeof(specific));
+ specific.flags = htonl(flags);
+ specific.target_addr = target;
- 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;
+ return libnet_build_icmpv6_common(
+ type, code, sum,
+ &specific, sizeof(specific), LIBNET_PBLOCK_ICMPV6_NDP_NADV_H,
+ payload, payload_s,
+ l, ptag);
}
-
-libnet_ptag_t libnet_build_icmpv6_nadv(uint32_t flags,
- struct libnet_in6_addr tgt,
- libnet_t* l, libnet_ptag_t ptag)
+libnet_ptag_t libnet_build_icmpv6_ndp_opt(
+ uint8_t type, uint8_t* option, uint32_t option_s,
+ libnet_t* l, libnet_ptag_t ptag)
{
- struct libnet_icmpv6_ndp_nsa na;
+ struct libnet_icmpv6_ndp_opt opt;
uint32_t n;
+ static uint8_t pad[8] = { 0 };
+ uint32_t pad_s = 0;
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;
+ if(!option)
+ option_s = 0;
- return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDNADV_H);
+ /* options need to be padded to a multiple of 8-bytes, and opts.len is in units of 8-bytes */
+ n = sizeof(opt) + option_s;
-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(n % 8)
+ {
+ n += 8 - (n % 8);
+ }
- if(l == NULL)
+ if(n > (0xff * 8))
+ {
return -1;
+ }
- if(!mac)
- maclen = 0;
+ pad_s = n - option_s - sizeof(opt);
- if(len == 0)
- len = (LIBNET_PBLOCK_ICMPV6_NDPOPT_H + maclen);
+ assert((n % 8) == 0);
+ assert(pad_s < sizeof(pad));
- n = LIBNET_ICMPV6_NDP_OPT_H + maclen;
- p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDPOPT_H);
+ p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_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)
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type;
+ opt.len = n / 8;
+
+ if(libnet_pblock_append(l, p, &opt, sizeof(opt)) == -1)
goto bad;
- if(mac != NULL) {
- if(libnet_pblock_append(l, p, mac, maclen) == -1)
- goto bad;
- }
+ if(libnet_pblock_append(l, p, option, option_s) == -1)
+ goto bad;
+
+ if(libnet_pblock_append(l, p, pad, pad_s) == -1)
+ goto bad;
- return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDPOPT_H);
+ return ptag ? ptag : libnet_pblock_update(l, p, n, LIBNET_PBLOCK_ICMPV6_NDP_OPT_H);
bad:
libnet_pblock_delete(l, p);
return -1;
}
-/* EOF */
diff --git a/libnet/src/libnet_internal.c b/libnet/src/libnet_internal.c
index fc481ce..1998149 100644
--- a/libnet/src/libnet_internal.c
+++ b/libnet/src/libnet_internal.c
@@ -307,6 +307,12 @@ libnet_diag_dump_pblock_type(uint8_t type)
return ("icmpv6");
case LIBNET_PBLOCK_ICMPV6_UNREACH_H:
return ("icmpv6_unreach");
+ case LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H:
+ return ("icmpv6_ndp_nsol");
+ case LIBNET_PBLOCK_ICMPV6_NDP_NADV_H:
+ return ("icmpv6_ndp_nadv");
+ case LIBNET_PBLOCK_ICMPV6_NDP_OPT_H:
+ return ("icmpv6_ndp_opt");
}
return ("unrecognized pblock");
}
diff --git a/libnet/src/libnet_pblock.c b/libnet/src/libnet_pblock.c
index 1e2f62a..3b86101 100644
--- a/libnet/src/libnet_pblock.c
+++ b/libnet/src/libnet_pblock.c
@@ -268,6 +268,13 @@ libnet_pblock_find(libnet_t *l, libnet_ptag_t ptag)
int
libnet_pblock_append(libnet_t *l, libnet_pblock_t *p, const void *buf, uint32_t len)
{
+ if (len && !buf)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ return -1;
+ }
+
if (p->copied + len > p->b_len)
{
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
@@ -575,7 +582,10 @@ libnet_pblock_p2p(uint8_t type)
case LIBNET_PBLOCK_ICMPV4_TS_H:
return (IPPROTO_ICMP);
case LIBNET_PBLOCK_ICMPV6_H:
+ case LIBNET_PBLOCK_ICMPV6_ECHO_H:
case LIBNET_PBLOCK_ICMPV6_UNREACH_H:
+ case LIBNET_PBLOCK_ICMPV6_NDP_NSOL_H:
+ case LIBNET_PBLOCK_ICMPV6_NDP_NADV_H:
return (IPPROTO_ICMPV6);
case LIBNET_PBLOCK_IGMP_H:
return (IPPROTO_IGMP);