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