xref: /freebsd/sbin/ipf/libipf/load_hash.c (revision d4eeb02986980bf33dd56c41ceb9fc5f180c0d47)
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(iphtable_t *iphp, iphtent_t *list, ioctlfunc_t iocfunc)
20 {
21 	iplookupop_t op;
22 	iphtable_t iph;
23 	iphtent_t *a;
24 	size_t size;
25 	int n;
26 
27 	if (pool_open() == -1)
28 		return (-1);
29 
30 	for (n = 0, a = list; a != NULL; a = a->ipe_next)
31 		n++;
32 
33 	bzero((char *)&iph, sizeof(iph));
34 	op.iplo_arg = 0;
35 	op.iplo_type = IPLT_HASH;
36 	op.iplo_unit = iphp->iph_unit;
37 	strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name));
38 	if (*op.iplo_name == '\0')
39 		op.iplo_arg = IPHASH_ANON;
40 	op.iplo_size = sizeof(iph);
41 	op.iplo_struct = &iph;
42 	iph = *iphp;
43 	if (n <= 0)
44 		n = 1;
45 	if (iphp->iph_size == 0)
46 		size = n * 2 - 1;
47 	else
48 		size = iphp->iph_size;
49 	if ((list == NULL) && (size == 1)) {
50 		fprintf(stderr,
51 			"WARNING: empty hash table %s, recommend setting %s\n",
52 			iphp->iph_name, "size to match expected use");
53 	}
54 	iph.iph_size = size;
55 	iph.iph_table = NULL;
56 	iph.iph_list = NULL;
57 	iph.iph_ref = 0;
58 
59 	if ((opts & OPT_REMOVE) == 0) {
60 		if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op))
61 			if ((opts & OPT_DONOTHING) == 0) {
62 				return (ipf_perror_fd(pool_fd(), iocfunc,
63 					"add lookup hash table"));
64 			}
65 	}
66 
67 	strncpy(iph.iph_name, op.iplo_name, sizeof(op.iplo_name));
68 	strncpy(iphp->iph_name, op.iplo_name, sizeof(op.iplo_name));
69 
70 	if (opts & OPT_VERBOSE) {
71 		iph.iph_table = calloc(size, sizeof(*iph.iph_table));
72 		if (iph.iph_table == NULL) {
73 			perror("calloc(size, sizeof(*iph.iph_table))");
74 			return (-1);
75 		}
76 		iph.iph_list = list;
77 		printhash(&iph, bcopywrap, iph.iph_name, opts, NULL);
78 		free(iph.iph_table);
79 
80 		for (a = list; a != NULL; a = a->ipe_next) {
81 			a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr);
82 			a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr);
83 		}
84 	}
85 
86 	if (opts & OPT_DEBUG)
87 		printf("Hash %s:\n", iph.iph_name);
88 
89 	for (a = list; a != NULL; a = a->ipe_next)
90 		load_hashnode(iphp->iph_unit, iph.iph_name, a, 0, iocfunc);
91 
92 	if ((opts & OPT_REMOVE) != 0) {
93 		if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op))
94 			if ((opts & OPT_DONOTHING) == 0) {
95 				return (ipf_perror_fd(pool_fd(), iocfunc,
96 					"delete lookup hash table"));
97 			}
98 	}
99 	return (0);
100 }
101