version 1.1.1.1, 2012/02/21 22:14:23
|
version 1.1.1.2, 2013/07/22 11:54:42
|
Line 40
|
Line 40
|
#endif |
#endif |
|
|
libnet_ptag_t |
libnet_ptag_t |
libnet_build_tcp(u_int16_t sp, u_int16_t dp, u_int32_t seq, u_int32_t ack, | libnet_build_tcp( |
u_int8_t control, u_int16_t win, u_int16_t sum, u_int16_t urg, u_int16_t len, | uint16_t sp, uint16_t dp, uint32_t seq, uint32_t ack, |
u_int8_t *payload, u_int32_t payload_s, libnet_t *l, libnet_ptag_t ptag) | uint8_t control, uint16_t win, uint16_t sum, uint16_t urg, uint16_t h_len, |
| const uint8_t *payload, uint32_t payload_s, libnet_t *l, libnet_ptag_t ptag) |
{ |
{ |
int n, offset; |
int n, offset; |
u_int32_t i, j; | libnet_pblock_t *p = NULL; |
libnet_pblock_t *p, *p_data, *p_temp; | libnet_ptag_t ptag_data = 0; |
libnet_ptag_t ptag_hold, ptag_data; | |
struct libnet_tcp_hdr tcp_hdr; |
struct libnet_tcp_hdr tcp_hdr; |
struct libnet_ipv4_hdr *ip_hdr; |
|
|
|
if (l == NULL) |
if (l == NULL) |
{ | return -1; |
return (-1); | |
} | |
|
|
ptag_data = 0; /* for possible options */ | if (payload_s && !payload) |
| { |
| snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
| "%s(): payload inconsistency\n", __func__); |
| return -1; |
| } |
|
|
/* |
|
* Find the existing protocol block if a ptag is specified, or create |
|
* a new one. |
|
*/ |
|
p = libnet_pblock_probe(l, ptag, LIBNET_TCP_H, LIBNET_PBLOCK_TCP_H); |
p = libnet_pblock_probe(l, ptag, LIBNET_TCP_H, LIBNET_PBLOCK_TCP_H); |
if (p == NULL) |
if (p == NULL) |
{ | return -1; |
return (-1); | |
} | |
|
|
memset(&tcp_hdr, 0, sizeof(tcp_hdr)); |
memset(&tcp_hdr, 0, sizeof(tcp_hdr)); |
tcp_hdr.th_sport = htons(sp); /* source port */ |
tcp_hdr.th_sport = htons(sp); /* source port */ |
Line 78 u_int8_t *payload, u_int32_t payload_s, libnet_t *l, l
|
Line 74 u_int8_t *payload, u_int32_t payload_s, libnet_t *l, l
|
tcp_hdr.th_off = 5; /* 20 byte header */ |
tcp_hdr.th_off = 5; /* 20 byte header */ |
|
|
/* check to see if there are TCP options to include */ |
/* check to see if there are TCP options to include */ |
if (p->prev) | if (p->prev && p->prev->type == LIBNET_PBLOCK_TCPO_H) |
{ |
{ |
p_temp = p->prev; | /* Note that the tcp options pblock is already padded */ |
while ((p_temp->prev) && (p_temp->type != LIBNET_PBLOCK_TCPO_H)) | tcp_hdr.th_off += (p->prev->b_len/4); |
{ | |
p_temp = p_temp->prev; | |
} | |
if (p_temp->type == LIBNET_PBLOCK_TCPO_H) | |
{ | |
/* | |
* Count up number of 32-bit words in options list, padding if | |
* neccessary. | |
*/ | |
for (i = 0, j = 0; i < p_temp->b_len; i++) | |
{ | |
(i % 4) ? j : j++; | |
} | |
tcp_hdr.th_off += j; | |
} | |
} |
} |
|
|
tcp_hdr.th_win = htons(win); /* window size */ |
tcp_hdr.th_win = htons(win); /* window size */ |
tcp_hdr.th_sum = (sum ? htons(sum) : 0); /* checksum */ |
tcp_hdr.th_sum = (sum ? htons(sum) : 0); /* checksum */ |
tcp_hdr.th_urp = htons(urg); /* urgent pointer */ |
tcp_hdr.th_urp = htons(urg); /* urgent pointer */ |
|
|
n = libnet_pblock_append(l, p, (u_int8_t *)&tcp_hdr, LIBNET_TCP_H); | n = libnet_pblock_append(l, p, (uint8_t *)&tcp_hdr, LIBNET_TCP_H); |
if (n == -1) |
if (n == -1) |
{ |
{ |
goto bad; |
goto bad; |
} |
} |
|
|
ptag_hold = ptag; |
|
if (ptag == LIBNET_PTAG_INITIALIZER) |
if (ptag == LIBNET_PTAG_INITIALIZER) |
{ |
{ |
ptag = libnet_pblock_update(l, p, len, LIBNET_PBLOCK_TCP_H); | libnet_pblock_update(l, p, h_len, LIBNET_PBLOCK_TCP_H); |
} |
} |
|
|
/* find and set the appropriate ptag, or else use the default of 0 */ |
|
offset = payload_s; |
offset = payload_s; |
if (ptag_hold && p->prev) | |
| /* If we are going to modify a TCP data block, find it, and figure out the |
| * "offset", the possibly negative amount by which we are increasing the ip |
| * data length. */ |
| if (ptag) |
{ |
{ |
p_temp = p->prev; | libnet_pblock_t* datablock = p->prev; |
while (p_temp->prev && | |
(p_temp->type != LIBNET_PBLOCK_TCPDATA) && | |
(p_temp->type != LIBNET_PBLOCK_TCP_H)) | |
{ | |
p_temp = p_temp->prev; | |
} | |
|
|
if (p_temp->type == LIBNET_PBLOCK_TCPDATA) | if (datablock && datablock->type == LIBNET_PBLOCK_TCPO_H) |
| datablock = datablock->prev; |
| |
| if (datablock && datablock->type == LIBNET_PBLOCK_TCPDATA) |
{ |
{ |
ptag_data = p_temp->ptag; | ptag_data = datablock->ptag; |
offset -= p_temp->b_len; | offset -= datablock->b_len; |
p->h_len += offset; | |
} |
} |
else | p->h_len += offset; |
{ | } |
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, | |
"%s(): TCP data pblock not found\n", __func__); | |
} | |
} | |
|
|
/* update ip_len if present */ | /* If we are modifying a TCP block, we should look forward and apply the offset |
if (ptag_hold && p->next) | * to our IPv4 header, if we have one. |
| */ |
| if (p->next) |
{ |
{ |
p_temp = p->next; | libnet_pblock_t* ipblock = p->next; |
while (p_temp->next && (p_temp->type != LIBNET_PBLOCK_IPV4_H)) | |
| if(ipblock->type == LIBNET_PBLOCK_IPO_H) |
| ipblock = ipblock->next; |
| |
| if(ipblock && ipblock->type == LIBNET_PBLOCK_IPV4_H) |
{ |
{ |
p_temp = p_temp->next; | struct libnet_ipv4_hdr * ip_hdr = (struct libnet_ipv4_hdr *)ipblock->buf; |
| int ip_len = ntohs(ip_hdr->ip_len) + offset; |
| ip_hdr->ip_len = htons(ip_len); |
} |
} |
if (p_temp->type == LIBNET_PBLOCK_IPV4_H) |
|
{ |
|
ip_hdr = (struct libnet_ipv4_hdr *)p_temp->buf; |
|
n = ntohs(ip_hdr->ip_len) + offset; |
|
ip_hdr->ip_len = htons(n); |
|
} |
|
} |
} |
|
|
if ((payload && !payload_s) || (!payload && payload_s)) |
|
{ |
|
snprintf(l->err_buf, LIBNET_ERRBUF_SIZE, |
|
"%s(): payload inconsistency\n", __func__); |
|
goto bad; |
|
} |
|
|
|
/* if there is a payload, add it in the context */ |
/* if there is a payload, add it in the context */ |
if (payload && payload_s) | if (payload_s) |
{ |
{ |
/* update ptag_data with the new payload */ |
/* update ptag_data with the new payload */ |
p_data = libnet_pblock_probe(l, ptag_data, payload_s, | libnet_pblock_t* p_data = libnet_pblock_probe(l, ptag_data, payload_s, LIBNET_PBLOCK_TCPDATA); |
LIBNET_PBLOCK_TCPDATA); | if (!p_data) |
if (p_data == NULL) | |
{ |
{ |
return (-1); | goto bad; |
} |
} |
|
|
if (libnet_pblock_append(l, p_data, payload, payload_s) == -1) | n = libnet_pblock_append(l, p_data, payload, payload_s); |
| if (n == -1) |
{ |
{ |
goto bad; |
goto bad; |
} |
} |
|
|
if (ptag_data == LIBNET_PTAG_INITIALIZER) |
if (ptag_data == LIBNET_PTAG_INITIALIZER) |
{ |
{ |
if (p_data->prev->type == LIBNET_PBLOCK_TCP_H) | int insertbefore = p->ptag; |
{ | |
libnet_pblock_update(l, p_data, payload_s, | |
LIBNET_PBLOCK_TCPDATA); | |
/* swap pblocks to correct the protocol order */ | |
libnet_pblock_swap(l, p->ptag, p_data->ptag); | |
} | |
else | |
{ | |
/* update without setting this as the final pblock */ | |
p_data->type = LIBNET_PBLOCK_TCPDATA; | |
p_data->ptag = ++(l->ptag_state); | |
p_data->h_len = payload_s; | |
|
|
/* Adjust h_len for checksum. */ | /* Then we created it, and we need to shuffle it back until it's before |
p->h_len += payload_s; | * the tcp header and options. */ |
| libnet_pblock_update(l, p_data, payload_s, LIBNET_PBLOCK_TCPDATA); |
|
|
/* data was added after the initial construction */ | if(p->prev && p->prev->type == LIBNET_PBLOCK_TCPO_H) |
for (p_temp = l->protocol_blocks; | insertbefore = p->prev->ptag; |
p_temp->type == LIBNET_PBLOCK_TCP_H || | |
p_temp->type == LIBNET_PBLOCK_TCPO_H; | |
p_temp = p_temp->next) | |
{ | |
libnet_pblock_insert_before(l, p_temp->ptag, p_data->ptag); | |
break; | |
} | |
/* The end block needs to have its next pointer cleared. */ | |
l->pblock_end->next = NULL; | |
} | |
|
|
if (p_data->prev && p_data->prev->type == LIBNET_PBLOCK_TCPO_H) | libnet_pblock_insert_before(l, insertbefore, p_data->ptag); |
{ | |
libnet_pblock_swap(l, p_data->prev->ptag, p_data->ptag); | |
} | |
} |
} |
} |
} |
else |
else |
{ |
{ |
p_data = libnet_pblock_find(l, ptag_data); | libnet_pblock_t* p_data = libnet_pblock_find(l, ptag_data); |
if (p_data) | libnet_pblock_delete(l, p_data); |
{ | |
libnet_pblock_delete(l, p_data); | |
} | |
} |
} |
|
|
if (sum == 0) |
if (sum == 0) |
Line 235 u_int8_t *payload, u_int32_t payload_s, libnet_t *l, l
|
Line 178 u_int8_t *payload, u_int32_t payload_s, libnet_t *l, l
|
*/ |
*/ |
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); |
libnet_pblock_setflags(p, LIBNET_PBLOCK_DO_CHECKSUM); |
} |
} |
return (ptag); | return (p->ptag); |
bad: |
bad: |
libnet_pblock_delete(l, p); |
libnet_pblock_delete(l, p); |
return (-1); |
return (-1); |
} |
} |
|
|
|
|
libnet_ptag_t |
libnet_ptag_t |
libnet_build_tcp_options(u_int8_t *options, u_int32_t options_s, libnet_t *l, | libnet_build_tcp_options(const uint8_t *options, uint32_t options_s, libnet_t *l, |
libnet_ptag_t ptag) |
libnet_ptag_t ptag) |
{ |
{ |
int offset, underflow; | static const uint8_t padding[] = { 0 }; |
u_int32_t i, j, n, adj_size; | int n, offset, underflow; |
| uint32_t i, j, adj_size; |
libnet_pblock_t *p, *p_temp; |
libnet_pblock_t *p, *p_temp; |
struct libnet_ipv4_hdr *ip_hdr; |
struct libnet_ipv4_hdr *ip_hdr; |
struct libnet_tcp_hdr *tcp_hdr; |
struct libnet_tcp_hdr *tcp_hdr; |
Line 302 libnet_ptag_t ptag)
|
Line 245 libnet_ptag_t ptag)
|
{ |
{ |
return (-1); |
return (-1); |
} |
} |
| |
n = libnet_pblock_append(l, p, options, adj_size); | n = libnet_pblock_append(l, p, options, options_s); |
if (n == -1) |
if (n == -1) |
{ |
{ |
goto bad; |
goto bad; |
} |
} |
| |
| n = libnet_pblock_append(l, p, padding, adj_size - options_s); |
| if (n == -1) |
| { |
| goto bad; |
| } |
| |
if (ptag && p->next) |
if (ptag && p->next) |
{ |
{ |
p_temp = p->next; |
p_temp = p->next; |