/src/suricata8/src/decode-ipv4.c
Line | Count | Source |
1 | | /* Copyright (C) 2007-2024 Open Information Security Foundation |
2 | | * |
3 | | * You can copy, redistribute or modify this Program under the terms of |
4 | | * the GNU General Public License version 2 as published by the Free |
5 | | * Software Foundation. |
6 | | * |
7 | | * This program is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | | * GNU General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU General Public License |
13 | | * version 2 along with this program; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
15 | | * 02110-1301, USA. |
16 | | */ |
17 | | |
18 | | /** |
19 | | * \ingroup decode |
20 | | * |
21 | | * @{ |
22 | | */ |
23 | | |
24 | | |
25 | | /** |
26 | | * \file |
27 | | * |
28 | | * \author Victor Julien <victor@inliniac.net> |
29 | | * \author Brian Rectanus <brectanu@gmail.com> |
30 | | * |
31 | | * Decode IPv4 |
32 | | */ |
33 | | |
34 | | #include "suricata-common.h" |
35 | | #include "decode-ipv4.h" |
36 | | #include "decode.h" |
37 | | #include "defrag.h" |
38 | | #include "flow.h" |
39 | | #include "util-print.h" |
40 | | |
41 | | /* Generic validation |
42 | | * |
43 | | * [--type--][--len---] |
44 | | * |
45 | | * \todo This function needs removed in favor of specific validation. |
46 | | * |
47 | | * See: RFC 791 |
48 | | */ |
49 | | static int IPV4OptValidateGeneric(Packet *p, const IPV4Opt *o) |
50 | 54.8k | { |
51 | 54.8k | switch (o->type) { |
52 | | /* See: RFC 4782 */ |
53 | 2.61k | case IPV4_OPT_QS: |
54 | 2.61k | if (o->len < IPV4_OPT_QS_MIN) { |
55 | 2.08k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
56 | 2.08k | return -1; |
57 | 2.08k | } |
58 | 524 | break; |
59 | | /* See: RFC 1108 */ |
60 | 20.7k | case IPV4_OPT_SEC: |
61 | 21.9k | case IPV4_OPT_ESEC: |
62 | 21.9k | if (unlikely(o->len < IPV4_OPT_SEC_MIN)) { |
63 | 20.0k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
64 | 20.0k | return -1; |
65 | 20.0k | } |
66 | 1.90k | break; |
67 | 4.21k | case IPV4_OPT_SID: |
68 | 4.21k | if (o->len != IPV4_OPT_SID_LEN) { |
69 | 3.80k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
70 | 3.80k | return -1; |
71 | 3.80k | } |
72 | 413 | break; |
73 | | /* See: RFC 2113 */ |
74 | 26.1k | case IPV4_OPT_RTRALT: |
75 | 26.1k | if (o->len != IPV4_OPT_RTRALT_LEN) { |
76 | 3.98k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
77 | 3.98k | return -1; |
78 | 3.98k | } |
79 | 22.1k | break; |
80 | 22.1k | default: |
81 | | /* Should never get here unless there is a coding error */ |
82 | 0 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_UNKNOWN); |
83 | 0 | return -1; |
84 | 54.8k | } |
85 | | |
86 | 24.9k | return 0; |
87 | 54.8k | } |
88 | | |
89 | | /* Validate route type options |
90 | | * |
91 | | * [--type--][--len---][--ptr---][address1]...[addressN] |
92 | | * |
93 | | * See: RFC 791 |
94 | | */ |
95 | | static int IPV4OptValidateRoute(Packet *p, const IPV4Opt *o) |
96 | 75.1k | { |
97 | 75.1k | uint8_t ptr; |
98 | | |
99 | | /* Check length */ |
100 | 75.1k | if (unlikely(o->len < IPV4_OPT_ROUTE_MIN)) { |
101 | 60.8k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
102 | 60.8k | return -1; |
103 | 60.8k | } |
104 | | |
105 | | /* Data is required */ |
106 | 14.3k | if (unlikely(o->data == NULL)) { |
107 | 0 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
108 | 0 | return -1; |
109 | 0 | } |
110 | 14.3k | ptr = *o->data; |
111 | | |
112 | | /* Address pointer is 1 based and points at least after type+len+ptr, |
113 | | * must be a incremented by 4 bytes (address size) and cannot extend |
114 | | * past option length. |
115 | | */ |
116 | 14.3k | if (unlikely((ptr < 4) || (ptr % 4) || (ptr > o->len + 1))) { |
117 | 9.53k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
118 | 9.53k | return -1; |
119 | 9.53k | } |
120 | | |
121 | 4.79k | return 0; |
122 | 14.3k | } |
123 | | |
124 | | /* Validate timestamp type options |
125 | | * |
126 | | * [--type--][--len---][--ptr---][ovfl][flag][rec1----...]...[recN----...] |
127 | | * NOTE: rec could be 4 (ts only) or 8 (ip+ts) bytes in length. |
128 | | * |
129 | | * See: RFC 781 |
130 | | */ |
131 | | static int IPV4OptValidateTimestamp(Packet *p, const IPV4Opt *o) |
132 | 6.43k | { |
133 | 6.43k | uint8_t ptr; |
134 | 6.43k | uint8_t flag; |
135 | 6.43k | uint8_t rec_size; |
136 | | |
137 | | /* Check length */ |
138 | 6.43k | if (unlikely(o->len < IPV4_OPT_TS_MIN)) { |
139 | 2.86k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
140 | 2.86k | return -1; |
141 | 2.86k | } |
142 | | |
143 | | /* Data is required */ |
144 | 3.57k | if (unlikely(o->data == NULL)) { |
145 | 0 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
146 | 0 | return -1; |
147 | 0 | } |
148 | 3.57k | ptr = *o->data; |
149 | | |
150 | | /* We need the flag to determine what is in the option payload */ |
151 | 3.57k | if (unlikely(ptr < 5)) { |
152 | 1.07k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
153 | 1.07k | return -1; |
154 | 1.07k | } |
155 | 2.49k | flag = *(o->data + 1) & 0x0f; |
156 | | |
157 | | /* A flag of 1|3 means we have both the ip+ts in each record */ |
158 | 2.49k | rec_size = ((flag == 1) || (flag == 3)) ? 8 : 4; |
159 | | |
160 | | /* Address pointer is 1 based and points at least after |
161 | | * type+len+ptr+ovfl+flag, must be incremented by by the rec_size |
162 | | * and cannot extend past option length. |
163 | | */ |
164 | 2.49k | if (unlikely(((ptr - 5) % rec_size) || (ptr > o->len + 1))) { |
165 | 1.70k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
166 | 1.70k | return -1; |
167 | 1.70k | } |
168 | | |
169 | 793 | return 0; |
170 | 2.49k | } |
171 | | |
172 | | /* Validate CIPSO option |
173 | | * |
174 | | * [--type--][--len---][--doi---][tags--...] |
175 | | * |
176 | | * See: draft-ietf-cipso-ipsecurity-01.txt |
177 | | * See: FIPS 188 (tags 6 & 7) |
178 | | */ |
179 | | static int IPV4OptValidateCIPSO(Packet *p, const IPV4Opt *o) |
180 | 12.6k | { |
181 | | // uint32_t doi; |
182 | 12.6k | const uint8_t *tag; |
183 | 12.6k | uint16_t len; |
184 | | |
185 | | /* Check length */ |
186 | 12.6k | if (unlikely(o->len < IPV4_OPT_CIPSO_MIN)) { |
187 | 5.70k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
188 | 5.70k | return -1; |
189 | 5.70k | } |
190 | | |
191 | | /* Data is required */ |
192 | 6.94k | if (unlikely(o->data == NULL)) { |
193 | 0 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
194 | 0 | return -1; |
195 | 0 | } |
196 | | // doi = *o->data; |
197 | 6.94k | tag = o->data + 4; |
198 | 6.94k | len = o->len - 1 - 1 - 4; /* Length of tags after header */ |
199 | | |
200 | | |
201 | | #if 0 |
202 | | /* Domain of Interest (DOI) of 0 is reserved and thus invalid */ |
203 | | /** \todo Apparently a DOI of zero is fine in practice - verify. */ |
204 | | if (doi == 0) { |
205 | | ENGINE_SET_EVENT(p,IPV4_OPT_MALFORMED); |
206 | | return -1; |
207 | | } |
208 | | #endif |
209 | | |
210 | | /* NOTE: We know len has passed min tests prior to this call */ |
211 | | |
212 | | /* Check that tags are formatted correctly |
213 | | * [-ttype--][--tlen--][-tagdata-...] |
214 | | */ |
215 | 7.67k | while (len) { |
216 | 7.18k | uint8_t ttype; |
217 | 7.18k | uint8_t tlen; |
218 | | |
219 | | /* Tag header must fit within option length */ |
220 | 7.18k | if (unlikely(len < 2)) { |
221 | | //printf("CIPSO tag header too large %" PRIu16 " < 2\n", len); |
222 | 105 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
223 | 105 | return -1; |
224 | 105 | } |
225 | | |
226 | | /* Tag header is type+len */ |
227 | 7.08k | ttype = *(tag++); |
228 | 7.08k | tlen = *(tag++); |
229 | | |
230 | | /* Tag length must fit within the option length */ |
231 | 7.08k | if (unlikely(tlen > len)) { |
232 | | //printf("CIPSO tag len too large %" PRIu8 " > %" PRIu16 "\n", tlen, len); |
233 | 398 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
234 | 398 | return -1; |
235 | 398 | } |
236 | | |
237 | 6.68k | switch(ttype) { |
238 | 442 | case 1: |
239 | 1.24k | case 2: |
240 | 1.75k | case 5: |
241 | 5.19k | case 6: |
242 | 5.41k | case 7: |
243 | | /* Tag is at least 4 and at most the remainder of option len */ |
244 | 5.41k | if (unlikely((tlen < 4) || (tlen > len))) { |
245 | | //printf("CIPSO tag %" PRIu8 " bad tlen=%" PRIu8 " len=%" PRIu8 "\n", ttype, tlen, len); |
246 | 3.27k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
247 | 3.27k | return -1; |
248 | 3.27k | } |
249 | | |
250 | | /* The alignment octet is always 0 except tag |
251 | | * type 7, which has no such field. |
252 | | */ |
253 | 2.14k | if (unlikely((ttype != 7) && (*tag != 0))) { |
254 | | //printf("CIPSO tag %" PRIu8 " ao=%" PRIu8 "\n", ttype, tlen); |
255 | 1.41k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
256 | 1.41k | return -1; |
257 | 1.41k | } |
258 | | |
259 | | /* Skip the rest of the tag payload */ |
260 | 730 | tag += tlen - 2; |
261 | 730 | len -= tlen; |
262 | | |
263 | 730 | continue; |
264 | 416 | case 0: |
265 | | /* Tag type 0 is reserved and thus invalid */ |
266 | | /** \todo Wireshark marks this a padding, but spec says reserved. */ |
267 | 416 | ENGINE_SET_INVALID_EVENT(p,IPV4_OPT_MALFORMED); |
268 | 416 | return -1; |
269 | 853 | default: |
270 | | //printf("CIPSO tag %" PRIu8 " unknown tag\n", ttype); |
271 | 853 | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_MALFORMED); |
272 | | /** \todo May not want to return error here on unknown tag type (at least not for 3|4) */ |
273 | 853 | return -1; |
274 | 6.68k | } |
275 | 6.68k | } |
276 | | |
277 | 491 | return 0; |
278 | 6.94k | } |
279 | | |
280 | | typedef struct IPV4Options_ { |
281 | | IPV4Opt o_rr; |
282 | | IPV4Opt o_qs; |
283 | | IPV4Opt o_ts; |
284 | | IPV4Opt o_sec; |
285 | | IPV4Opt o_lsrr; |
286 | | IPV4Opt o_esec; |
287 | | IPV4Opt o_cipso; |
288 | | IPV4Opt o_sid; |
289 | | IPV4Opt o_ssrr; |
290 | | IPV4Opt o_rtralt; |
291 | | } IPV4Options; |
292 | | |
293 | | /** |
294 | | * Decode/Validate IPv4 Options. |
295 | | */ |
296 | | static int DecodeIPV4Options(Packet *p, const uint8_t *pkt, uint16_t len, IPV4Options *opts) |
297 | 75.2k | { |
298 | 75.2k | uint16_t plen = len; |
299 | | |
300 | | #ifdef DEBUG |
301 | | if (SCLogDebugEnabled()) { |
302 | | uint16_t i; |
303 | | char buf[256] = ""; |
304 | | int offset = 0; |
305 | | |
306 | | for (i = 0; i < len; i++) { |
307 | | offset += snprintf(buf + offset, (sizeof(buf) - offset), "%02" PRIx8 " ", pkt[i]); |
308 | | } |
309 | | SCLogDebug("IPV4OPTS: { %s}", buf); |
310 | | } |
311 | | #endif |
312 | | |
313 | | /* Options length must be padded to 8byte boundary */ |
314 | 75.2k | if (plen % 8) { |
315 | 59.2k | ENGINE_SET_EVENT(p,IPV4_OPT_PAD_REQUIRED); |
316 | | /* Warn - we can keep going */ |
317 | 59.2k | } |
318 | | |
319 | 463k | while (plen) |
320 | 428k | { |
321 | 428k | p->l3.vars.ip4.opt_cnt++; |
322 | | |
323 | | /* single byte options */ |
324 | 428k | if (*pkt == IPV4_OPT_EOL) { |
325 | | /** \todo What if more data exist after EOL (possible covert channel or data leakage)? */ |
326 | 17.4k | SCLogDebug("IPV4OPT %" PRIu8 " len 1 @ %d/%d", |
327 | 17.4k | *pkt, (len - plen), (len - 1)); |
328 | 17.4k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_EOL; |
329 | 17.4k | break; |
330 | 411k | } else if (*pkt == IPV4_OPT_NOP) { |
331 | 5.07k | SCLogDebug("IPV4OPT %" PRIu8 " len 1 @ %d/%d", |
332 | 5.07k | *pkt, (len - plen), (len - 1)); |
333 | 5.07k | pkt++; |
334 | 5.07k | plen--; |
335 | | |
336 | 5.07k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_NOP; |
337 | | |
338 | | /* multibyte options */ |
339 | 406k | } else { |
340 | 406k | if (unlikely(plen < 2)) { |
341 | | /** \todo What if padding is non-zero (possible covert channel or data leakage)? */ |
342 | | /** \todo Spec seems to indicate EOL required if there is padding */ |
343 | 10.1k | ENGINE_SET_EVENT(p,IPV4_OPT_EOL_REQUIRED); |
344 | 10.1k | break; |
345 | 10.1k | } |
346 | | |
347 | | /* Option length is too big for packet */ |
348 | 396k | if (unlikely(*(pkt+1) > plen)) { |
349 | 8.00k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
350 | 8.00k | return -1; |
351 | 8.00k | } |
352 | | |
353 | 388k | IPV4Opt opt = {*pkt, *(pkt+1), plen > 2 ? (pkt + 2) : NULL }; |
354 | | |
355 | | /* we already know that the total options len is valid, |
356 | | * so here the len of the specific option must be bad. |
357 | | * Also check for invalid lengths 0 and 1. */ |
358 | 388k | if (unlikely(opt.len > plen || opt.len < 2)) { |
359 | 4.54k | ENGINE_SET_INVALID_EVENT(p, IPV4_OPT_INVALID_LEN); |
360 | 4.54k | return -1; |
361 | 4.54k | } |
362 | | /* we are parsing the most commonly used opts to prevent |
363 | | * us from having to walk the opts list for these all the |
364 | | * time. */ |
365 | | /** \todo Figure out which IP options are more common and list them first */ |
366 | 383k | switch (opt.type) { |
367 | 7.12k | case IPV4_OPT_TS: |
368 | 7.12k | if (opts->o_ts.type != 0) { |
369 | 685 | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
370 | | /* Warn - we can keep going */ |
371 | 6.43k | } else if (IPV4OptValidateTimestamp(p, &opt) == 0) { |
372 | 793 | opts->o_ts = opt; |
373 | 793 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_TS; |
374 | 793 | } |
375 | 7.12k | break; |
376 | 6.06k | case IPV4_OPT_RR: |
377 | 6.06k | if (opts->o_rr.type != 0) { |
378 | 162 | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
379 | | /* Warn - we can keep going */ |
380 | 5.90k | } else if (IPV4OptValidateRoute(p, &opt) == 0) { |
381 | 1.12k | opts->o_rr = opt; |
382 | 1.12k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_RR; |
383 | 1.12k | } |
384 | 6.06k | break; |
385 | 3.45k | case IPV4_OPT_QS: |
386 | 3.45k | if (opts->o_qs.type != 0) { |
387 | 839 | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
388 | | /* Warn - we can keep going */ |
389 | 2.61k | } else if (IPV4OptValidateGeneric(p, &opt) == 0) { |
390 | 524 | opts->o_qs = opt; |
391 | 524 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_QS; |
392 | 524 | } |
393 | 3.45k | break; |
394 | 21.3k | case IPV4_OPT_SEC: |
395 | 21.3k | if (opts->o_sec.type != 0) { |
396 | 656 | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
397 | | /* Warn - we can keep going */ |
398 | 20.7k | } else if (IPV4OptValidateGeneric(p, &opt) == 0) { |
399 | 1.12k | opts->o_sec = opt; |
400 | 1.12k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_SEC; |
401 | 1.12k | } |
402 | 21.3k | break; |
403 | 25.2k | case IPV4_OPT_LSRR: |
404 | 25.2k | if (opts->o_lsrr.type != 0) { |
405 | 1.38k | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
406 | | /* Warn - we can keep going */ |
407 | 23.8k | } else if (IPV4OptValidateRoute(p, &opt) == 0) { |
408 | 914 | opts->o_lsrr = opt; |
409 | 914 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_LSRR; |
410 | 914 | } |
411 | 25.2k | break; |
412 | 2.30k | case IPV4_OPT_ESEC: |
413 | 2.30k | if (opts->o_esec.type != 0) { |
414 | 1.08k | ENGINE_SET_EVENT(p, IPV4_OPT_DUPLICATE); |
415 | | /* Warn - we can keep going */ |
416 | 1.22k | } else if (IPV4OptValidateGeneric(p, &opt) == 0) { |
417 | 784 | opts->o_esec = opt; |
418 | 784 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_ESEC; |
419 | 784 | } |
420 | 2.30k | break; |
421 | 12.8k | case IPV4_OPT_CIPSO: |
422 | 12.8k | if (opts->o_cipso.type != 0) { |
423 | 199 | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
424 | | /* Warn - we can keep going */ |
425 | 12.6k | } else if (IPV4OptValidateCIPSO(p, &opt) == 0) { |
426 | 491 | opts->o_cipso = opt; |
427 | 491 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_CIPSO; |
428 | 491 | } |
429 | 12.8k | break; |
430 | 5.43k | case IPV4_OPT_SID: |
431 | 5.43k | if (opts->o_sid.type != 0) { |
432 | 1.21k | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
433 | | /* Warn - we can keep going */ |
434 | 4.21k | } else if (IPV4OptValidateGeneric(p, &opt) == 0) { |
435 | 413 | opts->o_sid = opt; |
436 | 413 | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_SID; |
437 | 413 | } |
438 | 5.43k | break; |
439 | 55.1k | case IPV4_OPT_SSRR: |
440 | 55.1k | if (opts->o_ssrr.type != 0) { |
441 | 9.75k | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
442 | | /* Warn - we can keep going */ |
443 | 45.4k | } else if (IPV4OptValidateRoute(p, &opt) == 0) { |
444 | 2.76k | opts->o_ssrr = opt; |
445 | 2.76k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_SSRR; |
446 | 2.76k | } |
447 | 55.1k | break; |
448 | 31.7k | case IPV4_OPT_RTRALT: |
449 | 31.7k | if (opts->o_rtralt.type != 0) { |
450 | 5.66k | ENGINE_SET_EVENT(p,IPV4_OPT_DUPLICATE); |
451 | | /* Warn - we can keep going */ |
452 | 26.1k | } else if (IPV4OptValidateGeneric(p, &opt) == 0) { |
453 | 22.1k | opts->o_rtralt = opt; |
454 | 22.1k | p->l3.vars.ip4.opts_set |= IPV4_OPT_FLAG_RTRALT; |
455 | 22.1k | } |
456 | 31.7k | break; |
457 | 212k | default: |
458 | 212k | SCLogDebug("IPV4OPT <unknown> (%" PRIu8 ") len %" PRIu8, |
459 | 212k | opt.type, opt.len); |
460 | 212k | ENGINE_SET_EVENT(p,IPV4_OPT_INVALID); |
461 | | /* Warn - we can keep going */ |
462 | 212k | break; |
463 | 383k | } |
464 | | |
465 | 383k | pkt += opt.len; |
466 | 383k | plen -= opt.len; |
467 | 383k | } |
468 | 428k | } |
469 | | |
470 | 62.7k | return 0; |
471 | 75.2k | } |
472 | | |
473 | | static const IPV4Hdr *DecodeIPV4Packet(Packet *p, const uint8_t *pkt, uint16_t len) |
474 | 10.1M | { |
475 | 10.1M | if (unlikely(len < IPV4_HEADER_LEN)) { |
476 | 29.5k | ENGINE_SET_INVALID_EVENT(p, IPV4_PKT_TOO_SMALL); |
477 | 29.5k | return NULL; |
478 | 29.5k | } |
479 | | |
480 | 10.0M | if (unlikely(IP_GET_RAW_VER(pkt) != 4)) { |
481 | 49.4k | SCLogDebug("wrong ip version %d",IP_GET_RAW_VER(pkt)); |
482 | 49.4k | ENGINE_SET_INVALID_EVENT(p, IPV4_WRONG_IP_VER); |
483 | 49.4k | return NULL; |
484 | 49.4k | } |
485 | | |
486 | 10.0M | const IPV4Hdr *ip4h = PacketSetIPV4(p, pkt); |
487 | | |
488 | 10.0M | if (unlikely(IPV4_GET_RAW_HLEN(ip4h) < IPV4_HEADER_LEN)) { |
489 | 4.92k | ENGINE_SET_INVALID_EVENT(p, IPV4_HLEN_TOO_SMALL); |
490 | 4.92k | return NULL; |
491 | 4.92k | } |
492 | | |
493 | 10.0M | if (unlikely(IPV4_GET_RAW_IPLEN(ip4h) < IPV4_GET_RAW_HLEN(ip4h))) { |
494 | 20.9k | ENGINE_SET_INVALID_EVENT(p, IPV4_IPLEN_SMALLER_THAN_HLEN); |
495 | 20.9k | return NULL; |
496 | 20.9k | } |
497 | | |
498 | 10.0M | if (unlikely(len < IPV4_GET_RAW_IPLEN(ip4h))) { |
499 | 417k | ENGINE_SET_INVALID_EVENT(p, IPV4_TRUNC_PKT); |
500 | 417k | return NULL; |
501 | 417k | } |
502 | | |
503 | | /* set the address struct */ |
504 | 9.59M | SET_IPV4_SRC_ADDR(ip4h, &p->src); |
505 | 9.59M | SET_IPV4_DST_ADDR(ip4h, &p->dst); |
506 | | |
507 | | /* save the options len */ |
508 | 9.59M | uint8_t ip_opt_len = IPV4_GET_RAW_HLEN(ip4h) - IPV4_HEADER_LEN; |
509 | 9.59M | if (ip_opt_len > 0) { |
510 | 75.2k | IPV4Options opts; |
511 | 75.2k | memset(&opts, 0x00, sizeof(opts)); |
512 | 75.2k | if (DecodeIPV4Options(p, pkt + IPV4_HEADER_LEN, ip_opt_len, &opts) < 0) { |
513 | 12.5k | return NULL; |
514 | 12.5k | } |
515 | 75.2k | } |
516 | | |
517 | 9.58M | return ip4h; |
518 | 9.59M | } |
519 | | |
520 | | int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, |
521 | | const uint8_t *pkt, uint16_t len) |
522 | 555k | { |
523 | 555k | StatsIncr(tv, dtv->counter_ipv4); |
524 | | |
525 | 555k | SCLogDebug("pkt %p len %"PRIu16"", pkt, len); |
526 | | |
527 | 555k | if (!PacketIncreaseCheckLayers(p)) { |
528 | 1 | return TM_ECODE_FAILED; |
529 | 1 | } |
530 | | /* do the actual decoding */ |
531 | 555k | const IPV4Hdr *ip4h = DecodeIPV4Packet(p, pkt, len); |
532 | 555k | if (unlikely(ip4h == NULL)) { |
533 | 3.20k | SCLogDebug("decoding IPv4 packet failed"); |
534 | 3.20k | PacketClearL3(p); |
535 | 3.20k | return TM_ECODE_FAILED; |
536 | 3.20k | } |
537 | 552k | p->proto = IPV4_GET_RAW_IPPROTO(ip4h); |
538 | | |
539 | | /* If a fragment, pass off for re-assembly. */ |
540 | 552k | if (unlikely(IPV4_GET_RAW_FRAGOFFSET(ip4h) > 0 || IPV4_GET_RAW_FLAG_MF(ip4h))) { |
541 | 67.6k | Packet *rp = Defrag(tv, dtv, p); |
542 | 67.6k | if (rp != NULL) { |
543 | 19.8k | PacketEnqueueNoLock(&tv->decode_pq, rp); |
544 | 19.8k | } |
545 | 67.6k | p->flags |= PKT_IS_FRAGMENT; |
546 | 67.6k | return TM_ECODE_OK; |
547 | 67.6k | } |
548 | | |
549 | | /* do hdr test, process hdr rules */ |
550 | | |
551 | | #ifdef DEBUG |
552 | | if (SCLogDebugEnabled()) { /* only convert the addresses if debug is really enabled */ |
553 | | /* debug print */ |
554 | | char s[16], d[16]; |
555 | | PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), s, sizeof(s)); |
556 | | PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), d, sizeof(d)); |
557 | | SCLogDebug("IPV4 %s->%s PROTO: %" PRIu32 " OFFSET: %" PRIu32 " RF: %" PRIu8 " DF: %" PRIu8 |
558 | | " MF: %" PRIu8 " ID: %" PRIu32 "", |
559 | | s, d, IPV4_GET_RAW_IPPROTO(ip4h), IPV4_GET_RAW_IPOFFSET(ip4h), |
560 | | IPV4_GET_RAW_FLAG_RF(ip4h), IPV4_GET_RAW_FLAG_DF(ip4h), IPV4_GET_RAW_FLAG_MF(ip4h), |
561 | | IPV4_GET_RAW_IPID(ip4h)); |
562 | | } |
563 | | #endif /* DEBUG */ |
564 | | |
565 | 484k | const uint8_t *data = pkt + IPV4_GET_RAW_HLEN(ip4h); |
566 | 484k | const uint16_t data_len = IPV4_GET_RAW_IPLEN(ip4h) - IPV4_GET_RAW_HLEN(ip4h); |
567 | | |
568 | | /* check what next decoder to invoke */ |
569 | 484k | switch (p->proto) { |
570 | 434k | case IPPROTO_TCP: |
571 | 434k | DecodeTCP(tv, dtv, p, data, data_len); |
572 | 434k | break; |
573 | 5.61k | case IPPROTO_UDP: |
574 | 5.61k | DecodeUDP(tv, dtv, p, data, data_len); |
575 | 5.61k | break; |
576 | 2.75k | case IPPROTO_ICMP: |
577 | 2.75k | DecodeICMPV4(tv, dtv, p, data, data_len); |
578 | 2.75k | break; |
579 | 21.0k | case IPPROTO_GRE: |
580 | 21.0k | DecodeGRE(tv, dtv, p, data, data_len); |
581 | 21.0k | break; |
582 | 42 | case IPPROTO_SCTP: |
583 | 42 | DecodeSCTP(tv, dtv, p, data, data_len); |
584 | 42 | break; |
585 | 61 | case IPPROTO_ESP: |
586 | 61 | DecodeESP(tv, dtv, p, data, data_len); |
587 | 61 | break; |
588 | 34 | case IPPROTO_IPV6: { |
589 | | /* spawn off tunnel packet */ |
590 | 34 | Packet *tp = PacketTunnelPktSetup(tv, dtv, p, data, data_len, DECODE_TUNNEL_IPV6); |
591 | 34 | if (tp != NULL) { |
592 | 16 | PKT_SET_SRC(tp, PKT_SRC_DECODER_IPV4); |
593 | 16 | PacketEnqueueNoLock(&tv->decode_pq, tp); |
594 | 16 | StatsIncr(tv, dtv->counter_ipv6inipv4); |
595 | 16 | } |
596 | 34 | FlowSetupPacket(p); |
597 | 34 | break; |
598 | 0 | } |
599 | 45 | case IPPROTO_IPIP: { |
600 | | /* spawn off tunnel packet */ |
601 | 45 | Packet *tp = PacketTunnelPktSetup(tv, dtv, p, data, data_len, DECODE_TUNNEL_IPV4); |
602 | 45 | if (tp != NULL) { |
603 | 18 | PKT_SET_SRC(tp, PKT_SRC_DECODER_IPV4); |
604 | 18 | PacketEnqueueNoLock(&tv->decode_pq, tp); |
605 | 18 | StatsIncr(tv, dtv->counter_ipv4inipv4); |
606 | 18 | } |
607 | 45 | FlowSetupPacket(p); |
608 | 45 | break; |
609 | 0 | } |
610 | 87 | case IPPROTO_IP: |
611 | | /* check PPP VJ uncompressed packets and decode tcp dummy */ |
612 | 87 | if (p->flags & PKT_PPP_VJ_UCOMP) { |
613 | 3 | DecodeTCP(tv, dtv, p, data, data_len); |
614 | 3 | } |
615 | 87 | break; |
616 | 22 | case IPPROTO_ICMPV6: |
617 | 22 | ENGINE_SET_INVALID_EVENT(p, IPV4_WITH_ICMPV6); |
618 | 22 | break; |
619 | 484k | } |
620 | | |
621 | 484k | return TM_ECODE_OK; |
622 | 484k | } |
623 | | |
624 | | /* UNITTESTS */ |
625 | | #ifdef UNITTESTS |
626 | | #include "packet.h" |
627 | | |
628 | | /** \test IPV4 with no options. */ |
629 | | static int DecodeIPV4OptionsNONETest01(void) |
630 | | { |
631 | | uint8_t raw_opts[] = { }; |
632 | | Packet *p = PacketGetFromAlloc(); |
633 | | FAIL_IF(unlikely(p == NULL)); |
634 | | |
635 | | IPV4Options opts; |
636 | | memset(&opts, 0x00, sizeof(opts)); |
637 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
638 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
639 | | |
640 | | SCFree(p); |
641 | | PASS; |
642 | | } |
643 | | |
644 | | /** \test IPV4 with EOL option. */ |
645 | | static int DecodeIPV4OptionsEOLTest01(void) |
646 | | { |
647 | | uint8_t raw_opts[] = { |
648 | | IPV4_OPT_EOL, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
649 | | }; |
650 | | Packet *p = PacketGetFromAlloc(); |
651 | | FAIL_IF(unlikely(p == NULL)); |
652 | | IPV4Options opts; |
653 | | memset(&opts, 0x00, sizeof(opts)); |
654 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
655 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
656 | | SCFree(p); |
657 | | PASS; |
658 | | } |
659 | | |
660 | | /** \test IPV4 with NOP option. */ |
661 | | static int DecodeIPV4OptionsNOPTest01(void) |
662 | | { |
663 | | uint8_t raw_opts[] = { |
664 | | IPV4_OPT_NOP, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
665 | | }; |
666 | | Packet *p = PacketGetFromAlloc(); |
667 | | FAIL_IF(unlikely(p == NULL)); |
668 | | IPV4Options opts; |
669 | | memset(&opts, 0x00, sizeof(opts)); |
670 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
671 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
672 | | SCFree(p); |
673 | | PASS; |
674 | | } |
675 | | |
676 | | /** \test IPV4 with RR option. */ |
677 | | static int DecodeIPV4OptionsRRTest01(void) |
678 | | { |
679 | | uint8_t raw_opts[] = { |
680 | | IPV4_OPT_RR, 0x27, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
681 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
682 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
683 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
684 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
685 | | }; |
686 | | Packet *p = PacketGetFromAlloc(); |
687 | | FAIL_IF(unlikely(p == NULL)); |
688 | | |
689 | | IPV4Options opts; |
690 | | memset(&opts, 0x00, sizeof(opts)); |
691 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
692 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
693 | | FAIL_IF(opts.o_rr.type != IPV4_OPT_RR); |
694 | | SCFree(p); |
695 | | PASS; |
696 | | } |
697 | | |
698 | | /** \test IPV4 with RR option (len too large). */ |
699 | | static int DecodeIPV4OptionsRRTest02(void) |
700 | | { |
701 | | uint8_t raw_opts[] = { |
702 | | IPV4_OPT_RR, 0xff, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
703 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
704 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
705 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
706 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
707 | | }; |
708 | | Packet *p = PacketGetFromAlloc(); |
709 | | FAIL_IF(unlikely(p == NULL)); |
710 | | |
711 | | IPV4Options opts; |
712 | | memset(&opts, 0x00, sizeof(opts)); |
713 | | FAIL_IF(DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts) != -1); |
714 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
715 | | FAIL_IF(opts.o_rr.type != 0); |
716 | | SCFree(p); |
717 | | PASS; |
718 | | } |
719 | | |
720 | | /** \test IPV4 with RR option (ptr too large). */ |
721 | | static int DecodeIPV4OptionsRRTest03(void) |
722 | | { |
723 | | uint8_t raw_opts[] = { |
724 | | IPV4_OPT_RR, 0x27, 0xff, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
725 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
726 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
727 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
728 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
729 | | }; |
730 | | Packet *p = PacketGetFromAlloc(); |
731 | | FAIL_IF(unlikely(p == NULL)); |
732 | | |
733 | | IPV4Options opts; |
734 | | memset(&opts, 0x00, sizeof(opts)); |
735 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
736 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
737 | | FAIL_IF(opts.o_rr.type != 0); |
738 | | SCFree(p); |
739 | | PASS; |
740 | | } |
741 | | |
742 | | /** \test IPV4 with RR option (ptr not in 4 byte increment). */ |
743 | | static int DecodeIPV4OptionsRRTest04(void) |
744 | | { |
745 | | uint8_t raw_opts[] = { |
746 | | IPV4_OPT_RR, 0x27, 0x05, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
747 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
748 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
749 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
750 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
751 | | }; |
752 | | Packet *p = PacketGetFromAlloc(); |
753 | | FAIL_IF(unlikely(p == NULL)); |
754 | | |
755 | | IPV4Options opts; |
756 | | memset(&opts, 0x00, sizeof(opts)); |
757 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
758 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
759 | | FAIL_IF(opts.o_rr.type != 0); |
760 | | SCFree(p); |
761 | | PASS; |
762 | | } |
763 | | |
764 | | /** \test IPV4 with QS option. */ |
765 | | static int DecodeIPV4OptionsQSTest01(void) |
766 | | { |
767 | | uint8_t raw_opts[] = { |
768 | | IPV4_OPT_QS, 0x08, 0x0d, 0x00, 0xbe, 0xef, 0x00, 0x00 |
769 | | }; |
770 | | Packet *p = PacketGetFromAlloc(); |
771 | | FAIL_IF(unlikely(p == NULL)); |
772 | | |
773 | | IPV4Options opts; |
774 | | memset(&opts, 0x00, sizeof(opts)); |
775 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
776 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
777 | | FAIL_IF(opts.o_qs.type != IPV4_OPT_QS); |
778 | | SCFree(p); |
779 | | PASS; |
780 | | } |
781 | | |
782 | | /** \test IPV4 with QS option (len too small) */ |
783 | | static int DecodeIPV4OptionsQSTest02(void) |
784 | | { |
785 | | uint8_t raw_opts[] = { |
786 | | IPV4_OPT_QS, 0x07, 0x0d, 0x00, 0xbe, 0xef, 0x00, 0x00 |
787 | | }; |
788 | | Packet *p = PacketGetFromAlloc(); |
789 | | FAIL_IF(unlikely(p == NULL)); |
790 | | |
791 | | IPV4Options opts; |
792 | | memset(&opts, 0x00, sizeof(opts)); |
793 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
794 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
795 | | FAIL_IF(opts.o_qs.type != 0); |
796 | | SCFree(p); |
797 | | PASS; |
798 | | } |
799 | | |
800 | | /** \test IPV4 with TS option. */ |
801 | | static int DecodeIPV4OptionsTSTest01(void) |
802 | | { |
803 | | uint8_t raw_opts[] = { |
804 | | IPV4_OPT_TS, 0x24, 0x0d, 0x01, 0x0a, 0x0a, 0x0a, 0x69, |
805 | | 0x04, 0xce, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, |
806 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
807 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
808 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
809 | | }; |
810 | | Packet *p = PacketGetFromAlloc(); |
811 | | FAIL_IF(unlikely(p == NULL)); |
812 | | |
813 | | IPV4Options opts; |
814 | | memset(&opts, 0x00, sizeof(opts)); |
815 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
816 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
817 | | FAIL_IF(opts.o_ts.type != IPV4_OPT_TS); |
818 | | SCFree(p); |
819 | | PASS; |
820 | | } |
821 | | |
822 | | /** \test IPV4 with TS option (ptr too small). */ |
823 | | static int DecodeIPV4OptionsTSTest02(void) |
824 | | { |
825 | | uint8_t raw_opts[] = { |
826 | | IPV4_OPT_TS, 0x24, 0x04, 0x01, 0x0a, 0x0a, 0x0a, 0x69, |
827 | | 0x04, 0xce, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, |
828 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
829 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
830 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
831 | | }; |
832 | | Packet *p = PacketGetFromAlloc(); |
833 | | FAIL_IF(unlikely(p == NULL)); |
834 | | |
835 | | IPV4Options opts; |
836 | | memset(&opts, 0x00, sizeof(opts)); |
837 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
838 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
839 | | FAIL_IF(opts.o_ts.type != 0); |
840 | | SCFree(p); |
841 | | PASS; |
842 | | } |
843 | | |
844 | | /** \test IPV4 with TS option (ptr too large). */ |
845 | | static int DecodeIPV4OptionsTSTest03(void) |
846 | | { |
847 | | uint8_t raw_opts[] = { |
848 | | IPV4_OPT_TS, 0x24, 0xff, 0x01, 0x0a, 0x0a, 0x0a, 0x69, |
849 | | 0x04, 0xce, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, |
850 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
851 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
852 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
853 | | }; |
854 | | Packet *p = PacketGetFromAlloc(); |
855 | | FAIL_IF(unlikely(p == NULL)); |
856 | | |
857 | | IPV4Options opts; |
858 | | memset(&opts, 0x00, sizeof(opts)); |
859 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
860 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
861 | | FAIL_IF(opts.o_ts.type != 0); |
862 | | SCFree(p); |
863 | | PASS; |
864 | | } |
865 | | |
866 | | /** \test IPV4 with TS option (ptr not valid). */ |
867 | | static int DecodeIPV4OptionsTSTest04(void) |
868 | | { |
869 | | uint8_t raw_opts[] = { |
870 | | IPV4_OPT_TS, 0x24, 0x0a, 0x01, 0x0a, 0x0a, 0x0a, 0x69, |
871 | | 0x04, 0xce, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, |
872 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
873 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
874 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
875 | | }; |
876 | | Packet *p = PacketGetFromAlloc(); |
877 | | FAIL_IF(unlikely(p == NULL)); |
878 | | |
879 | | IPV4Options opts; |
880 | | memset(&opts, 0x00, sizeof(opts)); |
881 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
882 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
883 | | FAIL_IF(opts.o_ts.type != 0); |
884 | | SCFree(p); |
885 | | PASS; |
886 | | } |
887 | | |
888 | | /** \test IPV4 with SEC option. */ |
889 | | static int DecodeIPV4OptionsSECTest01(void) |
890 | | { |
891 | | uint8_t raw_opts[] = { |
892 | | IPV4_OPT_SEC, 0x0b, 0xf1, 0x35, 0x00, 0x00, 0x00, 0x00, |
893 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
894 | | }; |
895 | | Packet *p = PacketGetFromAlloc(); |
896 | | FAIL_IF(unlikely(p == NULL)); |
897 | | |
898 | | IPV4Options opts; |
899 | | memset(&opts, 0x00, sizeof(opts)); |
900 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
901 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
902 | | FAIL_IF(opts.o_sec.type != IPV4_OPT_SEC); |
903 | | SCFree(p); |
904 | | PASS; |
905 | | } |
906 | | |
907 | | /** \test IPV4 with SEC option (invalid length). */ |
908 | | static int DecodeIPV4OptionsSECTest02(void) |
909 | | { |
910 | | uint8_t raw_opts[] = { IPV4_OPT_SEC, 0x02, 0xf1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
911 | | 0x00, 0x00, 0x00, 0x00, 0x00 }; |
912 | | Packet *p = PacketGetFromAlloc(); |
913 | | FAIL_IF(unlikely(p == NULL)); |
914 | | |
915 | | IPV4Options opts; |
916 | | memset(&opts, 0x00, sizeof(opts)); |
917 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
918 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
919 | | FAIL_IF(opts.o_sec.type != 0); |
920 | | SCFree(p); |
921 | | PASS; |
922 | | } |
923 | | |
924 | | /** \test IPV4 with ESEC option. */ |
925 | | static int DecodeIPV4OptionsESECTest01(void) |
926 | | { |
927 | | uint8_t raw_opts[] = { IPV4_OPT_ESEC, 0x0b, 0xf1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
928 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
929 | | Packet *p = PacketGetFromAlloc(); |
930 | | FAIL_IF(unlikely(p == NULL)); |
931 | | |
932 | | IPV4Options opts; |
933 | | memset(&opts, 0x00, sizeof(opts)); |
934 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
935 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
936 | | FAIL_IF(opts.o_esec.type != IPV4_OPT_ESEC); |
937 | | SCFree(p); |
938 | | PASS; |
939 | | } |
940 | | |
941 | | /** \test IPV4 with ESEC option (invalid length). */ |
942 | | static int DecodeIPV4OptionsESECTest02(void) |
943 | | { |
944 | | uint8_t raw_opts[] = { IPV4_OPT_ESEC, 0x02, 0xf1, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
945 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; |
946 | | Packet *p = PacketGetFromAlloc(); |
947 | | FAIL_IF(unlikely(p == NULL)); |
948 | | |
949 | | IPV4Options opts; |
950 | | memset(&opts, 0x00, sizeof(opts)); |
951 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
952 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
953 | | FAIL_IF(opts.o_esec.type != 0); |
954 | | SCFree(p); |
955 | | PASS; |
956 | | } |
957 | | |
958 | | /** \test IPV4 with LSRR option. */ |
959 | | static int DecodeIPV4OptionsLSRRTest01(void) |
960 | | { |
961 | | uint8_t raw_opts[] = { |
962 | | IPV4_OPT_LSRR, 0x27, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
963 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
964 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
965 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
966 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
967 | | }; |
968 | | Packet *p = PacketGetFromAlloc(); |
969 | | FAIL_IF(unlikely(p == NULL)); |
970 | | |
971 | | IPV4Options opts; |
972 | | memset(&opts, 0x00, sizeof(opts)); |
973 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
974 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
975 | | FAIL_IF(opts.o_lsrr.type != IPV4_OPT_LSRR); |
976 | | SCFree(p); |
977 | | PASS; |
978 | | } |
979 | | |
980 | | /** \test IPV4 with LSRR option (len too large). */ |
981 | | static int DecodeIPV4OptionsLSRRTest02(void) |
982 | | { |
983 | | uint8_t raw_opts[] = { |
984 | | IPV4_OPT_LSRR, 0xff, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
985 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
986 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
987 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
988 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
989 | | }; |
990 | | Packet *p = PacketGetFromAlloc(); |
991 | | FAIL_IF(unlikely(p == NULL)); |
992 | | |
993 | | IPV4Options opts; |
994 | | memset(&opts, 0x00, sizeof(opts)); |
995 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
996 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
997 | | FAIL_IF(opts.o_lsrr.type != 0); |
998 | | SCFree(p); |
999 | | PASS; |
1000 | | } |
1001 | | |
1002 | | /** \test IPV4 with LSRR option (ptr too large). */ |
1003 | | static int DecodeIPV4OptionsLSRRTest03(void) |
1004 | | { |
1005 | | uint8_t raw_opts[] = { |
1006 | | IPV4_OPT_LSRR, 0x27, 0xff, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1007 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1008 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1009 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1010 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1011 | | }; |
1012 | | Packet *p = PacketGetFromAlloc(); |
1013 | | FAIL_IF(unlikely(p == NULL)); |
1014 | | |
1015 | | IPV4Options opts; |
1016 | | memset(&opts, 0x00, sizeof(opts)); |
1017 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1018 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1019 | | FAIL_IF(opts.o_lsrr.type != 0); |
1020 | | SCFree(p); |
1021 | | PASS; |
1022 | | } |
1023 | | |
1024 | | /** \test IPV4 with LSRR option (ptr not in 4 byte increment). */ |
1025 | | static int DecodeIPV4OptionsLSRRTest04(void) |
1026 | | { |
1027 | | uint8_t raw_opts[] = { |
1028 | | IPV4_OPT_LSRR, 0x27, 0x05, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1029 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1030 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1031 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1032 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1033 | | }; |
1034 | | Packet *p = PacketGetFromAlloc(); |
1035 | | FAIL_IF(unlikely(p == NULL)); |
1036 | | |
1037 | | IPV4Options opts; |
1038 | | memset(&opts, 0x00, sizeof(opts)); |
1039 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1040 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1041 | | FAIL_IF(opts.o_lsrr.type != 0); |
1042 | | SCFree(p); |
1043 | | PASS; |
1044 | | } |
1045 | | |
1046 | | /** \test IPV4 with CIPSO option. */ |
1047 | | static int DecodeIPV4OptionsCIPSOTest01(void) |
1048 | | { |
1049 | | uint8_t raw_opts[] = { |
1050 | | IPV4_OPT_CIPSO, 0x18, 0x00, 0x00, 0x00, 0x05, 0x05, 0x12, |
1051 | | 0x00, 0x03, 0x00, 0xef, 0x00, 0xef, 0x00, 0x06, |
1052 | | 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00 |
1053 | | }; |
1054 | | Packet *p = PacketGetFromAlloc(); |
1055 | | FAIL_IF(unlikely(p == NULL)); |
1056 | | |
1057 | | IPV4Options opts; |
1058 | | memset(&opts, 0x00, sizeof(opts)); |
1059 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1060 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
1061 | | FAIL_IF(opts.o_cipso.type != IPV4_OPT_CIPSO); |
1062 | | SCFree(p); |
1063 | | PASS; |
1064 | | } |
1065 | | |
1066 | | /** \test IPV4 with SID option. */ |
1067 | | static int DecodeIPV4OptionsSIDTest01(void) |
1068 | | { |
1069 | | uint8_t raw_opts[] = { |
1070 | | IPV4_OPT_SID, 0x04, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 |
1071 | | }; |
1072 | | Packet *p = PacketGetFromAlloc(); |
1073 | | FAIL_IF(unlikely(p == NULL)); |
1074 | | |
1075 | | IPV4Options opts; |
1076 | | memset(&opts, 0x00, sizeof(opts)); |
1077 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1078 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
1079 | | FAIL_IF(opts.o_sid.type != IPV4_OPT_SID); |
1080 | | SCFree(p); |
1081 | | PASS; |
1082 | | } |
1083 | | |
1084 | | /** \test IPV4 with SID option (len invalid. */ |
1085 | | static int DecodeIPV4OptionsSIDTest02(void) |
1086 | | { |
1087 | | uint8_t raw_opts[] = { |
1088 | | IPV4_OPT_SID, 0x05, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 |
1089 | | }; |
1090 | | Packet *p = PacketGetFromAlloc(); |
1091 | | FAIL_IF(unlikely(p == NULL)); |
1092 | | |
1093 | | IPV4Options opts; |
1094 | | memset(&opts, 0x00, sizeof(opts)); |
1095 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1096 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1097 | | FAIL_IF(opts.o_sid.type != 0); |
1098 | | SCFree(p); |
1099 | | PASS; |
1100 | | } |
1101 | | |
1102 | | /** \test IPV4 with SSRR option. */ |
1103 | | static int DecodeIPV4OptionsSSRRTest01(void) |
1104 | | { |
1105 | | uint8_t raw_opts[] = { |
1106 | | IPV4_OPT_SSRR, 0x27, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1107 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1108 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1109 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1110 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1111 | | }; |
1112 | | Packet *p = PacketGetFromAlloc(); |
1113 | | FAIL_IF(unlikely(p == NULL)); |
1114 | | |
1115 | | IPV4Options opts; |
1116 | | memset(&opts, 0x00, sizeof(opts)); |
1117 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1118 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
1119 | | FAIL_IF(opts.o_ssrr.type != IPV4_OPT_SSRR); |
1120 | | SCFree(p); |
1121 | | PASS; |
1122 | | } |
1123 | | |
1124 | | /** \test IPV4 with SSRR option (len too large). */ |
1125 | | static int DecodeIPV4OptionsSSRRTest02(void) |
1126 | | { |
1127 | | uint8_t raw_opts[] = { |
1128 | | IPV4_OPT_SSRR, 0xff, 0x08, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1129 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1130 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1131 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1132 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1133 | | }; |
1134 | | Packet *p = PacketGetFromAlloc(); |
1135 | | FAIL_IF(unlikely(p == NULL)); |
1136 | | |
1137 | | IPV4Options opts; |
1138 | | memset(&opts, 0x00, sizeof(opts)); |
1139 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1140 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1141 | | FAIL_IF(opts.o_ssrr.type != 0); |
1142 | | SCFree(p); |
1143 | | PASS; |
1144 | | } |
1145 | | |
1146 | | /** \test IPV4 with SSRR option (ptr too large). */ |
1147 | | static int DecodeIPV4OptionsSSRRTest03(void) |
1148 | | { |
1149 | | uint8_t raw_opts[] = { |
1150 | | IPV4_OPT_SSRR, 0x27, 0xff, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1151 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1152 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1153 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1154 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1155 | | }; |
1156 | | Packet *p = PacketGetFromAlloc(); |
1157 | | FAIL_IF(unlikely(p == NULL)); |
1158 | | |
1159 | | IPV4Options opts; |
1160 | | memset(&opts, 0x00, sizeof(opts)); |
1161 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1162 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1163 | | FAIL_IF(opts.o_ssrr.type != 0); |
1164 | | SCFree(p); |
1165 | | PASS; |
1166 | | } |
1167 | | |
1168 | | /** \test IPV4 with SSRR option (ptr not in 4 byte increment). */ |
1169 | | static int DecodeIPV4OptionsSSRRTest04(void) |
1170 | | { |
1171 | | uint8_t raw_opts[] = { |
1172 | | IPV4_OPT_SSRR, 0x27, 0x05, 0xc0, 0xa8, 0x2a, 0x64, 0x00, |
1173 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1174 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1175 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
1176 | | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
1177 | | }; |
1178 | | Packet *p = PacketGetFromAlloc(); |
1179 | | FAIL_IF(unlikely(p == NULL)); |
1180 | | |
1181 | | IPV4Options opts; |
1182 | | memset(&opts, 0x00, sizeof(opts)); |
1183 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1184 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1185 | | FAIL_IF(opts.o_ssrr.type != 0); |
1186 | | SCFree(p); |
1187 | | PASS; |
1188 | | } |
1189 | | |
1190 | | /** \test IPV4 with RTRALT option. */ |
1191 | | static int DecodeIPV4OptionsRTRALTTest01(void) |
1192 | | { |
1193 | | uint8_t raw_opts[] = { |
1194 | | IPV4_OPT_RTRALT, 0x04, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 |
1195 | | }; |
1196 | | Packet *p = PacketGetFromAlloc(); |
1197 | | FAIL_IF(unlikely(p == NULL)); |
1198 | | |
1199 | | IPV4Options opts; |
1200 | | memset(&opts, 0x00, sizeof(opts)); |
1201 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1202 | | FAIL_IF(p->flags & PKT_IS_INVALID); |
1203 | | FAIL_IF(opts.o_rtralt.type != IPV4_OPT_RTRALT); |
1204 | | SCFree(p); |
1205 | | PASS; |
1206 | | } |
1207 | | |
1208 | | /** \test IPV4 with RTRALT option (len invalid. */ |
1209 | | static int DecodeIPV4OptionsRTRALTTest02(void) |
1210 | | { |
1211 | | uint8_t raw_opts[] = { |
1212 | | IPV4_OPT_RTRALT, 0x05, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00 |
1213 | | }; |
1214 | | Packet *p = PacketGetFromAlloc(); |
1215 | | FAIL_IF(unlikely(p == NULL)); |
1216 | | |
1217 | | IPV4Options opts; |
1218 | | memset(&opts, 0x00, sizeof(opts)); |
1219 | | DecodeIPV4Options(p, raw_opts, sizeof(raw_opts), &opts); |
1220 | | FAIL_IF((p->flags & PKT_IS_INVALID) == 0); |
1221 | | FAIL_IF(opts.o_rtralt.type != 0); |
1222 | | SCFree(p); |
1223 | | PASS; |
1224 | | } |
1225 | | |
1226 | | static int IPV4CalculateValidChecksumtest01(void) |
1227 | | { |
1228 | | uint16_t csum = 0; |
1229 | | |
1230 | | uint8_t raw_ipv4[] = { |
1231 | | 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, |
1232 | | 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, |
1233 | | 0xc0, 0xa8, 0x01, 0x03}; |
1234 | | |
1235 | | csum = *( ((uint16_t *)raw_ipv4) + 5); |
1236 | | |
1237 | | FAIL_IF(IPV4Checksum((uint16_t *)raw_ipv4, sizeof(raw_ipv4), csum) != 0); |
1238 | | PASS; |
1239 | | } |
1240 | | |
1241 | | static int IPV4CalculateInvalidChecksumtest02(void) |
1242 | | { |
1243 | | uint16_t csum = 0; |
1244 | | |
1245 | | uint8_t raw_ipv4[] = { |
1246 | | 0x45, 0x00, 0x00, 0x54, 0x00, 0x00, 0x40, 0x00, |
1247 | | 0x40, 0x01, 0xb7, 0x52, 0xc0, 0xa8, 0x01, 0x03, |
1248 | | 0xc0, 0xa8, 0x01, 0x07}; |
1249 | | |
1250 | | csum = *( ((uint16_t *)raw_ipv4) + 5); |
1251 | | |
1252 | | FAIL_IF(IPV4Checksum((uint16_t *)raw_ipv4, sizeof(raw_ipv4), csum) == 0); |
1253 | | PASS; |
1254 | | } |
1255 | | |
1256 | | /** |
1257 | | * \test IPV4 defrag and packet recursion level test |
1258 | | */ |
1259 | | static int DecodeIPV4DefragTest01(void) |
1260 | | { |
1261 | | uint8_t pkt1[] = { |
1262 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1263 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1264 | | 0x00, 0x1c, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06, |
1265 | | 0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1266 | | 0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1267 | | 0x81, 0x5e |
1268 | | }; |
1269 | | uint8_t pkt2[] = { |
1270 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1271 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1272 | | 0x00, 0x1c, 0xe9, 0xef, 0x20, 0x01, 0x40, 0x06, |
1273 | | 0x9a, 0xc7, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1274 | | 0xe1, 0x0c, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, |
1275 | | 0x80, 0x00 |
1276 | | }; |
1277 | | uint8_t pkt3[] = { |
1278 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1279 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1280 | | 0x00, 0x18, 0xe9, 0xef, 0x00, 0x02, 0x40, 0x06, |
1281 | | 0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1282 | | 0xe1, 0x0c, 0xb1, 0xa3, 0x00, 0x00 |
1283 | | }; |
1284 | | uint8_t tunnel_pkt[] = { |
1285 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1286 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1287 | | 0x00, 0x28, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06, |
1288 | | 0xba, 0xbc, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1289 | | 0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1290 | | 0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, |
1291 | | 0x80, 0x00, 0xb1, 0xa3, 0x00, 0x00 |
1292 | | }; |
1293 | | |
1294 | | Packet *p = PacketGetFromAlloc(); |
1295 | | FAIL_IF_NULL(p); |
1296 | | ThreadVars tv; |
1297 | | DecodeThreadVars dtv; |
1298 | | |
1299 | | memset(&tv, 0, sizeof(ThreadVars)); |
1300 | | memset(&dtv, 0, sizeof(DecodeThreadVars)); |
1301 | | |
1302 | | FlowInitConfig(FLOW_QUIET); |
1303 | | DefragInit(); |
1304 | | |
1305 | | PacketCopyData(p, pkt1, sizeof(pkt1)); |
1306 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1307 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1308 | | FAIL_IF(PacketIsTCP(p)); |
1309 | | PacketRecycle(p); |
1310 | | |
1311 | | PacketCopyData(p, pkt2, sizeof(pkt2)); |
1312 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1313 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1314 | | FAIL_IF(PacketIsTCP(p)); |
1315 | | PacketRecycle(p); |
1316 | | |
1317 | | PacketCopyData(p, pkt3, sizeof(pkt3)); |
1318 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1319 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1320 | | FAIL_IF(PacketIsTCP(p)); |
1321 | | Packet *tp = PacketDequeueNoLock(&tv.decode_pq); |
1322 | | FAIL_IF_NULL(tp); |
1323 | | FAIL_IF(tp->recursion_level != p->recursion_level); |
1324 | | FAIL_IF_NOT(PacketIsIPv4(tp)); |
1325 | | FAIL_IF_NOT(PacketIsTCP(tp)); |
1326 | | FAIL_IF(GET_PKT_LEN(tp) != sizeof(tunnel_pkt)); |
1327 | | FAIL_IF(memcmp(GET_PKT_DATA(tp), tunnel_pkt, sizeof(tunnel_pkt)) != 0); |
1328 | | PacketRecycle(tp); |
1329 | | SCFree(tp); |
1330 | | |
1331 | | DefragDestroy(); |
1332 | | PacketRecycle(p); |
1333 | | FlowShutdown(); |
1334 | | SCFree(p); |
1335 | | PASS; |
1336 | | } |
1337 | | |
1338 | | /** |
1339 | | * \test Don't send IPv4 fragments to the upper layer decoder and |
1340 | | * and packet recursion level test. |
1341 | | */ |
1342 | | static int DecodeIPV4DefragTest02(void) |
1343 | | { |
1344 | | uint8_t pkt1[] = { |
1345 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1346 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1347 | | 0x00, 0x24, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06, |
1348 | | 0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1349 | | 0xe1, 0x0c, |
1350 | | /* first frag */ |
1351 | | 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1352 | | 0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, |
1353 | | 0x80, 0x00, |
1354 | | }; |
1355 | | uint8_t pkt2[] = { |
1356 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1357 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1358 | | 0x00, 0x2c, 0xe9, 0xef, 0x20, 0x02, 0x40, 0x06, |
1359 | | 0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1360 | | 0xe1, 0x0c, |
1361 | | /* second frag */ |
1362 | | 0xb1, 0xa3, 0x00, 0x10, 0x5b, 0xa3, 0x81, 0x5e, |
1363 | | 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00, |
1364 | | 0xb1, 0xa3, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04 |
1365 | | }; |
1366 | | uint8_t pkt3[] = { |
1367 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1368 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1369 | | 0x00, 0x16, 0xe9, 0xef, 0x00, 0x05, 0x40, 0x06, |
1370 | | 0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1371 | | 0xe1, 0x0c, |
1372 | | /* final frag */ |
1373 | | 0xb1, 0xa3, |
1374 | | }; |
1375 | | |
1376 | | uint8_t tunnel_pkt[] = { |
1377 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1378 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1379 | | 0x00, 0x3e, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06, |
1380 | | 0xba, 0xae, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1381 | | 0xe1, 0x0c, |
1382 | | 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, 0x81, 0x5e, |
1383 | | 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00, |
1384 | | 0xb1, 0xa3, 0x00, 0x10, 0x5b, 0xa3, 0x81, 0x5e, |
1385 | | 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, 0x80, 0x00, |
1386 | | 0xb1, 0xa3, 0x00, 0x10, 0x01, 0x02, 0x03, 0x04, |
1387 | | 0xb1, 0xa3, |
1388 | | }; |
1389 | | |
1390 | | Packet *p = PacketGetFromAlloc(); |
1391 | | FAIL_IF_NULL(p); |
1392 | | ThreadVars tv; |
1393 | | DecodeThreadVars dtv; |
1394 | | |
1395 | | memset(&tv, 0, sizeof(ThreadVars)); |
1396 | | memset(&dtv, 0, sizeof(DecodeThreadVars)); |
1397 | | |
1398 | | FlowInitConfig(FLOW_QUIET); |
1399 | | DefragInit(); |
1400 | | |
1401 | | PacketCopyData(p, pkt1, sizeof(pkt1)); |
1402 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1403 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1404 | | FAIL_IF(PacketIsTCP(p)); |
1405 | | PacketRecycle(p); |
1406 | | |
1407 | | PacketCopyData(p, pkt2, sizeof(pkt2)); |
1408 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1409 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1410 | | FAIL_IF(PacketIsTCP(p)); |
1411 | | PacketRecycle(p); |
1412 | | |
1413 | | p->recursion_level = 3; |
1414 | | PacketCopyData(p, pkt3, sizeof(pkt3)); |
1415 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1416 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1417 | | FAIL_IF(PacketIsTCP(p)); |
1418 | | Packet *tp = PacketDequeueNoLock(&tv.decode_pq); |
1419 | | FAIL_IF_NULL(tp); |
1420 | | FAIL_IF(tp->recursion_level != p->recursion_level); |
1421 | | FAIL_IF_NOT(PacketIsIPv4(tp)); |
1422 | | FAIL_IF_NOT(PacketIsTCP(tp)); |
1423 | | FAIL_IF(GET_PKT_LEN(tp) != sizeof(tunnel_pkt)); |
1424 | | FAIL_IF(memcmp(GET_PKT_DATA(tp), tunnel_pkt, sizeof(tunnel_pkt)) != 0); |
1425 | | PacketRecycle(tp); |
1426 | | SCFree(tp); |
1427 | | |
1428 | | DefragDestroy(); |
1429 | | PacketRecycle(p); |
1430 | | FlowShutdown(); |
1431 | | SCFree(p); |
1432 | | PASS; |
1433 | | } |
1434 | | |
1435 | | /** |
1436 | | * \test IPV4 defrag and flow retrieval test. |
1437 | | */ |
1438 | | static int DecodeIPV4DefragTest03(void) |
1439 | | { |
1440 | | uint8_t pkt[] = { |
1441 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1442 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1443 | | 0x00, 0x28, 0xe9, 0xee, 0x00, 0x00, 0x40, 0x06, |
1444 | | 0xba, 0xbd, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1445 | | 0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1446 | | 0x81, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x50, 0x02, |
1447 | | 0x80, 0x00, 0x0c, 0xee, 0x00, 0x00 |
1448 | | }; |
1449 | | uint8_t pkt1[] = { |
1450 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1451 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1452 | | 0x00, 0x1c, 0xe9, 0xef, 0x20, 0x00, 0x40, 0x06, |
1453 | | 0x9a, 0xc8, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1454 | | 0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1455 | | 0x81, 0x5e |
1456 | | }; |
1457 | | uint8_t pkt2[] = { |
1458 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1459 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1460 | | 0x00, 0x1c, 0xe9, 0xef, 0x20, 0x01, 0x40, 0x06, |
1461 | | 0x9a, 0xc7, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1462 | | 0xe1, 0x0c, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, |
1463 | | 0x80, 0x00 |
1464 | | }; |
1465 | | uint8_t pkt3[] = { |
1466 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1467 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1468 | | 0x00, 0x18, 0xe9, 0xef, 0x00, 0x02, 0x40, 0x06, |
1469 | | 0xba, 0xca, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1470 | | 0xe1, 0x0c, 0xb1, 0xa3, 0x00, 0x00 |
1471 | | }; |
1472 | | uint8_t tunnel_pkt[] = { |
1473 | | 0x00, 0x50, 0x56, 0x00, 0x03, 0x05, 0xde, 0xad, |
1474 | | 0x01, 0xa3, 0xa2, 0x2f, 0x08, 0x00, 0x45, 0x00, |
1475 | | 0x00, 0x28, 0xe9, 0xef, 0x00, 0x00, 0x40, 0x06, |
1476 | | 0xba, 0xbc, 0x0a, 0x00, 0xe1, 0x17, 0x0a, 0x00, |
1477 | | 0xe1, 0x0c, 0x6e, 0x12, 0x01, 0xbd, 0x5b, 0xa3, |
1478 | | 0x81, 0x5e, 0xac, 0xb0, 0xae, 0x8a, 0x50, 0x10, |
1479 | | 0x80, 0x00, 0xb1, 0xa3, 0x00, 0x00 |
1480 | | }; |
1481 | | |
1482 | | Packet *p = PacketGetFromAlloc(); |
1483 | | FAIL_IF_NULL(p); |
1484 | | ThreadVars tv; |
1485 | | DecodeThreadVars dtv; |
1486 | | memset(&tv, 0, sizeof(ThreadVars)); |
1487 | | memset(&dtv, 0, sizeof(DecodeThreadVars)); |
1488 | | |
1489 | | FlowInitConfig(FLOW_QUIET); |
1490 | | DefragInit(); |
1491 | | |
1492 | | PacketCopyData(p, pkt, sizeof(pkt)); |
1493 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1494 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1495 | | FAIL_IF_NOT(PacketIsTCP(p)); |
1496 | | FAIL_IF(!(p->flags & PKT_WANTS_FLOW)); |
1497 | | PacketRecycle(p); |
1498 | | |
1499 | | PacketCopyData(p, pkt1, sizeof(pkt1)); |
1500 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1501 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1502 | | FAIL_IF(PacketIsTCP(p)); |
1503 | | PacketRecycle(p); |
1504 | | |
1505 | | PacketCopyData(p, pkt2, sizeof(pkt2)); |
1506 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1507 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1508 | | FAIL_IF(PacketIsTCP(p)); |
1509 | | PacketRecycle(p); |
1510 | | |
1511 | | PacketCopyData(p, pkt3, sizeof(pkt3)); |
1512 | | DecodeIPV4(&tv, &dtv, p, GET_PKT_DATA(p) + ETHERNET_HEADER_LEN, |
1513 | | GET_PKT_LEN(p) - ETHERNET_HEADER_LEN); |
1514 | | FAIL_IF(PacketIsTCP(p)); |
1515 | | |
1516 | | Packet *tp = PacketDequeueNoLock(&tv.decode_pq); |
1517 | | FAIL_IF_NULL(tp); |
1518 | | FAIL_IF(!(tp->flags & PKT_WANTS_FLOW)); |
1519 | | FAIL_IF(tp->flow_hash != p->flow_hash); |
1520 | | FAIL_IF(tp->recursion_level != p->recursion_level); |
1521 | | FAIL_IF_NOT(PacketIsIPv4(tp)); |
1522 | | FAIL_IF_NOT(PacketIsTCP(tp)); |
1523 | | FAIL_IF(GET_PKT_LEN(tp) != sizeof(tunnel_pkt)); |
1524 | | FAIL_IF(memcmp(GET_PKT_DATA(tp), tunnel_pkt, sizeof(tunnel_pkt)) != 0); |
1525 | | PacketRecycle(tp); |
1526 | | SCFree(tp); |
1527 | | |
1528 | | DefragDestroy(); |
1529 | | PacketRecycle(p); |
1530 | | FlowShutdown(); |
1531 | | SCFree(p); |
1532 | | PASS; |
1533 | | } |
1534 | | |
1535 | | /** |
1536 | | */ |
1537 | | static int DecodeEthernetTestIPv4Opt(void) |
1538 | | { |
1539 | | uint8_t raw_eth[] = { |
1540 | | 0xae, 0x71, 0x00, 0x00, 0x00, 0x4b, 0x06, 0x90, 0x61, 0x02, 0x00, 0xcd, 0x88, 0x64, 0x11, 0x00, |
1541 | | 0x15, 0x00, 0x80, 0x64, 0x00, 0x21, 0x4c, 0x00, 0x00, 0x30, 0x42, 0xd6, 0xff, 0xff, 0xbd, 0x2f, |
1542 | | 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, |
1543 | | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, |
1544 | | 0x01, 0x44, 0x05, 0x22, 0x02, 0x01 |
1545 | | }; |
1546 | | |
1547 | | DefragInit(); |
1548 | | |
1549 | | Packet *p = PacketGetFromAlloc(); |
1550 | | FAIL_IF_NULL(p); |
1551 | | ThreadVars tv; |
1552 | | DecodeThreadVars dtv; |
1553 | | |
1554 | | memset(&dtv, 0, sizeof(DecodeThreadVars)); |
1555 | | memset(&tv, 0, sizeof(ThreadVars)); |
1556 | | |
1557 | | DecodeEthernet(&tv, &dtv, p, raw_eth, sizeof(raw_eth)); |
1558 | | |
1559 | | SCFree(p); |
1560 | | DefragDestroy(); |
1561 | | PASS; |
1562 | | } |
1563 | | |
1564 | | #endif /* UNITTESTS */ |
1565 | | |
1566 | | void DecodeIPV4RegisterTests(void) |
1567 | 0 | { |
1568 | | #ifdef UNITTESTS |
1569 | | UtRegisterTest("DecodeIPV4OptionsNONETest01", DecodeIPV4OptionsNONETest01); |
1570 | | UtRegisterTest("DecodeIPV4OptionsEOLTest01", DecodeIPV4OptionsEOLTest01); |
1571 | | UtRegisterTest("DecodeIPV4OptionsNOPTest01", DecodeIPV4OptionsNOPTest01); |
1572 | | UtRegisterTest("DecodeIPV4OptionsRRTest01", DecodeIPV4OptionsRRTest01); |
1573 | | UtRegisterTest("DecodeIPV4OptionsRRTest02", DecodeIPV4OptionsRRTest02); |
1574 | | UtRegisterTest("DecodeIPV4OptionsRRTest03", DecodeIPV4OptionsRRTest03); |
1575 | | UtRegisterTest("DecodeIPV4OptionsRRTest04", DecodeIPV4OptionsRRTest04); |
1576 | | UtRegisterTest("DecodeIPV4OptionsQSTest01", DecodeIPV4OptionsQSTest01); |
1577 | | UtRegisterTest("DecodeIPV4OptionsQSTest02", DecodeIPV4OptionsQSTest02); |
1578 | | UtRegisterTest("DecodeIPV4OptionsTSTest01", DecodeIPV4OptionsTSTest01); |
1579 | | UtRegisterTest("DecodeIPV4OptionsTSTest02", DecodeIPV4OptionsTSTest02); |
1580 | | UtRegisterTest("DecodeIPV4OptionsTSTest03", DecodeIPV4OptionsTSTest03); |
1581 | | UtRegisterTest("DecodeIPV4OptionsTSTest04", DecodeIPV4OptionsTSTest04); |
1582 | | UtRegisterTest("DecodeIPV4OptionsSECTest01", DecodeIPV4OptionsSECTest01); |
1583 | | UtRegisterTest("DecodeIPV4OptionsSECTest02", DecodeIPV4OptionsSECTest02); |
1584 | | UtRegisterTest("DecodeIPV4OptionsESECTest01", DecodeIPV4OptionsESECTest01); |
1585 | | UtRegisterTest("DecodeIPV4OptionsESECTest02", DecodeIPV4OptionsESECTest02); |
1586 | | UtRegisterTest("DecodeIPV4OptionsLSRRTest01", DecodeIPV4OptionsLSRRTest01); |
1587 | | UtRegisterTest("DecodeIPV4OptionsLSRRTest02", DecodeIPV4OptionsLSRRTest02); |
1588 | | UtRegisterTest("DecodeIPV4OptionsLSRRTest03", DecodeIPV4OptionsLSRRTest03); |
1589 | | UtRegisterTest("DecodeIPV4OptionsLSRRTest04", DecodeIPV4OptionsLSRRTest04); |
1590 | | UtRegisterTest("DecodeIPV4OptionsCIPSOTest01", |
1591 | | DecodeIPV4OptionsCIPSOTest01); |
1592 | | UtRegisterTest("DecodeIPV4OptionsSIDTest01", DecodeIPV4OptionsSIDTest01); |
1593 | | UtRegisterTest("DecodeIPV4OptionsSIDTest02", DecodeIPV4OptionsSIDTest02); |
1594 | | UtRegisterTest("DecodeIPV4OptionsSSRRTest01", DecodeIPV4OptionsSSRRTest01); |
1595 | | UtRegisterTest("DecodeIPV4OptionsSSRRTest02", DecodeIPV4OptionsSSRRTest02); |
1596 | | UtRegisterTest("DecodeIPV4OptionsSSRRTest03", DecodeIPV4OptionsSSRRTest03); |
1597 | | UtRegisterTest("DecodeIPV4OptionsSSRRTest04", DecodeIPV4OptionsSSRRTest04); |
1598 | | UtRegisterTest("DecodeIPV4OptionsRTRALTTest01", |
1599 | | DecodeIPV4OptionsRTRALTTest01); |
1600 | | UtRegisterTest("DecodeIPV4OptionsRTRALTTest02", |
1601 | | DecodeIPV4OptionsRTRALTTest02); |
1602 | | UtRegisterTest("IPV4CalculateValidChecksumtest01", |
1603 | | IPV4CalculateValidChecksumtest01); |
1604 | | UtRegisterTest("IPV4CalculateInvalidChecksumtest02", |
1605 | | IPV4CalculateInvalidChecksumtest02); |
1606 | | UtRegisterTest("DecodeIPV4DefragTest01", DecodeIPV4DefragTest01); |
1607 | | UtRegisterTest("DecodeIPV4DefragTest02", DecodeIPV4DefragTest02); |
1608 | | UtRegisterTest("DecodeIPV4DefragTest03", DecodeIPV4DefragTest03); |
1609 | | UtRegisterTest("DecodeEthernetTestIPv4Opt", DecodeEthernetTestIPv4Opt); |
1610 | | #endif /* UNITTESTS */ |
1611 | 0 | } |
1612 | | /** |
1613 | | * @} |
1614 | | */ |