1 /*
2 * Regression test for bugs in ipv4 ip_offset and h_len handling, such as
3 * http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=418975
4 *
5 * Copyright (c) 2009 Sam Roberts <sroberts@wurldtech.com>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30 #if (HAVE_CONFIG_H)
31 #include "../include/config.h"
32 #endif
33 #include "./libnet_test.h"
34
35 #include <assert.h>
36
assert_eq_(long have,long want,const char * file,int line)37 static void assert_eq_(long have, long want, const char* file, int line) {
38 if(have != want) {
39 printf("%s:%d: fail - have %ld want %ld\n", file, line, have, want);
40 abort();
41 }
42 }
43 #define assert_eq(have, want) assert_eq_(have, want, __FILE__, __LINE__)
44
45
print_pblocks(libnet_t * l)46 static void print_pblocks(libnet_t* l)
47 {
48 libnet_pblock_t* p = l->protocol_blocks;
49
50 while(p) {
51 printf(" tag %2d flags %d type %20s/%#x buf %p b_len %2u h_len %2u copied %2u\n",
52 p->ptag, p->flags,
53 libnet_diag_dump_pblock_type(p->type), p->type,
54 p->buf, p->b_len, p->h_len, p->copied);
55 p = p->next;
56 }
57 printf(" link_offset %d aligner %d total_size %u nblocks %d\n",
58 l->link_offset, l->aligner, l->total_size, l->n_pblocks);
59
60 }
61
ptag_error(libnet_t * l,int ptag)62 static void ptag_error(libnet_t* l, int ptag)
63 {
64 if(ptag <= 0) {
65 printf("error: %s\n", libnet_geterror(l));
66 }
67 assert(ptag > 0);
68 }
69
build_ipo(libnet_t * l,libnet_ptag_t ptag,int payload_s)70 static int build_ipo(libnet_t* l, libnet_ptag_t ptag, int payload_s)
71 {
72 uint8_t* payload = malloc(payload_s);
73 assert(payload);
74 memset(payload, '\x88', payload_s);
75
76 ptag = libnet_build_ipv4_options(payload, payload_s, l, ptag);
77
78 ptag_error(l, ptag);
79
80 free(payload);
81
82 return ptag;
83 }
84
build_ipv4(libnet_t * l,libnet_ptag_t ptag,int payload_s,int ip_len)85 static int build_ipv4(libnet_t* l, libnet_ptag_t ptag, int payload_s, int ip_len)
86 {
87 u_long src_ip = 0xf101f1f1;
88 u_long dst_ip = 0xf102f1f1;
89 uint8_t* payload = malloc(payload_s);
90 assert(payload);
91 memset(payload, '\x99', payload_s);
92
93 if(!ip_len) {
94 ip_len = LIBNET_IPV4_H + payload_s;
95 }
96
97 ptag = libnet_build_ipv4(
98 ip_len, /* length */
99 0, /* TOS */
100 0xbbbb, /* IP ID */
101 0, /* IP Frag */
102 0xcc, /* TTL */
103 IPPROTO_UDP, /* protocol */
104 0, /* checksum */
105 src_ip, /* source IP */
106 dst_ip, /* destination IP */
107 payload_s ? payload : NULL, /* payload */
108 payload_s, /* payload size */
109 l, /* libnet handle */
110 ptag); /* libnet id */
111
112 ptag_error(l, ptag);
113
114 free(payload);
115
116 return ptag;
117 }
118
build_ethernet(libnet_t * l,libnet_ptag_t ptag)119 static int build_ethernet(libnet_t* l, libnet_ptag_t ptag)
120 {
121 uint8_t enet_src[6] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
122 uint8_t enet_dst[6] = {0x22, 0x22, 0x22, 0x22, 0x22, 0x22};
123
124 ptag = libnet_build_ethernet(
125 enet_dst, /* ethernet destination */
126 enet_src, /* ethernet source */
127 ETHERTYPE_IP, /* protocol type */
128 NULL, /* payload */
129 0, /* payload size */
130 l, /* libnet handle */
131 ptag); /* libnet id */
132
133 ptag_error(l, ptag);
134
135 return ptag;
136 }
137
138 static
assert_lengths(libnet_t * l,int ip_len,int ip_ihl,int payload_s)139 void assert_lengths(libnet_t* l, int ip_len, int ip_ihl, int payload_s)
140 {
141 uint8_t* pkt1 = NULL;
142 uint32_t pkt1_sz = 0;
143 struct libnet_ipv4_hdr* h1;
144 uint8_t* payload = NULL;
145
146
147 int r = libnet_pblock_coalesce(l, &pkt1, &pkt1_sz);
148 assert(r >= 0);
149
150 print_pblocks(l);
151
152 libnet_diag_dump_hex(pkt1, 14, 1, stdout);
153 libnet_diag_dump_hex(pkt1+14, pkt1_sz-14, 1, stdout);
154
155 /* check ip IHL value, total ip pkt length, and options value */
156 h1 = (struct libnet_ipv4_hdr*) (pkt1+14);
157 assert_eq(h1->ip_hl, ip_ihl);
158 assert_eq(ntohs(h1->ip_len), ip_len);
159
160 payload = ((uint8_t*) h1) + ip_ihl * 4;
161 if(payload_s > 0) {
162 assert(payload[0] == (uint8_t)'\x99');
163 assert(payload[payload_s-1] == (uint8_t)'\x99');
164 }
165 }
166
167 int
main(int argc,char * argv[])168 main(int argc, char *argv[])
169 {
170 libnet_t *l;
171 char *device = "eth0";
172 char errbuf[LIBNET_ERRBUF_SIZE];
173 libnet_ptag_t ipo_ptag = 0;
174 libnet_ptag_t ip_ptag = 0;
175 libnet_ptag_t eth_ptag = 0;
176 int ip_len = 0;
177
178 l = libnet_init( LIBNET_LINK, device, errbuf);
179
180 assert(l);
181
182 printf("Packet: options=4, payload=0\n");
183
184 ip_len = 20 + 4 + 0; /* ip + options + payload */
185 ipo_ptag = build_ipo(l, ipo_ptag, 4);
186 ip_ptag = build_ipv4(l, ip_ptag, 0, 24);
187 eth_ptag = build_ethernet(l, eth_ptag);
188
189 assert_lengths(l, 24, 6, 0);
190
191 ipo_ptag = ip_ptag = eth_ptag = 0;
192
193 libnet_clear_packet(l);
194
195 printf("Packet: options=3, payload=1\n");
196
197 ip_len = 20 + 4 + 1; /* ip + options + payload */
198 ipo_ptag = build_ipo(l, ipo_ptag, 3);
199 ip_ptag = build_ipv4(l, ip_ptag, 1, 25);
200 eth_ptag = build_ethernet(l, eth_ptag);
201
202 assert_lengths(l, 25, 6, 1);
203
204 ipo_ptag = ip_ptag = eth_ptag = 0;
205
206 libnet_clear_packet(l);
207
208 printf("Packet: options=3, payload=1\n");
209
210 ip_len = 20 + 4 + 1; /* ip + options + payload */
211 ipo_ptag = build_ipo(l, ipo_ptag, 3);
212 ip_ptag = build_ipv4(l, ip_ptag, 1, ip_len);
213 eth_ptag = build_ethernet(l, eth_ptag);
214
215 assert_lengths(l, 25, 6, 1);
216
217 printf("... modify -> options=40\n");
218
219 ip_len = 20 + 40 + 1; /* ip + options + payload */
220 ipo_ptag = build_ipo(l, ipo_ptag, 40);
221
222 assert_lengths(l, ip_len, 15, 1);
223
224 printf("... modify -> options=0\n");
225
226 ip_len = 20 + 0 + 1; /* ip + options + payload */
227 ipo_ptag = build_ipo(l, ipo_ptag, 0);
228
229 assert_lengths(l, ip_len, 5, 1);
230
231 printf("... modify -> options=5\n");
232
233 ip_len = 20 + 8 + 1; /* ip + options + payload */
234 ipo_ptag = build_ipo(l, ipo_ptag, 5);
235
236 assert_lengths(l, ip_len, 7, 1);
237
238 printf("... modify -> ip_payload=5\n");
239
240 ip_len = 20 + 8 + 5; /* ip + options + payload */
241 ip_ptag = build_ipv4(l, ip_ptag, 5, ip_len);
242
243 assert_lengths(l, ip_len, 7, 1);
244
245 ipo_ptag = ip_ptag = eth_ptag = 0;
246
247 libnet_clear_packet(l);
248
249
250 return (EXIT_SUCCESS);
251 }
252
253