487438901f01c67897bc2842c42e5c7830b04d7e
[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 void
61 ip_map_4to6(union olsr_ip_addr *addr) {
62   /* ipv4-mapped-ipv6 = ::ff:<ipv4> */
63   memmove(&addr->v6.s6_addr[12], &addr->v4.s_addr, 4 * sizeof(uint8_t));
64   memset(&addr->v6.s6_addr[0], 0x00, 10 * sizeof(uint8_t));
65   memset(&addr->v6.s6_addr[10], 0xff, 2 * sizeof(uint8_t));
66 }
67
68 int
69 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
70 {
71   int i = 0;
72   const int end = MIN(len, prefixlen / 8);
73
74   while (i < end) {
75     a[i++] = 0xff;
76   }
77   if (i < len) {
78     a[i++] = 0xff << (8 - (prefixlen % 8));
79     while (i < len) {
80       a[i++] = 0;
81     }
82   }
83
84   return (prefixlen <= len * 8);
85 }
86
87 uint8_t
88 netmask_to_prefix(const uint8_t * adr, int len)
89 {
90   const uint8_t *const a_end = adr + len;
91   uint16_t prefix = 0;
92   const uint8_t *a;
93 #if 0
94   struct ipaddr_str buf;
95 #endif
96
97   for (a = adr; a < a_end && *a == 0xff; a++) {
98     prefix += 8;
99   }
100   if (a < a_end) {
101     /* handle the last byte */
102     switch (*a) {
103     case 0:
104       prefix += 0;
105       break;
106     case 128:
107       prefix += 1;
108       break;
109     case 192:
110       prefix += 2;
111       break;
112     case 224:
113       prefix += 3;
114       break;
115     case 240:
116       prefix += 4;
117       break;
118     case 248:
119       prefix += 5;
120       break;
121     case 252:
122       prefix += 6;
123       break;
124     case 254:
125       prefix += 7;
126       break;
127     case 255:
128       prefix += 8;
129       break;                    /* Shouldn't happen */
130     default:
131       // removed because of cfg-checker
132       // OLSR_WARN(LOG_??, "Got bogus netmask %s\n", ip_to_string(len == 4 ? AF_INET : AF_INET6, &buf, (const union olsr_ip_addr *)adr));
133       prefix = len*8;
134       break;
135     }
136   }
137   return prefix;
138 }
139
140 const char *
141 ip_prefix_to_string(int af, struct ipprefix_str *const buf, const struct olsr_ip_prefix *prefix)
142 {
143   int len;
144   inet_ntop(af, &prefix->prefix, buf->buf, sizeof(buf->buf));
145   len = strlen(buf->buf);
146   snprintf(buf->buf + len, sizeof(buf->buf) - len, "/%d", prefix->prefix_len);
147   return buf->buf;
148 }
149
150
151 /* see if the ipaddr is in the net. That is equivalent to the fact that the net part
152  * of both are equal. So we must compare the first <prefixlen> bits.
153  */
154 int
155 ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net, int ip_version)
156 {
157   int rv;
158   if (ip_version == AF_INET) {
159     uint32_t netmask = ntohl(prefix_to_netmask4(net->prefix_len));
160     rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
161   } else {
162     /* IPv6 */
163     uint32_t netmask;
164     const uint32_t *i = (const uint32_t *)(ARM_NOWARN_ALIGN)&ipaddr->v6.s6_addr;
165     const uint32_t *n = (const uint32_t *)(ARM_NOWARN_ALIGN)&net->prefix.v6.s6_addr;
166     unsigned int prefix_len;
167     /* First we compare whole unsigned int's */
168     for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
169       if (*i != *n) {
170         return false;
171       }
172       i++;
173       n++;
174     }
175     /* And the remaining is the same as in the IPv4 case */
176     netmask = ntohl(prefix_to_netmask4(prefix_len));
177     rv = (*i & netmask) == (*n & netmask);
178   }
179   return rv;
180 }
181
182 static const char *
183 sockaddr4_to_string(char *const buf, int bufsize, const struct sockaddr *const addr)
184 {
185   char addrbuf[INET6_ADDRSTRLEN];
186   const struct sockaddr_in *const sin4 = (const struct sockaddr_in *)(const ARM_NOWARN_ALIGN)addr;
187   snprintf(buf, bufsize, "IPv4/%s:%d", inet_ntop(AF_INET, &sin4->sin_addr, addrbuf, sizeof(addrbuf)), sin4->sin_port);
188   return buf;
189 }
190
191 static const char *
192 sockaddr6_to_string(char *const buf, int bufsize, const struct sockaddr *const addr)
193 {
194   char addrbuf[INET6_ADDRSTRLEN];
195   const struct sockaddr_in6 *const sin6 = (const struct sockaddr_in6 *)(const ARM_NOWARN_ALIGN)addr;
196   snprintf(buf, bufsize,
197            "IPv6/[%s]:%d/%x/%x",
198            inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf)),
199            sin6->sin6_port, (unsigned)sin6->sin6_flowinfo, (unsigned)sin6->sin6_scope_id);
200   return buf;
201 }
202
203 const char *
204 sockaddr_to_string(char *const buf, int bufsize, const struct sockaddr *const addr, unsigned int addrsize)
205 {
206   switch (addr->sa_family) {
207   case AF_INET:
208     return sockaddr4_to_string(buf, bufsize, addr);
209   case AF_INET6:
210     return sockaddr6_to_string(buf, bufsize, addr);
211   default:
212     {
213       const int size = MIN(addrsize - sizeof(addr->sa_family), sizeof(addr->sa_data));
214       char sep = '/';
215       int i;
216       int len = snprintf(buf, bufsize, "%d", addr->sa_family);
217       for (i = 0; i < size; i++) {
218         len += snprintf(buf + len, bufsize - len, "%c%02x", sep, addr->sa_data[i]);
219         sep = ' ';
220       }
221     }
222     break;
223   }
224   return buf;
225 }
226
227
228 /*
229  * Local Variables:
230  * c-basic-offset: 2
231  * indent-tabs-mode: nil
232  * End:
233  */