1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 2005-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "norm.h"
25
26 #include "detection/ips_context.h"
27 #include "main/snort_config.h"
28 #include "packet_io/sfdaq.h"
29 #include "protocols/icmp4.h"
30 #include "protocols/icmp6.h"
31 #include "protocols/ipv4_options.h"
32 #include "protocols/tcp.h"
33 #include "protocols/tcp_options.h"
34 #include "stream/tcp/tcp_normalizer.h"
35
36 using namespace snort;
37
38 enum PegCounts
39 {
40 PC_IP4_TRIM,
41 PC_IP4_TOS,
42 PC_IP4_DF,
43 PC_IP4_RF,
44 PC_IP4_TTL,
45 PC_IP4_OPTS,
46 PC_ICMP4_ECHO,
47 PC_IP6_TTL,
48 PC_IP6_OPTS,
49 PC_ICMP6_ECHO,
50 PC_TCP_SYN_OPT,
51 PC_TCP_OPT,
52 PC_TCP_PAD,
53 PC_TCP_RSV,
54 PC_TCP_NS,
55 PC_TCP_URP,
56 PC_TCP_ECN_PKT,
57 PC_TCP_TS_ECR,
58 PC_TCP_REQ_URG,
59 PC_TCP_REQ_PAY,
60 PC_TCP_REQ_URP,
61 PC_MAX
62 };
63
64 const PegInfo norm_names[] =
65 {
66 { CountType::SUM, "ip4_trim", "eth packets trimmed to datagram size" },
67 { CountType::SUM, "ip4_tos", "type of service normalizations" },
68 { CountType::SUM, "ip4_df", "don't frag bit normalizations" },
69 { CountType::SUM, "ip4_rf", "reserved flag bit clears" },
70 { CountType::SUM, "ip4_ttl", "time-to-live normalizations" },
71 { CountType::SUM, "ip4_opts", "ip4 options cleared" },
72 { CountType::SUM, "icmp4_echo", "icmp4 ping normalizations" },
73 { CountType::SUM, "ip6_hops", "ip6 hop limit normalizations" },
74 { CountType::SUM, "ip6_options", "ip6 options cleared" },
75 { CountType::SUM, "icmp6_echo", "icmp6 echo normalizations" },
76 { CountType::SUM, "tcp_syn_options", "SYN only options cleared from non-SYN packets" },
77 { CountType::SUM, "tcp_options", "packets with options cleared" },
78 { CountType::SUM, "tcp_padding", "packets with padding cleared" },
79 { CountType::SUM, "tcp_reserved", "packets with reserved bits cleared" },
80 { CountType::SUM, "tcp_nonce", "packets with nonce bit cleared" },
81 { CountType::SUM, "tcp_urgent_ptr", "packets without data with urgent pointer cleared" },
82 { CountType::SUM, "tcp_ecn_pkt", "packets with ECN bits cleared" },
83 { CountType::SUM, "tcp_ts_ecr", "timestamp cleared on non-ACKs" },
84 { CountType::SUM, "tcp_req_urg", "cleared urgent pointer when urgent flag is not set" },
85 { CountType::SUM, "tcp_req_pay",
86 "cleared urgent pointer and urgent flag when there is no payload" },
87 { CountType::SUM, "tcp_req_urp", "cleared the urgent flag if the urgent pointer is not set" },
88 { CountType::END, nullptr, nullptr }
89 };
90
91 static THREAD_LOCAL PegCount normStats[PC_MAX+PC_TCP_MAX][NORM_MODE_MAX];
92
93 //static int Norm_Eth(Packet*, uint8_t layer, int changes);
94 static int Norm_IP4(NormalizerConfig*, Packet*, uint8_t layer, int changes);
95 static int Norm_ICMP4(NormalizerConfig*, Packet*, uint8_t layer, int changes);
96 static int Norm_IP6(NormalizerConfig*, Packet*, uint8_t layer, int changes);
97 static int Norm_ICMP6(NormalizerConfig*, Packet*, uint8_t layer, int changes);
98 static int Norm_IP6_Opts(NormalizerConfig*, Packet*, uint8_t layer, int changes);
99 //static int Norm_UDP(NormalizerConfig*, Packet*, uint8_t layer, int changes);
100 static int Norm_TCP(NormalizerConfig*, Packet*, uint8_t layer, int changes);
101
102 static const uint8_t MAX_EOL_PAD[TCP_OPTLENMAX] =
103 {
104 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
106 };
107
108 // go from inner to outer
Norm_Packet(NormalizerConfig * c,Packet * p)109 int Norm_Packet(NormalizerConfig* c, Packet* p)
110 {
111 uint8_t lyr = p->num_layers;
112 int changes = 0;
113
114 while ( lyr > 0 )
115 {
116 ProtocolId proto_id = p->layers[--lyr].prot_id;
117 NormalFunc n = c->normalizers[PacketManager::proto_idx(proto_id)];
118
119 if ( n )
120 changes = n(c, p, lyr, changes);
121 }
122
123 if ( changes > 0 )
124 {
125 p->packet_flags |= PKT_MODIFIED;
126 return 1;
127 }
128 if ( p->packet_flags & (PKT_RESIZED|PKT_MODIFIED) )
129 {
130 return 1;
131 }
132 return 0;
133 }
134
135 //-----------------------------------------------------------------------
136 // in the following code, we mostly use the actual packet data and the
137 // packet layers[]. use of other decoded packet members is largely
138 // avoided to ensure that we don't get tripped up by nested protocols.
139 // TCP options count and length are a notable exception.
140 //
141 // also note that checksums are not calculated here. they are only
142 // calculated once after all normalizations are done (here, stream)
143 // and any replacements are made.
144 //-----------------------------------------------------------------------
145
146 #if 0
147 static int Norm_Eth(Packet* p, uint8_t layer, int changes)
148 {
149 return 0;
150 }
151
152 #endif
153
154 //-----------------------------------------------------------------------
155
156 #define IP4_FLAG_RF 0x8000
157 #define IP4_FLAG_DF 0x4000
158 #define IP4_FLAG_MF 0x2000
159
160 // TBD support configurable minimum length / obtain from DAQ
161 // ether header + min payload (excludes FCS, which makes it 64 total)
162 #define ETH_MIN_LEN 60
163
get_norm_mode(const Packet * const p)164 static inline NormMode get_norm_mode(const Packet * const p)
165 {
166 NormMode mode = NORM_MODE_ON;
167
168 if ( get_inspection_policy()->policy_mode != POLICY_MODE__INLINE )
169 mode = NORM_MODE_TEST;
170
171 if ( !SFDAQ::forwarding_packet(p->pkth) )
172 mode = NORM_MODE_TEST;
173
174 return mode;
175 }
176
Norm_IP4(NormalizerConfig * c,Packet * p,uint8_t layer,int changes)177 static int Norm_IP4(
178 NormalizerConfig* c, Packet* p, uint8_t layer, int changes)
179 {
180 ip::IP4Hdr* h = (ip::IP4Hdr*)const_cast<uint8_t*>(p->layers[layer].start);
181 uint16_t fragbits = ntohs(h->ip_off);
182 uint16_t origbits = fragbits;
183 const NormMode mode = get_norm_mode(p);
184
185 if ( Norm_IsEnabled(c, NORM_IP4_TRIM) && (layer == 1) )
186 {
187 uint32_t len = p->layers[0].length + ntohs(h->ip_len);
188
189 if ( (len < p->pkth->pktlen) &&
190 ((len >= ETH_MIN_LEN) || (p->pkth->pktlen > ETH_MIN_LEN)) )
191 {
192 if ( mode == NORM_MODE_ON )
193 {
194 (const_cast<DAQ_PktHdr_t*>(p->pkth))->pktlen =
195 (len < ETH_MIN_LEN) ? ETH_MIN_LEN : len;
196
197 p->packet_flags |= PKT_RESIZED;
198 changes++;
199 }
200 normStats[PC_IP4_TRIM][mode]++;
201 }
202 }
203 if ( Norm_IsEnabled(c, NORM_IP4_TOS) )
204 {
205 if ( h->ip_tos )
206 {
207 if ( mode == NORM_MODE_ON )
208 {
209 h->ip_tos = 0;
210 changes++;
211 }
212 normStats[PC_IP4_TOS][mode]++;
213 }
214 }
215 #if 0
216 if ( Norm_IsEnabled(c, NORM_IP4_ID) )
217 {
218 // TBD implement IP ID normalization / randomization
219 }
220 #endif
221 if ( Norm_IsEnabled(c, NORM_IP4_DF) )
222 {
223 if ( fragbits & IP4_FLAG_DF )
224 {
225 if ( mode == NORM_MODE_ON )
226 {
227 fragbits &= ~IP4_FLAG_DF;
228 changes++;
229 }
230 normStats[PC_IP4_DF][mode]++;
231 }
232 }
233 if ( Norm_IsEnabled(c, NORM_IP4_RF) )
234 {
235 if ( fragbits & IP4_FLAG_RF )
236 {
237 if ( mode == NORM_MODE_ON )
238 {
239 fragbits &= ~IP4_FLAG_RF;
240 changes++;
241 }
242 normStats[PC_IP4_RF][mode]++;
243 }
244 }
245 if ( fragbits != origbits )
246 {
247 h->ip_off = htons(fragbits);
248 }
249 if ( Norm_IsEnabled(c, NORM_IP4_TTL) )
250 {
251 if ( h->ip_ttl < p->context->conf->min_ttl() )
252 {
253 if ( mode == NORM_MODE_ON )
254 {
255 h->ip_ttl = p->context->conf->new_ttl();
256 p->ptrs.decode_flags &= ~DECODE_ERR_BAD_TTL;
257 changes++;
258 }
259 normStats[PC_IP4_TTL][mode]++;
260 }
261 }
262 if ( p->layers[layer].length > ip::IP4_HEADER_LEN )
263 {
264 if ( mode == NORM_MODE_ON )
265 {
266 uint8_t* opts = const_cast<uint8_t*>(p->layers[layer].start) + ip::IP4_HEADER_LEN;
267 uint8_t len = p->layers[layer].length - ip::IP4_HEADER_LEN;
268 // expect len > 0 because IHL yields a multiple of 4
269 memset(opts, static_cast<uint8_t>(ip::IPOptionCodes::NOP), len);
270 changes++;
271 }
272 normStats[PC_IP4_OPTS][mode]++;
273 }
274 return changes;
275 }
276
277 //-----------------------------------------------------------------------
278
Norm_ICMP4(NormalizerConfig *,Packet * p,uint8_t layer,int changes)279 static int Norm_ICMP4(
280 NormalizerConfig*, Packet* p, uint8_t layer, int changes)
281 {
282 ICMPHdr* h = reinterpret_cast<ICMPHdr*>(const_cast<uint8_t*>(p->layers[layer].start));
283 const NormMode mode = get_norm_mode(p);
284
285 if ( (h->type == ICMP_ECHO || h->type == ICMP_ECHOREPLY) &&
286 (h->code != icmp::IcmpCode::ECHO_CODE) )
287 {
288 if ( mode == NORM_MODE_ON )
289 {
290 h->code = icmp::IcmpCode::ECHO_CODE;
291 changes++;
292 }
293 normStats[PC_ICMP4_ECHO][mode]++;
294 }
295 return changes;
296 }
297
298 //-----------------------------------------------------------------------
299
Norm_IP6(NormalizerConfig * c,Packet * p,uint8_t layer,int changes)300 static int Norm_IP6(
301 NormalizerConfig* c, Packet* p, uint8_t layer, int changes)
302 {
303 if ( Norm_IsEnabled(c, NORM_IP6_TTL) )
304 {
305 ip::IP6Hdr* h =
306 reinterpret_cast<ip::IP6Hdr*>(const_cast<uint8_t*>(p->layers[layer].start));
307
308 if ( h->ip6_hoplim < p->context->conf->min_ttl() )
309 {
310 const NormMode mode = get_norm_mode(p);
311
312 if ( mode == NORM_MODE_ON )
313 {
314 h->ip6_hoplim = p->context->conf->new_ttl();
315 p->ptrs.decode_flags &= ~DECODE_ERR_BAD_TTL;
316 changes++;
317 }
318 normStats[PC_IP6_TTL][mode]++;
319 }
320 }
321 return changes;
322 }
323
324 //-----------------------------------------------------------------------
325
Norm_ICMP6(NormalizerConfig *,Packet * p,uint8_t layer,int changes)326 static int Norm_ICMP6(
327 NormalizerConfig*, Packet* p, uint8_t layer, int changes)
328 {
329 ICMPHdr* h = reinterpret_cast<ICMPHdr*>(const_cast<uint8_t*>(p->layers[layer].start));
330
331 if ( ((uint16_t)h->type == icmp::Icmp6Types::ECHO_REQUEST ||
332 (uint16_t)h->type == icmp::Icmp6Types::ECHO_REPLY) &&
333 (h->code != 0) )
334 {
335 const NormMode mode = get_norm_mode(p);
336
337 if ( mode == NORM_MODE_ON )
338 {
339 h->code = static_cast<icmp::IcmpCode>(0);
340 changes++;
341 }
342 normStats[PC_ICMP6_ECHO][mode]++;
343 }
344 return changes;
345 }
346
347 //-----------------------------------------------------------------------
348 // we assume here that the decoder has not pushed ip6 option extension
349 // headers unless the basic sizing is correct (size = N*8 octets, N>0).
350
351 struct ExtOpt
352 {
353 uint8_t next;
354 uint8_t xlen;
355 uint8_t type;
356 uint8_t olen;
357 };
358
359 #define IP6_OPT_PAD_N 1
360
Norm_IP6_Opts(NormalizerConfig *,Packet * p,uint8_t layer,int changes)361 static int Norm_IP6_Opts(
362 NormalizerConfig*, Packet* p, uint8_t layer, int changes)
363 {
364 NormMode mode = get_norm_mode(p);
365
366 if ( mode == NORM_MODE_ON )
367 {
368 uint8_t* b = const_cast<uint8_t*>(p->layers[layer].start);
369 ExtOpt* x = reinterpret_cast<ExtOpt*>(b);
370
371 // whatever was here, turn it into one PADN option
372 x->type = IP6_OPT_PAD_N;
373 x->olen = (x->xlen * 8) + 8 - sizeof(*x);
374 memset(b+sizeof(*x), 0, x->olen);
375
376 changes++;
377 }
378 normStats[PC_IP6_OPTS][mode]++;
379 return changes;
380 }
381
382 //-----------------------------------------------------------------------
383
384 #if 0
385 static int Norm_UDP(Packet* p, uint8_t layer, int changes)
386 {
387 return 0;
388 }
389
390 #endif
391
392 //-----------------------------------------------------------------------
393
NopDaOpt(uint8_t * opt,uint8_t len)394 static inline void NopDaOpt(uint8_t* opt, uint8_t len)
395 {
396 memset(opt, (uint8_t)tcp::TcpOptCode::NOP, len);
397 }
398
399 #define TS_ECR_OFFSET 6
400 #define TS_ECR_LENGTH 4
401
Norm_TCPOptions(NormalizerConfig * config,const NormMode mode,uint8_t * opts,size_t len,const tcp::TCPHdr * h,uint8_t validated_len,int changes)402 static inline int Norm_TCPOptions(NormalizerConfig* config, const NormMode mode,
403 uint8_t* opts, size_t len, const tcp::TCPHdr* h, uint8_t validated_len, int changes)
404 {
405 size_t i = 0;
406
407 while ( (i < len) &&
408 (opts[i] != (uint8_t)tcp::TcpOptCode::EOL) &&
409 (i < validated_len) )
410 {
411 uint8_t olen = ( opts[i] <= 1 ) ? 1 : opts[i+1];
412
413 // we know that the first numOpts options have valid lengths
414 // so we should not need to check individual or total option lengths.
415 // however, we keep this as a sanity check.
416 if ( i + olen > len)
417 break;
418
419 switch ( static_cast<tcp::TcpOptCode>(opts[i]) )
420 {
421 case tcp::TcpOptCode::NOP:
422 break;
423
424 case tcp::TcpOptCode::MAXSEG:
425 case tcp::TcpOptCode::WSCALE:
426 if ( !(h->th_flags & TH_SYN) )
427 {
428 if ( mode == NORM_MODE_ON )
429 {
430 NopDaOpt(opts+i, olen);
431 changes++;
432 }
433 normStats[PC_TCP_SYN_OPT][mode]++;
434 }
435 break;
436
437 case tcp::TcpOptCode::TIMESTAMP:
438 if ( !(h->th_flags & TH_ACK) &&
439 // use memcmp because opts have arbitrary alignment
440 memcmp(opts+i+TS_ECR_OFFSET, MAX_EOL_PAD, TS_ECR_LENGTH) )
441 {
442 if ( mode == NORM_MODE_ON )
443 {
444 // TSecr should be zero unless ACK is set
445 memset(opts+i+TS_ECR_OFFSET, 0, TS_ECR_LENGTH);
446 changes++;
447 }
448 normStats[PC_TCP_TS_ECR][mode]++;
449 }
450 break;
451
452 default:
453 if ( !Norm_TcpIsOptional(config, opts[i]) )
454 {
455 if ( mode == NORM_MODE_ON )
456 {
457 NopDaOpt(opts+i, olen);
458 changes++;
459 }
460 normStats[PC_TCP_OPT][mode]++;
461 }
462 }
463 i += olen;
464 }
465 if ( ++i < len && memcmp(opts+i, MAX_EOL_PAD, len-i) )
466 {
467 if ( mode == NORM_MODE_ON )
468 {
469 memset(opts+i, 0, len-i);
470 changes++;
471 }
472 normStats[PC_TCP_PAD][mode]++;
473 }
474 return changes;
475 }
476
Norm_TCPPadding(NormalizerConfig *,const NormMode mode,uint8_t * opts,size_t len,uint8_t validated_len,int changes)477 static inline int Norm_TCPPadding(NormalizerConfig*, const NormMode mode,
478 uint8_t* opts, size_t len, uint8_t validated_len, int changes)
479 {
480 size_t i = 0;
481
482 while ( (i < len) &&
483 (opts[i] != (uint8_t)tcp::TcpOptCode::EOL) &&
484 (i < validated_len) )
485 {
486 i += ( opts[i] <= 1 ) ? 1 : opts[i+1];
487 }
488 if ( ++i < len && memcmp(opts+i, MAX_EOL_PAD, len-i) )
489 {
490 if ( mode == NORM_MODE_ON )
491 {
492 memset(opts+i, 0, len-i);
493 changes++;
494 }
495 normStats[PC_TCP_PAD][mode]++;
496 }
497 return changes;
498 }
499
Norm_TCP(NormalizerConfig * c,Packet * p,uint8_t layer,int changes)500 static int Norm_TCP(
501 NormalizerConfig* c, Packet* p, uint8_t layer, int changes)
502 {
503 tcp::TCPHdr* h = reinterpret_cast<tcp::TCPHdr*>(const_cast<uint8_t*>(p->layers[layer].start));
504 const NormMode mode = get_norm_mode(p);
505
506 if ( Norm_IsEnabled(c, NORM_TCP_RSV) )
507 {
508 if ( h->th_offx2 & TH_RSV )
509 {
510 if ( mode == NORM_MODE_ON )
511 {
512 h->th_offx2 &= ~TH_RSV;
513 changes++;
514 }
515 normStats[PC_TCP_RSV][mode]++;
516 }
517 }
518 if ( Norm_IsEnabled(c, NORM_TCP_ECN_PKT) )
519 {
520 if ( h->th_flags & (TH_CWR|TH_ECE) )
521 {
522 if ( mode == NORM_MODE_ON )
523 {
524 h->th_flags &= ~(TH_CWR|TH_ECE);
525 changes++;
526 }
527 normStats[PC_TCP_ECN_PKT][mode]++;
528 }
529 if ( h->th_offx2 & TH_NS )
530 {
531 if ( mode == NORM_MODE_ON )
532 {
533 h->th_offx2 &= ~TH_NS;
534 changes++;
535 }
536 normStats[PC_TCP_NS][mode]++;
537 }
538 }
539 if ( h->th_urp )
540 {
541 if ( !(h->th_flags & TH_URG) )
542 {
543 if ( Norm_IsEnabled(c, NORM_TCP_REQ_URG) )
544 {
545 if ( mode == NORM_MODE_ON )
546 {
547 h->th_urp = 0;
548 changes++;
549 }
550 normStats[PC_TCP_REQ_URG][mode]++;
551 }
552 }
553 else if ( !p->dsize )
554 {
555 if ( Norm_IsEnabled(c, NORM_TCP_REQ_PAY) )
556 {
557 if ( mode == NORM_MODE_ON )
558 {
559 h->th_flags &= ~TH_URG;
560 h->th_urp = 0;
561 changes++;
562 }
563 normStats[PC_TCP_REQ_PAY][mode]++;
564 }
565 }
566 else if ( h->urp() > p->dsize )
567 {
568 if ( Norm_IsEnabled(c, NORM_TCP_URP) )
569 {
570 if ( mode == NORM_MODE_ON )
571 {
572 h->set_urp(p->dsize);
573 changes++;
574 }
575 normStats[PC_TCP_URP][mode]++;
576 }
577 }
578 }
579 else if ( Norm_IsEnabled(c, NORM_TCP_REQ_URP) )
580 {
581 if ( h->th_flags & TH_URG )
582 {
583 if ( mode == NORM_MODE_ON )
584 {
585 h->th_flags &= ~TH_URG;
586 changes++;
587 }
588 normStats[PC_TCP_REQ_URP][mode]++;
589 }
590 }
591
592 uint8_t tcp_options_len = h->options_len();
593
594 if ( tcp_options_len > 0 )
595 {
596 const Layer& lyr = p->layers[layer];
597 uint8_t* opts = const_cast<uint8_t*>(lyr.start) + tcp::TCP_MIN_HEADER_LEN;
598 // lyr.length only includes valid tcp options
599 uint8_t valid_opts_len = lyr.length - tcp::TCP_MIN_HEADER_LEN;
600
601 if ( Norm_IsEnabled(c, NORM_TCP_OPT) )
602 {
603 changes = Norm_TCPOptions(c, mode, opts,
604 tcp_options_len, h, valid_opts_len, changes);
605 }
606 else if ( Norm_IsEnabled(c, NORM_TCP_PAD) )
607 {
608 changes = Norm_TCPPadding(c, mode, opts,
609 tcp_options_len, valid_opts_len, changes);
610 }
611 }
612 return changes;
613 }
614
615 //-----------------------------------------------------------------------
616
Norm_GetPegs()617 const PegInfo* Norm_GetPegs()
618 { return norm_names; }
619
Norm_GetCounts(unsigned & c)620 NormPegs Norm_GetCounts(unsigned& c)
621 {
622 c = PC_MAX;
623 return normStats;
624 }
625
626 //-----------------------------------------------------------------------
627
Norm_SetConfig(NormalizerConfig * nc)628 int Norm_SetConfig(NormalizerConfig* nc)
629 {
630 if ( !nc->normalizer_flags )
631 {
632 return 0;
633 }
634 if ( Norm_IsEnabled(nc, (NormFlags)NORM_IP4_ANY) )
635 {
636 nc->normalizers[PacketManager::proto_idx(ProtocolId::ETHERTYPE_IPV4)] = Norm_IP4;
637 }
638 if ( Norm_IsEnabled(nc, NORM_ICMP4) )
639 {
640 nc->normalizers[PacketManager::proto_idx(ProtocolId::ICMPV4)] = Norm_ICMP4;
641 }
642 if ( Norm_IsEnabled(nc, (NormFlags)NORM_IP6_ANY) )
643 {
644 nc->normalizers[PacketManager::proto_idx(ProtocolId::IPV6)] = Norm_IP6;
645 nc->normalizers[PacketManager::proto_idx(ProtocolId::HOPOPTS)] = Norm_IP6_Opts;
646 nc->normalizers[PacketManager::proto_idx(ProtocolId::DSTOPTS)] = Norm_IP6_Opts;
647 }
648 if ( Norm_IsEnabled(nc, NORM_ICMP6) )
649 {
650 nc->normalizers[PacketManager::proto_idx(ProtocolId::ICMPV6)] = Norm_ICMP6;
651 }
652 if ( Norm_IsEnabled(nc, (NormFlags)NORM_TCP_ANY) )
653 {
654 nc->normalizers[PacketManager::proto_idx(ProtocolId::TCP)] = Norm_TCP;
655 }
656 return 0;
657 }
658
659