Port all olsrd 0.6.0 OS specific files and adapt them to the new interface.
[olsrd.git] / src / ipcalc.c
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) 2008, Alina Friedrichsen <x-alina-at-gmx.net>
7  * Copyright (c) 2008, Bernd Petrovitsch <bernd-at-firmix.at>
8  * Copyright (c) 2008, John Hay <jhay-at-meraka.org.za>
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 #include "ipcalc.h"
50
51 #define IN6ADDR_V4MAPPED_LOOPBACK_INIT \
52         { { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
53               0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 } } }
54
55 const struct in6_addr in6addr_v4mapped_loopback = IN6ADDR_V4MAPPED_LOOPBACK_INIT;
56
57 /* initialize it with all zeroes */
58 const union olsr_ip_addr all_zero = {.v6 = IN6ADDR_ANY_INIT };
59
60 /* ipv4 prefix 0.0.0.0/0 */
61 const struct olsr_ip_prefix ipv4_internet_route =
62 {
63     .prefix.v4.s_addr = 0,
64     .prefix_len = 0
65 };
66
67 /* ipv6 prefix ::ffff:0:0/96 */
68 const struct olsr_ip_prefix ipv6_mappedv4_route =
69 {
70     .prefix.v6.s6_addr = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 },
71     .prefix_len = 96
72 };
73
74 /* ipv6 prefix 2000::/3 */
75 const struct olsr_ip_prefix ipv6_internet_route =
76 {
77     .prefix.v6.s6_addr = { 0x20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
78     .prefix_len = 3
79 };
80
81
82 void
83 ip_map_4to6(union olsr_ip_addr *addr) {
84   /* ipv4-mapped-ipv6 = ::ff:<ipv4> */
85   memmove(&addr->v6.s6_addr[12], &addr->v4.s_addr, 4 * sizeof(uint8_t));
86   memset(&addr->v6.s6_addr[0], 0x00, 10 * sizeof(uint8_t));
87   memset(&addr->v6.s6_addr[10], 0xff, 2 * sizeof(uint8_t));
88 }
89
90 int
91 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
92 {
93   int i = 0;
94   const int end = MIN(len, prefixlen / 8);
95
96   while (i < end) {
97     a[i++] = 0xff;
98   }
99   if (i < len) {
100     a[i++] = 0xff << (8 - (prefixlen % 8));
101     while (i < len) {
102       a[i++] = 0;
103     }
104   }
105
106   return (prefixlen <= len * 8);
107 }
108
109 uint8_t
110 netmask_to_prefix(const uint8_t * adr, int len)
111 {
112   const uint8_t *const a_end = adr + len;
113   uint16_t prefix = 0;
114   const uint8_t *a;
115 #if 0
116   struct ipaddr_str buf;
117 #endif
118
119   for (a = adr; a < a_end && *a == 0xff; a++) {
120     prefix += 8;
121   }
122   if (a < a_end) {
123     /* handle the last byte */
124     switch (*a) {
125     case 0:
126       prefix += 0;
127       break;
128     case 128:
129       prefix += 1;
130       break;
131     case 192:
132       prefix += 2;
133       break;
134     case 224:
135       prefix += 3;
136       break;
137     case 240:
138       prefix += 4;
139       break;
140     case 248:
141       prefix += 5;
142       break;
143     case 252:
144       prefix += 6;
145       break;
146     case 254:
147       prefix += 7;
148       break;
149     case 255:
150       prefix += 8;
151       break;                    /* Shouldn't happen */
152     default:
153       // removed because of cfg-checker
154       // OLSR_WARN(LOG_??, "Got bogus netmask %s\n", ip_to_string(len == 4 ? AF_INET : AF_INET6, &buf, (const union olsr_ip_addr *)adr));
155       prefix = len*8;
156       break;
157     }
158   }
159   return prefix;
160 }
161
162 const char *
163 ip_prefix_to_string(int af, struct ipprefix_str *const buf, const struct olsr_ip_prefix *prefix)
164 {
165   int len;
166   inet_ntop(af, &prefix->prefix, buf->buf, sizeof(buf->buf));
167   len = strlen(buf->buf);
168   snprintf(buf->buf + len, sizeof(buf->buf) - len, "/%d", prefix->prefix_len);
169   return buf->buf;
170 }
171
172
173 /* see if the ipaddr is in the net. That is equivalent to the fact that the net part
174  * of both are equal. So we must compare the first <prefixlen> bits.
175  */
176 int
177 ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net, int ip_version)
178 {
179   int rv;
180   if (ip_version == AF_INET) {
181     uint32_t netmask = ntohl(prefix_to_netmask4(net->prefix_len));
182     rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
183   } else {
184     /* IPv6 */
185     uint32_t netmask;
186     const uint32_t *i = (const uint32_t *) (ARM_NOWARN_ALIGN(&ipaddr->v6.s6_addr));
187     const uint32_t *n = (const uint32_t *) (ARM_NOWARN_ALIGN(&net->prefix.v6.s6_addr));
188     unsigned int prefix_len;
189     /* First we compare whole unsigned int's */
190     for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
191       if (*i != *n) {
192         return false;
193       }
194       i++;
195       n++;
196     }
197     /* And the remaining is the same as in the IPv4 case */
198     netmask = ntohl(prefix_to_netmask4(prefix_len));
199     rv = (*i & netmask) == (*n & netmask);
200   }
201   return rv;
202 }
203
204 static const char *
205 sockaddr4_to_string(char *const buf, int bufsize, const struct sockaddr *const addr)
206 {
207   char addrbuf[INET6_ADDRSTRLEN];
208   const struct sockaddr_in *const sin4 = (const struct sockaddr_in *)(ARM_CONST_NOWARN_ALIGN)addr;
209   snprintf(buf, bufsize, "IPv4/%s:%d", inet_ntop(AF_INET, &sin4->sin_addr, addrbuf, sizeof(addrbuf)), sin4->sin_port);
210   return buf;
211 }
212
213 static const char *
214 sockaddr6_to_string(char *const buf, int bufsize, const struct sockaddr *const addr)
215 {
216   char addrbuf[INET6_ADDRSTRLEN];
217   const struct sockaddr_in6 *const sin6 = (const struct sockaddr_in6 *)(ARM_CONST_NOWARN_ALIGN)addr;
218   snprintf(buf, bufsize,
219            "IPv6/[%s]:%d/%x/%x",
220            inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf)),
221            sin6->sin6_port, (unsigned)sin6->sin6_flowinfo, (unsigned)sin6->sin6_scope_id);
222   return buf;
223 }
224
225 const char *
226 sockaddr_to_string(char *const buf, int bufsize, const struct sockaddr *const addr, unsigned int addrsize)
227 {
228   switch (addr->sa_family) {
229   case AF_INET:
230     return sockaddr4_to_string(buf, bufsize, addr);
231   case AF_INET6:
232     return sockaddr6_to_string(buf, bufsize, addr);
233   default:
234     {
235       const int size = MIN(addrsize - sizeof(addr->sa_family), sizeof(addr->sa_data));
236       char sep = '/';
237       int i;
238       int len = snprintf(buf, bufsize, "%d", addr->sa_family);
239       for (i = 0; i < size; i++) {
240         len += snprintf(buf + len, bufsize - len, "%c%02x", sep, addr->sa_data[i]);
241         sep = ' ';
242       }
243     }
244     break;
245   }
246   return buf;
247 }
248
249 bool is_prefix_inetgw(const struct olsr_ip_prefix *prefix) {
250   if (olsr_cnf->ip_version == AF_INET && ip_prefix_is_v4_inetgw(prefix)) {
251     return true;
252   }
253   if (olsr_cnf->ip_version == AF_INET6) {
254     if (ip_prefix_is_v6_inetgw(prefix) || ip_prefix_is_mappedv4_inetgw(prefix)) {
255       return true;
256     }
257   }
258   return false;
259 }
260
261 /*
262  * Local Variables:
263  * c-basic-offset: 2
264  * indent-tabs-mode: nil
265  * End:
266  */