Annotation of embedaddon/ntp/lib/isc/netaddr.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
3: * Copyright (C) 1999-2002 Internet Software Consortium.
4: *
5: * Permission to use, copy, modify, and/or distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15: * PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: /* $Id: netaddr.c,v 1.38 2007/06/18 23:47:44 tbox Exp $ */
19:
20: /*! \file */
21:
22: #include <config.h>
23:
24: #include <stdio.h>
25:
26: #include <isc/buffer.h>
27: #include <isc/msgs.h>
28: #include <isc/net.h>
29: #include <isc/netaddr.h>
30: #include <isc/print.h>
31: #include <isc/sockaddr.h>
32: #include <isc/string.h>
33: #include <isc/util.h>
34:
35: isc_boolean_t
36: isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
37: REQUIRE(a != NULL && b != NULL);
38:
39: if (a->family != b->family)
40: return (ISC_FALSE);
41:
42: if (a->zone != b->zone)
43: return (ISC_FALSE);
44:
45: switch (a->family) {
46: case AF_INET:
47: if (a->type.in.s_addr != b->type.in.s_addr)
48: return (ISC_FALSE);
49: break;
50: case AF_INET6:
51: if (memcmp(&a->type.in6, &b->type.in6,
52: sizeof(a->type.in6)) != 0 ||
53: a->zone != b->zone)
54: return (ISC_FALSE);
55: break;
56: #ifdef ISC_PLATFORM_HAVESYSUNH
57: case AF_UNIX:
58: if (strcmp(a->type.un, b->type.un) != 0)
59: return (ISC_FALSE);
60: break;
61: #endif
62: default:
63: return (ISC_FALSE);
64: }
65: return (ISC_TRUE);
66: }
67:
68: isc_boolean_t
69: isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
70: unsigned int prefixlen)
71: {
72: const unsigned char *pa, *pb;
73: unsigned int ipabytes; /* Length of whole IP address in bytes */
74: unsigned int nbytes; /* Number of significant whole bytes */
75: unsigned int nbits; /* Number of significant leftover bits */
76:
77: REQUIRE(a != NULL && b != NULL);
78:
79: if (a->family != b->family)
80: return (ISC_FALSE);
81:
82: if (a->zone != b->zone && b->zone != 0)
83: return (ISC_FALSE);
84:
85: switch (a->family) {
86: case AF_INET:
87: pa = (const unsigned char *) &a->type.in;
88: pb = (const unsigned char *) &b->type.in;
89: ipabytes = 4;
90: break;
91: case AF_INET6:
92: pa = (const unsigned char *) &a->type.in6;
93: pb = (const unsigned char *) &b->type.in6;
94: ipabytes = 16;
95: break;
96: default:
97: pa = pb = NULL; /* Avoid silly compiler warning. */
98: ipabytes = 0; /* Ditto. */
99: return (ISC_FALSE);
100: }
101:
102: /*
103: * Don't crash if we get a pattern like 10.0.0.1/9999999.
104: */
105: if (prefixlen > ipabytes * 8)
106: prefixlen = ipabytes * 8;
107:
108: nbytes = prefixlen / 8;
109: nbits = prefixlen % 8;
110:
111: if (nbytes > 0) {
112: if (memcmp(pa, pb, nbytes) != 0)
113: return (ISC_FALSE);
114: }
115: if (nbits > 0) {
116: unsigned int bytea, byteb, mask;
117: INSIST(nbytes < ipabytes);
118: INSIST(nbits < 8);
119: bytea = pa[nbytes];
120: byteb = pb[nbytes];
121: mask = (0xFF << (8-nbits)) & 0xFF;
122: if ((bytea & mask) != (byteb & mask))
123: return (ISC_FALSE);
124: }
125: return (ISC_TRUE);
126: }
127:
128: isc_result_t
129: isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
130: char abuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
131: char zbuf[sizeof("%4294967295")];
132: unsigned int alen;
133: int zlen;
134: const char *r;
135: const void *type;
136:
137: REQUIRE(netaddr != NULL);
138:
139: switch (netaddr->family) {
140: case AF_INET:
141: type = &netaddr->type.in;
142: break;
143: case AF_INET6:
144: type = &netaddr->type.in6;
145: break;
146: #ifdef ISC_PLATFORM_HAVESYSUNH
147: case AF_UNIX:
148: alen = strlen(netaddr->type.un);
149: if (alen > isc_buffer_availablelength(target))
150: return (ISC_R_NOSPACE);
151: isc_buffer_putmem(target,
152: (const unsigned char *)(netaddr->type.un),
153: alen);
154: return (ISC_R_SUCCESS);
155: #endif
156: default:
157: return (ISC_R_FAILURE);
158: }
159: r = inet_ntop(netaddr->family, type, abuf, sizeof(abuf));
160: if (r == NULL)
161: return (ISC_R_FAILURE);
162:
163: alen = strlen(abuf);
164: INSIST(alen < sizeof(abuf));
165:
166: zlen = 0;
167: if (netaddr->family == AF_INET6 && netaddr->zone != 0) {
168: zlen = snprintf(zbuf, sizeof(zbuf), "%%%u", netaddr->zone);
169: if (zlen < 0)
170: return (ISC_R_FAILURE);
171: INSIST((unsigned int)zlen < sizeof(zbuf));
172: }
173:
174: if (alen + zlen > isc_buffer_availablelength(target))
175: return (ISC_R_NOSPACE);
176:
177: isc_buffer_putmem(target, (unsigned char *)abuf, alen);
178: isc_buffer_putmem(target, (unsigned char *)zbuf, zlen);
179:
180: return (ISC_R_SUCCESS);
181: }
182:
183: void
184: isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) {
185: isc_result_t result;
186: isc_buffer_t buf;
187:
188: isc_buffer_init(&buf, array, size);
189: result = isc_netaddr_totext(na, &buf);
190:
191: /*
192: * Null terminate.
193: */
194: if (result == ISC_R_SUCCESS) {
195: if (isc_buffer_availablelength(&buf) >= 1)
196: isc_buffer_putuint8(&buf, 0);
197: else
198: result = ISC_R_NOSPACE;
199: }
200:
201: if (result != ISC_R_SUCCESS) {
202: snprintf(array, size,
203: isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
204: ISC_MSG_UNKNOWNADDR,
205: "<unknown address, family %u>"),
206: na->family);
207: array[size - 1] = '\0';
208: }
209: }
210:
211:
212: isc_result_t
213: isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) {
214: static const unsigned char zeros[16] = { 0 };
215: unsigned int nbits, nbytes, ipbytes;
216: const unsigned char *p;
217:
218: switch (na->family) {
219: case AF_INET:
220: p = (const unsigned char *) &na->type.in;
221: ipbytes = 4;
222: if (prefixlen > 32)
223: return (ISC_R_RANGE);
224: break;
225: case AF_INET6:
226: p = (const unsigned char *) &na->type.in6;
227: ipbytes = 16;
228: if (prefixlen > 128)
229: return (ISC_R_RANGE);
230: break;
231: default:
232: ipbytes = 0;
233: return (ISC_R_NOTIMPLEMENTED);
234: }
235: nbytes = prefixlen / 8;
236: nbits = prefixlen % 8;
237: if (nbits != 0) {
238: if ((p[nbytes] & (0xff>>nbits)) != 0U)
239: return (ISC_R_FAILURE);
240: nbytes++;
241: }
242: if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0)
243: return (ISC_R_FAILURE);
244: return (ISC_R_SUCCESS);
245: }
246:
247: isc_result_t
248: isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
249: unsigned int nbits, nbytes, ipbytes, i;
250: const unsigned char *p;
251:
252: switch (s->family) {
253: case AF_INET:
254: p = (const unsigned char *) &s->type.in;
255: ipbytes = 4;
256: break;
257: case AF_INET6:
258: p = (const unsigned char *) &s->type.in6;
259: ipbytes = 16;
260: break;
261: default:
262: ipbytes = 0;
263: return (ISC_R_NOTIMPLEMENTED);
264: }
265: nbytes = nbits = 0;
266: for (i = 0; i < ipbytes; i++) {
267: if (p[i] != 0xFF)
268: break;
269: }
270: nbytes = i;
271: if (i < ipbytes) {
272: unsigned int c = p[nbytes];
273: while ((c & 0x80) != 0 && nbits < 8) {
274: c <<= 1; nbits++;
275: }
276: if ((c & 0xFF) != 0)
277: return (ISC_R_MASKNONCONTIG);
278: i++;
279: }
280: for (; i < ipbytes; i++) {
281: if (p[i] != 0)
282: return (ISC_R_MASKNONCONTIG);
283: i++;
284: }
285: *lenp = nbytes * 8 + nbits;
286: return (ISC_R_SUCCESS);
287: }
288:
289: void
290: isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
291: memset(netaddr, 0, sizeof(*netaddr));
292: netaddr->family = AF_INET;
293: netaddr->type.in = *ina;
294: }
295:
296: void
297: isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
298: memset(netaddr, 0, sizeof(*netaddr));
299: netaddr->family = AF_INET6;
300: netaddr->type.in6 = *ina6;
301: }
302:
303: isc_result_t
304: isc_netaddr_frompath(isc_netaddr_t *netaddr, const char *path) {
305: #ifdef ISC_PLATFORM_HAVESYSUNH
306: if (strlen(path) > sizeof(netaddr->type.un) - 1)
307: return (ISC_R_NOSPACE);
308:
309: memset(netaddr, 0, sizeof(*netaddr));
310: netaddr->family = AF_UNIX;
311: strcpy(netaddr->type.un, path);
312: netaddr->zone = 0;
313: return (ISC_R_SUCCESS);
314: #else
315: UNUSED(netaddr);
316: UNUSED(path);
317: return (ISC_R_NOTIMPLEMENTED);
318: #endif
319: }
320:
321:
322: void
323: isc_netaddr_setzone(isc_netaddr_t *netaddr, isc_uint32_t zone) {
324: /* we currently only support AF_INET6. */
325: REQUIRE(netaddr->family == AF_INET6);
326:
327: netaddr->zone = zone;
328: }
329:
330: isc_uint32_t
331: isc_netaddr_getzone(const isc_netaddr_t *netaddr) {
332: return (netaddr->zone);
333: }
334:
335: void
336: isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
337: int family = s->type.sa.sa_family;
338: t->family = family;
339: switch (family) {
340: case AF_INET:
341: t->type.in = s->type.sin.sin_addr;
342: t->zone = 0;
343: break;
344: case AF_INET6:
345: memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
346: #ifdef ISC_PLATFORM_HAVESCOPEID
347: t->zone = s->type.sin6.sin6_scope_id;
348: #else
349: t->zone = 0;
350: #endif
351: break;
352: #ifdef ISC_PLATFORM_HAVESYSUNH
353: case AF_UNIX:
354: memcpy(t->type.un, s->type.sunix.sun_path, sizeof(t->type.un));
355: t->zone = 0;
356: break;
357: #endif
358: default:
359: INSIST(0);
360: }
361: }
362:
363: void
364: isc_netaddr_any(isc_netaddr_t *netaddr) {
365: memset(netaddr, 0, sizeof(*netaddr));
366: netaddr->family = AF_INET;
367: netaddr->type.in.s_addr = INADDR_ANY;
368: }
369:
370: void
371: isc_netaddr_any6(isc_netaddr_t *netaddr) {
372: memset(netaddr, 0, sizeof(*netaddr));
373: netaddr->family = AF_INET6;
374: netaddr->type.in6 = in6addr_any;
375: }
376:
377: isc_boolean_t
378: isc_netaddr_ismulticast(isc_netaddr_t *na) {
379: switch (na->family) {
380: case AF_INET:
381: return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
382: case AF_INET6:
383: return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
384: default:
385: return (ISC_FALSE); /* XXXMLG ? */
386: }
387: }
388:
389: isc_boolean_t
390: isc_netaddr_isexperimental(isc_netaddr_t *na) {
391: switch (na->family) {
392: case AF_INET:
393: return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
394: default:
395: return (ISC_FALSE); /* XXXMLG ? */
396: }
397: }
398:
399: isc_boolean_t
400: isc_netaddr_islinklocal(isc_netaddr_t *na) {
401: switch (na->family) {
402: case AF_INET:
403: return (ISC_FALSE);
404: case AF_INET6:
405: return (ISC_TF(IN6_IS_ADDR_LINKLOCAL(&na->type.in6)));
406: default:
407: return (ISC_FALSE);
408: }
409: }
410:
411: isc_boolean_t
412: isc_netaddr_issitelocal(isc_netaddr_t *na) {
413: switch (na->family) {
414: case AF_INET:
415: return (ISC_FALSE);
416: case AF_INET6:
417: return (ISC_TF(IN6_IS_ADDR_SITELOCAL(&na->type.in6)));
418: default:
419: return (ISC_FALSE);
420: }
421: }
422:
423: void
424: isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
425: isc_netaddr_t *src;
426:
427: DE_CONST(s, src); /* Must come before IN6_IS_ADDR_V4MAPPED. */
428:
429: REQUIRE(s->family == AF_INET6);
430: REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
431:
432: memset(t, 0, sizeof(*t));
433: t->family = AF_INET;
434: memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
435: return;
436: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>