Merge from vendor branch GDB:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / netaddr.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and 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.18.2.2 2004/03/09 06:11:49 marka Exp $ */
19
20 #include <config.h>
21
22 #include <stdio.h>
23
24 #include <isc/buffer.h>
25 #include <isc/msgs.h>
26 #include <isc/net.h>
27 #include <isc/netaddr.h>
28 #include <isc/print.h>
29 #include <isc/sockaddr.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
32
33 isc_boolean_t
34 isc_netaddr_equal(const isc_netaddr_t *a, const isc_netaddr_t *b) {
35         REQUIRE(a != NULL && b != NULL);
36
37         if (a->family != b->family)
38                 return (ISC_FALSE);
39
40         switch (a->family) {
41         case AF_INET:
42                 if (a->type.in.s_addr != b->type.in.s_addr)
43                         return (ISC_FALSE);
44                 break;
45         case AF_INET6:
46                 if (memcmp(&a->type.in6, &b->type.in6, sizeof a->type.in6)
47                     != 0)
48                         return (ISC_FALSE);
49                 break;
50         default:
51                 return (ISC_FALSE);
52         }
53         return (ISC_TRUE);
54 }
55
56 isc_boolean_t
57 isc_netaddr_eqprefix(const isc_netaddr_t *a, const isc_netaddr_t *b,
58                      unsigned int prefixlen)
59 {
60         const unsigned char *pa, *pb;
61         unsigned int ipabytes; /* Length of whole IP address in bytes */
62         unsigned int nbytes;   /* Number of significant whole bytes */
63         unsigned int nbits;    /* Number of significant leftover bits */
64
65         REQUIRE(a != NULL && b != NULL);
66
67         if (a->family != b->family)
68                 return (ISC_FALSE);
69
70         switch (a->family) {
71         case AF_INET:
72                 pa = (const unsigned char *) &a->type.in;
73                 pb = (const unsigned char *) &b->type.in;
74                 ipabytes = 4;
75                 break;
76         case AF_INET6:
77                 pa = (const unsigned char *) &a->type.in6;
78                 pb = (const unsigned char *) &b->type.in6;
79                 ipabytes = 16;
80                 break;
81         default:
82                 pa = pb = NULL; /* Avoid silly compiler warning. */
83                 ipabytes = 0; /* Ditto. */
84                 return (ISC_FALSE);
85         }
86
87         /*
88          * Don't crash if we get a pattern like 10.0.0.1/9999999.
89          */
90         if (prefixlen > ipabytes * 8)
91                 prefixlen = ipabytes * 8;
92
93         nbytes = prefixlen / 8;
94         nbits = prefixlen % 8;
95
96         if (nbytes > 0) {
97                 if (memcmp(pa, pb, nbytes) != 0)
98                         return (ISC_FALSE);
99         }
100         if (nbits > 0) {
101                 unsigned int bytea, byteb, mask;
102                 INSIST(nbytes < ipabytes);
103                 INSIST(nbits < 8);
104                 bytea = pa[nbytes];
105                 byteb = pb[nbytes];
106                 mask = (0xFF << (8-nbits)) & 0xFF;
107                 if ((bytea & mask) != (byteb & mask))
108                         return (ISC_FALSE);
109         }
110         return (ISC_TRUE);
111 }
112
113 isc_result_t
114 isc_netaddr_totext(const isc_netaddr_t *netaddr, isc_buffer_t *target) {
115         char abuf[sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255"];
116         unsigned int alen;
117         const char *r;
118
119         REQUIRE(netaddr != NULL);
120
121         r = inet_ntop(netaddr->family, &netaddr->type, abuf, sizeof abuf);
122         if (r == NULL)
123                 return (ISC_R_FAILURE);
124
125         alen = strlen(abuf);
126         INSIST(alen < sizeof(abuf));
127
128         if (alen > isc_buffer_availablelength(target))
129                 return (ISC_R_NOSPACE);
130
131         isc_buffer_putmem(target, (unsigned char *)abuf, alen);
132
133         return (ISC_R_SUCCESS);
134 }
135
136 void
137 isc_netaddr_format(isc_netaddr_t *na, char *array, unsigned int size) {
138         isc_result_t result;
139         isc_buffer_t buf;
140
141         isc_buffer_init(&buf, array, size);
142         result = isc_netaddr_totext(na, &buf);
143
144         /*
145          * Null terminate.
146          */
147         if (result == ISC_R_SUCCESS) {
148                 if (isc_buffer_availablelength(&buf) >= 1)
149                         isc_buffer_putuint8(&buf, 0);
150                 else
151                         result = ISC_R_NOSPACE;
152         }
153
154         if (result != ISC_R_SUCCESS) {
155                 snprintf(array, size,
156                          isc_msgcat_get(isc_msgcat, ISC_MSGSET_NETADDR,
157                                         ISC_MSG_UNKNOWNADDR,
158                                         "<unknown address, family %u>"),
159                          na->family);
160                 array[size - 1] = '\0';
161         }
162 }
163
164 isc_result_t
165 isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) {
166         unsigned int nbits, nbytes, ipbytes, i;
167         const unsigned char *p;
168
169         switch (s->family) {
170         case AF_INET:
171                 p = (const unsigned char *) &s->type.in;
172                 ipbytes = 4;
173                 break;
174         case AF_INET6:
175                 p = (const unsigned char *) &s->type.in6;
176                 ipbytes = 16;
177                 break;
178         default:
179                 ipbytes = 0;
180                 return (ISC_R_NOTIMPLEMENTED);
181         }
182         nbytes = nbits = 0;
183         for (i = 0; i < ipbytes; i++) {
184                 if (p[i] != 0xFF)
185                         break;
186         }
187         nbytes = i;
188         if (i < ipbytes) {
189                 unsigned int c = p[nbytes];
190                 while ((c & 0x80) != 0 && nbits < 8) {
191                         c <<= 1; nbits++;
192                 }
193                 if ((c & 0xFF) != 0)
194                         return (ISC_R_MASKNONCONTIG);
195                 i++;
196         }
197         for (; i < ipbytes; i++) {
198                 if (p[i] != 0)
199                         return (ISC_R_MASKNONCONTIG);
200                 i++;
201         }
202         *lenp = nbytes * 8 + nbits;
203         return (ISC_R_SUCCESS);
204 }
205
206 void
207 isc_netaddr_fromin(isc_netaddr_t *netaddr, const struct in_addr *ina) {
208         memset(netaddr, 0, sizeof *netaddr);
209         netaddr->family = AF_INET;
210         netaddr->type.in = *ina;
211 }
212
213 void
214 isc_netaddr_fromin6(isc_netaddr_t *netaddr, const struct in6_addr *ina6) {
215         memset(netaddr, 0, sizeof *netaddr);
216         netaddr->family = AF_INET6;
217         netaddr->type.in6 = *ina6;
218 }
219
220 void
221 isc_netaddr_fromsockaddr(isc_netaddr_t *t, const isc_sockaddr_t *s) {
222         int family = s->type.sa.sa_family;
223         t->family = family;
224         switch (family) {
225         case AF_INET:
226                 t->type.in = s->type.sin.sin_addr;
227                 break;
228         case AF_INET6:
229                 memcpy(&t->type.in6, &s->type.sin6.sin6_addr, 16);
230                 break;
231         default:
232                 INSIST(0);
233         }
234 }
235
236 void
237 isc_netaddr_any(isc_netaddr_t *netaddr) {
238         memset(netaddr, 0, sizeof *netaddr);
239         netaddr->family = AF_INET;
240         netaddr->type.in.s_addr = INADDR_ANY;
241 }
242
243 void
244 isc_netaddr_any6(isc_netaddr_t *netaddr) {
245         memset(netaddr, 0, sizeof *netaddr);
246         netaddr->family = AF_INET6;
247         netaddr->type.in6 = in6addr_any;
248 }
249
250 isc_boolean_t
251 isc_netaddr_ismulticast(isc_netaddr_t *na) {
252         switch (na->family) {
253         case AF_INET:
254                 return (ISC_TF(ISC_IPADDR_ISMULTICAST(na->type.in.s_addr)));
255         case AF_INET6:
256                 return (ISC_TF(IN6_IS_ADDR_MULTICAST(&na->type.in6)));
257         default:
258                 return (ISC_FALSE);  /* XXXMLG ? */
259         }
260 }
261
262 isc_boolean_t
263 isc_netaddr_isexperimental(isc_netaddr_t *na) {
264         switch (na->family) {
265         case AF_INET:
266                 return (ISC_TF(ISC_IPADDR_ISEXPERIMENTAL(na->type.in.s_addr)));
267         default:
268                 return (ISC_FALSE);  /* XXXMLG ? */
269         }
270 }
271
272 void
273 isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s) {
274         isc_netaddr_t *src;
275
276         DE_CONST(s, src);       /* Must come before IN6_IS_ADDR_V4MAPPED. */
277
278         REQUIRE(s->family == AF_INET6);
279         REQUIRE(IN6_IS_ADDR_V4MAPPED(&src->type.in6));
280
281         memset(t, 0, sizeof(*t));
282         t->family = AF_INET;
283         memcpy(&t->type.in, (char *)&src->type.in6 + 12, 4);
284         return;
285 }