1 /*
2 * The olsr.org Optimized Link-State Routing daemon (olsrd)
3 *
4 * (c) by the OLSR project
5 *
6 * See our Git repository to find out who worked on this file
7 * and thus is a copyright holder on it.
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 *
15 * * Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * * Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * * Neither the name of olsr.org, olsrd nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 *
38 * Visit http://www.olsr.org for more information.
39 *
40 * If you find this software useful feel free to make a donation
41 * to the project. For more information see the website or contact
42 * the copyright holders.
43 *
44 */
45
46 #include "defs.h"
47 #include "ipcalc.h"
48
49 /* ipv4 prefix 0.0.0.0/0 */
50 const struct olsr_ip_prefix ipv4_internet_route =
51 {
52 .prefix.v4.s_addr = 0,
53 .prefix_len = 0
54 };
55
56 /* ipv6 prefix ::ffff:0:0/96 */
57 const struct olsr_ip_prefix ipv6_mappedv4_route =
58 {
59 .prefix.v6.s6_addr = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff,0,0,0,0 },
60 .prefix_len = 96
61 };
62
63 /* ipv6 prefix 2000::/3 */
64 const struct olsr_ip_prefix ipv6_internet_route =
65 {
66 .prefix.v6.s6_addr = { 0x20, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
67 .prefix_len = 3
68 };
69
70 /* ip address zero */
71 const union olsr_ip_addr olsr_ip_zero =
72 {
73 .v6.s6_addr = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
74 };
75
76 /* Default IPv6 multicast addresses FF02::6D(linklocal manet routers, see RFC 5498) */
77 const union olsr_ip_addr ipv6_def_multicast = {
78 .v6.s6_addr = { 0xFF, 0x02, 0,0,0,0,0,0,0,0,0,0,0,0,0, 0x6D }
79 };
80
81 /* Host-byte-order! */
82 int
prefix_to_netmask(uint8_t * a,int len,uint8_t prefixlen)83 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
84 {
85 #if !defined(NODEBUG) && defined(DEBUG)
86 struct ipaddr_str buf;
87 const uint8_t *a_start = a;
88 #endif /* !defined(NODEBUG) && defined(DEBUG) */
89 int p;
90 const uint8_t *a_end;
91
92 if (len <= 0 || !a) {
93 return 0;
94 }
95
96 a_end = a + len;
97 for (p = prefixlen; a < a_end && p > 8; p -= 8) {
98 *a++ = 0xff;
99 }
100 if (a >= a_end) {
101 return 0;
102 }
103 *a++ = 0xff << (8 - p);
104 while (a < a_end) {
105 *a++ = 0;
106 }
107
108 #ifdef DEBUG
109 OLSR_PRINTF(3, "Prefix %d = Netmask: %s\n", prefixlen, inet_ntop(olsr_cnf->ip_version, a_start, buf.buf, sizeof(buf.buf)));
110 #endif /* DEBUG */
111 return 1;
112 }
113
114 uint8_t
netmask_to_prefix(const uint8_t * adr,int len)115 netmask_to_prefix(const uint8_t * adr, int len)
116 {
117 struct ipaddr_str buf;
118 const uint8_t *const a_end = adr + len;
119 uint16_t prefix = 0;
120 const uint8_t *a;
121 for (a = adr; a < a_end && *a == 0xff; a++) {
122 prefix += 8;
123 }
124 if (a < a_end) {
125 /* handle the last byte */
126 switch (*a) {
127 case 0:
128 prefix += 0;
129 break;
130 case 128:
131 prefix += 1;
132 break;
133 case 192:
134 prefix += 2;
135 break;
136 case 224:
137 prefix += 3;
138 break;
139 case 240:
140 prefix += 4;
141 break;
142 case 248:
143 prefix += 5;
144 break;
145 case 252:
146 prefix += 6;
147 break;
148 case 254:
149 prefix += 7;
150 break;
151 case 255:
152 prefix += 8;
153 break; /* Shouldn't happen */
154 default:
155 OLSR_PRINTF(0, "%s: Got bogus netmask %s\n", __func__, olsr_ip_to_string(&buf, (const union olsr_ip_addr *)(const void *)adr));
156 prefix = UCHAR_MAX;
157 break;
158 }
159 }
160 #ifdef DEBUG
161 OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(&buf, (const union olsr_ip_addr *)(const void *)adr), prefix);
162 #endif /* DEBUG */
163 return prefix;
164 }
165
166 const char *
olsr_ip_prefix_to_string(const struct olsr_ip_prefix * prefix)167 olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix)
168 {
169 /* We need for IPv6 an IP address + '/' + prefix and for IPv4 an IP address + '/' + a netmask */
170 static char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN)];
171 const char *rv;
172
173 if (olsr_cnf->ip_version == AF_INET) {
174 /* IPv4 */
175 int len;
176 union olsr_ip_addr netmask;
177 rv = inet_ntop(AF_INET, &prefix->prefix.v4, buf, sizeof(buf));
178 len = strlen(buf);
179 buf[len++] = '/';
180 olsr_prefix_to_netmask(&netmask, prefix->prefix_len);
181 inet_ntop(AF_INET, &netmask.v4, buf + len, sizeof(buf) - len);
182 } else {
183 /* IPv6 */
184 int len;
185 rv = inet_ntop(AF_INET6, &prefix->prefix.v6, buf, sizeof(buf));
186 len = strlen(buf);
187 buf[len++] = '/';
188 snprintf(buf + len, sizeof(buf) - len, "%d", prefix->prefix_len);
189 }
190 return rv;
191 }
192
193 int
olsr_string_to_prefix(int ipversion,struct olsr_ip_prefix * dst,const char * string)194 olsr_string_to_prefix(int ipversion, struct olsr_ip_prefix *dst, const char *string) {
195 static char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN)];
196 char *ptr;
197
198 strscpy(buf, string, sizeof(buf));
199 dst->prefix_len = ipversion == AF_INET ? 32 : 128;
200
201 ptr = strchr(buf, '/');
202 if (!ptr) {
203 ptr = strchr(buf, ' ');
204 }
205
206 if (ptr) {
207 *ptr++ = 0;
208 if (olsr_cnf->ip_version == AF_INET && strchr(ptr, '.')) {
209 uint8_t subnetbuf[4];
210 if (inet_pton(AF_INET, ptr, subnetbuf) != 1) {
211 return -1;
212 }
213
214 dst->prefix_len = netmask_to_prefix(subnetbuf, sizeof(subnetbuf));
215 }
216 else {
217 dst->prefix_len = atoi(ptr);
218 }
219 }
220 return inet_pton(ipversion, buf, &dst->prefix) == 1 ? 0 : -1;
221 }
222
223 /* we need to handle one value specifically since shifting
224 * 32 bits of a 32 bit integer is the same as shifting 0 bits.
225 * The result is in host-byte-order.
226 */
227 static INLINE uint32_t
prefix_to_netmask4(uint8_t prefixlen)228 prefix_to_netmask4(uint8_t prefixlen)
229 {
230 return prefixlen == 0 ? 0 : (~0U << (32 - prefixlen));
231 }
232
233 /* see if the ipaddr is in the net. That is equivalent to the fact that the net part
234 * of both are equal. So we must compare the first <prefixlen> bits. Network-byte-order!
235 */
236 int
ip_in_net(const union olsr_ip_addr * ipaddr,const struct olsr_ip_prefix * net)237 ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net)
238 {
239 int rv;
240 if (olsr_cnf->ip_version == AF_INET) {
241 uint32_t netmask = htonl(prefix_to_netmask4(net->prefix_len));
242 rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
243 } else {
244 /* IPv6 */
245 uint32_t netmask;
246 const uint32_t *i = (const uint32_t *)&ipaddr->v6;
247 const uint32_t *n = (const uint32_t *)&net->prefix.v6;
248 unsigned int prefix_len;
249 /* First we compare whole unsigned int's */
250 for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
251 if (*i != *n) {
252 return false;
253 }
254 i++;
255 n++;
256 }
257 /* And the remaining is the same as in the IPv4 case */
258 netmask = htonl(prefix_to_netmask4(prefix_len));
259 rv = (*i & netmask) == (*n & netmask);
260 }
261 return rv;
262 }
263
is_prefix_inetgw(const struct olsr_ip_prefix * prefix)264 bool is_prefix_inetgw(const struct olsr_ip_prefix *prefix) {
265 if (olsr_cnf->ip_version == AF_INET && ip_prefix_is_v4_inetgw(prefix)) {
266 return true;
267 }
268 if (olsr_cnf->ip_version == AF_INET6) {
269 if (ip_prefix_is_v6_inetgw(prefix) || ip_prefix_is_mappedv4_inetgw(prefix)) {
270 return true;
271 }
272 }
273 return false;
274 }
275
276 /*
277 * Local Variables:
278 * c-basic-offset: 2
279 * indent-tabs-mode: nil
280 * End:
281 */
282