e7922d891a27c3358dc2440eec1ba610aed13659
[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 i;
51   const int end = MIN(len, prefixlen / 8);
52   for (i = 0; i < end; i++) {
53     a[i] = 0xff;
54   }
55   if (i >= len) {
56     return 0;
57   }
58   a[i++] = 0xff << (8 - (prefixlen % 8));
59   while (i < len) {
60     a[i++] = 0;
61   }
62
63 #ifdef DEBUG
64   OLSR_PRINTF(3, "Prefix %d = Netmask: %s\n", prefixlen, inet_ntop(olsr_cnf->ip_version, a_start, buf.buf, sizeof(buf.buf)));
65 #endif
66   return 1;
67 }
68
69 olsr_u8_t
70 netmask_to_prefix(const olsr_u8_t *adr, int len)
71 {
72   struct ipaddr_str buf;
73   const olsr_u8_t * const a_end = adr+len;
74   olsr_u16_t prefix = 0;
75   const olsr_u8_t *a;
76   for (a = adr; a < a_end && *a == 0xff; a++) {
77     prefix += 8;
78   }
79   if (a < a_end) {
80     /* handle the last byte */
81     switch (*a) {
82     case   0: prefix += 0; break;
83     case 128: prefix += 1; break;
84     case 192: prefix += 2; break;
85     case 224: prefix += 3; break;
86     case 240: prefix += 4; break;
87     case 248: prefix += 5; break;
88     case 252: prefix += 6; break;
89     case 254: prefix += 7; break;
90     case 255: prefix += 8; break; /* Shouldn't happen */
91     default:
92       OLSR_PRINTF(0, "%s: Got bogus netmask %s\n", __func__, olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr));
93       prefix = UCHAR_MAX;
94       *(int *)0 = 0;
95       break;
96     }
97   }
98 #ifdef DEBUG
99   OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(&buf, (const union olsr_ip_addr *)adr), prefix);
100 #endif
101   return prefix;
102 }
103
104 const char *
105 olsr_ip_prefix_to_string(struct ipprefix_str * const buf, const struct olsr_ip_prefix *prefix)
106 {
107   int len;
108   inet_ntop(olsr_cnf->ip_version, &prefix->prefix, buf->buf, sizeof(buf->buf));
109   len = strlen(buf->buf);
110   snprintf(buf->buf+len, sizeof(buf->buf)-len, "/%d", prefix->prefix_len);
111   return buf->buf;
112 }
113
114
115 /* see if the ipaddr is in the net. That is equivalent to the fact that the net part
116  * of both are equal. So we must compare the first <prefixlen> bits.
117  */
118 int ip_in_net(const union olsr_ip_addr *ipaddr, const struct olsr_ip_prefix *net)
119 {
120   int rv;
121   if(olsr_cnf->ip_version == AF_INET) {
122     olsr_u32_t netmask = ntohl(~0 << (32 - net->prefix_len));
123     rv = (ipaddr->v4.s_addr & netmask) == (net->prefix.v4.s_addr & netmask);
124   } else {
125     /* IPv6 */
126     olsr_u32_t netmask;
127     const olsr_u32_t *i = (const olsr_u32_t *)&ipaddr->v6.s6_addr;
128     const olsr_u32_t *n = (const olsr_u32_t *)&net->prefix.v6.s6_addr;
129     unsigned int prefix_len;
130     for (prefix_len = net->prefix_len; prefix_len > 32; prefix_len -= 32) {
131       if (*i != *n) {
132         return OLSR_FALSE;
133       }
134       i++;
135       n++;
136     }
137     netmask = ntohl(~0 << (32 - prefix_len));
138     rv = (*i & netmask) == (*n & netmask);
139   }
140   return rv;
141 }
142
143 const char *sockaddr4_to_string(char * const buf, int bufsize, const struct sockaddr * const addr)
144 {
145   char addrbuf[INET6_ADDRSTRLEN];
146   const struct sockaddr_in * const sin4 = (const struct sockaddr_in *)addr;
147   snprintf(buf, bufsize,
148            "IPv4/%s:%u",
149            inet_ntop(AF_INET, &sin4->sin_addr, addrbuf, sizeof(addrbuf)),
150            sin4->sin_port);
151   return buf;
152 }
153
154 const char *sockaddr6_to_string(char * const buf, int bufsize, const struct sockaddr * const addr)
155 {
156   char addrbuf[INET6_ADDRSTRLEN];
157   const struct sockaddr_in6 * const sin6 = (const struct sockaddr_in6 *)addr;
158   snprintf(buf, bufsize,
159            "IPv6/[%s]:%u/%x/%x",
160            inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf)),
161            sin6->sin6_port,
162            (unsigned)sin6->sin6_flowinfo,
163            (unsigned)sin6->sin6_scope_id);
164   return buf;
165 }
166
167 const char *sockaddr_to_string(char * const buf, int bufsize, const struct sockaddr * const addr, unsigned int addrsize)
168 {
169   switch (addr->sa_family) {
170   case AF_INET:
171     return sockaddr4_to_string(buf, bufsize, addr);
172   case AF_INET6:
173     return sockaddr6_to_string(buf, bufsize, addr);
174   default:
175     {
176       const int size = MIN(addrsize-sizeof(addr->sa_family), sizeof(addr->sa_data));
177       char sep = '/';
178       int i;
179       int len = snprintf(buf, bufsize, "%u", addr->sa_family);
180       for (i = 0; i < size; i++) {
181         len += snprintf(buf+len, bufsize-len, "%c%02x", sep, addr->sa_data[i]);
182         sep = ' ';
183       }
184     }
185     break;
186   }
187   return buf;
188 }
189
190
191 /*
192  * Local Variables:
193  * c-basic-offset: 2
194  * indent-tabs-mode: nil
195  * End:
196  */