1 /* Copyright (C) 2007-2013 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_IPV6_H__
25 #define __DECODE_IPV6_H__
26 
27 #define IPV6_HEADER_LEN            40
28 #define	IPV6_MAXPACKET	           65535 /* maximum packet size */
29 #define IPV6_MAX_OPT               40
30 
31 typedef struct IPV6Hdr_
32 {
33     union {
34         struct ip6_un1_ {
35             uint32_t ip6_un1_flow; /* 20 bits of flow-ID */
36             uint16_t ip6_un1_plen; /* payload length */
37             uint8_t  ip6_un1_nxt;  /* next header */
38             uint8_t  ip6_un1_hlim; /* hop limit */
39         } ip6_un1;
40         uint8_t ip6_un2_vfc;   /* 4 bits version, top 4 bits class */
41     } ip6_hdrun;
42 
43     union {
44         struct {
45             uint32_t ip6_src[4];
46             uint32_t ip6_dst[4];
47         } ip6_un2;
48         uint16_t ip6_addrs[16];
49     } ip6_hdrun2;
50 } IPV6Hdr;
51 
52 #define s_ip6_src                       ip6_hdrun2.ip6_un2.ip6_src
53 #define s_ip6_dst                       ip6_hdrun2.ip6_un2.ip6_dst
54 #define s_ip6_addrs                     ip6_hdrun2.ip6_addrs
55 
56 #define s_ip6_vfc                       ip6_hdrun.ip6_un2_vfc
57 #define s_ip6_flow                      ip6_hdrun.ip6_un1.ip6_un1_flow
58 #define s_ip6_plen                      ip6_hdrun.ip6_un1.ip6_un1_plen
59 #define s_ip6_nxt                       ip6_hdrun.ip6_un1.ip6_un1_nxt
60 #define s_ip6_hlim                      ip6_hdrun.ip6_un1.ip6_un1_hlim
61 
62 #define IPV6_GET_RAW_VER(ip6h)          (((ip6h)->s_ip6_vfc & 0xf0) >> 4)
63 #define IPV6_GET_RAW_CLASS(ip6h)        ((SCNtohl((ip6h)->s_ip6_flow) & 0x0FF00000) >> 20)
64 #define IPV6_GET_RAW_FLOW(ip6h)         (SCNtohl((ip6h)->s_ip6_flow) & 0x000FFFFF)
65 #define IPV6_GET_RAW_NH(ip6h)           ((ip6h)->s_ip6_nxt)
66 #define IPV6_GET_RAW_PLEN(ip6h)         (SCNtohs((ip6h)->s_ip6_plen))
67 #define IPV6_GET_RAW_HLIM(ip6h)         ((ip6h)->s_ip6_hlim)
68 
69 #define IPV6_SET_RAW_VER(ip6h, value)   ((ip6h)->s_ip6_vfc = (((ip6h)->s_ip6_vfc & 0x0f) | (value << 4)))
70 #define IPV6_SET_RAW_NH(ip6h, value)    ((ip6h)->s_ip6_nxt = (value))
71 
72 #define IPV6_SET_L4PROTO(p,proto)       (p)->ip6vars.l4proto = (proto)
73 #define IPV6_SET_EXTHDRS_LEN(p,len)     (p)->ip6vars.exthdrs_len = (len)
74 
75 
76 /* ONLY call these functions after making sure that:
77  * 1. p->ip6h is set
78  * 2. p->ip6h is valid (len is correct)
79  */
80 #define IPV6_GET_VER(p) \
81     IPV6_GET_RAW_VER((p)->ip6h)
82 #define IPV6_GET_CLASS(p) \
83     IPV6_GET_RAW_CLASS((p)->ip6h)
84 #define IPV6_GET_FLOW(p) \
85     IPV6_GET_RAW_FLOW((p)->ip6h)
86 #define IPV6_GET_NH(p) \
87     (IPV6_GET_RAW_NH((p)->ip6h))
88 #define IPV6_GET_PLEN(p) \
89     IPV6_GET_RAW_PLEN((p)->ip6h)
90 #define IPV6_GET_HLIM(p) \
91     (IPV6_GET_RAW_HLIM((p)->ip6h))
92 
93 #define IPV6_GET_L4PROTO(p) \
94     ((p)->ip6vars.l4proto)
95 #define IPV6_GET_EXTHDRS_LEN(p) \
96     ((p)->ip6vars.exthdrs_len)
97 
98 /** \brief get the highest proto/next header field we know */
99 //#define IPV6_GET_UPPER_PROTO(p)         (p)->ip6eh.ip6_exthdrs_cnt ?
100 //    (p)->ip6eh.ip6_exthdrs[(p)->ip6eh.ip6_exthdrs_cnt - 1].next : IPV6_GET_NH((p))
101 
102 /* helper structure with parsed ipv6 info */
103 typedef struct IPV6Vars_
104 {
105     uint8_t l4proto;       /**< the proto after the extension headers
106                             *   store while decoding so we don't have
107                             *   to loop through the exthdrs all the time */
108     uint16_t exthdrs_len;  /**< length of the exthdrs */
109 } IPV6Vars;
110 
111 #define CLEAR_IPV6_PACKET(p) do { \
112     (p)->ip6h = NULL; \
113     (p)->ip6vars.l4proto = 0; \
114     (p)->ip6vars.exthdrs_len = 0; \
115     memset(&(p)->ip6eh, 0x00, sizeof((p)->ip6eh)); \
116 } while (0)
117 
118 /* Fragment header */
119 typedef struct IPV6FragHdr_
120 {
121     uint8_t  ip6fh_nxt;             /* next header */
122     uint8_t  ip6fh_reserved;        /* reserved field */
123     uint16_t ip6fh_offlg;           /* offset, reserved, and flag */
124     uint32_t ip6fh_ident;           /* identification */
125 } __attribute__((__packed__)) IPV6FragHdr;
126 
127 #define IPV6_EXTHDR_GET_FH_NH(p)            (p)->ip6eh.fh_nh
128 #define IPV6_EXTHDR_GET_FH_OFFSET(p)        (p)->ip6eh.fh_offset
129 #define IPV6_EXTHDR_GET_FH_FLAG(p)          (p)->ip6eh.fh_more_frags_set
130 #define IPV6_EXTHDR_GET_FH_ID(p)            (p)->ip6eh.fh_id
131 
132 /* rfc 1826 */
133 typedef struct IPV6AuthHdr_
134 {
135     uint8_t ip6ah_nxt;              /* next header */
136     uint8_t ip6ah_len;              /* header length in units of 8 bytes, not
137                                         including first 8 bytes. */
138     uint16_t ip6ah_reserved;        /* reserved for future use */
139     uint32_t ip6ah_spi;             /* SECURITY PARAMETERS INDEX (SPI) */
140     uint32_t ip6ah_seq;             /* sequence number */
141 } __attribute__((__packed__)) IPV6AuthHdr;
142 
143 typedef struct IPV6EspHdr_
144 {
145     uint32_t ip6esph_spi;           /* SECURITY PARAMETERS INDEX (SPI) */
146     uint32_t ip6esph_seq;           /* sequence number */
147 } __attribute__((__packed__)) IPV6EspHdr;
148 
149 typedef struct IPV6RouteHdr_
150 {
151     uint8_t ip6rh_nxt;               /* next header */
152     uint8_t ip6rh_len;               /* header length in units of 8 bytes, not
153                                         including first 8 bytes. */
154     uint8_t ip6rh_type;              /* routing type */
155     uint8_t ip6rh_segsleft;          /* segments left */
156 } __attribute__((__packed__)) IPV6RouteHdr;
157 
158 
159 /* Hop-by-Hop header and Destination Options header use options that are
160  * defined here. */
161 
162 #define IPV6OPT_PAD1                  0x00
163 #define IPV6OPT_PADN                  0x01
164 #define IPV6OPT_RA                    0x05
165 #define IPV6OPT_JUMBO                 0xC2
166 #define IPV6OPT_HAO                   0xC9
167 
168 /* Home Address Option */
169 typedef struct IPV6OptHAO_
170 {
171     uint8_t ip6hao_type;             /* Option type */
172     uint8_t ip6hao_len;              /* Option Data len (excludes type and len) */
173     struct in6_addr ip6hao_hoa;       /* Home address. */
174 } IPV6OptHAO;
175 
176 /* Router Alert Option */
177 typedef struct IPV6OptRA_
178 {
179     uint8_t ip6ra_type;             /* Option type */
180     uint8_t ip6ra_len;              /* Option Data len (excludes type and len) */
181     uint16_t ip6ra_value;           /* Router Alert value */
182 } IPV6OptRA;
183 
184 /* Jumbo Option */
185 typedef struct IPV6OptJumbo_
186 {
187     uint8_t ip6j_type;             /* Option type */
188     uint8_t ip6j_len;              /* Option Data len (excludes type and len) */
189     uint32_t ip6j_payload_len;     /* Jumbo Payload Length */
190 } IPV6OptJumbo;
191 
192 typedef struct IPV6HopOptsHdr_
193 {
194     uint8_t ip6hh_nxt;              /* next header */
195     uint8_t ip6hh_len;              /* header length in units of 8 bytes, not
196                                        including first 8 bytes. */
197 } __attribute__((__packed__)) IPV6HopOptsHdr;
198 
199 typedef struct IPV6DstOptsHdr_
200 {
201     uint8_t ip6dh_nxt;              /* next header */
202     uint8_t ip6dh_len;              /* header length in units of 8 bytes, not
203                                        including first 8 bytes. */
204 } __attribute__((__packed__)) IPV6DstOptsHdr;
205 
206 typedef struct IPV6GenOptHdr_
207 {
208     uint8_t type;
209     uint8_t next;
210     uint8_t len;
211     uint8_t *data;
212 }   IPV6GenOptHdr;
213 
214 typedef struct IPV6ExtHdrs_
215 {
216     bool rh_set;
217     uint8_t rh_type;
218 
219     bool fh_set;
220     bool fh_more_frags_set;
221     uint8_t fh_nh;
222 
223     uint8_t fh_prev_nh;
224     uint16_t fh_prev_hdr_offset;
225 
226     uint16_t fh_header_offset;
227     uint16_t fh_data_offset;
228     uint16_t fh_data_len;
229 
230     /* In fh_offset we store the offset of this extension into the packet past
231      * the ipv6 header. We use it in defrag for creating a defragmented packet
232      * without the frag header */
233     uint16_t fh_offset;
234     uint32_t fh_id;
235 
236 } IPV6ExtHdrs;
237 
238 #define IPV6_EXTHDR_SET_FH(p)       (p)->ip6eh.fh_set = TRUE
239 #define IPV6_EXTHDR_ISSET_FH(p)     (p)->ip6eh.fh_set
240 #define IPV6_EXTHDR_SET_RH(p)       (p)->ip6eh.rh_set = TRUE
241 #define IPV6_EXTHDR_ISSET_RH(p)     (p)->ip6eh.rh_set
242 
243 void DecodeIPV6RegisterTests(void);
244 
245 #endif /* __DECODE_IPV6_H__ */
246 
247