4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
30 #include <sys/stream.h>
32 #include <sys/stropts.h>
33 #include <sys/strlog.h>
34 #include <sys/systm.h>
36 #include <sys/cmn_err.h>
38 #include <sys/param.h>
39 #include <sys/tihdr.h>
40 #include <netinet/in.h>
41 #include <netinet/ip6.h>
43 #include <inet/common.h>
47 #include <inet/ip_listutils.h>
50 * These functions perform set operations on sets of ipv6 addresses.
51 * The sets are formatted as slist_t's (defined in <inet/ip.h>):
52 * typedef struct slist_s {
54 * in6_addr_t sl_addr[MAX_FILTER_SIZE];
57 * The functions were designed specifically for the implementation of
58 * IGMPv3 and MLDv2 in ip; they were not meant to be general-purpose.
62 * Tells if lists A and B are different or not - true if different;
63 * caller guarantees that lists are <= MAX_FILTER_SIZE
66 lists_are_different(const slist_t
*a
, const slist_t
*b
)
69 int acnt
= SLIST_CNT(a
);
70 int bcnt
= SLIST_CNT(b
);
76 ASSERT(acnt
<= MAX_FILTER_SIZE
);
77 ASSERT(bcnt
<= MAX_FILTER_SIZE
);
79 for (i
= 0; i
< acnt
; i
++) {
81 for (j
= 0; j
< bcnt
; j
++) {
82 if (IN6_ARE_ADDR_EQUAL(
83 &a
->sl_addr
[i
], &b
->sl_addr
[j
])) {
95 * Tells if list a contains address addr - true if it does, false if not;
96 * caller guarantees that list is <= MAX_FILTER_SIZE.
99 list_has_addr(const slist_t
*a
, const in6_addr_t
*addr
)
103 if (SLIST_IS_EMPTY(a
))
106 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
108 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
109 if (IN6_ARE_ADDR_EQUAL(&a
->sl_addr
[i
], addr
))
116 * Implements a * b and stores the result in target; caller guarantees
117 * that a and b are <= MAX_FILTER_SIZE, and that target is a valid pointer.
118 * target must not be the same as a or b; for that case see
119 * l_intersection_in_a().
122 l_intersection(const slist_t
*a
, const slist_t
*b
, slist_t
*target
)
126 target
->sl_numsrc
= 0;
128 if (SLIST_IS_EMPTY(a
) || SLIST_IS_EMPTY(b
))
131 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
132 ASSERT(b
->sl_numsrc
<= MAX_FILTER_SIZE
);
134 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
135 for (j
= 0; j
< b
->sl_numsrc
; j
++) {
136 if (IN6_ARE_ADDR_EQUAL(
137 &a
->sl_addr
[i
], &b
->sl_addr
[j
])) {
138 target
->sl_addr
[target
->sl_numsrc
++] =
147 * Implements a - b and stores the result in target; caller guarantees
148 * that a and b are <= MAX_FILTER_SIZE, and that target is a valid pointer.
149 * target must not be the same as a or b; for that case see l_difference_in_a().
152 l_difference(const slist_t
*a
, const slist_t
*b
, slist_t
*target
)
155 boolean_t found
= B_FALSE
;
157 target
->sl_numsrc
= 0;
159 if (SLIST_IS_EMPTY(a
))
162 if (SLIST_IS_EMPTY(b
)) {
167 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
168 ASSERT(b
->sl_numsrc
<= MAX_FILTER_SIZE
);
170 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
171 for (j
= 0; j
< b
->sl_numsrc
; j
++) {
172 if (IN6_ARE_ADDR_EQUAL(
173 &a
->sl_addr
[i
], &b
->sl_addr
[j
])) {
179 target
->sl_addr
[target
->sl_numsrc
++] = a
->sl_addr
[i
];
187 * Removes addr from list a. Caller guarantees that addr is a valid
188 * pointer, and that a <= MAX_FILTER_SIZE. addr will only be removed
189 * once from the list; if it appears in the list multiple times, extra
193 l_remove(slist_t
*a
, const in6_addr_t
*addr
)
197 if (SLIST_IS_EMPTY(a
))
200 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
202 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
203 if (IN6_ARE_ADDR_EQUAL(&a
->sl_addr
[i
], addr
)) {
205 mvsize
= (a
->sl_numsrc
- i
) * sizeof (in6_addr_t
);
206 (void) memmove(&a
->sl_addr
[i
], &a
->sl_addr
[i
+ 1],
214 * Make a copy of list a by allocating a new slist_t and copying only
215 * a->sl_numsrc addrs. Caller guarantees that a <= MAX_FILTER_SIZE.
216 * Return a pointer to the newly alloc'd list, or NULL if a is empty
217 * (no memory is alloc'd in this case).
220 l_alloc_copy(const slist_t
*a
)
224 if (SLIST_IS_EMPTY(a
))
227 if ((b
= l_alloc()) == NULL
)
236 * Copy the address list from slist a into slist b, overwriting anything
237 * that might already be in slist b. Assumes that a <= MAX_FILTER_SIZE
238 * and that b points to a properly allocated slist.
241 l_copy(const slist_t
*a
, slist_t
*b
)
243 if (SLIST_IS_EMPTY(a
)) {
248 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
250 b
->sl_numsrc
= a
->sl_numsrc
;
251 (void) memcpy(b
->sl_addr
, a
->sl_addr
,
252 a
->sl_numsrc
* sizeof (in6_addr_t
));
256 * Append to a any addrs in b that are not already in a (i.e. perform
257 * a + b and store the result in a). If b is empty, the function returns
258 * without taking any action.
260 * Caller guarantees that a and b are <= MAX_FILTER_SIZE, and that a
261 * and overflow are valid pointers.
263 * If an overflow occurs (a + b > MAX_FILTER_SIZE), a will contain the
264 * first MAX_FILTER_SIZE addresses of the union, and *overflow will be
265 * set to true. Otherwise, *overflow will be set to false.
268 l_union_in_a(slist_t
*a
, const slist_t
*b
, boolean_t
*overflow
)
275 if (SLIST_IS_EMPTY(b
))
278 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
279 ASSERT(b
->sl_numsrc
<= MAX_FILTER_SIZE
);
281 for (i
= 0; i
< b
->sl_numsrc
; i
++) {
283 for (j
= 0; j
< a
->sl_numsrc
; j
++) {
284 if (IN6_ARE_ADDR_EQUAL(
285 &b
->sl_addr
[i
], &a
->sl_addr
[j
])) {
291 if (a
->sl_numsrc
== MAX_FILTER_SIZE
) {
295 a
->sl_addr
[a
->sl_numsrc
++] = b
->sl_addr
[i
];
302 * Remove from list a any addresses that are not also in list b
303 * (i.e. perform a * b and store the result in a).
305 * Caller guarantees that a and b are <= MAX_FILTER_SIZE, and that
306 * a is a valid pointer.
309 l_intersection_in_a(slist_t
*a
, const slist_t
*b
)
314 if (SLIST_IS_EMPTY(b
)) {
319 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
320 ASSERT(b
->sl_numsrc
<= MAX_FILTER_SIZE
);
323 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
325 for (j
= 0; j
< b
->sl_numsrc
; j
++) {
326 if (IN6_ARE_ADDR_EQUAL(
327 &a
->sl_addr
[i
], &b
->sl_addr
[j
])) {
335 a
->sl_addr
[i
- shift
] = a
->sl_addr
[i
];
337 a
->sl_numsrc
-= shift
;
341 * Remove from list a any addresses that are in list b (i.e. perform
342 * a - b and store the result in a).
344 * Caller guarantees that a and b are <= MAX_FILTER_SIZE. If either
345 * list is empty (or a null pointer), the function returns without
349 l_difference_in_a(slist_t
*a
, const slist_t
*b
)
354 if (SLIST_IS_EMPTY(a
) || SLIST_IS_EMPTY(b
))
357 ASSERT(a
->sl_numsrc
<= MAX_FILTER_SIZE
);
358 ASSERT(b
->sl_numsrc
<= MAX_FILTER_SIZE
);
361 for (i
= 0; i
< a
->sl_numsrc
; i
++) {
363 for (j
= 0; j
< b
->sl_numsrc
; j
++) {
364 if (IN6_ARE_ADDR_EQUAL(
365 &a
->sl_addr
[i
], &b
->sl_addr
[j
])) {
373 a
->sl_addr
[i
- shift
] = a
->sl_addr
[i
];
375 a
->sl_numsrc
-= shift
;
379 * Wrapper function to alloc an slist_t.
386 p
= (slist_t
*)mi_alloc(sizeof (slist_t
), BPRI_MED
);
393 * Frees an slist_t structure. Provided for symmetry with l_alloc().