summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrepolho <repura0@gmail.com>2011-11-09 17:40:45 -0200
committerSam Roberts <vieuxtech@gmail.com>2012-03-05 16:49:56 -0800
commitc91be816ed58d40d8d3f88b6388a21de320bcdb0 (patch)
tree0acf4ec2b34c5962c54a71706c0ddfd17a728c06
parentbdbf78c0d578484b407abcc86ba22808cce2e7d6 (diff)
downloadlibnet-c91be816ed58d40d8d3f88b6388a21de320bcdb0.tar.gz
Implemented libnet_autobuild_ipv6()
-rw-r--r--libnet/include/libnet/libnet-functions.h9
-rw-r--r--libnet/src/libnet_build_ip.c62
2 files changed, 67 insertions, 4 deletions
diff --git a/libnet/include/libnet/libnet-functions.h b/libnet/include/libnet/libnet-functions.h
index 6f98ab0..9de11ef 100644
--- a/libnet/include/libnet/libnet-functions.h
+++ b/libnet/include/libnet/libnet-functions.h
@@ -1036,7 +1036,14 @@ libnet_build_ipv6_hbhopts(uint8_t nh, uint8_t len, const uint8_t* payload,
uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
/**
- * This function is not yet implement and is a NOOP.
+ * Autobuilds a version 6 RFC 2460 Internet Protocol (IP) header. The function
+ * is useful to build an IP header quickly when you do not need a granular
+ * level of control. The function takes the same len, nh, and dst arguments
+ * as libnet_build_ipv4(). The function does not accept a ptag argument, but it
+ * does return a ptag. In other words, you can use it to build a new IP header
+ * but not to modify an existing one.
+ * This function requires libnet_get_ipaddr6(), which is not yet implemented
+ * for Win32 platforms.
* @param len length
* @param nh next header
* @param dst destination IPv6 address
diff --git a/libnet/src/libnet_build_ip.c b/libnet/src/libnet_build_ip.c
index 340ab7e..1ecbc76 100644
--- a/libnet/src/libnet_build_ip.c
+++ b/libnet/src/libnet_build_ip.c
@@ -749,10 +749,66 @@ libnet_ptag_t
libnet_autobuild_ipv6(uint16_t len, uint8_t nh, struct libnet_in6_addr dst,
libnet_t *l, libnet_ptag_t ptag)
{
+ int libnet_in6_addr_cmp(struct libnet_in6_addr addr1, struct libnet_in6_addr addr2) {
+ /* Returns != 0 if addresses are equal, 0 otherwise. */
+ uint32_t *p1 = (uint32_t*)&addr1.__u6_addr, *p2 = (uint32_t*)&addr2.__u6_addr;
+ return ((p1[0] == p2[0]) && (p1[1] == p2[1]) && (p1[2] == p2[2]) &&
+ (p1[3] == p2[3]));
+ }
+
+ uint32_t n;
+ libnet_pblock_t *p;
+ struct libnet_ipv6_hdr ip_hdr;
+ struct libnet_in6_addr src;
+
+ if (l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_IPV6_H; /* 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_IPV6_H);
+ if (p == NULL)
+ {
+ return (-1);
+ }
+
+ src = libnet_get_ipaddr6(l);
+ if (libnet_in6_addr_cmp(src, in6addr_error))
+ {
+ /* err msg set in libnet_get_ipaddr6() */
+ return (-1);
+ }
+
+ memset(&ip_hdr, 0, sizeof(ip_hdr));
+ ip_hdr.ip_flags[0] = 0x06 << 4; /* ip version */
+ ip_hdr.ip_flags[1] = 0;
+ ip_hdr.ip_flags[2] = 0;
+ ip_hdr.ip_flags[3] = 0;
+ ip_hdr.ip_len = htons(len);
+ ip_hdr.ip_nh = nh;
+ ip_hdr.ip_hl = 64;
+ ip_hdr.ip_src = src;
+ ip_hdr.ip_dst = dst;
+
+ n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV6_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
- /* NYI */
- snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
- "%s(): not yet implemented\n", __func__);
+ /* no checksum for IPv6 */
+ ptag = ptag ? ptag : libnet_pblock_update(l, p, LIBNET_IPV6_H,
+ LIBNET_PBLOCK_IPV6_H);
+
+ return ptag;
+
+bad:
+ libnet_pblock_delete(l, p);
return (-1);
}