porting routing code from stable to master (and change many arm-nowarn-alignments)
[olsrd.git] / src / ipcalc.h
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2007, Bernd Petrovitsch <bernd-at-firmix.at>
5  * Copyright (c) 2007, Hannes Gredler <hannes-at-gredler.at>
6  * Copyright (c) 2007, Sven-Ola Tuecke <sven-ola-at-gmx.de>
7  * Copyright (c) 2008, Bernd Petrovitsch <bernd-at-firmix.at>
8  * Copyright (c) 2008, Hannes Gredler <hannes-at-gredler.at>
9  * Copyright (c) 2008, Sven-Ola Tuecke <sven-ola-at-gmx.de>
10  * Copyright (c) 2009, Henning Rogge <rogge-at-fgan.de>
11  * Copyright (c) 2009, Sven-Ola Tuecke <sven-ola-at-gmx.de>
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  *
18  * * Redistributions of source code must retain the above copyright
19  *   notice, this list of conditions and the following disclaimer.
20  * * Redistributions in binary form must reproduce the above copyright
21  *   notice, this list of conditions and the following disclaimer in
22  *   the documentation and/or other materials provided with the
23  *   distribution.
24  * * Neither the name of olsr.org, olsrd nor the names of its
25  *   contributors may be used to endorse or promote products derived
26  *   from this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39  * POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Visit http://www.olsr.org for more information.
42  *
43  * If you find this software useful feel free to make a donation
44  * to the project. For more information see the website or contact
45  * the copyright holders.
46  *
47  */
48
49 #ifndef _IPCALC
50 #define _IPCALC
51
52 #include "olsr_types.h"
53 #include "defs.h"
54 #include "olsr_cfg.h"
55
56 #include <limits.h>
57 #include <string.h>
58 #include <arpa/inet.h>
59
60 extern const union olsr_ip_addr all_zero;
61
62 extern const struct olsr_ip_prefix ipv4_internet_route;
63 extern const struct olsr_ip_prefix ipv6_mappedv4_route;
64 extern const struct olsr_ip_prefix ipv6_internet_route;
65
66 struct ipaddr_str {
67   char buf[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];
68 };
69
70 struct ipprefix_str {
71   /* We need for IPv6 an IP address + '/' + prefix and for IPv4 an IP address + '/' + a netmask */
72   char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + 2)];
73 };
74
75 /*
76  * Macros for comparing and copying IP addresses
77  */
78 static INLINE int
79 ip4cmp(const struct in_addr *a, const struct in_addr *b)
80 {
81   return a->s_addr > b->s_addr ? +1 : a->s_addr < b->s_addr ? -1 : 0;
82 }
83
84 static INLINE int
85 ip6cmp(const struct in6_addr *a, const struct in6_addr *b)
86 {
87   return memcmp(a, b, sizeof(*a));
88 }
89
90 static INLINE int
91 ipcmp(int ip_version, const union olsr_ip_addr *a, const union olsr_ip_addr *b)
92 {
93   return ip_version == AF_INET ? ip4cmp(&a->v4, &b->v4) : ip6cmp(&a->v6, &b->v6);
94 }
95
96 static INLINE int
97 olsr_ipcmp(const union olsr_ip_addr *a, const union olsr_ip_addr *b)
98 {
99   return ipcmp(olsr_cnf->ip_version, a, b);
100 }
101
102 /* Do not use this - this is as evil as the COPY_IP() macro was and only used in
103  * source which also needs cleanups.
104  */
105 static INLINE void
106 genipcopy(void *dst, const void *src)
107 {
108   memcpy(dst, src, olsr_cnf->ipsize);
109 }
110
111 int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net, int ip_version);
112
113
114 int EXPORT(prefix_to_netmask) (uint8_t *, int, uint8_t);
115
116 static INLINE int
117 olsr_prefix_to_netmask(union olsr_ip_addr *adr, uint8_t prefixlen)
118 {
119   return prefix_to_netmask(adr->v6.s6_addr, olsr_cnf->ipsize, prefixlen);
120 }
121
122 uint8_t EXPORT(netmask_to_prefix) (const uint8_t *, int);
123
124 static INLINE uint8_t
125 olsr_netmask_to_prefix(const union olsr_ip_addr *adr)
126 {
127   return netmask_to_prefix(adr->v6.s6_addr, olsr_cnf->ipsize);
128 }
129
130 static INLINE uint8_t
131 olsr_netmask4_to_prefix(const uint32_t * a)
132 {
133   return netmask_to_prefix((const uint8_t *)a, sizeof(*a));
134 }
135 static INLINE uint8_t
136 olsr_netmask6_to_prefix(const struct in6_addr *a)
137 {
138   return netmask_to_prefix((const uint8_t *)a, sizeof(*a));
139 }
140
141 static INLINE const char *
142 ip4_to_string(struct ipaddr_str *const buf, const struct in_addr addr4)
143 {
144   return inet_ntop(AF_INET, &addr4, buf->buf, sizeof(buf->buf));
145 }
146
147 static INLINE const char *
148 ip6_to_string(struct ipaddr_str *const buf, const struct in6_addr *const addr6)
149 {
150   return inet_ntop(AF_INET6, addr6, buf->buf, sizeof(buf->buf));
151 }
152
153 static INLINE const char *
154 ip_to_string(int af, struct ipaddr_str *const buf, const union olsr_ip_addr *addr)
155 {
156   return inet_ntop(af, addr, buf->buf, sizeof(buf->buf));
157 }
158
159 static INLINE const char *
160 olsr_ip_to_string(struct ipaddr_str *const buf, const union olsr_ip_addr *addr)
161 {
162   return ip_to_string(olsr_cnf->ip_version, buf, addr);
163 }
164
165 const char *EXPORT(ip_prefix_to_string) (int af, struct ipprefix_str * const buf, const struct olsr_ip_prefix * prefix);
166
167 static INLINE const char *
168 olsr_ip_prefix_to_string(struct ipprefix_str *const buf, const struct olsr_ip_prefix *prefix)
169 {
170   return ip_prefix_to_string(olsr_cnf->ip_version, buf, prefix);
171 }
172
173 const char *sockaddr_to_string(char *buf, int bufsize, const struct sockaddr *const addr, unsigned int addrsize);
174
175 /* we need to handle one value specifically since shifting 32 bits of a 32 bit integer is the same as shifting 0 bits.
176  * The result is in host-byte-order.
177  */
178 static INLINE uint32_t
179 prefix_to_netmask4(uint8_t prefixlen)
180 {
181   return prefixlen == 0 ? 0 : (~0U << (32 - prefixlen));
182 }
183
184 extern const struct in6_addr EXPORT(in6addr_v4mapped_loopback);
185
186 void EXPORT(ip_map_4to6) (union olsr_ip_addr *ip);
187
188 static INLINE bool
189 is_prefix_niit_ipv6(const struct olsr_ip_prefix *p) {
190   return olsr_cnf->ip_version == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&p->prefix.v6)
191       && p->prefix_len >= ipv6_mappedv4_route.prefix_len;
192 }
193
194 static INLINE struct olsr_ip_prefix *
195 prefix_mappedv4_to_v4(struct olsr_ip_prefix *v4, const struct olsr_ip_prefix *v6) {
196   memcpy(&v4->prefix.v4, &v6->prefix.v6.s6_addr[12], sizeof(struct in_addr));
197       v4->prefix_len = v6->prefix_len - 96;
198   return v4;
199 }
200
201 static INLINE bool
202 ip_is_linklocal(const union olsr_ip_addr *ip) {
203   return olsr_cnf->ip_version == AF_INET6
204       && ip->v6.s6_addr[0] == 0xfe && (ip->v6.s6_addr[1] & 0xc0) == 0x80;
205 }
206
207 static INLINE bool
208 ip_prefix_is_mappedv4(const struct olsr_ip_prefix *prefix) {
209   return prefix->prefix_len >= ipv6_mappedv4_route.prefix_len
210       && memcmp(prefix, &ipv6_mappedv4_route, ipv6_mappedv4_route.prefix_len / 8) == 0;
211 }
212
213 static INLINE bool
214 ip_prefix_is_mappedv4_inetgw(const struct olsr_ip_prefix *prefix) {
215   return prefix->prefix_len == ipv6_mappedv4_route.prefix_len
216       && memcmp(prefix, &ipv6_mappedv4_route, ipv6_mappedv4_route.prefix_len / 8) == 0;
217 }
218
219 static INLINE bool
220 ip_prefix_is_v4_inetgw(const struct olsr_ip_prefix *prefix) {
221   return prefix->prefix_len == ipv4_internet_route.prefix_len
222       && prefix->prefix.v4.s_addr == ipv4_internet_route.prefix.v4.s_addr;
223 }
224
225 static INLINE bool
226 ip_prefix_is_v6_inetgw(const struct olsr_ip_prefix *prefix) {
227   return prefix->prefix_len == ipv6_internet_route.prefix_len
228       && memcmp(prefix, &ipv6_internet_route, ipv6_internet_route.prefix_len/8) == 0;
229 }
230
231 extern bool is_prefix_inetgw(const struct olsr_ip_prefix *prefix);
232
233 #endif
234
235 /*
236  * Local Variables:
237  * c-basic-offset: 2
238  * indent-tabs-mode: nil
239  * End:
240  */