1 /* 2 * Copyright (C) 2002 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * $Id: load_hash.c,v 1.11.2.2 2005/02/01 02:44:05 darrenr Exp $ 7 * 8 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 9 * Use is subject to license terms. 10 * 11 * Copyright (c) 2014, Joyent, Inc. All rights reserved. 12 */ 13 14 #include <fcntl.h> 15 #include <sys/ioctl.h> 16 #include "ipf.h" 17 #include "netinet/ip_lookup.h" 18 #include "netinet/ip_htable.h" 19 #include "ipfzone.h" 20 21 static int hashfd = -1; 22 23 24 int load_hash(iphp, list, iocfunc) 25 iphtable_t *iphp; 26 iphtent_t *list; 27 ioctlfunc_t iocfunc; 28 { 29 iplookupop_t op; 30 iphtable_t iph; 31 iphtent_t *a; 32 size_t size; 33 int n; 34 35 if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) 36 hashfd = open(IPLOOKUP_NAME, O_RDWR); 37 if ((hashfd == -1) && ((opts & OPT_DONOTHING) == 0)) 38 return -1; 39 if (setzone(hashfd) != 0) { 40 close(hashfd); 41 return -1; 42 } 43 44 for (n = 0, a = list; a != NULL; a = a->ipe_next) 45 n++; 46 47 op.iplo_arg = 0; 48 op.iplo_type = IPLT_HASH; 49 op.iplo_unit = iphp->iph_unit; 50 strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name)); 51 if (*op.iplo_name == '\0') 52 op.iplo_arg = IPHASH_ANON; 53 op.iplo_size = sizeof(iph); 54 op.iplo_struct = &iph; 55 iph.iph_unit = iphp->iph_unit; 56 iph.iph_type = iphp->iph_type; 57 strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); 58 iph.iph_flags = iphp->iph_flags; 59 if (n <= 0) 60 n = 1; 61 if (iphp->iph_size == 0) 62 size = n * 2 - 1; 63 else 64 size = iphp->iph_size; 65 if ((list == NULL) && (size == 1)) { 66 fprintf(stderr, 67 "WARNING: empty hash table %s, recommend setting %s\n", 68 iphp->iph_name, "size to match expected use"); 69 } 70 iph.iph_size = size; 71 iph.iph_seed = iphp->iph_seed; 72 iph.iph_table = NULL; 73 iph.iph_ref = 0; 74 75 if ((opts & OPT_REMOVE) == 0) { 76 if ((*iocfunc)(hashfd, SIOCLOOKUPADDTABLE, &op)) 77 if ((opts & OPT_DONOTHING) == 0) { 78 perror("load_hash:SIOCLOOKUPADDTABLE"); 79 return -1; 80 } 81 } 82 83 strncpy(op.iplo_name, iph.iph_name, sizeof(op.iplo_name)); 84 strncpy(iphp->iph_name, iph.iph_name, sizeof(op.iplo_name)); 85 86 if (opts & OPT_VERBOSE) { 87 for (a = list; a != NULL; a = a->ipe_next) { 88 if (a->ipe_family == AF_INET) { 89 a->ipe_addr.in4_addr = ntohl(a->ipe_addr.in4_addr); 90 a->ipe_mask.in4_addr = ntohl(a->ipe_mask.in4_addr); 91 } 92 } 93 iph.iph_table = calloc(size, sizeof(*iph.iph_table)); 94 if (iph.iph_table == NULL) { 95 perror("calloc(size, sizeof(*iph.iph_table))"); 96 return -1; 97 } 98 iph.iph_table[0] = list; 99 printhash(&iph, bcopywrap, iph.iph_name, opts); 100 free(iph.iph_table); 101 102 for (a = list; a != NULL; a = a->ipe_next) { 103 if (a->ipe_family == AF_INET) { 104 a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr); 105 a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr); 106 } 107 } 108 } 109 110 if (opts & OPT_DEBUG) 111 printf("Hash %s:\n", iph.iph_name); 112 113 for (a = list; a != NULL; a = a->ipe_next) 114 load_hashnode(iphp->iph_unit, iph.iph_name, a, iocfunc); 115 116 if ((opts & OPT_REMOVE) != 0) { 117 if ((*iocfunc)(hashfd, SIOCLOOKUPDELTABLE, &op)) 118 if ((opts & OPT_DONOTHING) == 0) { 119 perror("load_hash:SIOCLOOKUPDELTABLE"); 120 return -1; 121 } 122 } 123 return 0; 124 } 125