source: mainline/uspace/lib/c/generic/inet/addr.c@ a2e3ee6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a2e3ee6 was a2e3ee6, checked in by Martin Decky <martin@…>, 12 years ago

use new network address infrastructure (towards IPv6 support)

  • Property mode set to 100644
File size: 8.1 KB
Line 
1/*
2 * Copyright (c) 2013 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - 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 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file Internet address parsing and formatting.
33 */
34
35#include <errno.h>
36#include <unistd.h>
37#include <net/socket_codes.h>
38#include <inet/addr.h>
39#include <net/inet.h>
40#include <stdio.h>
41
42static inet_addr_t inet_addr_any_addr = {
43 .family = AF_INET,
44 .addr = {0, 0, 0, 0}
45};
46
47static inet_addr_t inet_addr_any_addr6 = {
48 .family = AF_INET6,
49 .addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
50};
51
52/** Parse network address family.
53 *
54 * @param text Network address in common notation.
55 * @param af Place to store network address family.
56 *
57 * @return EOK on success, EINVAL if input is not in valid format.
58 *
59 */
60int inet_addr_family(const char *text, uint16_t *af)
61{
62 char *dot = str_chr(text, '.');
63 if (dot != NULL) {
64 *af = AF_INET;
65 return EOK;
66 }
67
68 char *collon = str_chr(text, ':');
69 if (collon != NULL) {
70 *af = AF_INET6;
71 return EOK;
72 }
73
74 *af = AF_NONE;
75 return EINVAL;
76}
77
78/** Parse node address.
79 *
80 * @param text Network address in common notation.
81 * @param addr Place to store node address.
82 *
83 * @return EOK on success, EINVAL if input is not in valid format.
84 *
85 */
86int inet_addr_parse(const char *text, inet_addr_t *addr)
87{
88 int rc = inet_addr_family(text, &addr->family);
89 if (rc != EOK)
90 return rc;
91
92 rc = inet_pton(addr->family, text, addr->addr);
93 if (rc != EOK)
94 return rc;
95
96 return EOK;
97}
98
99/** Parse network address.
100 *
101 * @param text Network address in common notation.
102 * @param naddr Place to store network address.
103 *
104 * @return EOK on success, EINVAL if input is not in valid format.
105 *
106 */
107int inet_naddr_parse(const char *text, inet_naddr_t *naddr)
108{
109 char *slash = str_chr(text, '/');
110 if (slash == NULL)
111 return EINVAL;
112
113 *slash = 0;
114
115 int rc = inet_addr_family(text, &naddr->family);
116 if (rc != EOK)
117 return rc;
118
119 rc = inet_pton(naddr->family, text, naddr->addr);
120 *slash = '/';
121
122 if (rc != EOK)
123 return rc;
124
125 slash++;
126
127 switch (naddr->family) {
128 case AF_INET:
129 naddr->prefix = strtoul(slash, &slash, 10);
130 if (naddr->prefix > 32)
131 return EINVAL;
132 break;
133 case AF_INET6:
134 naddr->prefix = strtoul(slash, &slash, 10);
135 if (naddr->prefix > 128)
136 return EINVAL;
137 break;
138 default:
139 return ENOTSUP;
140 }
141
142 return EOK;
143}
144
145/** Format node address.
146 *
147 * @param addr Node address.
148 * @param bufp Place to store pointer to formatted string.
149 *
150 * @return EOK on success.
151 * @return ENOMEM if out of memory.
152 * @return ENOTSUP on unsupported address family.
153 *
154 */
155int inet_addr_format(inet_addr_t *addr, char **bufp)
156{
157 int rc;
158
159 switch (addr->family) {
160 case AF_NONE:
161 rc = asprintf(bufp, "none");
162 break;
163 case AF_INET:
164 rc = asprintf(bufp, "%u.%u.%u.%u", addr->addr[0],
165 addr->addr[1], addr->addr[2], addr->addr[3]);
166 break;
167 case AF_INET6:
168 // FIXME TODO
169 break;
170 default:
171 return ENOTSUP;
172 }
173
174 if (rc < 0)
175 return ENOMEM;
176
177 return EOK;
178}
179
180/** Format network address.
181 *
182 * @param naddr Network address.
183 * @param bufp Place to store pointer to formatted string.
184 *
185 * @return EOK on success.
186 * @return ENOMEM if out of memory.
187 * @return ENOTSUP on unsupported address family.
188 *
189 */
190int inet_naddr_format(inet_naddr_t *naddr, char **bufp)
191{
192 int rc;
193
194 switch (naddr->family) {
195 case AF_NONE:
196 rc = asprintf(bufp, "none");
197 break;
198 case AF_INET:
199 rc = asprintf(bufp, "%u.%u.%u.%u/%u", naddr->addr[0],
200 naddr->addr[1], naddr->addr[2], naddr->addr[3],
201 naddr->prefix);
202 break;
203 case AF_INET6:
204 // FIXME TODO
205 break;
206 default:
207 return ENOTSUP;
208 }
209
210 if (rc < 0)
211 return ENOMEM;
212
213 return EOK;
214}
215
216/** Create packed IPv4 address
217 *
218 * Convert an IPv4 address to a packed 32 bit representation.
219 *
220 * @param addr Source address.
221 * @param packed Place to store the packed 32 bit representation.
222 *
223 * @return EOK on success.
224 * @return EINVAL if addr is not an IPv4 address.
225 *
226 */
227int inet_addr_pack(inet_addr_t *addr, uint32_t *packed)
228{
229 if (addr->family != AF_INET)
230 return EINVAL;
231
232 *packed = (addr->addr[0] << 24) | (addr->addr[1] << 16) |
233 (addr->addr[2] << 8) | addr->addr[3];
234 return EOK;
235}
236
237/** Create packed IPv4 address
238 *
239 * Convert an IPv4 address to a packed 32 bit representation.
240 *
241 * @param naddr Source address.
242 * @param packed Place to store the packed 32 bit representation.
243 * @param prefix Place to store the number of valid bits.
244 *
245 * @return EOK on success.
246 * @return EINVAL if addr is not an IPv4 address.
247 *
248 */
249int inet_naddr_pack(inet_naddr_t *naddr, uint32_t *packed, uint8_t *prefix)
250{
251 if (naddr->family != AF_INET)
252 return EINVAL;
253
254 *packed = (naddr->addr[0] << 24) | (naddr->addr[1] << 16) |
255 (naddr->addr[2] << 8) | naddr->addr[3];
256 *prefix = naddr->prefix;
257
258 return EOK;
259}
260
261void inet_addr_unpack(uint32_t packed, inet_addr_t *addr)
262{
263 addr->family = AF_INET;
264 addr->addr[0] = (packed >> 24) & 0xff;
265 addr->addr[1] = (packed >> 16) & 0xff;
266 addr->addr[2] = (packed >> 8) & 0xff;
267 addr->addr[3] = packed & 0xff;
268}
269
270void inet_naddr_unpack(uint32_t packed, uint8_t prefix, inet_naddr_t *naddr)
271{
272 naddr->family = AF_INET;
273 naddr->addr[0] = (packed >> 24) & 0xff;
274 naddr->addr[1] = (packed >> 16) & 0xff;
275 naddr->addr[2] = (packed >> 8) & 0xff;
276 naddr->addr[3] = packed & 0xff;
277 naddr->prefix = prefix;
278}
279
280int inet_addr_sockaddr_in(inet_addr_t *addr, sockaddr_in_t *sockaddr_in)
281{
282 uint32_t packed;
283 int rc = inet_addr_pack(addr, &packed);
284 if (rc != EOK)
285 return rc;
286
287 sockaddr_in->sin_family = AF_INET;
288 sockaddr_in->sin_addr.s_addr = host2uint32_t_be(packed);
289 return EOK;
290}
291
292void inet_naddr_addr(inet_naddr_t *naddr, inet_addr_t *addr)
293{
294 addr->family = naddr->family;
295 memcpy(addr->addr, naddr->addr, INET_ADDR_SIZE);
296}
297
298void inet_addr(inet_addr_t *addr, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
299{
300 addr->family = AF_INET;
301 addr->addr[0] = a;
302 addr->addr[1] = b;
303 addr->addr[2] = c;
304 addr->addr[3] = d;
305}
306
307void inet_naddr(inet_naddr_t *naddr, uint8_t a, uint8_t b, uint8_t c, uint8_t d,
308 uint8_t prefix)
309{
310 naddr->family = AF_INET;
311 naddr->addr[0] = a;
312 naddr->addr[1] = b;
313 naddr->addr[2] = c;
314 naddr->addr[3] = d;
315 naddr->prefix = prefix;
316}
317
318void inet_addr_any(inet_addr_t *addr)
319{
320 addr->family = 0;
321 memset(addr->addr, 0, INET_ADDR_SIZE);
322}
323
324void inet_naddr_any(inet_naddr_t *naddr)
325{
326 naddr->family = 0;
327 memset(naddr->addr, 0, INET_ADDR_SIZE);
328 naddr->prefix = 0;
329}
330
331int inet_addr_compare(inet_addr_t *a, inet_addr_t *b)
332{
333 if (a->family != b->family)
334 return 0;
335
336 switch (a->family) {
337 case AF_INET:
338 return ((a->addr[0] == b->addr[0]) && (a->addr[1] == b->addr[1]) &&
339 (a->addr[2] == b->addr[2]) && (a->addr[3] == b->addr[3]));
340 case AF_INET6:
341 // FIXME TODO
342 return 0;
343 default:
344 return 0;
345 }
346}
347
348int inet_addr_is_any(inet_addr_t *addr)
349{
350 return ((addr->family == 0) ||
351 (inet_addr_compare(addr, &inet_addr_any_addr)) ||
352 (inet_addr_compare(addr, &inet_addr_any_addr6)));
353}
354
355/** @}
356 */
Note: See TracBrowser for help on using the repository browser.