058da1c256ec36376ca5108833be9772043ee806
[olsrd.git] / src / ipcalc.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2007, Bernd Petrovitsch <berndæfirmix.at>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   contributors may be used to endorse or promote products derived
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "ipcalc.h"
43
44 int
45 prefix_to_netmask(uint8_t * a, int len, uint8_t prefixlen)
46 {
47 #if !defined(NODEBUG) && defined(DEBUG)
48   struct ipaddr_str buf;
49   const uint8_t *a_start = a;
50 #endif
51   int p;
52   const uint8_t *a_end;
53
54   a_end = a + len;
55   for (p = prefixlen; a < a_end && p > 8; p -= 8) {
56     *a++ = 0xff;
57   }
58   if (a >= a_end) {
59     return 0;
60   }
61   *a++ = 0xff << (8 - p);
62   while (a < a_end) {
63     *a++ = 0;
64   }
65
66 #ifdef DEBUG
67   OLSR_PRINTF(3, "Prefix %d = Netmask: %s\n", prefixlen, inet_ntop(olsr_cnf->ip_version, a_start, buf.buf, sizeof(buf.buf)));
68 #endif
69   return 1;
70 }
71
72 uint8_t
73 netmask_to_prefix(const uint8_t * adr, int len)
74 {
75   struct ipaddr_str buf;
76   const uint8_t *const a_end = adr + len;
77   uint16_t prefix = 0;
78   const uint8_t *a;
79   for (a = adr; a < a_end && *a == 0xff; a++) {
80     prefix += 8;
81   }
82   if (a < a_end) {
83     /* handle the last byte */
84     switch (*a) {
85     case 0:
86       prefix += 0;
87       break;
88     case 128:
89       prefix += 1;
90       break;
91     case 192:
92       prefix += 2;
93       break;
94     case 224:
95       prefix += 3;
96       break;
97     case 240:
98       prefix += 4;
99       break;
100     case 248:
101       prefix += 5;
102       break;
103     case 252:
104       prefix += 6;
105       break;
106     case 254:
107       prefix += 7;
108       break;
109     case 255:
110       prefix += 8;
111       break;                    /* Shouldn't happen */
112     default:
113       OLSR_PRINTF(0, "%s: Got bogus netmask %s\n", __func__, olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr));
114       prefix = UCHAR_MAX;
115       *(int *)0 = 0;
116       break;
117     }
118   }
119 #ifdef DEBUG
120   OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr), prefix);
121 #endif
122   return prefix;
123 }
124
125 const char *
126 olsr_ip_prefix_to_string(const struct olsr_ip_prefix *prefix)
127 {
128   /* We need for IPv6 an IP address + '/' + prefix and for IPv4 an IP address + '/' + a netmask */
129   static char buf[MAX(INET6_ADDRSTRLEN + 1 + 3, INET_ADDRSTRLEN + 1 + INET_ADDRSTRLEN)];
130   const char *rv;
131
132   if (olsr_cnf->ip_version == AF_INET) {
133     /* IPv4 */
134     int len;
135     union olsr_ip_addr netmask;
136     rv = inet_ntop(AF_INET, &prefix->prefix.v4, buf, sizeof(buf));
137     len = strlen(buf);
138     buf[len++] = '/';
139     olsr_prefix_to_netmask(&netmask, prefix->prefix_len);
140     inet_ntop(AF_INET, &netmask.v4, buf + len, sizeof(buf) - len);
141   } else {
142     /* IPv6 */
143     int len;
144     rv = inet_ntop(AF_INET6, &prefix->prefix.v6, buf, sizeof(buf));
145     len = strlen(buf);
146     buf[len++] = '/';
147     snprintf(buf + len, sizeof(buf) - len, "/%d", prefix->prefix_len);
148   }
149   return rv;
150 }
151
152 /* see if the ipaddr is in the net. That is equivalent to the fact that the net part
153  * of both are equal. So we must compare the first <prefixlen> bits.
154  */
155 int
156 ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net)
157 {
158   int rv;
159   if (olsr_cnf->ip_version == AF_INET) {
160     uint32_t netmask = prefix_to_netmask4(net->prefix_len);
161     rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
162   } else {
163     /* IPv6 */
164     uint32_t netmask;
165     const uint32_t *i = (const uint32_t *)&ipaddr->v6;
166     const uint32_t *n = (const uint32_t *)&net->prefix.v6;
167     unsigned int prefix_len;
168     /* First we compare whole unsigned int's */
169     for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
170       if (*i != *n) {
171         return false;
172       }
173       i++;
174       n++;
175     }
176     /* And the remaining is the same as in the IPv4 case */
177     netmask = prefix_to_netmask4(prefix_len);
178     rv = (*i & netmask) == (*n & netmask);
179   }
180   return rv;
181 }
182
183 /*
184  * Local Variables:
185  * c-basic-offset: 2
186  * indent-tabs-mode: nil
187  * End:
188  */