diff options
author | Sam Roberts <vieuxtech@gmail.com> | 2011-11-20 13:23:15 +0000 |
---|---|---|
committer | Sam Roberts <vieuxtech@gmail.com> | 2012-03-05 13:32:22 -0800 |
commit | 29e72f7ad1ecf82a8fb5c33786dfe6b4cad4ac9b (patch) | |
tree | cf25322e3aee3aa86e1edabb25f5f1bb33bae8b1 | |
parent | 508502b8eef27ca194e57f6144d9ad43809154a9 (diff) | |
download | libnet-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.h | 89 | ||||
-rw-r--r-- | libnet/include/libnet/libnet-headers.h | 129 | ||||
-rw-r--r-- | libnet/include/libnet/libnet-structures.h | 10 | ||||
-rw-r--r-- | libnet/src/libnet_build_icmp.c | 266 | ||||
-rw-r--r-- | libnet/src/libnet_internal.c | 6 | ||||
-rw-r--r-- | libnet/src/libnet_pblock.c | 10 |
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); |