]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pim6dd/inet6.c
This commit was generated by cvs2svn to compensate for changes in r58653,
[FreeBSD/FreeBSD.git] / usr.sbin / pim6dd / inet6.c
1 /*
2  * Copyright (C) 1998 WIDE Project.
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #include "defs.h"
33
34 int
35 inet6_uvif2scopeid(struct sockaddr_in6 *sa, struct uvif *v)
36 {
37         if (IN6_IS_ADDR_MULTICAST(&sa->sin6_addr)) {
38                 if (IN6_IS_ADDR_MC_LINKLOCAL(&sa->sin6_addr))
39                         return(v->uv_ifindex);
40                 if (IN6_IS_ADDR_MC_SITELOCAL(&sa->sin6_addr))
41                         return(v->uv_siteid);
42         }
43         else {
44                 if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr))
45                         return(v->uv_ifindex);
46
47                 if (IN6_IS_ADDR_SITELOCAL(&sa->sin6_addr))
48                         return(v->uv_siteid);
49         }
50
51         return(0);
52 }
53
54 int
55 inet6_localif_address(struct sockaddr_in6 *sa, struct uvif *v)
56 {
57         struct phaddr *pa;
58
59         for (pa = v->uv_addrs; pa; pa = pa->pa_next)
60                 if (inet6_equal(sa, &pa->pa_addr))
61                         return(TRUE);
62
63         return(FALSE);
64 }
65
66 int
67 inet6_valid_host(struct sockaddr_in6 *addr)
68 {
69         if (IN6_IS_ADDR_MULTICAST(&addr->sin6_addr))
70                 return(FALSE);
71
72         return(TRUE);
73 }
74
75 int
76 inet6_equal(struct sockaddr_in6 *sa1, struct sockaddr_in6 *sa2)
77 {
78         if (sa1->sin6_scope_id == sa2->sin6_scope_id &&
79             IN6_ARE_ADDR_EQUAL(&sa1->sin6_addr, &sa2->sin6_addr))
80                 return(1);
81
82         return(0);
83 }
84
85 int
86 inet6_lessthan(struct sockaddr_in6 *sa1, struct sockaddr_in6 *sa2)
87 {
88         u_int32_t s32_1, s32_2;
89         int i;
90
91         if (sa1->sin6_scope_id < sa2->sin6_scope_id)
92                 return(1);
93         if (sa1->sin6_scope_id == sa2->sin6_scope_id) {
94                 for (i = 0; i < 4; i++) {
95                         s32_1 = ntohl(*(u_int32_t *)&sa1->sin6_addr.s6_addr[i * 4]);
96                         s32_2 = ntohl(*(u_int32_t *)&sa2->sin6_addr.s6_addr[i * 4]);
97
98                         if (s32_1 > s32_2)
99                                 return(0);
100                         if (s32_1 < s32_2)
101                                 return(1);
102
103                         /* otherwide, continue to compare */
104                 }
105         }
106
107         return(0);
108 }
109
110 int
111 inet6_lessoreq(struct sockaddr_in6 *sa1, struct sockaddr_in6 *sa2)
112 {
113         u_int32_t s32_1, s32_2;
114         int i;
115
116         if (sa1->sin6_scope_id < sa2->sin6_scope_id)
117                 return(1);
118         if (sa1->sin6_scope_id == sa2->sin6_scope_id) {
119                 for (i = 0; i < 4; i++) {
120                         s32_1 = ntohl(*(u_int32_t *)&sa1->sin6_addr.s6_addr[i * 4]);
121                         s32_2 = ntohl(*(u_int32_t *)&sa2->sin6_addr.s6_addr[i * 4]);
122
123                         if (s32_1 > s32_2)
124                                 return(0);
125                         if (s32_1 < s32_2)
126                                 return(1);
127
128                         /* otherwide, continue to compare */
129                 }
130                 /* sa1 == sa2 */
131                 return(1);
132         }
133
134         return(0);
135 }
136
137 int
138 inet6_greaterthan(struct sockaddr_in6 *sa1, struct sockaddr_in6 *sa2)
139 {
140         u_int32_t s32_1, s32_2;
141         int i;
142
143         if (sa1->sin6_scope_id > sa2->sin6_scope_id)
144                 return(1);
145         if (sa1->sin6_scope_id == sa2->sin6_scope_id) {
146                 for (i = 0; i < 4; i++) {
147                         s32_1 = ntohl(*(u_int32_t *)&sa1->sin6_addr.s6_addr[i * 4]);
148                         s32_2 = ntohl(*(u_int32_t *)&sa2->sin6_addr.s6_addr[i * 4]);
149
150                         if (s32_1 < s32_2)
151                                 return(0);
152                         if (s32_1 > s32_2)
153                                 return(1);
154
155                         /* otherwide, continue to compare */
156                 }
157         }
158
159         return(0);
160 }
161
162 int
163 inet6_greateroreq(struct sockaddr_in6 *sa1, struct sockaddr_in6 *sa2)
164 {
165         u_int32_t s32_1, s32_2;
166         int i;
167
168         if (sa1->sin6_scope_id > sa2->sin6_scope_id)
169                 return(1);
170         if (sa1->sin6_scope_id == sa2->sin6_scope_id) {
171                 for (i = 0; i < 4; i++) {
172                         s32_1 = ntohl(*(u_int32_t *)&sa1->sin6_addr.s6_addr[i * 4]);
173                         s32_2 = ntohl(*(u_int32_t *)&sa2->sin6_addr.s6_addr[i * 4]);
174
175                         if (s32_1 < s32_2)
176                                 return(0);
177                         if (s32_1 > s32_2)
178                                 return(1);
179
180                         /* otherwide, continue to compare */
181                 }
182                 /* sa1 == sa2 */
183                 return(1);
184         }
185
186         return(0);
187 }
188
189 int
190 inet6_match_prefix(sa1, sa2, mask)
191         struct sockaddr_in6 *sa1, *sa2;
192         struct in6_addr *mask;
193 {
194         int i;
195
196         if (sa1->sin6_scope_id != sa2->sin6_scope_id)
197                 return(0);
198
199         for (i = 0; i < 16; i++) {
200                 if ((sa1->sin6_addr.s6_addr[i] ^ sa2->sin6_addr.s6_addr[i]) &
201                     mask->s6_addr[i])
202                         return(0);
203         }
204
205         return(1);
206 }
207
208 char *
209 inet6_fmt(struct in6_addr *addr)
210 {
211         static char ip6buf[8][INET6_ADDRSTRLEN];
212         static int ip6round = 0;
213         char *cp;
214
215         ip6round = (ip6round + 1) & 7;
216         cp = ip6buf[ip6round];
217
218         inet_ntop(AF_INET6, addr, cp, INET6_ADDRSTRLEN);
219         return(cp);
220 }
221
222 char *
223 ifindex2str(int ifindex)
224 {
225         static char ifname[IFNAMSIZ];
226
227         return(if_indextoname(ifindex, ifname));
228 }
229
230 int
231 inet6_mask2plen(struct in6_addr *mask)
232 {
233         int masklen;
234         u_char *p = (u_char *)mask;
235         u_char *lim = p + 16;
236
237         for (masklen = 0; p < lim; p++) {
238                 switch (*p) {
239                  case 0xff:
240                          masklen += 8;
241                          break;
242                  case 0xfe:
243                          masklen += 7;
244                          break;
245                  case 0xfc:
246                          masklen += 6;
247                          break;
248                  case 0xf8:
249                          masklen += 5;
250                          break;
251                  case 0xf0:
252                          masklen += 4;
253                          break;
254                  case 0xe0:
255                          masklen += 3;
256                          break;
257                  case 0xc0:
258                          masklen += 2;
259                          break;
260                  case 0x80:
261                          masklen += 1;
262                          break;
263                  case 0x00:
264                          break;
265                 }
266         }
267
268         return(masklen);
269 }
270
271 char *
272 net6name(struct in6_addr *prefix, struct in6_addr *mask)
273 {
274         static char ip6buf[8][INET6_ADDRSTRLEN + 4]; /* length of addr/plen */
275         static int ip6round = 0;
276         char *cp;
277
278         ip6round = (ip6round + 1) & 7;
279         cp = ip6buf[ip6round];
280
281         inet_ntop(AF_INET6, prefix, cp, INET6_ADDRSTRLEN);
282         cp += strlen(cp);
283         *cp = '/';
284         cp++;
285         sprintf(cp, "%d", inet6_mask2plen(mask));
286
287         return(ip6buf[ip6round]);
288 }