1 /*****************************************************************************
2 * ip.h: Internet Protocol (IP)
3 *****************************************************************************
4 * Copyright (C) 2015 VideoLAN
5 *
6 * Authors: Benjamin Cohen <bencoh@notk.org>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject
14 * to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 *****************************************************************************/
27
28 /*
29 * Normative references:
30 * - IETF RFC 791 INTERNET PROTOCOL (September 1981)
31 * - IETF RFC 790 ASSIGNED NUMBERS (September 1981)
32 */
33
34 #ifndef __BITSTREAM_IETF_IP_H__
35 #define __BITSTREAM_IETF_IP_H__
36
37 #include <stdint.h>
38
39 #ifdef __cplusplus
40 extern "C"
41 {
42 #endif
43
44 /*
45 * Reminder: IP header
46 0 1 2 3
47 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
48 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 |Version| IHL |Type of Service| Total Length |
50 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
51 | Identification |Flags| Fragment Offset |
52 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 | Time to Live | Protocol | Header Checksum |
54 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 | Source Address |
56 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
57 | Destination Address |
58 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 | Options | Padding |
60 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 */
62
63 #define IP_HEADER_MINSIZE 20
64
65 #define IP_PROTO_ICMP 1
66 #define IP_PROTO_TCP 6
67 #define IP_PROTO_UDP 17
68
ip_set_version(uint8_t * p_ip,uint8_t version)69 static inline void ip_set_version(uint8_t *p_ip, uint8_t version)
70 {
71 p_ip[0] &= ~0xf0;
72 p_ip[0] |= (version & 0xf) << 4;
73 }
74
ip_get_version(const uint8_t * p_ip)75 static inline uint8_t ip_get_version(const uint8_t *p_ip)
76 {
77 return (p_ip[0] >> 4) & 0xf;
78 }
79
ip_set_ihl(uint8_t * p_ip,uint8_t ihl)80 static inline void ip_set_ihl(uint8_t *p_ip, uint8_t ihl)
81 {
82 p_ip[0] &= ~0xf;
83 p_ip[0] |= (ihl & 0xf);
84 }
85
ip_get_ihl(const uint8_t * p_ip)86 static inline uint8_t ip_get_ihl(const uint8_t *p_ip)
87 {
88 return p_ip[0] & 0xf;
89 }
90
ip_set_tos(uint8_t * p_ip,uint8_t tos)91 static inline void ip_set_tos(uint8_t *p_ip, uint8_t tos)
92 {
93 p_ip[1] = tos;
94 }
95
ip_get_tos(const uint8_t * p_ip)96 static inline uint8_t ip_get_tos(const uint8_t *p_ip)
97 {
98 return p_ip[1];
99 }
100
ip_set_len(uint8_t * p_ip,uint16_t len)101 static inline void ip_set_len(uint8_t *p_ip, uint16_t len)
102 {
103 p_ip[2] = (len & 0xff00) >> 8;
104 p_ip[3] = (len & 0xff);
105 }
106
ip_get_len(const uint8_t * p_ip)107 static inline uint16_t ip_get_len(const uint8_t *p_ip)
108 {
109 return (p_ip[2] << 8) | p_ip[3];
110 }
111
ip_set_id(uint8_t * p_ip,uint16_t id)112 static inline void ip_set_id(uint8_t *p_ip, uint16_t id)
113 {
114
115 p_ip[4] = (id & 0xff00) >> 8;
116 p_ip[5] = (id & 0xff);
117 }
118
ip_get_id(const uint8_t * p_ip)119 static inline uint16_t ip_get_id(const uint8_t *p_ip)
120 {
121 return (p_ip[4] << 8) | p_ip[5];
122 }
123
ip_set_flag_reserved(uint8_t * p_ip,uint8_t flag)124 static inline void ip_set_flag_reserved(uint8_t *p_ip, uint8_t flag)
125 {
126 p_ip[6] &= ~0x80;
127 p_ip[6] |= (flag & 1) << 7;
128 }
129
ip_get_flag_reservered(const uint8_t * p_ip)130 static inline uint8_t ip_get_flag_reservered(const uint8_t *p_ip)
131 {
132 return (p_ip[6] & 0x80);
133 }
134
ip_set_flag_df(uint8_t * p_ip,uint8_t flag)135 static inline void ip_set_flag_df(uint8_t *p_ip, uint8_t flag)
136 {
137 p_ip[6] &= ~0x40;
138 p_ip[6] |= (flag & 1) << 6;
139 }
140
ip_get_flag_df(const uint8_t * p_ip)141 static inline uint8_t ip_get_flag_df(const uint8_t *p_ip)
142 {
143 return (p_ip[6] & 0x40);
144 }
145
ip_set_flag_mf(uint8_t * p_ip,uint8_t flag)146 static inline void ip_set_flag_mf(uint8_t *p_ip, uint8_t flag)
147 {
148 p_ip[6] &= ~0x20;
149 p_ip[6] |= (flag & 1) << 5;
150 }
151
ip_get_flag_mf(const uint8_t * p_ip)152 static inline uint8_t ip_get_flag_mf(const uint8_t *p_ip)
153 {
154 return (p_ip[6] & 0x20);
155 }
156
ip_set_frag_offset(uint8_t * p_ip,uint16_t offset)157 static inline void ip_set_frag_offset(uint8_t *p_ip, uint16_t offset)
158 {
159 p_ip[6] &= ~0x1f;
160 p_ip[6] |= (offset & 0x1f00) >> 8;
161 p_ip[7] = (offset & 0xff);
162 }
163
ip_get_frag_offset(const uint8_t * p_ip)164 static inline uint8_t ip_get_frag_offset(const uint8_t *p_ip)
165 {
166 return ((p_ip[6] & 0x1f) << 8 | p_ip[7]);
167 }
168
ip_set_ttl(uint8_t * p_ip,uint8_t ttl)169 static inline void ip_set_ttl(uint8_t *p_ip, uint8_t ttl)
170 {
171 p_ip[8] = ttl;
172 }
173
ip_get_ttl(const uint8_t * p_ip)174 static inline uint8_t ip_get_ttl(const uint8_t *p_ip)
175 {
176 return p_ip[8];
177 }
178
ip_set_proto(uint8_t * p_ip,uint8_t proto)179 static inline void ip_set_proto(uint8_t *p_ip, uint8_t proto)
180 {
181 p_ip[9] = proto;
182 }
183
ip_get_proto(const uint8_t * p_ip)184 static inline uint8_t ip_get_proto(const uint8_t *p_ip)
185 {
186 return p_ip[9];
187 }
188
ip_set_cksum(uint8_t * p_ip,uint16_t cksum)189 static inline void ip_set_cksum(uint8_t *p_ip, uint16_t cksum)
190 {
191 p_ip[10] = (cksum & 0xff00) >> 8;
192 p_ip[11] = (cksum & 0xff);
193 }
194
ip_get_cksum(const uint8_t * p_ip)195 static inline uint16_t ip_get_cksum(const uint8_t *p_ip)
196 {
197 return (p_ip[10] << 8) | p_ip[11];
198 }
199
ip_set_srcaddr(uint8_t * p_ip,uint32_t addr)200 static inline void ip_set_srcaddr(uint8_t *p_ip, uint32_t addr)
201 {
202 p_ip[12] = (addr & 0xff000000) >> 24;
203 p_ip[13] = (addr & 0x00ff0000) >> 16;
204 p_ip[14] = (addr & 0x0000ff00) >> 8;
205 p_ip[15] = (addr & 0x000000ff);
206 }
207
ip_get_srcaddr(const uint8_t * p_ip)208 static inline uint32_t ip_get_srcaddr(const uint8_t *p_ip)
209 {
210 return (p_ip[12] << 24) | (p_ip[13] << 16) | (p_ip[14] << 8) | p_ip[15];
211 }
212
ip_srcaddr(uint8_t * p_ip)213 static inline uint8_t *ip_srcaddr(uint8_t *p_ip)
214 {
215 return p_ip + 12;
216 }
217
ip_set_dstaddr(uint8_t * p_ip,uint32_t addr)218 static inline void ip_set_dstaddr(uint8_t *p_ip, uint32_t addr)
219 {
220 p_ip[16] = (addr & 0xff000000) >> 24;
221 p_ip[17] = (addr & 0x00ff0000) >> 16;
222 p_ip[18] = (addr & 0x0000ff00) >> 8;
223 p_ip[19] = (addr & 0x000000ff);
224 }
225
ip_dstaddr(uint8_t * p_ip)226 static inline uint8_t *ip_dstaddr(uint8_t *p_ip)
227 {
228 return p_ip + 16;
229 }
230
ip_get_dstaddr(const uint8_t * p_ip)231 static inline uint32_t ip_get_dstaddr(const uint8_t *p_ip)
232 {
233 return (p_ip[16] << 24) | (p_ip[17] << 16) | (p_ip[18] << 8) | p_ip[19];
234 }
235
ip_payload(uint8_t * p_ip)236 static inline uint8_t *ip_payload(uint8_t *p_ip)
237 {
238 return p_ip + 4 * ip_get_ihl(p_ip); /* ihl is in 32b words */
239 }
240
241 #ifdef __cplusplus
242 }
243 #endif
244
245 #endif
246