xref: /freebsd/sbin/ipf/libipf/load_hash.c (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
1 /*	$FreeBSD$	*/
2 
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * $Id$
9  */
10 
11 #include <fcntl.h>
12 #include <sys/ioctl.h>
13 #include "ipf.h"
14 #include "netinet/ip_lookup.h"
15 #include "netinet/ip_htable.h"
16 
17 
18 int
19 load_hash(iphp, list, iocfunc)
20 	iphtable_t *iphp;
21 	iphtent_t *list;
22 	ioctlfunc_t iocfunc;
23 {
24 	iplookupop_t op;
25 	iphtable_t iph;
26 	iphtent_t *a;
27 	size_t size;
28 	int n;
29 
30 	if (pool_open() == -1)
31 		return -1;
32 
33 	for (n = 0, a = list; a != NULL; a = a->ipe_next)
34 		n++;
35 
36 	bzero((char *)&iph, sizeof(iph));
37 	op.iplo_arg = 0;
38 	op.iplo_type = IPLT_HASH;
39 	op.iplo_unit = iphp->iph_unit;
40 	strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name));
41 	if (*op.iplo_name == '\0')
42 		op.iplo_arg = IPHASH_ANON;
43 	op.iplo_size = sizeof(iph);
44 	op.iplo_struct = &iph;
45 	iph = *iphp;
46 	if (n <= 0)
47 		n = 1;
48 	if (iphp->iph_size == 0)
49 		size = n * 2 - 1;
50 	else
51 		size = iphp->iph_size;
52 	if ((list == NULL) && (size == 1)) {
53 		fprintf(stderr,
54 			"WARNING: empty hash table %s, recommend setting %s\n",
55 			iphp->iph_name, "size to match expected use");
56 	}
57 	iph.iph_size = size;
58 	iph.iph_table = NULL;
59 	iph.iph_list = NULL;
60 	iph.iph_ref = 0;
61 
62 	if ((opts & OPT_REMOVE) == 0) {
63 		if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op))
64 			if ((opts & OPT_DONOTHING) == 0) {
65 				return ipf_perror_fd(pool_fd(), iocfunc,
66 					"add lookup hash table");
67 			}
68 	}
69 
70 	strncpy(iph.iph_name, op.iplo_name, sizeof(op.iplo_name));
71 	strncpy(iphp->iph_name, op.iplo_name, sizeof(op.iplo_name));
72 
73 	if (opts & OPT_VERBOSE) {
74 		iph.iph_table = calloc(size, sizeof(*iph.iph_table));
75 		if (iph.iph_table == NULL) {
76 			perror("calloc(size, sizeof(*iph.iph_table))");
77 			return -1;
78 		}
79 		iph.iph_list = list;
80 		printhash(&iph, bcopywrap, iph.iph_name, opts, NULL);
81 		free(iph.iph_table);
82 
83 		for (a = list; a != NULL; a = a->ipe_next) {
84 			a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr);
85 			a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr);
86 		}
87 	}
88 
89 	if (opts & OPT_DEBUG)
90 		printf("Hash %s:\n", iph.iph_name);
91 
92 	for (a = list; a != NULL; a = a->ipe_next)
93 		load_hashnode(iphp->iph_unit, iph.iph_name, a, 0, iocfunc);
94 
95 	if ((opts & OPT_REMOVE) != 0) {
96 		if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op))
97 			if ((opts & OPT_DONOTHING) == 0) {
98 				return ipf_perror_fd(pool_fd(), iocfunc,
99 					"delete lookup hash table");
100 			}
101 	}
102 	return 0;
103 }
104