summaryrefslogtreecommitdiff
path: root/nuttx/include/nuttx/net/ip.h
blob: 5e573f2d67438847547dca6dd2fdc009b76a350d (plain) (blame)
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
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/****************************************************************************
 * include/nuttx/net/ip.h
 *
 * The uIP header file contains IP-related definitions for a number of C
 * macros that are used by applications as well as internally by the
 * OS networking logic.
 *
 *   Copyright (C) 2007-2012, 2014 Gregory Nutt. All rights reserved.
 *   Author: Gregory Nutt <gnutt@nuttx.org>
 *
 * This logic was leveraged from uIP which also has a BSD-style license:
 *
 *   Author Adam Dunkels <adam@dunkels.com>
 *   Copyright (c) 2001-2003, Adam Dunkels.
 *   All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote
 *    products derived from this software without specific prior
 *    written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

#ifndef __INCLUDE_NUTTX_NET_IP_H
#define __INCLUDE_NUTTX_NET_IP_H

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <nuttx/config.h>

#include <stdint.h>
#include <stdbool.h>
#include <queue.h>

#include <arpa/inet.h>
#include <netinet/in.h>

#include <nuttx/net/netconfig.h>

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/
/* Values for the IP protocol field */

#define IP_PROTO_ICMP     1
#define IP_PROTO_IGMP     2
#define IP_PROTO_TCP      6
#define IP_PROTO_UDP      17
#define IP_PROTO_ICMP6    58

/* Flag bits in 16-bit flags + fragment offset IPv4 header field */

#define IP_FLAG_RESERVED  0x8000
#define IP_FLAG_DONTFRAG  0x4000
#define IP_FLAG_MOREFRAGS 0x2000

/* IP Header sizes */

#ifdef CONFIG_NET_IPv4
#  define IPv4_HDRLEN     20    /* Size of IPv4 header */
#endif

#ifdef CONFIG_NET_IPv6
#  define IPv6_HDRLEN     40    /* Size of IPv6 header */
#endif

/****************************************************************************
 * Public Type Definitions
 ****************************************************************************/

/* Representation of an IP address */

typedef uint16_t net_ipv6addr_t[8];

#ifdef CONFIG_NET_IPv6
typedef net_ipv6addr_t net_ipaddr_t;
#else
typedef in_addr_t net_ipaddr_t;
#endif

#ifdef CONFIG_NET_IPv4
/* The IPv4 header */

struct net_iphdr_s
{
  uint8_t  vhl;              /*  8-bit Version (4) and header length (5 or 6) */
  uint8_t  tos;              /*  8-bit Type of service (e.g., 6=TCP) */
  uint8_t  len[2];           /* 16-bit Total length */
  uint8_t  ipid[2];          /* 16-bit Identification */
  uint8_t  ipoffset[2];      /* 16-bit IP flags + fragment offset */
  uint8_t  ttl;              /*  8-bit Time to Live */
  uint8_t  proto;            /*  8-bit Protocol */
  uint16_t ipchksum;         /* 16-bit Header checksum */
  uint16_t srcipaddr[2];     /* 32-bit Source IP address */
  uint16_t destipaddr[2];    /* 32-bit Destination IP address */
};
#endif

#ifdef CONFIG_NET_IPv6
/* The IPv6 header */

struct net_ipv6hdr_s
{
  uint8_t  vtc;              /* Bits 0-3: version, bits 4-7: traffic class (MS) */
  uint8_t  tcf;              /* Bits 0-3: traffic class (LS), 4-bits: flow label (MS) */
  uint16_t flow;             /* 16-bit flow label (LS) */
  uint8_t  len[2];           /* 16-bit Payload length */
  uint8_t  proto;            /*  8-bit Next header (same as IPv4 protocol field) */
  uint8_t  ttl;              /*  8-bit Hop limit (like IPv4 TTL field) */
  net_ipv6addr_t srcipaddr;  /* 128-bit Source address */
  net_ipv6addr_t destipaddr; /* 128-bit Destination address */
};
#endif

/****************************************************************************
 * Public Data
 ****************************************************************************/

/****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

/* Construct an IPv4 address from four bytes.
 *
 * This function constructs an IPv4 address in network byte order.
 *
 *   addr  A pointer to a net_ipaddr_t variable that will be
 *         filled in with the IPv4 address.
 *   addr0 The first octet of the IPv4 address.
 *   addr1 The second octet of the IPv4 address.
 *   addr2 The third octet of the IPv4 address.
 *   addr3 The forth octet of the IPv4 address.
 */

#define net_ipaddr(addr, addr0, addr1, addr2, addr3) \
  do { \
    addr = HTONL((uint32_t)(addr0) << 24 | (uint32_t)(addr1) << 16 | \
                 (uint32_t)(addr2) << 8  | (uint32_t)(addr3)); \
  } while (0)

/* Convert an IPv4 address of the form uint16_t[2] to an in_addr_t */

#ifdef CONFIG_ENDIAN_BIG
#  define net_ip4addr_conv32(addr) (((in_addr_t)((uint16_t*)addr)[0] << 16) | (in_addr_t)((uint16_t*)addr)[1])
#else
#  define net_ip4addr_conv32(addr) (((in_addr_t)((uint16_t*)addr)[1] << 16) | (in_addr_t)((uint16_t*)addr)[0])
#endif

/* Extract individual bytes from a 32-bit IPv4 IP address that is in network
 * byte order.
 */

#ifdef CONFIG_ENDIAN_BIG
   /* Big-endian byte order: 11223344 */

#  define ip4_addr1(ipaddr) (((ipaddr) >> 24) & 0xff)
#  define ip4_addr2(ipaddr) (((ipaddr) >> 16) & 0xff)
#  define ip4_addr3(ipaddr) (((ipaddr) >>  8) & 0xff)
#  define ip4_addr4(ipaddr)  ((ipaddr)        & 0xff)
#else
   /* Little endian byte order: 44223311 */

#  define ip4_addr1(ipaddr)  ((ipaddr)        & 0xff)
#  define ip4_addr2(ipaddr) (((ipaddr) >>  8) & 0xff)
#  define ip4_addr3(ipaddr) (((ipaddr) >> 16) & 0xff)
#  define ip4_addr4(ipaddr) (((ipaddr) >> 24) & 0xff)
#endif

/* Construct an IPv6 address from eight 16-bit words.
 *
 * This function constructs an IPv6 address.
 */

#define ip6_addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) \
  do { \
    ((uint16_t*)(addr))[0] = HTONS((addr0)); \
    ((uint16_t*)(addr))[1] = HTONS((addr1)); \
    ((uint16_t*)(addr))[2] = HTONS((addr2)); \
    ((uint16_t*)(addr))[3] = HTONS((addr3)); \
    ((uint16_t*)(addr))[4] = HTONS((addr4)); \
    ((uint16_t*)(addr))[5] = HTONS((addr5)); \
    ((uint16_t*)(addr))[6] = HTONS((addr6)); \
    ((uint16_t*)(addr))[7] = HTONS((addr7)); \
  } while (0)

/* Copy an IP address from one place to another.
 *
 * Example:
 *
 *   net_ipaddr_t ipaddr1, ipaddr2;
 *
 *   net_ipaddr(&ipaddr1, 192,16,1,2);
 *   net_ipaddr_copy(&ipaddr2, &ipaddr1);
 *
 * dest The destination for the copy.
 * src The source from where to copy.
 */

#define net_ipv4addr_copy(dest, src) \
   do { \
     (dest) = (in_addr_t)(src); \
   } while (0)
#define net_ipv4addr_hdrcopy(dest, src) \
   do { \
     ((uint16_t*)(dest))[0] = ((uint16_t*)(src))[0]; \
     ((uint16_t*)(dest))[1] = ((uint16_t*)(src))[1]; \
   } while (0)

#define net_ipv6addr_copy(dest, src)    memcpy(&dest, &src, sizeof(net_ipv6addr_t))
#define net_ipv6addr_hdrcopy(dest, src) net_ipv6addr_copy(dest, src)

#ifndef CONFIG_NET_IPv6
#  define net_ipaddr_copy(dest, src)    net_ipv4addr_copy(dest, src)
#  define net_ipaddr_hdrcopy(dest, src) net_ipv4addr_hdrcopy(dest, src)
#else /* !CONFIG_NET_IPv6 */
#  define net_ipaddr_copy(dest, src)    net_ipv6addr_copy(dest, src)
#  define net_ipaddr_hdrcopy(dest, src) net_ipv6addr_hdrcopy(dest, src)
#endif /* !CONFIG_NET_IPv6 */

/* Compare two IP addresses
 *
 * Example:
 *
 *   net_ipaddr_t ipaddr1, ipaddr2;
 *
 *   net_ipaddr(&ipaddr1, 192,16,1,2);
 *   if (net_ipaddr_cmp(ipaddr2, ipaddr1))
 *     {
 *       printf("They are the same");
 *     }
 *
 * addr1 The first IP address.
 * addr2 The second IP address.
 */

#define net_ipv4addr_cmp(addr1, addr2) \
  (addr1 == addr2)
#define net_ipv4addr_hdrcmp(addr1, addr2) \
  net_ipv4addr_cmp(net_ip4addr_conv32(addr1), net_ip4addr_conv32(addr2))

#define net_ipv6addr_cmp(addr1, addr2) \
  (memcmp(&addr1, &addr2, sizeof(net_ipv6addr_t)) == 0)
#define net_ipv6addr_hdrcmp(addr1, addr2) \
  net_ipv6addr_cmp(addr1, addr2)

#if defined(CONFIG_NET_IPv4)
#  define net_ipaddr_cmp(addr1, addr2)    net_ipv4addr_cmp(addr1, addr2)
#  define net_ipaddr_hdrcmp(addr1, addr2) net_ipv4addr_hdrcmp(addr1, addr2)
#elif defined(CONFIG_NET_IPv6)
#  define net_ipaddr_cmp(addr1, addr2)    net_ipv6addr_cmp(addr1, addr2)
#  define net_ipaddr_hdrcmp(addr1, addr2) net_ipv6addr_hdrcmp(addr1, addr2)
#endif

/* Compare two IP addresses under a netmask.  The mask is used to mask
 * out the bits that are to be compared:  Buts within the mask much
 * match exactly; bits outside if the mask are ignored.
 *
 * Example:
 *
 *   in_addr_t ipaddr1;
 *   in_addr_t ipaddr2;
 *   in_addr_t mask;
 *
 *   net_ipaddr(&mask, 255,255,255,0);
 *   net_ipaddr(&ipaddr1, 192,16,1,2);
 *   net_ipaddr(&ipaddr2, 192,16,1,3);
 *   if (net_ipaddr_maskcmp(ipaddr1, ipaddr2, &mask))
 *     {
 *       printf("They are the same");
 *     }
 *
 * addr1 The first IP address.
 * addr2 The second IP address.
 * mask The netmask.
 */

#define net_ipv4addr_maskcmp(addr1, addr2, mask) \
  (((in_addr_t)(addr1) & (in_addr_t)(mask)) == \
   ((in_addr_t)(addr2) & (in_addr_t)(mask)))

#ifndef CONFIG_NET_IPv6
#  define net_ipaddr_maskcmp(a,b,m) net_ipv4addr_maskcmp(a,b,m)

#else
bool net_ipv6addr_maskcmp(const net_ipv6addr_t addr1,
                          const net_ipv6addr_t addr2,
                          const net_ipv6addr_t mask);

#  define net_ipaddr_maskcmp(a,b,m) net_ipv6addr_maskcmp(a,b,m)
#endif

/* Mask out the network part of an IP address, given the address and
 * the netmask.
 *
 * Example:
 *
 *   net_ipaddr_t ipaddr1, ipaddr2, netmask;
 *
 *   net_ipaddr(&ipaddr1, 192,16,1,2);
 *   net_ipaddr(&netmask, 255,255,255,0);
 *   net_ipaddr_mask(&ipaddr2, &ipaddr1, &netmask);
 *
 * In the example above, the variable "ipaddr2" will contain the IP
 * address 192.168.1.0.
 *
 * dest Where the result is to be placed.
 * src The IP address.
 * mask The netmask.
 */

#define net_ipaddr_mask(dest, src, mask) \
  do { \
    (in_addr_t)(dest) = (in_addr_t)(src) & (in_addr_t)(mask); \
  } while (0)

#endif /* __INCLUDE_NUTTX_NET_IP_H */