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