BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file ipaddr.h
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * @section DESCRIPTION
30 *
31 * IP address parsing functions.
32 */
33  
34 #ifndef BADVPN_MISC_IPADDR_H
35 #define BADVPN_MISC_IPADDR_H
36  
37 #include <string.h>
38 #include <stdlib.h>
39  
40 #include <misc/debug.h>
41 #include <misc/byteorder.h>
42 #include <misc/parse_number.h>
43 #include <misc/find_char.h>
44 #include <misc/print_macros.h>
45 #include <misc/memref.h>
46  
47 struct ipv4_ifaddr {
48 uint32_t addr;
49 int prefix;
50 };
51  
52 static int ipaddr_parse_ipv4_addr (MemRef name, uint32_t *out_addr);
53 static int ipaddr_parse_ipv4_prefix (MemRef str, int *num);
54 static int ipaddr_parse_ipv4_ifaddr (MemRef str, struct ipv4_ifaddr *out);
55 static int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out);
56 static uint32_t ipaddr_ipv4_mask_from_prefix (int prefix);
57 static int ipaddr_ipv4_prefix_from_mask (uint32_t mask, int *out_prefix);
58 static int ipaddr_ipv4_addrs_in_network (uint32_t addr1, uint32_t addr2, int netprefix);
59  
60 #define IPADDR_PRINT_MAX 19
61  
62 static void ipaddr_print_addr (uint32_t addr, char *out);
63 static void ipaddr_print_ifaddr (struct ipv4_ifaddr ifaddr, char *out);
64  
65 int ipaddr_parse_ipv4_addr (MemRef name, uint32_t *out_addr)
66 {
67 for (size_t i = 0; ; i++) {
68 size_t j;
69 for (j = 0; j < name.len && name.ptr[j] != '.'; j++);
70  
71 if ((j == name.len && i < 3) || (j < name.len && i == 3)) {
72 return 0;
73 }
74  
75 if (j < 1 || j > 3) {
76 return 0;
77 }
78  
79 uintmax_t d;
80 if (!parse_unsigned_integer(MemRef_SubTo(name, j), &d)) {
81 return 0;
82 }
83  
84 if (d > 255) {
85 return 0;
86 }
87  
88 ((uint8_t *)out_addr)[i] = d;
89  
90 if (i == 3) {
91 return 1;
92 }
93  
94 name.ptr += j + 1;
95 name.len -= j + 1;
96 }
97 }
98  
99 int ipaddr_parse_ipv4_prefix (MemRef str, int *num)
100 {
101 uintmax_t d;
102 if (!parse_unsigned_integer(str, &d)) {
103 return 0;
104 }
105 if (d > 32) {
106 return 0;
107 }
108  
109 *num = d;
110 return 1;
111 }
112  
113 int ipaddr_parse_ipv4_ifaddr (MemRef str, struct ipv4_ifaddr *out)
114 {
115 size_t slash_pos;
116 if (!MemRef_FindChar(str, '/', &slash_pos)) {
117 return 0;
118 }
119  
120 return (ipaddr_parse_ipv4_addr(MemRef_SubTo(str, slash_pos), &out->addr) &&
121 ipaddr_parse_ipv4_prefix(MemRef_SubFrom(str, slash_pos + 1), &out->prefix));
122 }
123  
124 int ipaddr_ipv4_ifaddr_from_addr_mask (uint32_t addr, uint32_t mask, struct ipv4_ifaddr *out)
125 {
126 int prefix;
127 if (!ipaddr_ipv4_prefix_from_mask(mask, &prefix)) {
128 return 0;
129 }
130  
131 out->addr = addr;
132 out->prefix = prefix;
133 return 1;
134 }
135  
136 uint32_t ipaddr_ipv4_mask_from_prefix (int prefix)
137 {
138 ASSERT(prefix >= 0)
139 ASSERT(prefix <= 32)
140  
141 uint32_t t = 0;
142 for (int i = 0; i < prefix; i++) {
143 t |= 1 << (32 - i - 1);
144 }
145  
146 return hton32(t);
147 }
148  
149 int ipaddr_ipv4_prefix_from_mask (uint32_t mask, int *out_prefix)
150 {
151 uint32_t t = 0;
152 int i;
153 for (i = 0; i <= 32; i++) {
154 if (ntoh32(mask) == t) {
155 break;
156 }
157 if (i < 32) {
158 t |= (1 << (32 - i - 1));
159 }
160 }
161 if (!(i <= 32)) {
162 return 0;
163 }
164  
165 *out_prefix = i;
166 return 1;
167 }
168  
169 int ipaddr_ipv4_addrs_in_network (uint32_t addr1, uint32_t addr2, int netprefix)
170 {
171 ASSERT(netprefix >= 0)
172 ASSERT(netprefix <= 32)
173  
174 uint32_t mask = ipaddr_ipv4_mask_from_prefix(netprefix);
175  
176 return !!((addr1 & mask) == (addr2 & mask));
177 }
178  
179 void ipaddr_print_addr (uint32_t addr, char *out)
180 {
181 ASSERT(out)
182  
183 uint8_t *b = (uint8_t *)&addr;
184  
185 sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8,
186 b[0], b[1], b[2], b[3]);
187 }
188  
189 void ipaddr_print_ifaddr (struct ipv4_ifaddr ifaddr, char *out)
190 {
191 ASSERT(ifaddr.prefix >= 0)
192 ASSERT(ifaddr.prefix <= 32)
193 ASSERT(out)
194  
195 uint8_t *b = (uint8_t *)&ifaddr.addr;
196  
197 sprintf(out, "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8"/%d",
198 b[0], b[1], b[2], b[3], ifaddr.prefix);
199 }
200  
201 #endif