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