|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* $Id: libnet_build_ip.c,v 1.19 2004/04/13 17:32:28 mike Exp $
|
|
Packit |
03b34a |
*
|
|
Packit |
03b34a |
* libnet
|
|
Packit |
03b34a |
* libnet_build_ip.c - IP packet assembler
|
|
Packit |
03b34a |
*
|
|
Packit |
03b34a |
* Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
|
|
Packit |
03b34a |
* All rights reserved.
|
|
Packit |
03b34a |
*
|
|
Packit |
03b34a |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
03b34a |
* modification, are permitted provided that the following conditions
|
|
Packit |
03b34a |
* are met:
|
|
Packit |
03b34a |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit |
03b34a |
* notice, this list of conditions and the following disclaimer.
|
|
Packit |
03b34a |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit |
03b34a |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit |
03b34a |
* documentation and/or other materials provided with the distribution.
|
|
Packit |
03b34a |
*
|
|
Packit |
03b34a |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit |
03b34a |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
03b34a |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
03b34a |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
Packit |
03b34a |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
03b34a |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit |
03b34a |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit |
03b34a |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit |
03b34a |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit |
03b34a |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit |
03b34a |
* SUCH DAMAGE.
|
|
Packit |
03b34a |
*
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
#if (HAVE_CONFIG_H)
|
|
Packit |
03b34a |
#include "../include/config.h"
|
|
Packit |
03b34a |
#endif
|
|
Packit |
03b34a |
#if (!(_WIN32) || (__CYGWIN__))
|
|
Packit |
03b34a |
#include "../include/libnet.h"
|
|
Packit |
03b34a |
#else
|
|
Packit |
03b34a |
#include "../include/win32/libnet.h"
|
|
Packit |
03b34a |
#endif
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* TODO len - should be calculated if -1 */
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv4(uint16_t ip_len, uint8_t tos, uint16_t id, uint16_t frag,
|
|
Packit |
03b34a |
uint8_t ttl, uint8_t prot, uint16_t sum, uint32_t src, uint32_t dst,
|
|
Packit |
03b34a |
const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n = LIBNET_IPV4_H; /* size of memory block */
|
|
Packit |
03b34a |
libnet_pblock_t *p, *p_data, *p_temp;
|
|
Packit |
03b34a |
struct libnet_ipv4_hdr ip_hdr;
|
|
Packit |
03b34a |
libnet_ptag_t ptag_data = 0; /* used if there is ipv4 payload */
|
|
Packit |
03b34a |
libnet_ptag_t ptag_hold;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ip_hdr, 0, sizeof(ip_hdr));
|
|
Packit |
03b34a |
ip_hdr.ip_v = 4; /* version 4 */
|
|
Packit |
03b34a |
ip_hdr.ip_hl = 5; /* 20 byte header, measured in 32-bit words */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* check to see if there are IP options to include */
|
|
Packit |
03b34a |
if (p->prev)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
if (p->prev->type == LIBNET_PBLOCK_IPO_H)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* IPO block's length must be multiple of 4, or it's incorrectly
|
|
Packit |
03b34a |
* padded, in which case there is no "correct" IP header length,
|
|
Packit |
03b34a |
* it will too short or too long, we choose too short.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
ip_hdr.ip_hl += p->prev->b_len / 4;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
/* Note that p->h_len is not adjusted. This seems a bug, but it is because
|
|
Packit |
03b34a |
* it is not used! libnet_do_checksum() is passed the h_len (as `len'),
|
|
Packit |
03b34a |
* but for IPPROTO_IP it is ignored in favor of the ip_hl.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
ip_hdr.ip_tos = tos; /* IP tos */
|
|
Packit |
03b34a |
ip_hdr.ip_len = htons(ip_len); /* total length */
|
|
Packit |
03b34a |
ip_hdr.ip_id = htons(id); /* IP ID */
|
|
Packit |
03b34a |
ip_hdr.ip_off = htons(frag); /* fragmentation flags */
|
|
Packit |
03b34a |
ip_hdr.ip_ttl = ttl; /* time to live */
|
|
Packit |
03b34a |
ip_hdr.ip_p = prot; /* transport protocol */
|
|
Packit |
03b34a |
ip_hdr.ip_sum = (sum ? htons(sum) : 0); /* checksum */
|
|
Packit |
03b34a |
ip_hdr.ip_src.s_addr = src; /* source ip */
|
|
Packit |
03b34a |
ip_hdr.ip_dst.s_addr = dst; /* destination ip */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV4_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* save the original ptag value */
|
|
Packit |
03b34a |
ptag_hold = ptag;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (ptag == LIBNET_PTAG_INITIALIZER)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* find and set the appropriate ptag, or else use the default of 0 */
|
|
Packit |
03b34a |
/* When updating the ipv4 block, we need to find the data block, and
|
|
Packit |
03b34a |
* adjust our ip_offset if the new payload size is different from what
|
|
Packit |
03b34a |
* it used to be.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
if (ptag_hold && p->prev)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
p_temp = p->prev;
|
|
Packit |
03b34a |
while (p_temp->prev &&
|
|
Packit |
03b34a |
(p_temp->type != LIBNET_PBLOCK_IPDATA) &&
|
|
Packit |
03b34a |
(p_temp->type != LIBNET_PBLOCK_IPV4_H))
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
p_temp = p_temp->prev;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (p_temp->type == LIBNET_PBLOCK_IPDATA)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
ptag_data = p_temp->ptag;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
else
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IPv4 data pblock not found\n", __func__);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (payload_s && !payload)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): payload inconsistency\n", __func__);
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (payload_s)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* update ptag_data with the new payload */
|
|
Packit |
03b34a |
/* on create:
|
|
Packit |
03b34a |
* b_len = payload_s
|
|
Packit |
03b34a |
* l->total_size += b_len
|
|
Packit |
03b34a |
* h_len = 0
|
|
Packit |
03b34a |
* on update:
|
|
Packit |
03b34a |
* b_len = payload_s
|
|
Packit |
03b34a |
* h_len += <diff in size between new b_len and old b_len>
|
|
Packit |
03b34a |
* increments if if b_len goes up, down if it goes down
|
|
Packit |
03b34a |
* in either case:
|
|
Packit |
03b34a |
* copied = 0
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p_data = libnet_pblock_probe(l, ptag_data, payload_s,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPDATA);
|
|
Packit |
03b34a |
if (p_data == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (libnet_pblock_append(l, p_data, payload, payload_s) == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (ptag_data == LIBNET_PTAG_INITIALIZER)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* IPDATA's h_len gets set to payload_s in both branches */
|
|
Packit |
03b34a |
if (p_data->prev->type == LIBNET_PBLOCK_IPV4_H)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
libnet_pblock_update(l, p_data, payload_s,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPDATA);
|
|
Packit |
03b34a |
/* swap pblocks to correct the protocol order */
|
|
Packit |
03b34a |
libnet_pblock_swap(l, p->ptag, p_data->ptag);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
else
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* SR - I'm not sure how to reach this code. Maybe if the first
|
|
Packit |
03b34a |
* time we added an ipv4 block, there was no payload, but when
|
|
Packit |
03b34a |
* we modify the block the next time, we have payload?
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* update without setting this as the final pblock */
|
|
Packit |
03b34a |
p_data->type = LIBNET_PBLOCK_IPDATA;
|
|
Packit |
03b34a |
p_data->ptag = ++(l->ptag_state);
|
|
Packit |
03b34a |
p_data->h_len = payload_s; /* TODO dead code, data blocks don't have headers */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* data was added after the initial construction */
|
|
Packit |
03b34a |
for (p_temp = l->protocol_blocks;
|
|
Packit |
03b34a |
p_temp->type == LIBNET_PBLOCK_IPV4_H ||
|
|
Packit |
03b34a |
p_temp->type == LIBNET_PBLOCK_IPO_H;
|
|
Packit |
03b34a |
p_temp = p_temp->next)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag);
|
|
Packit |
03b34a |
break;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* the end block needs to have its next pointer cleared */
|
|
Packit |
03b34a |
l->pblock_end->next = NULL;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_IPO_H)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
else
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
p_data = libnet_pblock_find(l, ptag_data);
|
|
Packit |
03b34a |
if (p_data)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p_data);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
else
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* XXX - When this completes successfully, libnet errbuf contains
|
|
Packit |
03b34a |
* an error message so to come correct, we'll clear it.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
memset(l->err_buf, 0, sizeof (l->err_buf));
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
if (sum == 0)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* If checksum is zero, by default libnet will compute a checksum
|
|
Packit |
03b34a |
* for the user. The programmer can override this by calling
|
|
Packit |
03b34a |
* libnet_toggle_checksum(l, ptag, 1);
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
return (ptag);
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_autobuild_ipv4(uint16_t len, uint8_t prot, uint32_t dst, libnet_t *l)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n, i, j, src;
|
|
Packit |
03b34a |
uint16_t h;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
libnet_ptag_t ptag;
|
|
Packit |
03b34a |
struct libnet_ipv4_hdr ip_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = LIBNET_IPV4_H; /* size of memory block */
|
|
Packit |
03b34a |
h = len; /* header length */
|
|
Packit |
03b34a |
ptag = LIBNET_PTAG_INITIALIZER;
|
|
Packit |
03b34a |
src = libnet_get_ipaddr4(l);
|
|
Packit |
03b34a |
if (src == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* err msg set in libnet_get_ipaddr() */
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Create a new pblock.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV4_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ip_hdr, 0, sizeof(ip_hdr));
|
|
Packit |
03b34a |
ip_hdr.ip_v = 4; /* version 4 */
|
|
Packit |
03b34a |
ip_hdr.ip_hl = 5; /* 20 byte header */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* check to see if there are IP options to include */
|
|
Packit |
03b34a |
if (p->prev)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
if (p->prev->type == LIBNET_PBLOCK_IPO_H)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Count up number of 32-bit words in options list, padding if
|
|
Packit |
03b34a |
* neccessary.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
for (i = 0, j = 0; i < p->prev->b_len; i++)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
(i % 4) ? j : j++;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
ip_hdr.ip_hl += j;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
ip_hdr.ip_tos = 0; /* IP tos */
|
|
Packit |
03b34a |
ip_hdr.ip_len = htons(h); /* total length */
|
|
Packit |
03b34a |
ip_hdr.ip_id = htons((l->ptag_state) & 0x0000ffff); /* IP ID */
|
|
Packit |
03b34a |
ip_hdr.ip_off = 0; /* fragmentation flags */
|
|
Packit |
03b34a |
ip_hdr.ip_ttl = 64; /* time to live */
|
|
Packit |
03b34a |
ip_hdr.ip_p = prot; /* transport protocol */
|
|
Packit |
03b34a |
ip_hdr.ip_sum = 0; /* checksum */
|
|
Packit |
03b34a |
ip_hdr.ip_src.s_addr = src; /* source ip */
|
|
Packit |
03b34a |
ip_hdr.ip_dst.s_addr = dst; /* destination ip */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV4_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM);
|
|
Packit |
03b34a |
ptag = libnet_pblock_update(l, p, LIBNET_IPV4_H, LIBNET_PBLOCK_IPV4_H);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
return (ptag);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv4_options(const uint8_t *options, uint32_t options_s, libnet_t *l,
|
|
Packit |
03b34a |
libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
int options_size_increase = 0; /* increase will be negative if it's a decrease */
|
|
Packit |
03b34a |
uint32_t n, adj_size;
|
|
Packit |
03b34a |
libnet_pblock_t *p, *p_temp;
|
|
Packit |
03b34a |
struct libnet_ipv4_hdr *ip_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* check options list size */
|
|
Packit |
03b34a |
if (options_s > LIBNET_MAXOPTION_SIZE)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): options list is too large %d\n", __func__, options_s);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
adj_size = options_s;
|
|
Packit |
03b34a |
if (adj_size % 4)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
/* size of memory block with padding */
|
|
Packit |
03b34a |
adj_size += 4 - (options_s % 4);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* if this pblock already exists, determine if there is a size diff */
|
|
Packit |
03b34a |
if (ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
p_temp = libnet_pblock_find(l, ptag);
|
|
Packit |
03b34a |
if (p_temp)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
options_size_increase = adj_size - p_temp->b_len;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
/* If we aren't modifying an options block, we are pushing a new one, and
|
|
Packit |
03b34a |
* since it must be pushed before the IPv4 block is pushed, there is no
|
|
Packit |
03b34a |
* need to remember that options size has "increased".
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, adj_size, LIBNET_PBLOCK_IPO_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* append options */
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, options, options_s);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* append padding */
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t*)"\0\0\0", adj_size - options_s);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (ptag && p->next)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
p_temp = p->next;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* fix the IP header sizes */
|
|
Packit |
03b34a |
if (p_temp->type == LIBNET_PBLOCK_IPV4_H)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
ip_hdr = (struct libnet_ipv4_hdr *) p_temp->buf;
|
|
Packit |
03b34a |
ip_hdr->ip_hl = 5 + adj_size / 4; /* 4 bits wide, so no byte order concerns */
|
|
Packit |
03b34a |
ip_hdr->ip_len = htons(ntohs(ip_hdr->ip_len) + options_size_increase);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
p_temp->h_len = ip_hdr->ip_hl * 4; /* Dead code, h_len isn't used for IPv4 block */
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
return (ptag ? ptag : libnet_pblock_update(l, p, adj_size,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPO_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv6(uint8_t tc, uint32_t fl, uint16_t len, uint8_t nh,
|
|
Packit |
03b34a |
uint8_t hl, struct libnet_in6_addr src, struct libnet_in6_addr dst,
|
|
Packit |
03b34a |
const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
struct libnet_ipv6_hdr ip_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = LIBNET_IPV6_H + payload_s; /* size of memory block */
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (LIBNET_IPV6_H + payload_s > IP_MAXPACKET)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IP packet too large\n", __func__);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ip_hdr, 0, sizeof(ip_hdr));
|
|
Packit |
03b34a |
ip_hdr.ip_flags[0] = (0x06 << 4) | ((tc & 0xF0) >> 4);
|
|
Packit |
03b34a |
ip_hdr.ip_flags[1] = ((tc & 0x0F) << 4) | ((fl & 0xF0000) >> 16);
|
|
Packit |
03b34a |
ip_hdr.ip_flags[2] = fl & 0x0FF00 >> 8;
|
|
Packit |
03b34a |
ip_hdr.ip_flags[3] = fl & 0x000FF;
|
|
Packit |
03b34a |
ip_hdr.ip_len = htons(len);
|
|
Packit |
03b34a |
ip_hdr.ip_nh = nh;
|
|
Packit |
03b34a |
ip_hdr.ip_hl = hl;
|
|
Packit |
03b34a |
ip_hdr.ip_src = src;
|
|
Packit |
03b34a |
ip_hdr.ip_dst = dst;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ip_hdr, LIBNET_IPV6_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* boilerplate payload sanity check / append macro */
|
|
Packit |
03b34a |
LIBNET_DO_PAYLOAD(l, p);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* no checksum for IPv6 */
|
|
Packit |
03b34a |
ptag = ptag ? ptag : libnet_pblock_update(l, p, LIBNET_IPV6_H,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPV6_H);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
return ptag;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv6_frag(uint8_t nh, uint8_t reserved, uint16_t frag,
|
|
Packit |
03b34a |
uint32_t id, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
|
|
Packit |
03b34a |
libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n;
|
|
Packit |
03b34a |
uint16_t h;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
struct libnet_ipv6_frag_hdr ipv6_frag_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
n = LIBNET_IPV6_FRAG_H + payload_s;
|
|
Packit |
03b34a |
h = 0;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (LIBNET_IPV6_FRAG_H + payload_s > IP_MAXPACKET)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IP packet too large\n", __func__);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_FRAG_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ipv6_frag_hdr, 0 , sizeof(ipv6_frag_hdr));
|
|
Packit |
03b34a |
ipv6_frag_hdr.ip_nh = nh;
|
|
Packit |
03b34a |
ipv6_frag_hdr.ip_reserved = reserved;
|
|
Packit |
03b34a |
ipv6_frag_hdr.ip_frag = frag;
|
|
Packit |
03b34a |
ipv6_frag_hdr.ip_id = id;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Appened the protocol unit to the list.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_frag_hdr,
|
|
Packit |
03b34a |
LIBNET_IPV6_FRAG_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* boilerplate payload sanity check / append macro */
|
|
Packit |
03b34a |
LIBNET_DO_PAYLOAD(l, p);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Update the protocol block's meta information and return the protocol
|
|
Packit |
03b34a |
* tag id of this pblock. This tag will be used to locate the pblock
|
|
Packit |
03b34a |
* in order to modify the protocol header in subsequent calls.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
return (ptag ? ptag : libnet_pblock_update(l, p, h,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPV6_FRAG_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv6_routing(uint8_t nh, uint8_t len, uint8_t rtype,
|
|
Packit |
03b34a |
uint8_t segments, const uint8_t *payload, uint32_t payload_s, libnet_t *l,
|
|
Packit |
03b34a |
libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n;
|
|
Packit |
03b34a |
uint16_t h;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
struct libnet_ipv6_routing_hdr ipv6_routing_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* Important: IPv6 routing header routes are specified using the payload
|
|
Packit |
03b34a |
* interface!
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = LIBNET_IPV6_ROUTING_H + payload_s;
|
|
Packit |
03b34a |
h = 0;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (LIBNET_IPV6_ROUTING_H + payload_s > IP_MAXPACKET)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IP packet too large\n", __func__);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_ROUTING_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ipv6_routing_hdr, 0 , sizeof(ipv6_routing_hdr));
|
|
Packit |
03b34a |
ipv6_routing_hdr.ip_nh = nh;
|
|
Packit |
03b34a |
ipv6_routing_hdr.ip_len = len;
|
|
Packit |
03b34a |
ipv6_routing_hdr.ip_rtype = rtype;
|
|
Packit |
03b34a |
ipv6_routing_hdr.ip_segments = segments;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Appened the protocol unit to the list.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_routing_hdr,
|
|
Packit |
03b34a |
LIBNET_IPV6_ROUTING_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* boilerplate payload sanity check / append macro */
|
|
Packit |
03b34a |
LIBNET_DO_PAYLOAD(l, p);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Update the protocol block's meta information and return the protocol
|
|
Packit |
03b34a |
* tag id of this pblock. This tag will be used to locate the pblock
|
|
Packit |
03b34a |
* in order to modify the protocol header in subsequent calls.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
return (ptag ? ptag : libnet_pblock_update(l, p, h,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPV6_ROUTING_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv6_destopts(uint8_t nh, uint8_t len, const uint8_t *payload,
|
|
Packit |
03b34a |
uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n;
|
|
Packit |
03b34a |
uint16_t h;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
struct libnet_ipv6_destopts_hdr ipv6_destopts_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* Important: IPv6 dest opts information is specified using the payload
|
|
Packit |
03b34a |
* interface!
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = LIBNET_IPV6_DESTOPTS_H + payload_s;
|
|
Packit |
03b34a |
h = 0;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (LIBNET_IPV6_DESTOPTS_H + payload_s > IP_MAXPACKET)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IP packet too large\n", __func__);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_DESTOPTS_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ipv6_destopts_hdr, 0 , sizeof(ipv6_destopts_hdr));
|
|
Packit |
03b34a |
ipv6_destopts_hdr.ip_nh = nh;
|
|
Packit |
03b34a |
ipv6_destopts_hdr.ip_len = len;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Appened the protocol unit to the list.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_destopts_hdr,
|
|
Packit |
03b34a |
LIBNET_IPV6_DESTOPTS_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* boilerplate payload sanity check / append macro */
|
|
Packit |
03b34a |
LIBNET_DO_PAYLOAD(l, p);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Update the protocol block's meta information and return the protocol
|
|
Packit |
03b34a |
* tag id of this pblock. This tag will be used to locate the pblock
|
|
Packit |
03b34a |
* in order to modify the protocol header in subsequent calls.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
return (ptag ? ptag : libnet_pblock_update(l, p, h,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPV6_DESTOPTS_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_build_ipv6_hbhopts(uint8_t nh, uint8_t len, const uint8_t *payload,
|
|
Packit |
03b34a |
uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
uint32_t n;
|
|
Packit |
03b34a |
uint16_t h;
|
|
Packit |
03b34a |
libnet_pblock_t *p;
|
|
Packit |
03b34a |
struct libnet_ipv6_hbhopts_hdr ipv6_hbhopts_hdr;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (l == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* Important: IPv6 hop by hop opts information is specified using the
|
|
Packit |
03b34a |
* payload interface!
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = LIBNET_IPV6_HBHOPTS_H + payload_s;
|
|
Packit |
03b34a |
h = 0;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (LIBNET_IPV6_HBHOPTS_H + payload_s > IP_MAXPACKET)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
|
|
Packit |
03b34a |
"%s(): IP packet too large\n", __func__);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Find the existing protocol block if a ptag is specified, or create
|
|
Packit |
03b34a |
* a new one.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
p = libnet_pblock_probe(l, ptag, n, LIBNET_PBLOCK_IPV6_HBHOPTS_H);
|
|
Packit |
03b34a |
if (p == NULL)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
memset(&ipv6_hbhopts_hdr, 0 , sizeof(ipv6_hbhopts_hdr));
|
|
Packit |
03b34a |
ipv6_hbhopts_hdr.ip_nh = nh;
|
|
Packit |
03b34a |
ipv6_hbhopts_hdr.ip_len = len;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Appened the protocol unit to the list.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
n = libnet_pblock_append(l, p, (uint8_t *)&ipv6_hbhopts_hdr,
|
|
Packit |
03b34a |
LIBNET_IPV6_HBHOPTS_H);
|
|
Packit |
03b34a |
if (n == -1)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
goto bad;
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/* boilerplate payload sanity check / append macro */
|
|
Packit |
03b34a |
LIBNET_DO_PAYLOAD(l, p);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
/*
|
|
Packit |
03b34a |
* Update the protocol block's meta information and return the protocol
|
|
Packit |
03b34a |
* tag id of this pblock. This tag will be used to locate the pblock
|
|
Packit |
03b34a |
* in order to modify the protocol header in subsequent calls.
|
|
Packit |
03b34a |
*/
|
|
Packit |
03b34a |
return (ptag ? ptag : libnet_pblock_update(l, p, h,
|
|
Packit |
03b34a |
LIBNET_PBLOCK_IPV6_HBHOPTS_H));
|
|
Packit |
03b34a |
bad:
|
|
Packit |
03b34a |
libnet_pblock_delete(l, p);
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
libnet_ptag_t
|
|
Packit |
03b34a |
libnet_autobuild_ipv6(uint16_t len, uint8_t nh, struct libnet_in6_addr dst,
|
|
Packit |
03b34a |
libnet_t *l, libnet_ptag_t ptag)
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
struct libnet_in6_addr src;
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
src = libnet_get_ipaddr6(l);
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
if (libnet_in6_is_error(src))
|
|
Packit |
03b34a |
{
|
|
Packit |
03b34a |
return (-1);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|
|
Packit |
03b34a |
return libnet_build_ipv6(0, 0, len, nh, 64, src, dst, NULL, 0, l, ptag);
|
|
Packit |
03b34a |
}
|
|
Packit |
03b34a |
|