suricata
decode-icmpv6.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 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  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #ifndef __DECODE_ICMPV6_H__
25 #define __DECODE_ICMPV6_H__
26 
27 #include "decode-tcp.h"
28 #include "decode-sctp.h"
29 #include "decode-udp.h"
30 #include "decode-ipv6.h"
31 
32 #define ICMPV6_HEADER_LEN 8
33 #define ICMPV6_HEADER_PKT_OFFSET 8
34 
35 /** ICMPV6 Message Types: */
36 /** Error Messages: (type <128) */
37 #define ICMP6_DST_UNREACH 1
38 #define ICMP6_PACKET_TOO_BIG 2
39 #define ICMP6_TIME_EXCEEDED 3
40 #define ICMP6_PARAM_PROB 4
41 
42 /** Informational Messages (type>=128) */
43 #define ICMP6_ECHO_REQUEST 128
44 #define ICMP6_ECHO_REPLY 129
45 
46 #define MLD_LISTENER_QUERY 130
47 #define MLD_LISTENER_REPORT 131
48 #define MLD_LISTENER_REDUCTION 132
49 
50 #define ND_ROUTER_SOLICIT 133
51 #define ND_ROUTER_ADVERT 134
52 #define ND_NEIGHBOR_SOLICIT 135
53 #define ND_NEIGHBOR_ADVERT 136
54 #define ND_REDIRECT 137
55 
56 #define ICMP6_RR 138
57 #define ICMP6_NI_QUERY 139
58 #define ICMP6_NI_REPLY 140
59 #define ND_INVERSE_SOLICIT 141
60 #define ND_INVERSE_ADVERT 142
61 #define MLD_V2_LIST_REPORT 143
62 #define HOME_AGENT_AD_REQUEST 144
63 #define HOME_AGENT_AD_REPLY 145
64 #define MOBILE_PREFIX_SOLICIT 146
65 #define MOBILE_PREFIX_ADVERT 147
66 #define CERT_PATH_SOLICIT 148
67 #define CERT_PATH_ADVERT 149
68 #define ICMP6_MOBILE_EXPERIMENTAL 150
69 #define MC_ROUTER_ADVERT 151
70 #define MC_ROUTER_SOLICIT 152
71 #define MC_ROUTER_TERMINATE 153
72 #define FMIPV6_MSG 154
73 #define RPL_CONTROL_MSG 155
74 #define LOCATOR_UDATE_MSG 156
75 #define DUPL_ADDR_REQUEST 157
76 #define DUPL_ADDR_CONFIRM 158
77 #define MPL_CONTROL_MSG 159
78 
79 /** Destination Unreachable Message (type=1) Code: */
80 
81 #define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */
82 #define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */
83  /* administratively prohibited */
84 #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */
85 #define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */
86 #define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */
87 #define ICMP6_DST_UNREACH_FAILEDPOLICY 5 /* Source address failed ingress/egress policy */
88 #define ICMP6_DST_UNREACH_REJECTROUTE 6 /* Reject route to destination */
89 
90 
91 /** Time Exceeded Message (type=3) Code: */
92 #define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */
93 #define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */
94 
95 /** Parameter Problem Message (type=4) Code: */
96 #define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */
97 #define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */
98 #define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */
99 
100 
101 /** macro for icmpv6 "type" access */
102 #define ICMPV6_GET_TYPE(p) (p)->icmpv6h->type
103 /** macro for icmpv6 "code" access */
104 #define ICMPV6_GET_CODE(p) (p)->icmpv6h->code
105 /** macro for icmpv6 "csum" access */
106 #define ICMPV6_GET_RAW_CSUM(p) SCNtohs((p)->icmpv6h->csum)
107 #define ICMPV6_GET_CSUM(p) (p)->icmpv6h->csum
108 
109 /** If message is informational */
110 /** macro for icmpv6 "id" access */
111 #define ICMPV6_GET_ID(p) (p)->icmpv6vars.id
112 /** macro for icmpv6 "seq" access */
113 #define ICMPV6_GET_SEQ(p) (p)->icmpv6vars.seq
114 
115 /** If message is Error */
116 /** macro for icmpv6 "unused" access */
117 #define ICMPV6_GET_UNUSED(p) (p)->icmpv6h->icmpv6b.icmpv6e.unused
118 /** macro for icmpv6 "error_ptr" access */
119 #define ICMPV6_GET_ERROR_PTR(p) (p)->icmpv6h->icmpv6b.icmpv6e.error_ptr
120 /** macro for icmpv6 "mtu" accessibility */
121 // ICMPv6 has MTU only for type too big
122 #define ICMPV6_HAS_MTU(p) ((p)->icmpv6h->type == ICMP6_PACKET_TOO_BIG)
123 /** macro for icmpv6 "mtu" access */
124 #define ICMPV6_GET_MTU(p) SCNtohl((p)->icmpv6h->icmpv6b.icmpv6e.mtu)
125 
126 /** macro for icmpv6 embedded "protocol" access */
127 #define ICMPV6_GET_EMB_PROTO(p) (p)->icmpv6vars.emb_ip6_proto_next
128 /** macro for icmpv6 embedded "ipv6h" header access */
129 #define ICMPV6_GET_EMB_IPV6(p) (p)->icmpv6vars.emb_ipv6h
130 /** macro for icmpv6 embedded "tcph" header access */
131 #define ICMPV6_GET_EMB_TCP(p) (p)->icmpv6vars.emb_tcph
132 /** macro for icmpv6 embedded "udph" header access */
133 #define ICMPV6_GET_EMB_UDP(p) (p)->icmpv6vars.emb_udph
134 /** macro for icmpv6 embedded "icmpv6h" header access */
135 #define ICMPV6_GET_EMB_icmpv6h(p) (p)->icmpv6vars.emb_icmpv6h
136 
137 typedef struct ICMPV6Info_
138 {
139  uint16_t id;
140  uint16_t seq;
141 } ICMPV6Info;
142 
143 /** ICMPv6 header structure */
144 typedef struct ICMPV6Hdr_
145 {
146  uint8_t type;
147  uint8_t code;
148  uint16_t csum;
149 
150  union {
151  ICMPV6Info icmpv6i; /** Informational message */
152  union
153  {
154  uint32_t unused; /** for types 1 and 3, should be zero */
155  uint32_t error_ptr; /** for type 4, pointer to the octet that originate the error */
156  uint32_t mtu; /** for type 2, the Maximum Transmission Unit of the next-hop link */
157  } icmpv6e; /** Error Message */
158  } icmpv6b;
159 } ICMPV6Hdr;
160 
161 /** Data available from the decoded packet */
162 typedef struct ICMPV6Vars_ {
163  /* checksum of the icmpv6 packet */
164  uint16_t id;
165  uint16_t seq;
166  uint32_t mtu;
167  uint32_t error_ptr;
168 
169  /** Pointers to the embedded packet headers */
171  TCPHdr *emb_tcph;
172  UDPHdr *emb_udph;
174 
175  /** IPv6 src and dst address */
176  uint32_t emb_ip6_src[4];
177  uint32_t emb_ip6_dst[4];
179 
180  /** TCP/UDP ports */
181  uint16_t emb_sport;
182  uint16_t emb_dport;
183 
184 } ICMPV6Vars;
185 
186 
187 #define CLEAR_ICMPV6_PACKET(p) do { \
188  (p)->level4_comp_csum = -1; \
189  PACKET_CLEAR_L4VARS((p)); \
190  (p)->icmpv6h = NULL; \
191 } while(0)
192 
193 void DecodeICMPV6RegisterTests(void);
194 
195 int ICMPv6GetCounterpart(uint8_t type);
196 
197 /** -------- Inline functions --------- */
198 static inline uint16_t ICMPV6CalculateChecksum(uint16_t *, uint16_t *, uint16_t);
199 
200 /**
201  * \brief Calculates the checksum for the ICMPV6 packet
202  *
203  * \param shdr Pointer to source address field from the IPV6 packet. Used as a
204  * part of the psuedoheader for computing the checksum
205  * \param pkt Pointer to the start of the ICMPV6 packet
206  * \param tlen Total length of the ICMPV6 packet(header + payload)
207  *
208  * \retval csum Checksum for the ICMPV6 packet
209  */
210 static inline uint16_t ICMPV6CalculateChecksum(uint16_t *shdr, uint16_t *pkt,
211  uint16_t tlen)
212 {
213  uint16_t pad = 0;
214  uint32_t csum = shdr[0];
215 
216  csum += shdr[1] + shdr[2] + shdr[3] + shdr[4] + shdr[5] + shdr[6] +
217  shdr[7] + shdr[8] + shdr[9] + shdr[10] + shdr[11] + shdr[12] +
218  shdr[13] + shdr[14] + shdr[15] + htons(58 + tlen);
219 
220  csum += pkt[0];
221 
222  tlen -= 4;
223  pkt += 2;
224 
225  while (tlen >= 64) {
226  csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
227  pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
228  pkt[14] + pkt[15] + pkt[16] + pkt[17] + pkt[18] + pkt[19] +
229  pkt[20] + pkt[21] + pkt[22] + pkt[23] + pkt[24] + pkt[25] +
230  pkt[26] + pkt[27] + pkt[28] + pkt[29] + pkt[30] + pkt[31];
231  tlen -= 64;
232  pkt += 32;
233  }
234 
235  while (tlen >= 32) {
236  csum += pkt[0] + pkt[1] + pkt[2] + pkt[3] + pkt[4] + pkt[5] + pkt[6] +
237  pkt[7] + pkt[8] + pkt[9] + pkt[10] + pkt[11] + pkt[12] + pkt[13] +
238  pkt[14] + pkt[15];
239  tlen -= 32;
240  pkt += 16;
241  }
242 
243  while(tlen >= 8) {
244  csum += pkt[0] + pkt[1] + pkt[2] + pkt[3];
245  tlen -= 8;
246  pkt += 4;
247  }
248 
249  while(tlen >= 4) {
250  csum += pkt[0] + pkt[1];
251  tlen -= 4;
252  pkt += 2;
253  }
254 
255  while (tlen > 1) {
256  csum += pkt[0];
257  tlen -= 2;
258  pkt += 1;
259  }
260 
261  if (tlen == 1) {
262  *(uint8_t *)(&pad) = (*(uint8_t *)pkt);
263  csum += pad;
264  }
265 
266  csum = (csum >> 16) + (csum & 0x0000FFFF);
267  csum += (csum >> 16);
268 
269  return (uint16_t) ~csum;
270 }
271 
272 
273 #endif /* __DECODE_ICMPV6_H__ */
274 
ICMPV6Vars_::emb_ip6_src
uint32_t emb_ip6_src[4]
Definition: decode-icmpv6.h:176
decode-tcp.h
ICMPV6Hdr_::type
uint8_t type
Definition: decode-icmpv6.h:146
ICMPV6Hdr_::error_ptr
uint32_t error_ptr
Definition: decode-icmpv6.h:155
ICMPV6Hdr
struct ICMPV6Hdr_ ICMPV6Hdr
ICMPV6Vars_::emb_tcph
TCPHdr * emb_tcph
Definition: decode-icmpv6.h:171
ICMPV6Info_::id
uint16_t id
Definition: decode-icmpv6.h:139
ICMPV6Info
struct ICMPV6Info_ ICMPV6Info
ICMPV6Hdr_::csum
uint16_t csum
Definition: decode-icmpv6.h:148
decode-udp.h
ICMPV6Hdr_::icmpv6e
union ICMPV6Hdr_::@35::@36 icmpv6e
ICMPV6Hdr_::unused
uint32_t unused
Definition: decode-icmpv6.h:154
ICMPV6Vars_::emb_sport
uint16_t emb_sport
Definition: decode-icmpv6.h:181
DecodeICMPV6RegisterTests
void DecodeICMPV6RegisterTests(void)
Registers ICMPV6 unit tests.
Definition: decode-icmpv6.c:1585
pad
uint16_t pad
Definition: source-erf-file.c:8
decode-ipv6.h
ICMPV6Hdr_::mtu
uint32_t mtu
Definition: decode-icmpv6.h:156
type
uint8_t type
Definition: decode-icmpv4.h:2
ICMPV6Vars_::error_ptr
uint32_t error_ptr
Definition: decode-icmpv6.h:167
ICMPV6Vars_::emb_ip6_proto_next
uint8_t emb_ip6_proto_next
Definition: decode-icmpv6.h:178
ICMPV6Hdr_::code
uint8_t code
Definition: decode-icmpv6.h:147
ICMPV6Vars
struct ICMPV6Vars_ ICMPV6Vars
ICMPV6Info_::seq
uint16_t seq
Definition: decode-icmpv6.h:140
IPV6Hdr_
Definition: decode-ipv6.h:31
ICMPV6Vars_::emb_dport
uint16_t emb_dport
Definition: decode-icmpv6.h:182
ICMPV6Vars_::emb_udph
UDPHdr * emb_udph
Definition: decode-icmpv6.h:172
ICMPV6Hdr_
Definition: decode-icmpv6.h:144
ICMPV6Vars_
Definition: decode-icmpv6.h:162
ICMPv6GetCounterpart
int ICMPv6GetCounterpart(uint8_t type)
Definition: decode-icmpv6.c:156
ICMPV6Vars_::seq
uint16_t seq
Definition: decode-icmpv6.h:165
decode-sctp.h
ICMPV6Vars_::emb_ip6_dst
uint32_t emb_ip6_dst[4]
Definition: decode-icmpv6.h:177
ICMPV6Hdr_::icmpv6b
union ICMPV6Hdr_::@35 icmpv6b
ICMPV6Vars_::mtu
uint32_t mtu
Definition: decode-icmpv6.h:166
ICMPV6Vars_::id
uint16_t id
Definition: decode-icmpv6.h:164
ICMPV6Hdr_::icmpv6i
ICMPV6Info icmpv6i
Definition: decode-icmpv6.h:151
ICMPV6Vars_::emb_ipv6h
IPV6Hdr * emb_ipv6h
Definition: decode-icmpv6.h:170
ICMPV6Vars_::emb_icmpv6h
ICMPV6Hdr * emb_icmpv6h
Definition: decode-icmpv6.h:173
ICMPV6Info_
Definition: decode-icmpv6.h:137