1*2393Syz155240 /* 2*2393Syz155240 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3*2393Syz155240 * 4*2393Syz155240 * See the IPFILTER.LICENCE file for details on licencing. 5*2393Syz155240 * 6*2393Syz155240 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 7*2393Syz155240 * Use is subject to license terms. 8*2393Syz155240 */ 9*2393Syz155240 10*2393Syz155240 #pragma ident "%Z%%M% %I% %E% SMI" 11*2393Syz155240 12*2393Syz155240 #if defined(KERNEL) || defined(_KERNEL) 13*2393Syz155240 # undef KERNEL 14*2393Syz155240 # undef _KERNEL 15*2393Syz155240 # define KERNEL 1 16*2393Syz155240 # define _KERNEL 1 17*2393Syz155240 #endif 18*2393Syz155240 #include <sys/param.h> 19*2393Syz155240 #include <sys/types.h> 20*2393Syz155240 #include <sys/errno.h> 21*2393Syz155240 #include <sys/time.h> 22*2393Syz155240 #include <sys/file.h> 23*2393Syz155240 #if !defined(_KERNEL) 24*2393Syz155240 # include <stdlib.h> 25*2393Syz155240 # include <string.h> 26*2393Syz155240 # define _KERNEL 27*2393Syz155240 # ifdef __OpenBSD__ 28*2393Syz155240 struct file; 29*2393Syz155240 # endif 30*2393Syz155240 # include <sys/uio.h> 31*2393Syz155240 # undef _KERNEL 32*2393Syz155240 #endif 33*2393Syz155240 #include <sys/socket.h> 34*2393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 35*2393Syz155240 # include <sys/malloc.h> 36*2393Syz155240 #endif 37*2393Syz155240 #if defined(__FreeBSD__) 38*2393Syz155240 # include <sys/cdefs.h> 39*2393Syz155240 # include <sys/proc.h> 40*2393Syz155240 #endif 41*2393Syz155240 #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \ 42*2393Syz155240 !defined(linux) 43*2393Syz155240 # include <sys/mbuf.h> 44*2393Syz155240 #endif 45*2393Syz155240 #if defined(_KERNEL) 46*2393Syz155240 # include <sys/systm.h> 47*2393Syz155240 #else 48*2393Syz155240 # include <stdio.h> 49*2393Syz155240 #endif 50*2393Syz155240 #include <netinet/in.h> 51*2393Syz155240 #include <net/if.h> 52*2393Syz155240 53*2393Syz155240 #include "netinet/ip_compat.h" 54*2393Syz155240 #include "netinet/ip_fil.h" 55*2393Syz155240 #include "netinet/ip_lookup.h" 56*2393Syz155240 #include "netinet/ip_htable.h" 57*2393Syz155240 /* END OF INCLUDES */ 58*2393Syz155240 59*2393Syz155240 #if !defined(lint) 60*2393Syz155240 static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $"; 61*2393Syz155240 #endif 62*2393Syz155240 63*2393Syz155240 #ifdef IPFILTER_LOOKUP 64*2393Syz155240 static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *)); 65*2393Syz155240 #ifdef USE_INET6 66*2393Syz155240 static iphtent_t *fr_iphmfind6 __P((iphtable_t *, struct in6_addr *)); 67*2393Syz155240 static uint32_t sum4(uint32_t *); 68*2393Syz155240 static void left_shift_ipv6 __P((char *)); 69*2393Syz155240 #endif 70*2393Syz155240 71*2393Syz155240 static u_long ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 72*2393Syz155240 static u_long ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 73*2393Syz155240 static u_long ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 74*2393Syz155240 75*2393Syz155240 iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL, 76*2393Syz155240 NULL, NULL, NULL, NULL }; 77*2393Syz155240 78*2393Syz155240 79*2393Syz155240 void fr_htable_unload() 80*2393Syz155240 { 81*2393Syz155240 iplookupflush_t fop; 82*2393Syz155240 83*2393Syz155240 fop.iplf_unit = IPL_LOGALL; 84*2393Syz155240 (void)fr_flushhtable(&fop); 85*2393Syz155240 } 86*2393Syz155240 87*2393Syz155240 88*2393Syz155240 int fr_gethtablestat(op) 89*2393Syz155240 iplookupop_t *op; 90*2393Syz155240 { 91*2393Syz155240 iphtstat_t stats; 92*2393Syz155240 93*2393Syz155240 if (op->iplo_size != sizeof(stats)) 94*2393Syz155240 return EINVAL; 95*2393Syz155240 96*2393Syz155240 stats.iphs_tables = ipf_htables[op->iplo_unit]; 97*2393Syz155240 stats.iphs_numtables = ipf_nhtables[op->iplo_unit]; 98*2393Syz155240 stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit]; 99*2393Syz155240 stats.iphs_nomem = ipht_nomem[op->iplo_unit]; 100*2393Syz155240 101*2393Syz155240 return COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 102*2393Syz155240 103*2393Syz155240 } 104*2393Syz155240 105*2393Syz155240 106*2393Syz155240 /* 107*2393Syz155240 * Create a new hash table using the template passed. 108*2393Syz155240 */ 109*2393Syz155240 int fr_newhtable(op) 110*2393Syz155240 iplookupop_t *op; 111*2393Syz155240 { 112*2393Syz155240 iphtable_t *iph, *oiph; 113*2393Syz155240 char name[FR_GROUPLEN]; 114*2393Syz155240 int err, i, unit; 115*2393Syz155240 116*2393Syz155240 KMALLOC(iph, iphtable_t *); 117*2393Syz155240 if (iph == NULL) { 118*2393Syz155240 ipht_nomem[op->iplo_unit]++; 119*2393Syz155240 return ENOMEM; 120*2393Syz155240 } 121*2393Syz155240 122*2393Syz155240 err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); 123*2393Syz155240 if (err != 0) { 124*2393Syz155240 KFREE(iph); 125*2393Syz155240 return EFAULT; 126*2393Syz155240 } 127*2393Syz155240 128*2393Syz155240 unit = op->iplo_unit; 129*2393Syz155240 if (iph->iph_unit != unit) { 130*2393Syz155240 KFREE(iph); 131*2393Syz155240 return EINVAL; 132*2393Syz155240 } 133*2393Syz155240 134*2393Syz155240 if ((op->iplo_arg & IPHASH_ANON) == 0) { 135*2393Syz155240 if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) { 136*2393Syz155240 KFREE(iph); 137*2393Syz155240 return EEXIST; 138*2393Syz155240 } 139*2393Syz155240 } else { 140*2393Syz155240 i = IPHASH_ANON; 141*2393Syz155240 do { 142*2393Syz155240 i++; 143*2393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL) 144*2393Syz155240 (void)SNPRINTF(name, sizeof(name), "%u", i); 145*2393Syz155240 #else 146*2393Syz155240 (void)sprintf(name, "%u", i); 147*2393Syz155240 #endif 148*2393Syz155240 for (oiph = ipf_htables[unit]; oiph != NULL; 149*2393Syz155240 oiph = oiph->iph_next) 150*2393Syz155240 if (strncmp(oiph->iph_name, name, 151*2393Syz155240 sizeof(oiph->iph_name)) == 0) 152*2393Syz155240 break; 153*2393Syz155240 } while (oiph != NULL); 154*2393Syz155240 (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name)); 155*2393Syz155240 err = COPYOUT(iph, op->iplo_struct, sizeof(*iph)); 156*2393Syz155240 if (err != 0) { 157*2393Syz155240 KFREE(iph); 158*2393Syz155240 return EFAULT; 159*2393Syz155240 } 160*2393Syz155240 iph->iph_type |= IPHASH_ANON; 161*2393Syz155240 } 162*2393Syz155240 163*2393Syz155240 KMALLOCS(iph->iph_table, iphtent_t **, 164*2393Syz155240 iph->iph_size * sizeof(*iph->iph_table)); 165*2393Syz155240 if (iph->iph_table == NULL) { 166*2393Syz155240 KFREE(iph); 167*2393Syz155240 ipht_nomem[unit]++; 168*2393Syz155240 return ENOMEM; 169*2393Syz155240 } 170*2393Syz155240 171*2393Syz155240 bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 172*2393Syz155240 iph->iph_masks[0] = 0; 173*2393Syz155240 iph->iph_masks[1] = 0; 174*2393Syz155240 iph->iph_masks[2] = 0; 175*2393Syz155240 iph->iph_masks[3] = 0; 176*2393Syz155240 177*2393Syz155240 iph->iph_next = ipf_htables[unit]; 178*2393Syz155240 iph->iph_pnext = &ipf_htables[unit]; 179*2393Syz155240 if (ipf_htables[unit] != NULL) 180*2393Syz155240 ipf_htables[unit]->iph_pnext = &iph->iph_next; 181*2393Syz155240 ipf_htables[unit] = iph; 182*2393Syz155240 183*2393Syz155240 ipf_nhtables[unit]++; 184*2393Syz155240 185*2393Syz155240 return 0; 186*2393Syz155240 } 187*2393Syz155240 188*2393Syz155240 189*2393Syz155240 /* 190*2393Syz155240 */ 191*2393Syz155240 int fr_removehtable(op) 192*2393Syz155240 iplookupop_t *op; 193*2393Syz155240 { 194*2393Syz155240 iphtable_t *iph; 195*2393Syz155240 196*2393Syz155240 197*2393Syz155240 iph = fr_findhtable(op->iplo_unit, op->iplo_name); 198*2393Syz155240 if (iph == NULL) 199*2393Syz155240 return ESRCH; 200*2393Syz155240 201*2393Syz155240 if (iph->iph_unit != op->iplo_unit) { 202*2393Syz155240 return EINVAL; 203*2393Syz155240 } 204*2393Syz155240 205*2393Syz155240 if (iph->iph_ref != 0) { 206*2393Syz155240 return EBUSY; 207*2393Syz155240 } 208*2393Syz155240 209*2393Syz155240 fr_delhtable(iph); 210*2393Syz155240 211*2393Syz155240 return 0; 212*2393Syz155240 } 213*2393Syz155240 214*2393Syz155240 215*2393Syz155240 void fr_delhtable(iph) 216*2393Syz155240 iphtable_t *iph; 217*2393Syz155240 { 218*2393Syz155240 iphtent_t *ipe; 219*2393Syz155240 int i; 220*2393Syz155240 221*2393Syz155240 for (i = 0; i < iph->iph_size; i++) 222*2393Syz155240 while ((ipe = iph->iph_table[i]) != NULL) 223*2393Syz155240 if (fr_delhtent(iph, ipe) != 0) 224*2393Syz155240 return; 225*2393Syz155240 226*2393Syz155240 *iph->iph_pnext = iph->iph_next; 227*2393Syz155240 if (iph->iph_next != NULL) 228*2393Syz155240 iph->iph_next->iph_pnext = iph->iph_pnext; 229*2393Syz155240 230*2393Syz155240 ipf_nhtables[iph->iph_unit]--; 231*2393Syz155240 232*2393Syz155240 if (iph->iph_ref == 0) { 233*2393Syz155240 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 234*2393Syz155240 KFREE(iph); 235*2393Syz155240 } 236*2393Syz155240 } 237*2393Syz155240 238*2393Syz155240 239*2393Syz155240 void fr_derefhtable(iph) 240*2393Syz155240 iphtable_t *iph; 241*2393Syz155240 { 242*2393Syz155240 iph->iph_ref--; 243*2393Syz155240 if (iph->iph_ref == 0) 244*2393Syz155240 fr_delhtable(iph); 245*2393Syz155240 } 246*2393Syz155240 247*2393Syz155240 248*2393Syz155240 iphtable_t *fr_findhtable(unit, name) 249*2393Syz155240 int unit; 250*2393Syz155240 char *name; 251*2393Syz155240 { 252*2393Syz155240 iphtable_t *iph; 253*2393Syz155240 254*2393Syz155240 for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next) 255*2393Syz155240 if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0) 256*2393Syz155240 break; 257*2393Syz155240 return iph; 258*2393Syz155240 } 259*2393Syz155240 260*2393Syz155240 261*2393Syz155240 size_t fr_flushhtable(op) 262*2393Syz155240 iplookupflush_t *op; 263*2393Syz155240 { 264*2393Syz155240 iphtable_t *iph; 265*2393Syz155240 size_t freed; 266*2393Syz155240 int i; 267*2393Syz155240 268*2393Syz155240 freed = 0; 269*2393Syz155240 270*2393Syz155240 for (i = 0; i <= IPL_LOGMAX; i++) { 271*2393Syz155240 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { 272*2393Syz155240 while ((iph = ipf_htables[i]) != NULL) { 273*2393Syz155240 fr_delhtable(iph); 274*2393Syz155240 freed++; 275*2393Syz155240 } 276*2393Syz155240 } 277*2393Syz155240 } 278*2393Syz155240 279*2393Syz155240 return freed; 280*2393Syz155240 } 281*2393Syz155240 282*2393Syz155240 283*2393Syz155240 /* 284*2393Syz155240 * Add an entry to a hash table. 285*2393Syz155240 */ 286*2393Syz155240 int fr_addhtent(iph, ipeo) 287*2393Syz155240 iphtable_t *iph; 288*2393Syz155240 iphtent_t *ipeo; 289*2393Syz155240 { 290*2393Syz155240 iphtent_t *ipe; 291*2393Syz155240 u_int hv; 292*2393Syz155240 int bits; 293*2393Syz155240 294*2393Syz155240 KMALLOC(ipe, iphtent_t *); 295*2393Syz155240 if (ipe == NULL) 296*2393Syz155240 return -1; 297*2393Syz155240 298*2393Syz155240 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe)); 299*2393Syz155240 #ifdef USE_INET6 300*2393Syz155240 if (ipe->ipe_family == AF_INET6) { 301*2393Syz155240 bits = count6bits((u_32_t *)ipe->ipe_mask.in6_addr8); 302*2393Syz155240 hv = IPE_HASH_FN(sum4((uint32_t *)ipe->ipe_addr.in6_addr8), 303*2393Syz155240 sum4((uint32_t *)ipe->ipe_mask.in6_addr8), 304*2393Syz155240 iph->iph_size); 305*2393Syz155240 } else 306*2393Syz155240 #endif 307*2393Syz155240 if (ipe->ipe_family == AF_INET) 308*2393Syz155240 { 309*2393Syz155240 ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr; 310*2393Syz155240 ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr); 311*2393Syz155240 bits = count4bits(ipe->ipe_mask.in4_addr); 312*2393Syz155240 ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr); 313*2393Syz155240 314*2393Syz155240 hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr, 315*2393Syz155240 iph->iph_size); 316*2393Syz155240 } else 317*2393Syz155240 return -1; 318*2393Syz155240 319*2393Syz155240 ipe->ipe_ref = 0; 320*2393Syz155240 ipe->ipe_next = iph->iph_table[hv]; 321*2393Syz155240 ipe->ipe_pnext = iph->iph_table + hv; 322*2393Syz155240 323*2393Syz155240 if (iph->iph_table[hv] != NULL) 324*2393Syz155240 iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next; 325*2393Syz155240 iph->iph_table[hv] = ipe; 326*2393Syz155240 #ifdef USE_INET6 327*2393Syz155240 if (ipe->ipe_family == AF_INET6) { 328*2393Syz155240 if ((bits >= 0) && (bits != 128)) 329*2393Syz155240 if (bits >= 96) 330*2393Syz155240 iph->iph_masks[0] |= 1 << (bits - 96); 331*2393Syz155240 else if (bits >= 64) 332*2393Syz155240 iph->iph_masks[1] |= 1 << (bits - 64); 333*2393Syz155240 else if (bits >= 32) 334*2393Syz155240 iph->iph_masks[2] |= 1 << (bits - 32); 335*2393Syz155240 else 336*2393Syz155240 iph->iph_masks[3] |= 1 << bits; 337*2393Syz155240 338*2393Syz155240 } else 339*2393Syz155240 #endif 340*2393Syz155240 { 341*2393Syz155240 if ((bits >= 0) && (bits != 32)) 342*2393Syz155240 iph->iph_masks[3] |= 1 << bits; 343*2393Syz155240 } 344*2393Syz155240 345*2393Syz155240 switch (iph->iph_type & ~IPHASH_ANON) 346*2393Syz155240 { 347*2393Syz155240 case IPHASH_GROUPMAP : 348*2393Syz155240 ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL, 349*2393Syz155240 iph->iph_flags, IPL_LOGIPF, 350*2393Syz155240 fr_active); 351*2393Syz155240 break; 352*2393Syz155240 353*2393Syz155240 default : 354*2393Syz155240 ipe->ipe_ptr = NULL; 355*2393Syz155240 ipe->ipe_value = 0; 356*2393Syz155240 break; 357*2393Syz155240 } 358*2393Syz155240 359*2393Syz155240 ipf_nhtnodes[iph->iph_unit]++; 360*2393Syz155240 361*2393Syz155240 return 0; 362*2393Syz155240 } 363*2393Syz155240 364*2393Syz155240 365*2393Syz155240 /* 366*2393Syz155240 * Delete an entry from a hash table. 367*2393Syz155240 */ 368*2393Syz155240 int fr_delhtent(iph, ipe) 369*2393Syz155240 iphtable_t *iph; 370*2393Syz155240 iphtent_t *ipe; 371*2393Syz155240 { 372*2393Syz155240 373*2393Syz155240 if (ipe->ipe_ref != 0) 374*2393Syz155240 return EBUSY; 375*2393Syz155240 376*2393Syz155240 377*2393Syz155240 *ipe->ipe_pnext = ipe->ipe_next; 378*2393Syz155240 if (ipe->ipe_next != NULL) 379*2393Syz155240 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; 380*2393Syz155240 381*2393Syz155240 switch (iph->iph_type & ~IPHASH_ANON) 382*2393Syz155240 { 383*2393Syz155240 case IPHASH_GROUPMAP : 384*2393Syz155240 if (ipe->ipe_group != NULL) 385*2393Syz155240 fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active); 386*2393Syz155240 break; 387*2393Syz155240 388*2393Syz155240 default : 389*2393Syz155240 ipe->ipe_ptr = NULL; 390*2393Syz155240 ipe->ipe_value = 0; 391*2393Syz155240 break; 392*2393Syz155240 } 393*2393Syz155240 394*2393Syz155240 KFREE(ipe); 395*2393Syz155240 396*2393Syz155240 ipf_nhtnodes[iph->iph_unit]--; 397*2393Syz155240 398*2393Syz155240 return 0; 399*2393Syz155240 } 400*2393Syz155240 401*2393Syz155240 402*2393Syz155240 void *fr_iphmfindgroup(tptr, version, aptr) 403*2393Syz155240 void *tptr; 404*2393Syz155240 int version; 405*2393Syz155240 void *aptr; 406*2393Syz155240 { 407*2393Syz155240 i6addr_t *addr; 408*2393Syz155240 iphtable_t *iph; 409*2393Syz155240 iphtent_t *ipe; 410*2393Syz155240 void *rval; 411*2393Syz155240 412*2393Syz155240 if ((version != 4) 413*2393Syz155240 #ifdef USE_INET6 414*2393Syz155240 && (version != 6) 415*2393Syz155240 #endif 416*2393Syz155240 ) 417*2393Syz155240 return NULL; 418*2393Syz155240 419*2393Syz155240 READ_ENTER(&ip_poolrw); 420*2393Syz155240 iph = tptr; 421*2393Syz155240 addr = aptr; 422*2393Syz155240 423*2393Syz155240 #ifdef USE_INET6 424*2393Syz155240 if (version == 6) 425*2393Syz155240 ipe = fr_iphmfind6(iph, &addr->in6); 426*2393Syz155240 else 427*2393Syz155240 #endif 428*2393Syz155240 if (version == 4) 429*2393Syz155240 ipe = fr_iphmfind(iph, &addr->in4); 430*2393Syz155240 else 431*2393Syz155240 ipe = NULL; 432*2393Syz155240 if (ipe != NULL) 433*2393Syz155240 rval = ipe->ipe_ptr; 434*2393Syz155240 else 435*2393Syz155240 rval = NULL; 436*2393Syz155240 RWLOCK_EXIT(&ip_poolrw); 437*2393Syz155240 return rval; 438*2393Syz155240 } 439*2393Syz155240 440*2393Syz155240 441*2393Syz155240 /* ------------------------------------------------------------------------ */ 442*2393Syz155240 /* Function: fr_iphmfindip */ 443*2393Syz155240 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 444*2393Syz155240 /* Parameters: tptr(I) - pointer to the pool to search */ 445*2393Syz155240 /* version(I) - IP protocol version (4 or 6) */ 446*2393Syz155240 /* aptr(I) - pointer to address information */ 447*2393Syz155240 /* */ 448*2393Syz155240 /* Search the hash table for a given address and return a search result. */ 449*2393Syz155240 /* ------------------------------------------------------------------------ */ 450*2393Syz155240 int fr_iphmfindip(tptr, version, aptr) 451*2393Syz155240 void *tptr, *aptr; 452*2393Syz155240 int version; 453*2393Syz155240 { 454*2393Syz155240 i6addr_t *addr; 455*2393Syz155240 iphtable_t *iph; 456*2393Syz155240 iphtent_t *ipe; 457*2393Syz155240 int rval; 458*2393Syz155240 459*2393Syz155240 if ((version != 4) 460*2393Syz155240 #ifdef USE_INET6 461*2393Syz155240 && (version != 6) 462*2393Syz155240 #endif 463*2393Syz155240 ) 464*2393Syz155240 return -1; 465*2393Syz155240 466*2393Syz155240 if (tptr == NULL || aptr == NULL) 467*2393Syz155240 return -1; 468*2393Syz155240 469*2393Syz155240 iph = tptr; 470*2393Syz155240 addr = aptr; 471*2393Syz155240 472*2393Syz155240 READ_ENTER(&ip_poolrw); 473*2393Syz155240 #ifdef USE_INET6 474*2393Syz155240 if (version == 6) 475*2393Syz155240 ipe = fr_iphmfind6(iph, &addr->in6); 476*2393Syz155240 else 477*2393Syz155240 #endif 478*2393Syz155240 if (version == 4) 479*2393Syz155240 ipe = fr_iphmfind(iph, &addr->in4); 480*2393Syz155240 else 481*2393Syz155240 ipe = NULL; 482*2393Syz155240 if (ipe != NULL) 483*2393Syz155240 rval = 0; 484*2393Syz155240 else 485*2393Syz155240 rval = 1; 486*2393Syz155240 RWLOCK_EXIT(&ip_poolrw); 487*2393Syz155240 return rval; 488*2393Syz155240 } 489*2393Syz155240 490*2393Syz155240 491*2393Syz155240 /* Locks: ip_poolrw */ 492*2393Syz155240 static iphtent_t *fr_iphmfind(iph, addr) 493*2393Syz155240 iphtable_t *iph; 494*2393Syz155240 struct in_addr *addr; 495*2393Syz155240 { 496*2393Syz155240 u_32_t hmsk, msk, ips; 497*2393Syz155240 iphtent_t *ipe; 498*2393Syz155240 u_int hv; 499*2393Syz155240 500*2393Syz155240 hmsk = iph->iph_masks[3]; 501*2393Syz155240 msk = 0xffffffff; 502*2393Syz155240 maskloop: 503*2393Syz155240 ips = ntohl(addr->s_addr) & msk; 504*2393Syz155240 hv = IPE_HASH_FN(ips, msk, iph->iph_size); 505*2393Syz155240 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 506*2393Syz155240 if (ipe->ipe_mask.in4_addr != msk || 507*2393Syz155240 ipe->ipe_addr.in4_addr != ips) { 508*2393Syz155240 continue; 509*2393Syz155240 } 510*2393Syz155240 break; 511*2393Syz155240 } 512*2393Syz155240 513*2393Syz155240 if ((ipe == NULL) && (hmsk != 0)) { 514*2393Syz155240 while (hmsk != 0) { 515*2393Syz155240 msk <<= 1; 516*2393Syz155240 if (hmsk & 0x80000000) 517*2393Syz155240 break; 518*2393Syz155240 hmsk <<= 1; 519*2393Syz155240 } 520*2393Syz155240 if (hmsk != 0) { 521*2393Syz155240 hmsk <<= 1; 522*2393Syz155240 goto maskloop; 523*2393Syz155240 } 524*2393Syz155240 } 525*2393Syz155240 return ipe; 526*2393Syz155240 } 527*2393Syz155240 528*2393Syz155240 529*2393Syz155240 #ifdef USE_INET6 530*2393Syz155240 /* Locks: ip_poolrw */ 531*2393Syz155240 static iphtent_t *fr_iphmfind6(iph, addr) 532*2393Syz155240 iphtable_t *iph; 533*2393Syz155240 struct in6_addr *addr; 534*2393Syz155240 { 535*2393Syz155240 u_32_t hmsk[4], msk[4], ips[4], *and; 536*2393Syz155240 iphtent_t *ipe; 537*2393Syz155240 u_int hv; 538*2393Syz155240 539*2393Syz155240 hmsk[0] = iph->iph_masks[0]; 540*2393Syz155240 hmsk[1] = iph->iph_masks[1]; 541*2393Syz155240 hmsk[2] = iph->iph_masks[2]; 542*2393Syz155240 hmsk[3] = iph->iph_masks[3]; 543*2393Syz155240 544*2393Syz155240 msk[0] = 0xffffffff; 545*2393Syz155240 msk[1] = 0xffffffff; 546*2393Syz155240 msk[2] = 0xffffffff; 547*2393Syz155240 msk[3] = 0xffffffff; 548*2393Syz155240 maskloop: 549*2393Syz155240 and = (u_32_t *)addr->s6_addr; 550*2393Syz155240 ips[0] = *and & msk[0]; 551*2393Syz155240 ips[1] = *(and + 1) & msk[1]; 552*2393Syz155240 ips[2] = *(and + 2) & msk[2]; 553*2393Syz155240 ips[3] = *(and + 3) & msk[3]; 554*2393Syz155240 555*2393Syz155240 hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk), 556*2393Syz155240 iph->iph_size); 557*2393Syz155240 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 558*2393Syz155240 if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) || 559*2393Syz155240 bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16)) 560*2393Syz155240 continue; 561*2393Syz155240 break; 562*2393Syz155240 } 563*2393Syz155240 564*2393Syz155240 if ((ipe == NULL) && ((hmsk[0] != 0) || 565*2393Syz155240 (hmsk[1] != 0) || 566*2393Syz155240 (hmsk[2] != 0) || 567*2393Syz155240 (hmsk[3] != 0) )) { 568*2393Syz155240 while ((hmsk[0] != 0) && (hmsk[1] != 0) && 569*2393Syz155240 (hmsk[2] != 0) && (hmsk[3] != 0)) { 570*2393Syz155240 left_shift_ipv6((char *)msk); 571*2393Syz155240 if (hmsk[0] & 0x80000000) 572*2393Syz155240 break; 573*2393Syz155240 left_shift_ipv6((char *)hmsk); 574*2393Syz155240 } 575*2393Syz155240 if ((hmsk[0] != 0) && (hmsk[1] != 0) && 576*2393Syz155240 (hmsk[2] != 0) && (hmsk[3] != 0)) { 577*2393Syz155240 left_shift_ipv6((char *)hmsk); 578*2393Syz155240 goto maskloop; 579*2393Syz155240 } 580*2393Syz155240 } 581*2393Syz155240 return ipe; 582*2393Syz155240 } 583*2393Syz155240 584*2393Syz155240 585*2393Syz155240 /* 586*2393Syz155240 * sum4: ipv6 add -> 4 bytes values 587*2393Syz155240 */ 588*2393Syz155240 static uint32_t sum4(add) 589*2393Syz155240 uint32_t *add; 590*2393Syz155240 { 591*2393Syz155240 return (*add + *(add + 1) + *(add + 2) + *(add + 3)); 592*2393Syz155240 } 593*2393Syz155240 594*2393Syz155240 /* 595*2393Syz155240 * left shift on 128 bits 596*2393Syz155240 */ 597*2393Syz155240 static void left_shift_ipv6(data) 598*2393Syz155240 char *data; 599*2393Syz155240 { 600*2393Syz155240 u_32_t *sd; 601*2393Syz155240 602*2393Syz155240 sd = (u_32_t *)data; 603*2393Syz155240 sd[0] <<= 1; 604*2393Syz155240 if (sd[1] >= 0x80000000) 605*2393Syz155240 sd[0] += 1; 606*2393Syz155240 607*2393Syz155240 sd[1] <<= 1; 608*2393Syz155240 if (sd[2] >= 0x80000000) 609*2393Syz155240 sd[1] += 1; 610*2393Syz155240 611*2393Syz155240 sd[2] <<= 1; 612*2393Syz155240 if (sd[3] >= 0x80000000) 613*2393Syz155240 sd[2] += 1; 614*2393Syz155240 615*2393Syz155240 sd[3] <<= 1; 616*2393Syz155240 } 617*2393Syz155240 #endif 618*2393Syz155240 #endif /* IPFILTER_LOOKUP */ 619