1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
28*7c478bd9Sstevel@tonic-gate #include <sys/stream.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/dlpi.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/strlog.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
35*7c478bd9Sstevel@tonic-gate
36*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/tihdr.h>
38*7c478bd9Sstevel@tonic-gate #include <netinet/in.h>
39*7c478bd9Sstevel@tonic-gate #include <netinet/ip6.h>
40*7c478bd9Sstevel@tonic-gate
41*7c478bd9Sstevel@tonic-gate #include <inet/common.h>
42*7c478bd9Sstevel@tonic-gate #include <inet/mi.h>
43*7c478bd9Sstevel@tonic-gate #include <inet/ip.h>
44*7c478bd9Sstevel@tonic-gate #include <inet/ip6.h>
45*7c478bd9Sstevel@tonic-gate #include <inet/ip_listutils.h>
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate /*
48*7c478bd9Sstevel@tonic-gate * These functions perform set operations on sets of ipv6 addresses.
49*7c478bd9Sstevel@tonic-gate * The sets are formatted as slist_t's (defined in <inet/ip.h>):
50*7c478bd9Sstevel@tonic-gate * typedef struct slist_s {
51*7c478bd9Sstevel@tonic-gate * int sl_nusmrc;
52*7c478bd9Sstevel@tonic-gate * in6_addr_t sl_addr[MAX_FILTER_SIZE];
53*7c478bd9Sstevel@tonic-gate * } slist_t;
54*7c478bd9Sstevel@tonic-gate *
55*7c478bd9Sstevel@tonic-gate * The functions were designed specifically for the implementation of
56*7c478bd9Sstevel@tonic-gate * IGMPv3 and MLDv2 in ip; they were not meant to be general-purpose.
57*7c478bd9Sstevel@tonic-gate */
58*7c478bd9Sstevel@tonic-gate
59*7c478bd9Sstevel@tonic-gate /*
60*7c478bd9Sstevel@tonic-gate * Tells if lists A and B are different or not - true if different;
61*7c478bd9Sstevel@tonic-gate * caller guarantees that lists are <= MAX_FILTER_SIZE
62*7c478bd9Sstevel@tonic-gate */
63*7c478bd9Sstevel@tonic-gate boolean_t
lists_are_different(const slist_t * a,const slist_t * b)64*7c478bd9Sstevel@tonic-gate lists_are_different(const slist_t *a, const slist_t *b)
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate int i, j;
67*7c478bd9Sstevel@tonic-gate int acnt = SLIST_CNT(a);
68*7c478bd9Sstevel@tonic-gate int bcnt = SLIST_CNT(b);
69*7c478bd9Sstevel@tonic-gate boolean_t found;
70*7c478bd9Sstevel@tonic-gate
71*7c478bd9Sstevel@tonic-gate if (acnt != bcnt)
72*7c478bd9Sstevel@tonic-gate return (B_TRUE);
73*7c478bd9Sstevel@tonic-gate
74*7c478bd9Sstevel@tonic-gate ASSERT(acnt <= MAX_FILTER_SIZE);
75*7c478bd9Sstevel@tonic-gate ASSERT(bcnt <= MAX_FILTER_SIZE);
76*7c478bd9Sstevel@tonic-gate
77*7c478bd9Sstevel@tonic-gate for (i = 0; i < acnt; i++) {
78*7c478bd9Sstevel@tonic-gate found = B_FALSE;
79*7c478bd9Sstevel@tonic-gate for (j = 0; j < bcnt; j++) {
80*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
81*7c478bd9Sstevel@tonic-gate &a->sl_addr[i], &b->sl_addr[j])) {
82*7c478bd9Sstevel@tonic-gate found = B_TRUE;
83*7c478bd9Sstevel@tonic-gate break;
84*7c478bd9Sstevel@tonic-gate }
85*7c478bd9Sstevel@tonic-gate }
86*7c478bd9Sstevel@tonic-gate if (!found)
87*7c478bd9Sstevel@tonic-gate return (B_TRUE);
88*7c478bd9Sstevel@tonic-gate }
89*7c478bd9Sstevel@tonic-gate return (B_FALSE);
90*7c478bd9Sstevel@tonic-gate }
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gate /*
93*7c478bd9Sstevel@tonic-gate * Tells if list a contains address addr - true if it does, false if not;
94*7c478bd9Sstevel@tonic-gate * caller guarantees that list is <= MAX_FILTER_SIZE.
95*7c478bd9Sstevel@tonic-gate */
96*7c478bd9Sstevel@tonic-gate boolean_t
list_has_addr(const slist_t * a,const in6_addr_t * addr)97*7c478bd9Sstevel@tonic-gate list_has_addr(const slist_t *a, const in6_addr_t *addr)
98*7c478bd9Sstevel@tonic-gate {
99*7c478bd9Sstevel@tonic-gate int i;
100*7c478bd9Sstevel@tonic-gate
101*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a))
102*7c478bd9Sstevel@tonic-gate return (B_FALSE);
103*7c478bd9Sstevel@tonic-gate
104*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
107*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&a->sl_addr[i], addr))
108*7c478bd9Sstevel@tonic-gate return (B_TRUE);
109*7c478bd9Sstevel@tonic-gate }
110*7c478bd9Sstevel@tonic-gate return (B_FALSE);
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate
113*7c478bd9Sstevel@tonic-gate /*
114*7c478bd9Sstevel@tonic-gate * Implements a * b and stores the result in target; caller guarantees
115*7c478bd9Sstevel@tonic-gate * that a and b are <= MAX_FILTER_SIZE, and that target is a valid pointer.
116*7c478bd9Sstevel@tonic-gate * target must not be the same as a or b; for that case see
117*7c478bd9Sstevel@tonic-gate * l_intersection_in_a().
118*7c478bd9Sstevel@tonic-gate */
119*7c478bd9Sstevel@tonic-gate void
l_intersection(const slist_t * a,const slist_t * b,slist_t * target)120*7c478bd9Sstevel@tonic-gate l_intersection(const slist_t *a, const slist_t *b, slist_t *target)
121*7c478bd9Sstevel@tonic-gate {
122*7c478bd9Sstevel@tonic-gate int i, j;
123*7c478bd9Sstevel@tonic-gate
124*7c478bd9Sstevel@tonic-gate target->sl_numsrc = 0;
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a) || SLIST_IS_EMPTY(b))
127*7c478bd9Sstevel@tonic-gate return;
128*7c478bd9Sstevel@tonic-gate
129*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
130*7c478bd9Sstevel@tonic-gate ASSERT(b->sl_numsrc <= MAX_FILTER_SIZE);
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
133*7c478bd9Sstevel@tonic-gate for (j = 0; j < b->sl_numsrc; j++) {
134*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
135*7c478bd9Sstevel@tonic-gate &a->sl_addr[i], &b->sl_addr[j])) {
136*7c478bd9Sstevel@tonic-gate target->sl_addr[target->sl_numsrc++] =
137*7c478bd9Sstevel@tonic-gate a->sl_addr[i];
138*7c478bd9Sstevel@tonic-gate break;
139*7c478bd9Sstevel@tonic-gate }
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate }
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate * Implements a - b and stores the result in target; caller guarantees
146*7c478bd9Sstevel@tonic-gate * that a and b are <= MAX_FILTER_SIZE, and that target is a valid pointer.
147*7c478bd9Sstevel@tonic-gate * target must not be the same as a or b; for that case see l_difference_in_a().
148*7c478bd9Sstevel@tonic-gate */
149*7c478bd9Sstevel@tonic-gate void
l_difference(const slist_t * a,const slist_t * b,slist_t * target)150*7c478bd9Sstevel@tonic-gate l_difference(const slist_t *a, const slist_t *b, slist_t *target)
151*7c478bd9Sstevel@tonic-gate {
152*7c478bd9Sstevel@tonic-gate int i, j;
153*7c478bd9Sstevel@tonic-gate boolean_t found = B_FALSE;
154*7c478bd9Sstevel@tonic-gate
155*7c478bd9Sstevel@tonic-gate target->sl_numsrc = 0;
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a))
158*7c478bd9Sstevel@tonic-gate return;
159*7c478bd9Sstevel@tonic-gate
160*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(b)) {
161*7c478bd9Sstevel@tonic-gate l_copy(a, target);
162*7c478bd9Sstevel@tonic-gate return;
163*7c478bd9Sstevel@tonic-gate }
164*7c478bd9Sstevel@tonic-gate
165*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
166*7c478bd9Sstevel@tonic-gate ASSERT(b->sl_numsrc <= MAX_FILTER_SIZE);
167*7c478bd9Sstevel@tonic-gate
168*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
169*7c478bd9Sstevel@tonic-gate for (j = 0; j < b->sl_numsrc; j++) {
170*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
171*7c478bd9Sstevel@tonic-gate &a->sl_addr[i], &b->sl_addr[j])) {
172*7c478bd9Sstevel@tonic-gate found = B_TRUE;
173*7c478bd9Sstevel@tonic-gate break;
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate if (!found) {
177*7c478bd9Sstevel@tonic-gate target->sl_addr[target->sl_numsrc++] = a->sl_addr[i];
178*7c478bd9Sstevel@tonic-gate } else {
179*7c478bd9Sstevel@tonic-gate found = B_FALSE;
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate }
183*7c478bd9Sstevel@tonic-gate
184*7c478bd9Sstevel@tonic-gate /*
185*7c478bd9Sstevel@tonic-gate * Removes addr from list a. Caller guarantees that addr is a valid
186*7c478bd9Sstevel@tonic-gate * pointer, and that a <= MAX_FILTER_SIZE. addr will only be removed
187*7c478bd9Sstevel@tonic-gate * once from the list; if it appears in the list multiple times, extra
188*7c478bd9Sstevel@tonic-gate * copies may remain.
189*7c478bd9Sstevel@tonic-gate */
190*7c478bd9Sstevel@tonic-gate void
l_remove(slist_t * a,const in6_addr_t * addr)191*7c478bd9Sstevel@tonic-gate l_remove(slist_t *a, const in6_addr_t *addr)
192*7c478bd9Sstevel@tonic-gate {
193*7c478bd9Sstevel@tonic-gate int i, mvsize;
194*7c478bd9Sstevel@tonic-gate
195*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a))
196*7c478bd9Sstevel@tonic-gate return;
197*7c478bd9Sstevel@tonic-gate
198*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
201*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(&a->sl_addr[i], addr)) {
202*7c478bd9Sstevel@tonic-gate a->sl_numsrc--;
203*7c478bd9Sstevel@tonic-gate mvsize = (a->sl_numsrc - i) * sizeof (in6_addr_t);
204*7c478bd9Sstevel@tonic-gate (void) memmove(&a->sl_addr[i], &a->sl_addr[i + 1],
205*7c478bd9Sstevel@tonic-gate mvsize);
206*7c478bd9Sstevel@tonic-gate break;
207*7c478bd9Sstevel@tonic-gate }
208*7c478bd9Sstevel@tonic-gate }
209*7c478bd9Sstevel@tonic-gate }
210*7c478bd9Sstevel@tonic-gate
211*7c478bd9Sstevel@tonic-gate /*
212*7c478bd9Sstevel@tonic-gate * Make a copy of list a by allocating a new slist_t and copying only
213*7c478bd9Sstevel@tonic-gate * a->sl_numsrc addrs. Caller guarantees that a <= MAX_FILTER_SIZE.
214*7c478bd9Sstevel@tonic-gate * Return a pointer to the newly alloc'd list, or NULL if a is empty
215*7c478bd9Sstevel@tonic-gate * (no memory is alloc'd in this case).
216*7c478bd9Sstevel@tonic-gate */
217*7c478bd9Sstevel@tonic-gate slist_t *
l_alloc_copy(const slist_t * a)218*7c478bd9Sstevel@tonic-gate l_alloc_copy(const slist_t *a)
219*7c478bd9Sstevel@tonic-gate {
220*7c478bd9Sstevel@tonic-gate slist_t *b;
221*7c478bd9Sstevel@tonic-gate
222*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a))
223*7c478bd9Sstevel@tonic-gate return (NULL);
224*7c478bd9Sstevel@tonic-gate
225*7c478bd9Sstevel@tonic-gate if ((b = l_alloc()) == NULL)
226*7c478bd9Sstevel@tonic-gate return (NULL);
227*7c478bd9Sstevel@tonic-gate
228*7c478bd9Sstevel@tonic-gate l_copy(a, b);
229*7c478bd9Sstevel@tonic-gate
230*7c478bd9Sstevel@tonic-gate return (b);
231*7c478bd9Sstevel@tonic-gate }
232*7c478bd9Sstevel@tonic-gate
233*7c478bd9Sstevel@tonic-gate /*
234*7c478bd9Sstevel@tonic-gate * Copy the address list from slist a into slist b, overwriting anything
235*7c478bd9Sstevel@tonic-gate * that might already be in slist b. Assumes that a <= MAX_FILTER_SIZE
236*7c478bd9Sstevel@tonic-gate * and that b points to a properly allocated slist.
237*7c478bd9Sstevel@tonic-gate */
238*7c478bd9Sstevel@tonic-gate void
l_copy(const slist_t * a,slist_t * b)239*7c478bd9Sstevel@tonic-gate l_copy(const slist_t *a, slist_t *b)
240*7c478bd9Sstevel@tonic-gate {
241*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a)) {
242*7c478bd9Sstevel@tonic-gate b->sl_numsrc = 0;
243*7c478bd9Sstevel@tonic-gate return;
244*7c478bd9Sstevel@tonic-gate }
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
247*7c478bd9Sstevel@tonic-gate
248*7c478bd9Sstevel@tonic-gate b->sl_numsrc = a->sl_numsrc;
249*7c478bd9Sstevel@tonic-gate (void) memcpy(b->sl_addr, a->sl_addr,
250*7c478bd9Sstevel@tonic-gate a->sl_numsrc * sizeof (in6_addr_t));
251*7c478bd9Sstevel@tonic-gate }
252*7c478bd9Sstevel@tonic-gate
253*7c478bd9Sstevel@tonic-gate /*
254*7c478bd9Sstevel@tonic-gate * Append to a any addrs in b that are not already in a (i.e. perform
255*7c478bd9Sstevel@tonic-gate * a + b and store the result in a). If b is empty, the function returns
256*7c478bd9Sstevel@tonic-gate * without taking any action.
257*7c478bd9Sstevel@tonic-gate *
258*7c478bd9Sstevel@tonic-gate * Caller guarantees that a and b are <= MAX_FILTER_SIZE, and that a
259*7c478bd9Sstevel@tonic-gate * and overflow are valid pointers.
260*7c478bd9Sstevel@tonic-gate *
261*7c478bd9Sstevel@tonic-gate * If an overflow occurs (a + b > MAX_FILTER_SIZE), a will contain the
262*7c478bd9Sstevel@tonic-gate * first MAX_FILTER_SIZE addresses of the union, and *overflow will be
263*7c478bd9Sstevel@tonic-gate * set to true. Otherwise, *overflow will be set to false.
264*7c478bd9Sstevel@tonic-gate */
265*7c478bd9Sstevel@tonic-gate void
l_union_in_a(slist_t * a,const slist_t * b,boolean_t * overflow)266*7c478bd9Sstevel@tonic-gate l_union_in_a(slist_t *a, const slist_t *b, boolean_t *overflow)
267*7c478bd9Sstevel@tonic-gate {
268*7c478bd9Sstevel@tonic-gate int i, j;
269*7c478bd9Sstevel@tonic-gate boolean_t found;
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate *overflow = B_FALSE;
272*7c478bd9Sstevel@tonic-gate
273*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(b))
274*7c478bd9Sstevel@tonic-gate return;
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
277*7c478bd9Sstevel@tonic-gate ASSERT(b->sl_numsrc <= MAX_FILTER_SIZE);
278*7c478bd9Sstevel@tonic-gate
279*7c478bd9Sstevel@tonic-gate for (i = 0; i < b->sl_numsrc; i++) {
280*7c478bd9Sstevel@tonic-gate found = B_FALSE;
281*7c478bd9Sstevel@tonic-gate for (j = 0; j < a->sl_numsrc; j++) {
282*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
283*7c478bd9Sstevel@tonic-gate &b->sl_addr[i], &a->sl_addr[j])) {
284*7c478bd9Sstevel@tonic-gate found = B_TRUE;
285*7c478bd9Sstevel@tonic-gate break;
286*7c478bd9Sstevel@tonic-gate }
287*7c478bd9Sstevel@tonic-gate }
288*7c478bd9Sstevel@tonic-gate if (!found) {
289*7c478bd9Sstevel@tonic-gate if (a->sl_numsrc == MAX_FILTER_SIZE) {
290*7c478bd9Sstevel@tonic-gate *overflow = B_TRUE;
291*7c478bd9Sstevel@tonic-gate break;
292*7c478bd9Sstevel@tonic-gate } else {
293*7c478bd9Sstevel@tonic-gate a->sl_addr[a->sl_numsrc++] = b->sl_addr[i];
294*7c478bd9Sstevel@tonic-gate }
295*7c478bd9Sstevel@tonic-gate }
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate
299*7c478bd9Sstevel@tonic-gate /*
300*7c478bd9Sstevel@tonic-gate * Remove from list a any addresses that are not also in list b
301*7c478bd9Sstevel@tonic-gate * (i.e. perform a * b and store the result in a).
302*7c478bd9Sstevel@tonic-gate *
303*7c478bd9Sstevel@tonic-gate * Caller guarantees that a and b are <= MAX_FILTER_SIZE, and that
304*7c478bd9Sstevel@tonic-gate * a is a valid pointer.
305*7c478bd9Sstevel@tonic-gate */
306*7c478bd9Sstevel@tonic-gate void
l_intersection_in_a(slist_t * a,const slist_t * b)307*7c478bd9Sstevel@tonic-gate l_intersection_in_a(slist_t *a, const slist_t *b)
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate int i, j, shift;
310*7c478bd9Sstevel@tonic-gate boolean_t found;
311*7c478bd9Sstevel@tonic-gate
312*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(b)) {
313*7c478bd9Sstevel@tonic-gate a->sl_numsrc = 0;
314*7c478bd9Sstevel@tonic-gate return;
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
318*7c478bd9Sstevel@tonic-gate ASSERT(b->sl_numsrc <= MAX_FILTER_SIZE);
319*7c478bd9Sstevel@tonic-gate
320*7c478bd9Sstevel@tonic-gate shift = 0;
321*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
322*7c478bd9Sstevel@tonic-gate found = B_FALSE;
323*7c478bd9Sstevel@tonic-gate for (j = 0; j < b->sl_numsrc; j++) {
324*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
325*7c478bd9Sstevel@tonic-gate &a->sl_addr[i], &b->sl_addr[j])) {
326*7c478bd9Sstevel@tonic-gate found = B_TRUE;
327*7c478bd9Sstevel@tonic-gate break;
328*7c478bd9Sstevel@tonic-gate }
329*7c478bd9Sstevel@tonic-gate }
330*7c478bd9Sstevel@tonic-gate if (!found)
331*7c478bd9Sstevel@tonic-gate shift++;
332*7c478bd9Sstevel@tonic-gate else if (shift > 0)
333*7c478bd9Sstevel@tonic-gate a->sl_addr[i - shift] = a->sl_addr[i];
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate a->sl_numsrc -= shift;
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate /*
339*7c478bd9Sstevel@tonic-gate * Remove from list a any addresses that are in list b (i.e. perform
340*7c478bd9Sstevel@tonic-gate * a - b and store the result in a).
341*7c478bd9Sstevel@tonic-gate *
342*7c478bd9Sstevel@tonic-gate * Caller guarantees that a and b are <= MAX_FILTER_SIZE. If either
343*7c478bd9Sstevel@tonic-gate * list is empty (or a null pointer), the function returns without
344*7c478bd9Sstevel@tonic-gate * taking any action.
345*7c478bd9Sstevel@tonic-gate */
346*7c478bd9Sstevel@tonic-gate void
l_difference_in_a(slist_t * a,const slist_t * b)347*7c478bd9Sstevel@tonic-gate l_difference_in_a(slist_t *a, const slist_t *b)
348*7c478bd9Sstevel@tonic-gate {
349*7c478bd9Sstevel@tonic-gate int i, j, shift;
350*7c478bd9Sstevel@tonic-gate boolean_t found;
351*7c478bd9Sstevel@tonic-gate
352*7c478bd9Sstevel@tonic-gate if (SLIST_IS_EMPTY(a) || SLIST_IS_EMPTY(b))
353*7c478bd9Sstevel@tonic-gate return;
354*7c478bd9Sstevel@tonic-gate
355*7c478bd9Sstevel@tonic-gate ASSERT(a->sl_numsrc <= MAX_FILTER_SIZE);
356*7c478bd9Sstevel@tonic-gate ASSERT(b->sl_numsrc <= MAX_FILTER_SIZE);
357*7c478bd9Sstevel@tonic-gate
358*7c478bd9Sstevel@tonic-gate shift = 0;
359*7c478bd9Sstevel@tonic-gate for (i = 0; i < a->sl_numsrc; i++) {
360*7c478bd9Sstevel@tonic-gate found = B_FALSE;
361*7c478bd9Sstevel@tonic-gate for (j = 0; j < b->sl_numsrc; j++) {
362*7c478bd9Sstevel@tonic-gate if (IN6_ARE_ADDR_EQUAL(
363*7c478bd9Sstevel@tonic-gate &a->sl_addr[i], &b->sl_addr[j])) {
364*7c478bd9Sstevel@tonic-gate found = B_TRUE;
365*7c478bd9Sstevel@tonic-gate break;
366*7c478bd9Sstevel@tonic-gate }
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate if (found)
369*7c478bd9Sstevel@tonic-gate shift++;
370*7c478bd9Sstevel@tonic-gate else if (shift > 0)
371*7c478bd9Sstevel@tonic-gate a->sl_addr[i - shift] = a->sl_addr[i];
372*7c478bd9Sstevel@tonic-gate }
373*7c478bd9Sstevel@tonic-gate a->sl_numsrc -= shift;
374*7c478bd9Sstevel@tonic-gate }
375*7c478bd9Sstevel@tonic-gate
376*7c478bd9Sstevel@tonic-gate /*
377*7c478bd9Sstevel@tonic-gate * Wrapper function to alloc an slist_t.
378*7c478bd9Sstevel@tonic-gate */
379*7c478bd9Sstevel@tonic-gate slist_t *
l_alloc()380*7c478bd9Sstevel@tonic-gate l_alloc()
381*7c478bd9Sstevel@tonic-gate {
382*7c478bd9Sstevel@tonic-gate slist_t *p;
383*7c478bd9Sstevel@tonic-gate
384*7c478bd9Sstevel@tonic-gate p = (slist_t *)mi_alloc(sizeof (slist_t), BPRI_MED);
385*7c478bd9Sstevel@tonic-gate if (p != NULL)
386*7c478bd9Sstevel@tonic-gate p->sl_numsrc = 0;
387*7c478bd9Sstevel@tonic-gate return (p);
388*7c478bd9Sstevel@tonic-gate }
389*7c478bd9Sstevel@tonic-gate
390*7c478bd9Sstevel@tonic-gate /*
391*7c478bd9Sstevel@tonic-gate * Frees an slist_t structure. Provided for symmetry with l_alloc().
392*7c478bd9Sstevel@tonic-gate */
393*7c478bd9Sstevel@tonic-gate void
l_free(slist_t * a)394*7c478bd9Sstevel@tonic-gate l_free(slist_t *a)
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate mi_free(a);
397*7c478bd9Sstevel@tonic-gate }
398