version 1.1, 2012/02/21 22:14:23
|
version 1.1.1.3, 2023/09/27 11:11:38
|
Line 30
|
Line 30
|
* |
* |
*/ |
*/ |
|
|
#if (HAVE_CONFIG_H) | #include "common.h" |
#include "../include/config.h" | #include <assert.h> |
#endif | |
#if (!(_WIN32) || (__CYGWIN__)) | |
#include "../include/libnet.h" | |
#else | |
#include "../include/win32/libnet.h" | |
#endif | |
|
|
libnet_pblock_t * |
libnet_pblock_t * |
libnet_pblock_probe(libnet_t *l, libnet_ptag_t ptag, u_int32_t n, u_int8_t type) | libnet_pblock_probe(libnet_t *l, libnet_ptag_t ptag, uint32_t b_len, uint8_t type) |
{ |
{ |
int offset; |
int offset; |
libnet_pblock_t *p; |
libnet_pblock_t *p; |
|
|
if (ptag == LIBNET_PTAG_INITIALIZER) |
if (ptag == LIBNET_PTAG_INITIALIZER) |
{ |
{ |
/* | return libnet_pblock_new(l, b_len); |
* Create a new pblock and enough buffer space for the packet. | } |
*/ | |
p = libnet_pblock_new(l, n); | /* |
if (p == NULL) | * Update this pblock, don't create a new one. Note that if the |
| * new packet size is larger than the old one we will do a malloc. |
| */ |
| p = libnet_pblock_find(l, ptag); |
| |
| if (p == NULL) |
| { |
| /* err msg set in libnet_pblock_find() */ |
| return (NULL); |
| } |
| if (p->type != type) |
| { |
| snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
| "%s(): ptag refers to different type than expected (0x%x != 0x%x)", |
| __func__, p->type, type); |
| return (NULL); |
| } |
| /* |
| * If size is greater than the original block of memory, we need |
| * to malloc more memory. Should we use realloc? |
| */ |
| if (b_len > p->b_len) |
| { |
| offset = b_len - p->b_len; /* how many bytes larger new pblock is */ |
| free(p->buf); |
| p->buf = malloc(b_len); |
| if (p->buf == NULL) |
{ |
{ |
/* err msg set in libnet_pblock_new() */ | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
| "%s(): can't resize pblock buffer: %s", __func__, |
| strerror(errno)); |
return (NULL); |
return (NULL); |
} |
} |
|
memset(p->buf, 0, b_len); |
|
p->h_len += offset; /* new length for checksums */ |
|
p->b_len = b_len; /* new buf len */ |
|
l->total_size += offset; |
} |
} |
else |
else |
{ |
{ |
/* | offset = p->b_len - b_len; |
* Update this pblock, don't create a new one. Note that if the | p->h_len -= offset; /* new length for checksums */ |
* new packet size is larger than the old one we will do a malloc. | p->b_len = b_len; /* new buf len */ |
*/ | l->total_size -= offset; |
p = libnet_pblock_find(l, ptag); | |
| |
if (p == NULL) | |
{ | |
/* err msg set in libnet_pblock_find() */ | |
return (NULL); | |
} | |
if (p->type != type) | |
{ | |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
"%s(): ptag refers to different type than expected (%d != %d)", | |
__func__, p->type, type); | |
return (NULL); | |
} | |
/* | |
* If size is greater than the original block of memory, we need | |
* to malloc more memory. Should we use realloc? | |
*/ | |
if (n > p->b_len) | |
{ | |
offset = n - p->b_len; /* how many bytes larger new pblock is */ | |
free(p->buf); | |
p->buf = malloc(n); | |
if (p->buf == NULL) | |
{ | |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
"%s(): can't resize pblock buffer: %s\n", __func__, | |
strerror(errno)); | |
return (NULL); | |
} | |
memset(p->buf, 0, n); | |
p->h_len += offset; /* new length for checksums */ | |
p->b_len = n; /* new buf len */ | |
l->total_size += offset; | |
} | |
else | |
{ | |
offset = p->b_len - n; | |
p->h_len -= offset; /* new length for checksums */ | |
p->b_len = n; /* new buf len */ | |
l->total_size -= offset; | |
} | |
p->copied = 0; /* reset copied counter */ | |
} |
} |
|
p->copied = 0; /* reset copied counter */ |
|
|
return (p); |
return (p); |
} |
} |
|
|
|
static void* zmalloc(libnet_t* l, uint32_t size, const char* func) |
|
{ |
|
void* v = malloc(size); |
|
if(v) |
|
memset(v, 0, size); |
|
else |
|
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s", func, |
|
strerror(errno)); |
|
return v; |
|
} |
|
|
libnet_pblock_t * |
libnet_pblock_t * |
libnet_pblock_new(libnet_t *l, u_int32_t size) | libnet_pblock_new(libnet_t *l, uint32_t b_len) |
{ |
{ |
libnet_pblock_t *p; | libnet_pblock_t *p = zmalloc(l, sizeof(libnet_pblock_t), __func__); |
/* | if(!p) |
* Should we do error checking the size of the pblock here, or | return NULL; |
* should we rely on the underlying operating system to complain when | |
* the user tries to write some ridiculously huge packet? | |
*/ | |
|
|
|
p->buf = zmalloc(l, b_len, __func__); |
|
|
|
if(!p->buf) |
|
{ |
|
free(p); |
|
return NULL; |
|
} |
|
|
|
p->b_len = b_len; |
|
|
|
l->total_size += b_len; |
|
l->n_pblocks++; |
|
|
/* make the head node if it doesn't exist */ |
/* make the head node if it doesn't exist */ |
if (l->protocol_blocks == NULL) |
if (l->protocol_blocks == NULL) |
{ |
{ |
p = l->protocol_blocks = malloc(sizeof (libnet_pblock_t)); | l->protocol_blocks = p; |
if (p == NULL) | l->pblock_end = p; |
{ | |
goto bad; | |
} | |
memset(p, 0, sizeof (libnet_pblock_t)); | |
} |
} |
else |
else |
{ |
{ |
p = l->pblock_end; | l->pblock_end->next = p; |
p->next = malloc(sizeof (libnet_pblock_t)); | p->prev = l->pblock_end; |
| l->pblock_end = p; |
if (p->next == NULL) | |
{ | |
goto bad; | |
} | |
memset(p->next, 0, sizeof (libnet_pblock_t)); | |
p->next->prev = p; | |
p = p->next; | |
} |
} |
|
|
p->buf = malloc(size); | return p; |
if (p->buf == NULL) | |
{ | |
free(p); | |
p = NULL; | |
goto bad; | |
} | |
memset(p->buf, 0, size); | |
p->b_len = size; | |
l->total_size += size; | |
l->n_pblocks++; | |
return (p); | |
| |
bad: | |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", __func__, | |
strerror(errno)); | |
return (NULL); | |
} |
} |
|
|
int |
int |
Line 203 libnet_pblock_swap(libnet_t *l, libnet_ptag_t ptag1, l
|
Line 182 libnet_pblock_swap(libnet_t *l, libnet_ptag_t ptag1, l
|
return (1); |
return (1); |
} |
} |
|
|
|
static void libnet_pblock_remove_from_list(libnet_t *l, libnet_pblock_t *p) |
|
{ |
|
if (p->prev) |
|
{ |
|
p->prev->next = p->next; |
|
} |
|
else |
|
{ |
|
l->protocol_blocks = p->next; |
|
} |
|
|
|
if (p->next) |
|
{ |
|
p->next->prev = p->prev; |
|
} |
|
else |
|
{ |
|
l->pblock_end = p->prev; |
|
} |
|
} |
|
|
int |
int |
libnet_pblock_insert_before(libnet_t *l, libnet_ptag_t ptag1, |
libnet_pblock_insert_before(libnet_t *l, libnet_ptag_t ptag1, |
libnet_ptag_t ptag2) |
libnet_ptag_t ptag2) |
Line 217 libnet_pblock_insert_before(libnet_t *l, libnet_ptag_t
|
Line 217 libnet_pblock_insert_before(libnet_t *l, libnet_ptag_t
|
return (-1); |
return (-1); |
} |
} |
|
|
|
/* check for already present before */ |
|
if(p2->next == p1) |
|
return 1; |
|
|
|
libnet_pblock_remove_from_list(l, p2); |
|
|
|
/* insert p2 into list */ |
p2->prev = p1->prev; |
p2->prev = p1->prev; |
p2->next = p1; |
p2->next = p1; |
p1->prev = p2; |
p1->prev = p2; |
Line 247 libnet_pblock_find(libnet_t *l, libnet_ptag_t ptag)
|
Line 254 libnet_pblock_find(libnet_t *l, libnet_ptag_t ptag)
|
} |
} |
} |
} |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): couldn't find protocol block\n", __func__); | "%s(): couldn't find protocol block", __func__); |
return (NULL); |
return (NULL); |
} |
} |
|
|
int |
int |
libnet_pblock_append(libnet_t *l, libnet_pblock_t *p, u_int8_t *buf, | libnet_pblock_append(libnet_t *l, libnet_pblock_t *p, const void *buf, uint32_t len) |
u_int32_t len) | |
{ |
{ |
|
if (len && !buf) |
|
{ |
|
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
|
"%s(): payload inconsistency", __func__); |
|
return -1; |
|
} |
|
|
if (p->copied + len > p->b_len) |
if (p->copied + len > p->b_len) |
{ |
{ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): memcpy would overflow buffer\n", __func__); | "%s(): memcpy would overflow buffer", __func__); |
return (-1); |
return (-1); |
} |
} |
memcpy(p->buf + p->copied, buf, len); |
memcpy(p->buf + p->copied, buf, len); |
Line 267 libnet_pblock_append(libnet_t *l, libnet_pblock_t *p,
|
Line 280 libnet_pblock_append(libnet_t *l, libnet_pblock_t *p,
|
} |
} |
|
|
void |
void |
libnet_pblock_setflags(libnet_pblock_t *p, u_int8_t flags) | libnet_pblock_setflags(libnet_pblock_t *p, uint8_t flags) |
{ |
{ |
p->flags = flags; |
p->flags = flags; |
} |
} |
|
|
|
/* FIXME both ptag setting and end setting should be done in pblock new and/or pblock probe. */ |
libnet_ptag_t |
libnet_ptag_t |
libnet_pblock_update(libnet_t *l, libnet_pblock_t *p, u_int32_t h, | libnet_pblock_update(libnet_t *l, libnet_pblock_t *p, uint32_t h_len, uint8_t type) |
u_int8_t type) | |
{ |
{ |
p->type = type; |
p->type = type; |
p->ptag = ++(l->ptag_state); |
p->ptag = ++(l->ptag_state); |
p->h_len = h; | p->h_len = h_len; |
l->pblock_end = p; /* point end of pblock list here */ |
l->pblock_end = p; /* point end of pblock list here */ |
|
|
return (p->ptag); |
return (p->ptag); |
} |
} |
|
|
int | static int pblock_is_ip(libnet_pblock_t* p) |
libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet, u_int32_t *size) | |
{ |
{ |
libnet_pblock_t *p, *q; | return p->type == LIBNET_PBLOCK_IPV4_H || p->type == LIBNET_PBLOCK_IPV6_H; |
u_int32_t c, n; | } |
|
|
|
/* q is either an ip hdr, or is followed by an ip hdr. return the offset |
|
* from end of packet. if there is no offset, we'll return the total size, |
|
* and things will break later |
|
*/ |
|
static int calculate_ip_offset(libnet_t* l, libnet_pblock_t* q) |
|
{ |
|
int ip_offset = 0; |
|
libnet_pblock_t* p = l->protocol_blocks; |
|
for(; p && p != q; p = p->next) { |
|
ip_offset += p->b_len; |
|
} |
|
assert(p == q); /* if not true, then q is not a pblock! */ |
|
|
|
for(; p; p = p->next) { |
|
ip_offset += p->b_len; |
|
if(pblock_is_ip(p)) |
|
break; |
|
} |
|
|
|
return ip_offset; |
|
} |
|
|
|
int |
|
libnet_pblock_coalesce(libnet_t *l, uint8_t **packet, uint32_t *size) |
|
{ |
/* |
/* |
* Determine the offset required to keep memory aligned (strict |
* Determine the offset required to keep memory aligned (strict |
* architectures like solaris enforce this, but's a good practice |
* architectures like solaris enforce this, but's a good practice |
Line 307 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
Line 344 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
l->aligner = 0; |
l->aligner = 0; |
} |
} |
|
|
*packet = malloc(l->aligner + l->total_size); | if(!l->total_size && !l->aligner) { |
| /* Avoid allocating zero bytes of memory, it perturbs electric fence. */ |
| *packet = malloc(1); |
| **packet =1; |
| } else { |
| *packet = malloc(l->aligner + l->total_size); |
| } |
if (*packet == NULL) |
if (*packet == NULL) |
{ |
{ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s\n", | snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, "%s(): malloc(): %s", |
__func__, strerror(errno)); |
__func__, strerror(errno)); |
return (-1); |
return (-1); |
} |
} |
Line 337 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
Line 380 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
(l->pblock_end->type != LIBNET_PBLOCK_802_3_H)) |
(l->pblock_end->type != LIBNET_PBLOCK_802_3_H)) |
{ |
{ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): packet assembly cannot find a layer 2 header\n", | "%s(): packet assembly cannot find a layer 2 header", |
__func__); |
__func__); |
return (-1); | goto err; |
} |
} |
break; |
break; |
case LIBNET_RAW4: |
case LIBNET_RAW4: |
if ((l->pblock_end->type != LIBNET_PBLOCK_IPV4_H)) |
if ((l->pblock_end->type != LIBNET_PBLOCK_IPV4_H)) |
{ |
{ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): packet assembly cannot find an IPv4 header\n", | "%s(): packet assembly cannot find an IPv4 header", |
__func__); |
__func__); |
return (-1); | goto err; |
} |
} |
break; |
break; |
case LIBNET_RAW6: |
case LIBNET_RAW6: |
if ((l->pblock_end->type != LIBNET_PBLOCK_IPV6_H)) |
if ((l->pblock_end->type != LIBNET_PBLOCK_IPV6_H)) |
{ |
{ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): packet assembly cannot find an IPv6 header\n", | "%s(): packet assembly cannot find an IPv6 header", |
__func__); |
__func__); |
return (-1); | goto err; |
} |
} |
break; |
break; |
default: |
default: |
/* we should not end up here ever */ |
/* we should not end up here ever */ |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
"%s(): suddenly the dungeon collapses -- you die\n", | "%s(): suddenly the dungeon collapses -- you die", |
__func__); |
__func__); |
return (-1); | goto err; |
break; |
break; |
} |
} |
} |
} |
|
|
q = NULL; | /* Build packet from end to start. */ |
for (n = l->aligner + l->total_size, p = l->protocol_blocks; p || q; ) | |
{ |
{ |
if (q) | /* |
| From top to bottom, go through pblocks pairwise: |
| |
| p is the currently being copied pblock, and steps through every block |
| q is the prev pblock to p that needs checksumming, it will |
| not step through every block as p does, it will skip any that do not |
| need checksumming. |
| n offset from start of packet to beginning of block we are writing |
| |
| q is NULL on first iteration |
| p is NULL on last iteration |
| |
| Checksums are done on q, to give p a chance to be copied over, since |
| checksumming q can require a lower-level header to be encoded, in the |
| case of IP protocols (which are the only kinds handled by libnet's |
| checksum implementation). |
| |
| This is very obscure, or would be much more clear if it was done in |
| two loops. |
| */ |
| libnet_pblock_t *q = NULL; |
| libnet_pblock_t *p = NULL; |
| uint32_t n; |
| |
| for (n = l->aligner + l->total_size, p = l->protocol_blocks; p || q; ) |
{ |
{ |
p = p->next; | if (q) |
} | |
if (p) | |
{ | |
n -= p->b_len; | |
/* copy over the packet chunk */ | |
memcpy(*packet + n, p->buf, p->b_len); | |
} | |
if (q) | |
{ | |
if (p == NULL || ((p->flags) & LIBNET_PBLOCK_DO_CHECKSUM)) | |
{ |
{ |
if ((q->flags) & LIBNET_PBLOCK_DO_CHECKSUM) | p = p->next; |
| } |
| if (p) |
| { |
| n -= p->b_len; |
| /* copy over the packet chunk */ |
| memcpy(*packet + n, p->buf, p->b_len); |
| } |
| #if 0 |
| printf("-- n %d/%d cksum? %d\n", n, l->aligner + l->total_size, |
| q && |
| (p == NULL || (p->flags & LIBNET_PBLOCK_DO_CHECKSUM)) && |
| (q->flags & LIBNET_PBLOCK_DO_CHECKSUM)); |
| if(q) |
| { |
| printf(" iph %d/%d offset -%d\n", |
| (l->total_size + l->aligner) - q->ip_offset, |
| l->total_size + l->aligner, |
| q->ip_offset |
| ); |
| } |
| if (p) |
| { |
| printf("p %p ptag %d b_len %d h_len %d cksum? %d type %s\n", |
| p, p->ptag, |
| p->b_len, p->h_len, |
| p->flags & LIBNET_PBLOCK_DO_CHECKSUM, |
| libnet_diag_dump_pblock_type(p->type) |
| ); |
| } |
| if (q) |
| { |
| printf("q %p ptag %d b_len %d h_len %d cksum? %d type %s\n", |
| q, q->ptag, |
| q->b_len, q->h_len, |
| q->flags & LIBNET_PBLOCK_DO_CHECKSUM, |
| libnet_diag_dump_pblock_type(q->type) |
| ); |
| } |
| #endif |
| if (q) |
| { |
| if (p == NULL || (p->flags & LIBNET_PBLOCK_DO_CHECKSUM)) |
{ |
{ |
int offset = (l->total_size + l->aligner) - q->ip_offset; | if (q->flags & LIBNET_PBLOCK_DO_CHECKSUM) |
c = libnet_do_checksum(l, *packet + offset, | |
libnet_pblock_p2p(q->type), q->h_len); | |
if (c == -1) | |
{ |
{ |
/* err msg set in libnet_do_checksum() */ | uint32_t c; |
return (-1); | uint8_t* end = *packet + l->aligner + l->total_size; |
| uint8_t* beg = *packet + n; |
| int ip_offset = calculate_ip_offset(l, q); |
| uint8_t* iph = end - ip_offset; |
| #if 0 |
| printf("p %d/%s q %d/%s offset calculated %d\n", |
| p ? p->ptag : -1, p ? libnet_diag_dump_pblock_type(p->type) : "nil", |
| q->ptag, libnet_diag_dump_pblock_type(q->type), |
| ip_offset); |
| #endif |
| c = libnet_inet_checksum(l, iph, |
| libnet_pblock_p2p(q->type), q->h_len, |
| beg, end); |
| if (c == -1) |
| { |
| /* err msg set in libnet_do_checksum() */ |
| goto err; |
| } |
} |
} |
|
q = p; |
} |
} |
|
} |
|
else |
|
{ |
q = p; |
q = p; |
} |
} |
} |
} |
else |
|
{ |
|
q = p; |
|
} |
|
} |
} |
*size = l->aligner + l->total_size; |
*size = l->aligner + l->total_size; |
|
|
Line 419 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
Line 531 libnet_pblock_coalesce(libnet_t *l, u_int8_t **packet,
|
*size -= l->aligner; |
*size -= l->aligner; |
} |
} |
return (1); |
return (1); |
|
|
|
err: |
|
free(*packet); |
|
*packet = NULL; |
|
return (-1); |
} |
} |
|
|
void |
void |
Line 428 libnet_pblock_delete(libnet_t *l, libnet_pblock_t *p)
|
Line 545 libnet_pblock_delete(libnet_t *l, libnet_pblock_t *p)
|
{ |
{ |
l->total_size -= p->b_len; |
l->total_size -= p->b_len; |
l->n_pblocks--; |
l->n_pblocks--; |
if (p->prev) |
|
{ |
|
p->prev->next = p->next; |
|
} |
|
else |
|
{ |
|
l->protocol_blocks = p->next; |
|
} |
|
|
|
if (p->next) | libnet_pblock_remove_from_list(l, p); |
{ | |
p->next->prev = p->prev; | |
} | |
else | |
{ | |
l->pblock_end = p->prev; | |
} | |
|
|
if (p->buf) |
if (p->buf) |
{ |
{ |
free(p->buf); | free(p->buf); |
| p->buf = NULL; |
} |
} |
|
|
free(p); |
free(p); |
p = NULL; |
|
} |
} |
} |
} |
|
|
int |
int |
libnet_pblock_p2p(u_int8_t type) | libnet_pblock_p2p(uint8_t type) |
{ |
{ |
/* for checksum; return the protocol number given a pblock type*/ |
/* for checksum; return the protocol number given a pblock type*/ |
switch (type) |
switch (type) |
Line 472 libnet_pblock_p2p(u_int8_t type)
|
Line 574 libnet_pblock_p2p(u_int8_t type)
|
case LIBNET_PBLOCK_ICMPV4_REDIRECT_H: |
case LIBNET_PBLOCK_ICMPV4_REDIRECT_H: |
case LIBNET_PBLOCK_ICMPV4_TS_H: |
case LIBNET_PBLOCK_ICMPV4_TS_H: |
return (IPPROTO_ICMP); |
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: |
case LIBNET_PBLOCK_IGMP_H: |
return (IPPROTO_IGMP); |
return (IPPROTO_IGMP); |
case LIBNET_PBLOCK_IPV4_H: |
case LIBNET_PBLOCK_IPV4_H: |
return (IPPROTO_IP); |
return (IPPROTO_IP); |
|
case LIBNET_PBLOCK_IPV6_H: |
|
return (IPPROTO_IPV6); |
case LIBNET_ISL_H: |
case LIBNET_ISL_H: |
return (LIBNET_PROTO_ISL); |
return (LIBNET_PROTO_ISL); |
case LIBNET_PBLOCK_OSPF_H: |
case LIBNET_PBLOCK_OSPF_H: |
Line 496 libnet_pblock_p2p(u_int8_t type)
|
Line 606 libnet_pblock_p2p(u_int8_t type)
|
} |
} |
|
|
void |
void |
libnet_pblock_record_ip_offset(libnet_t *l, u_int32_t offset) | libnet_pblock_record_ip_offset(libnet_t *l, libnet_pblock_t *p) |
{ |
{ |
libnet_pblock_t *p = l->pblock_end; | (void) l; |
| (void) p; |
do | /* For backwards compatibility, libnet_pblock_t no longer includes |
{ | an ip_offset, so calling this is unnecessary. |
p->ip_offset = offset; | */ |
p = p->prev; | |
} while (p && p->type != LIBNET_PBLOCK_IPV4_H); | |
} |
} |
|
|
| /** |
/* EOF */ | * Local Variables: |
| * indent-tabs-mode: nil |
| * c-file-style: "stroustrup" |
| * End: |
| */ |