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