PERFORCE change 100526 for review
Clément Lecigne
clem1 at FreeBSD.org
Mon Jul 3 21:11:02 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=100526
Change 100526 by clem1 at clem1_ipv6vulns on 2006/07/03 21:10:22
ICMPv6 option support in libnet.
Affected files ...
.. //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-functions.h#6 edit
.. //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-headers.h#5 edit
.. //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-structures.h#4 edit
.. //depot/projects/soc2006/clem1_ipv6vulns/libnet/src/libnet_build_icmpv6.c#3 edit
Differences ...
==== //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-functions.h#6 (text+ko) ====
@@ -999,6 +999,100 @@
u_int32_t unused, struct libnet_in6_addr, struct libnet_in6_addr,
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag);
+/**
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * target link layer option header
+ * @param type of ICMP option packet (should be ICMP6_OPT_TLLA)
+ * @param code of ICMP option packet (should be 0)
+ * @param target mac 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_opt_tlla(u_int8_t type, u_int8_t length,
+ u_int8_t *target, u_int8_t *payload, u_int32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag);
+
+/**
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * source link layer option header
+ * @param type of ICMP option packet (should be ICMP6_OPT_SLLA)
+ * @param len of ICMP option packet
+ * @param source mac 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_opt_slla(u_int8_t type, u_int8_t length,
+ u_int8_t *source, u_int8_t *payload, u_int32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag);
+
+/**
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * prefix information option header
+ * @param type of ICMP option packet (should be ICMP6_OPT_PI)
+ * @param len of ICMP option packet
+ * @param prefix len
+ * @param on link flag
+ * @param autonomous addr configuration flag
+ * @param valid lifetime
+ * @param preferred lifetime
+ * @param reserved
+ * @param ip6 prefix
+ * @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_opt_pi(u_int8_t type, u_int8_t length, u_int8_t prefixlen,
+ u_int8_t ol, u_int8_t a, u_int32_t validlt, u_int32_t preferredlt,
+ u_int32_t reserved, struct libnet_in6_addr prefix,
+ u_int32_t payload_s, u_int8_t *payload, libnet_t *l,
+ libnet_ptag_t ptag);
+
+/**
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * redirected option header
+ * @param type of ICMP option packet (should be ICMP6_OPT_RH)
+ * @param len of ICMP option packet
+ * @param reserved
+ * @param reserved
+ * @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_opt_rh(u_int8_t type, u_int8_t length, u_int16_t r1,
+ u_int32_t r2, u_int32_t payload_s, u_int8_t *payload, libnet_t *l,
+ libnet_ptag_t ptag);
+
+/**
+ * Builds an IP version 6 RFC 2461 Internet Control Message Protocol (ICMP)
+ * MTU option header
+ * @param type of ICMP option packet (should be ICMP6_OPT_RH)
+ * @param len of ICMP option packet
+ * @param reserved
+ * @param MTU
+ * @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_opt_mtu(u_int8_t type, u_int8_t length, u_int16_t r,
+ u_int32_t mtu, u_int32_t payload_s, u_int8_t *payload, libnet_t *l,
+ libnet_ptag_t ptag);
/**
* Builds an RFC 1112 Internet Group Memebership Protocol (IGMP) header.
==== //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-headers.h#5 (text+ko) ====
@@ -75,6 +75,11 @@
#define LIBNET_ICMPV6_RA_H 0x10 /**< ICMPV6_RA header: 16 bytes */
#define LIBNET_ICMPV6_NS_H 0x18 /**< ICMPV6_NS header: 24 bytes */
#define LIBNET_ICMPV6_NA_H 0x18 /**< ICMPV6_NA header: 24 bytes */
+#define LIBNET_ICMPV6_OPT_SLLA_H 0x08 /**< ICMPV6_LLLA header: 8 bytes */
+#define LIBNET_ICMPV6_OPT_TLLA_H 0x08 /**< ICMPV6_TLLA header: 8 bytes */
+#define LIBNET_ICMPV6_OPT_PI_H 0x20 /**< ICMPV6_PI header: 32 bytes */
+#define LIBNET_ICMPV6_OPT_MTU_H 0x08 /**< ICMPV6_MTU header: 8 bytes */
+#define LIBNET_ICMPV6_OPT_RH_H 0x08 /**< ICMPV6_RH header: 8 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 */
@@ -967,7 +972,7 @@
#undef icmp_maxdelay
#undef icmp_reserved2
#define icmp_maxdelay hun.mld.maxdelay
-#define icmp_reserved hun.mld.reserved2
+#define icmp_reserved2 hun.mld.reserved2
u_int32_t pointer; /* ICMP pointer */
#undef icmp_pointer
#define icmp_pointer hun.pointer
@@ -1015,8 +1020,74 @@
}qun;
};
+/*
+ * ICMPV6 link-layer address option header
+ * Base header size: 8 bytes
+ */
+struct libnet_icmpv6_opt_lla_hdr
+{
+ u_int8_t type; /* ICMP opt type */
+#ifndef ICMP6_OPT_SLLA
+#define ICMP6_OPT_SLLA 1
+#endif
+#ifndef ICMP6_OPT_TLLA
+#define ICMP6_OPT_TLLA 2
+#endif
+ u_int8_t len; /* ICMP opt header len */
+ int8_t addr[6];
+};
/*
+ * ICMPV6 prefix information option header
+ * Header size: 32 bytes
+ */
+struct libnet_icmpv6_opt_pi_hdr
+{
+ u_int8_t type; /* ICMP opt type */
+#ifndef ICMP6_OPT_PI
+#define ICMP6_OPT_PI 3
+#endif
+ u_int8_t len;
+ u_int8_t prefixlen;
+ u_int8_t la;
+ u_int32_t validlt;
+ u_int32_t preferredlt;
+ u_int32_t reserved;
+ struct libnet_in6_addr prefix;
+};
+
+/*
+ * ICMPV6 redirect option header
+ * Header size: 8 bytes
+ */
+struct libnet_icmpv6_opt_rh_hdr
+{
+ u_int8_t type;
+#ifndef ICMP6_OPT_RH
+#define ICMP6_OPT_RH 4
+#endif
+ u_int8_t len;
+ u_int16_t reserved1;
+ u_int32_t reserved2;
+};
+
+/*
+ * ICMPV6 MTU option header
+ * Header size: 8 bytes
+ */
+struct libnet_icmpv6_opt_mtu_hdr
+{
+ u_int8_t type;
+#ifndef ICMP6_OPT_MTU
+#define ICMP6_OPT_MTU 5
+#endif
+ u_int8_t len;
+ u_int16_t reserved;
+ u_int32_t mtu;
+};
+
+
+/*
* ICMP header
* Internet Control Message Protocol
* Base header size: 4 bytes
==== //depot/projects/soc2006/clem1_ipv6vulns/libnet/include/libnet/libnet-structures.h#4 (text+ko) ====
@@ -159,6 +159,11 @@
#define LIBNET_PBLOCK_ICMPV6_MULTICAST_H 0x4a /* ICMP6 multicast group management header */
#define LIBNET_PBLOCK_ICMPV6_NI_H 0x4b /* ICMP6 node information header */
#define LIBNET_PBLOCK_ICMPV6_UNREACH_H 0x4c /* ICMP6 destination unreach packet */
+#define LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H 0x4d /* ICMP6 option target link layer header */
+#define LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H 0x4e /* ICMP6 option source link layer header */
+#define LIBNET_PBLOCK_ICMPV6_OPT_PI_H 0x4f /* ICMP6 option prefix information header */
+#define LIBNET_PBLOCK_ICMPV6_OPT_RH_H 0x50 /* ICMP6 option redirect header */
+#define LIBNET_PBLOCK_ICMPV6_OPT_MTU_H 0x51 /* ICMP6 option MTU header */
u_int8_t flags; /* control flags */
#define LIBNET_PBLOCK_DO_CHECKSUM 0x01 /* needs a checksum */
libnet_ptag_t ptag; /* protocol block tag */
==== //depot/projects/soc2006/clem1_ipv6vulns/libnet/src/libnet_build_icmpv6.c#3 (text+ko) ====
@@ -461,6 +461,31 @@
}
}
+ /*
+ * Some shits around icmpv6 option and related to checksumming
+ */
+ if (p->prev && sum == 0)
+ {
+ switch(p->prev->type)
+ {
+ case LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H:
+ case LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H:
+ h += LIBNET_ICMPV6_OPT_TLLA_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_PI_H:
+ h += LIBNET_ICMPV6_OPT_PI_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_RH_H:
+ h += LIBNET_ICMPV6_OPT_RH_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_MTU_H:
+ h += LIBNET_ICMPV6_OPT_MTU_H;
+ break;
+ default:
+ break;
+ }
+ }
+
if (sum == 0)
{
/*
@@ -613,6 +638,31 @@
}
}
+ /*
+ * Some shits around icmpv6 option and related to checksumming
+ */
+ if (p->prev && sum == 0)
+ {
+ switch(p->prev->type)
+ {
+ case LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H:
+ case LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H:
+ h += LIBNET_ICMPV6_OPT_TLLA_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_PI_H:
+ h += LIBNET_ICMPV6_OPT_PI_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_RH_H:
+ h += LIBNET_ICMPV6_OPT_RH_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_MTU_H:
+ h += LIBNET_ICMPV6_OPT_MTU_H;
+ break;
+ default:
+ break;
+ }
+ }
+
if (sum == 0)
{
/*
@@ -685,6 +735,31 @@
}
}
+ /*
+ * Some shits around icmpv6 option and related to checksumming
+ */
+ if (p->prev && sum == 0)
+ {
+ switch(p->prev->type)
+ {
+ case LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H:
+ case LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H:
+ h += LIBNET_ICMPV6_OPT_TLLA_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_PI_H:
+ h += LIBNET_ICMPV6_OPT_PI_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_RH_H:
+ h += LIBNET_ICMPV6_OPT_RH_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_MTU_H:
+ h += LIBNET_ICMPV6_OPT_MTU_H;
+ break;
+ default:
+ break;
+ }
+ }
+
if (sum == 0)
{
/*
@@ -764,6 +839,31 @@
}
}
+ /*
+ * Some shits around icmpv6 option and related to checksumming
+ */
+ if (p->prev && sum == 0)
+ {
+ switch(p->prev->type)
+ {
+ case LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H:
+ case LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H:
+ h += LIBNET_ICMPV6_OPT_TLLA_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_PI_H:
+ h += LIBNET_ICMPV6_OPT_PI_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_RH_H:
+ h += LIBNET_ICMPV6_OPT_RH_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_MTU_H:
+ h += LIBNET_ICMPV6_OPT_MTU_H;
+ break;
+ default:
+ break;
+ }
+ }
+
if (sum == 0)
{
/*
@@ -844,6 +944,31 @@
}
}
+ /*
+ * Some shits around icmpv6 option and related to checksumming
+ */
+ if (p->prev && sum == 0)
+ {
+ switch(p->prev->type)
+ {
+ case LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H:
+ case LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H:
+ h += LIBNET_ICMPV6_OPT_TLLA_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_PI_H:
+ h += LIBNET_ICMPV6_OPT_PI_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_RH_H:
+ h += LIBNET_ICMPV6_OPT_RH_H;
+ break;
+ case LIBNET_PBLOCK_ICMPV6_OPT_MTU_H:
+ h += LIBNET_ICMPV6_OPT_MTU_H;
+ break;
+ default:
+ break;
+ }
+ }
+
if (sum == 0)
{
/*
@@ -860,3 +985,322 @@
return (-1);
}
+libnet_ptag_t
+libnet_build_icmpv6_opt_tlla(u_int8_t type, u_int8_t length,
+ u_int8_t *target, u_int8_t *payload, u_int32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag)
+{
+ u_int32_t n, h, i;
+ libnet_pblock_t *p;
+ struct libnet_icmpv6_opt_lla_hdr opt;
+
+ if(l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_ICMPV6_OPT_TLLA_H + payload_s; /* size of memory block */
+ h = LIBNET_ICMPV6_OPT_TLLA_H + payload_s; /* hl for checksum */
+
+ /*
+ * 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_OPT_TLLA_H);
+ if(p == NULL)
+ {
+ return (-1);
+ }
+
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type; /* option type */
+ opt.len = length; /* header len */
+ for (i = 0; i < 8; i++)
+ {
+ opt.addr[i] = target[i]; /* target */
+ }
+
+ n = libnet_pblock_append(l, p, (u_int8_t *)&opt, LIBNET_ICMPV6_OPT_TLLA_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
+
+ if ((payload && !payload_s) || (!payload && payload_s))
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ goto bad;
+ }
+
+ if (payload && payload_s)
+ {
+ n = libnet_pblock_append(l, p, payload, payload_s);
+ if (n == -1)
+ {
+ goto bad;
+ }
+ }
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, h,
+ LIBNET_PBLOCK_ICMPV6_OPT_TLLA_H));
+bad:
+ libnet_pblock_delete(l, p);
+ return (-1);
+}
+
+libnet_ptag_t
+libnet_build_icmpv6_opt_slla(u_int8_t type, u_int8_t length,
+ u_int8_t *source, u_int8_t *payload, u_int32_t payload_s,
+ libnet_t *l, libnet_ptag_t ptag)
+{
+ u_int32_t n, h, i;
+ libnet_pblock_t *p;
+ struct libnet_icmpv6_opt_lla_hdr opt;
+
+ if(l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_ICMPV6_OPT_SLLA_H + payload_s; /* size of memory block */
+ h = LIBNET_ICMPV6_OPT_SLLA_H + payload_s; /* hl for checksum */
+
+ /*
+ * 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_OPT_SLLA_H);
+ if(p == NULL)
+ {
+ return (-1);
+ }
+
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type; /* option type */
+ opt.len = length; /* packet code */
+ for (i = 0; i < 8; i++)
+ {
+ opt.addr[i] = source[i]; /* target */
+ }
+
+ n = libnet_pblock_append(l, p, (u_int8_t *)&opt, LIBNET_ICMPV6_OPT_SLLA_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
+
+ if ((payload && !payload_s) || (!payload && payload_s))
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ goto bad;
+ }
+
+ if (payload && payload_s)
+ {
+ n = libnet_pblock_append(l, p, payload, payload_s);
+ if (n == -1)
+ {
+ goto bad;
+ }
+ }
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, h,
+ LIBNET_PBLOCK_ICMPV6_OPT_SLLA_H));
+bad:
+ libnet_pblock_delete(l, p);
+ return (-1);
+}
+
+libnet_ptag_t
+libnet_build_icmpv6_opt_pi(u_int8_t type, u_int8_t length, u_int8_t prefixlen,
+ u_int8_t ol, u_int8_t a, u_int32_t validlt, u_int32_t preferredlt,
+ u_int32_t reserved, struct libnet_in6_addr prefix,
+ u_int32_t payload_s, u_int8_t *payload, libnet_t *l,
+ libnet_ptag_t ptag)
+{
+ u_int32_t n, h;
+ libnet_pblock_t *p;
+ struct libnet_icmpv6_opt_pi_hdr opt;
+
+ if(l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_ICMPV6_OPT_PI_H + payload_s; /* size of memory block */
+ h = LIBNET_ICMPV6_OPT_PI_H + payload_s; /* hl for checksum */
+
+ /*
+ * 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_OPT_PI_H);
+ if(p == NULL)
+ {
+ return (-1);
+ }
+
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type; /* option type */
+ opt.len = length; /* packet header len */
+ opt.prefixlen = prefixlen;
+ opt.la = (ol << 7) + (a << 6);
+ opt.validlt = validlt;
+ opt.preferredlt = preferredlt;
+ opt.reserved = reserved;
+ opt.prefix = prefix;
+
+ n = libnet_pblock_append(l, p, (u_int8_t *)&opt, LIBNET_ICMPV6_OPT_PI_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
+
+ if ((payload && !payload_s) || (!payload && payload_s))
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ goto bad;
+ }
+
+ if (payload && payload_s)
+ {
+ n = libnet_pblock_append(l, p, payload, payload_s);
+ if (n == -1)
+ {
+ goto bad;
+ }
+ }
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, h,
+ LIBNET_PBLOCK_ICMPV6_OPT_PI_H));
+bad:
+ libnet_pblock_delete(l, p);
+ return (-1);
+}
+
+libnet_ptag_t
+libnet_build_icmpv6_opt_rh(u_int8_t type, u_int8_t length, u_int16_t r1,
+ u_int32_t r2, u_int32_t payload_s, u_int8_t *payload, libnet_t *l,
+ libnet_ptag_t ptag)
+{
+ u_int32_t n, h;
+ libnet_pblock_t *p;
+ struct libnet_icmpv6_opt_rh_hdr opt;
+
+ if(l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_ICMPV6_OPT_RH_H + payload_s; /* size of memory block */
+ h = LIBNET_ICMPV6_OPT_RH_H + payload_s; /* hl for checksum */
+
+ /*
+ * 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_OPT_RH_H);
+ if(p == NULL)
+ {
+ return (-1);
+ }
+
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type; /* option type */
+ opt.len = length; /* packet header len */
+ opt.reserved1 = r1;
+ opt.reserved2 = r2;
+
+ n = libnet_pblock_append(l, p, (u_int8_t *)&opt, LIBNET_ICMPV6_OPT_RH_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
+
+ if ((payload && !payload_s) || (!payload && payload_s))
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ goto bad;
+ }
+
+ if (payload && payload_s)
+ {
+ n = libnet_pblock_append(l, p, payload, payload_s);
+ if (n == -1)
+ {
+ goto bad;
+ }
+ }
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, h,
+ LIBNET_PBLOCK_ICMPV6_OPT_RH_H));
+bad:
+ libnet_pblock_delete(l, p);
+ return (-1);
+}
+
+libnet_ptag_t
+libnet_build_icmpv6_opt_mtu(u_int8_t type, u_int8_t length, u_int16_t r,
+ u_int32_t mtu, u_int32_t payload_s, u_int8_t *payload,
+ libnet_t *l, libnet_ptag_t ptag)
+{
+ u_int32_t n, h;
+ libnet_pblock_t *p;
+ struct libnet_icmpv6_opt_mtu_hdr opt;
+
+ if(l == NULL)
+ {
+ return (-1);
+ }
+
+ n = LIBNET_ICMPV6_OPT_MTU_H + payload_s; /* size of memory block */
+ h = LIBNET_ICMPV6_OPT_MTU_H + payload_s; /* hl for checksum */
+
+ /*
+ * 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_OPT_MTU_H);
+ if(p == NULL)
+ {
+ return (-1);
+ }
+
+ memset(&opt, 0, sizeof(opt));
+ opt.type = type; /* option type */
+ opt.len = length; /* packet header len */
+ opt.reserved = r;
+ opt.mtu = mtu;
+
+ n = libnet_pblock_append(l, p, (u_int8_t *)&opt, LIBNET_ICMPV6_OPT_MTU_H);
+ if (n == -1)
+ {
+ goto bad;
+ }
+
+ if ((payload && !payload_s) || (!payload && payload_s))
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): payload inconsistency\n", __func__);
+ goto bad;
+ }
+
+ if (payload && payload_s)
+ {
+ n = libnet_pblock_append(l, p, payload, payload_s);
+ if (n == -1)
+ {
+ goto bad;
+ }
+ }
+
+ return (ptag ? ptag : libnet_pblock_update(l, p, h,
+ LIBNET_PBLOCK_ICMPV6_OPT_MTU_H));
+bad:
+ libnet_pblock_delete(l, p);
+ return (-1);
+}
More information about the p4-projects
mailing list