summaryrefslogtreecommitdiff
path: root/libnet/src/libnet_build_icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnet/src/libnet_build_icmp.c')
-rw-r--r--libnet/src/libnet_build_icmp.c266
1 files changed, 135 insertions, 131 deletions
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 */