Work on the radix code, added support to compile on OpenWRT,
[ipfw.git] / dummynet / new_glue.c
1 #include "missing.h"
2
3 #define IPFW_INTERNAL
4 #include <netinet/ip_fw.h>
5
6 #include "hashtable.h"
7 #define IPFW_NEWTABLES_MAX      256
8
9 struct t_o {
10         /* Object stored in the hash table */
11         uint32_t addr;
12         uint32_t value;
13         uint8_t mask;
14 };
15
16 MALLOC_DEFINE(M_IPFW_HTBL, "ipfw_tbl", "IpFw tables");
17
18 int add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
19                        uint8_t mlen, uint32_t value);
20 int new_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr);
21 int del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
22                     uint8_t mlen);
23 int new_flush_table(struct ip_fw_chain *ch, uint16_t tbl);
24 int flush_table(struct ip_fw_chain *ch, uint16_t tbl);
25 int lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr, 
26                 uint32_t *val);
27 int new_count_table_entry(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
28 int count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt);
29 int new_dump_table_entry(struct ip_fw_chain *ch, ipfw_table *tbl);
30 int dump_table(struct ip_fw_chain *ch, ipfw_table *tbl);
31 int init_tables(struct ip_fw_chain *ch);
32
33 /* hash and compare functions for 32-bit entries */
34 static uint32_t
35 simple_hash32(const void *key, uint32_t size)
36 {
37         uint32_t ret = *(const uint32_t *)key % size;
38
39         return ret;
40 }
41
42 static int
43 cmp_func32(const void *key1, const void *key2, int sz)
44 {
45         int k1 = *(const int *)key1;
46         int k2 = *(const int *)key2;
47         int ret;
48
49         if (k1 < k2)
50                 ret = -1;
51         else if (k1 > k2)
52                 ret = 1;
53         else
54                 ret = 0;
55
56         return ret;
57 }
58
59 int
60 add_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
61     uint8_t mlen, uint32_t value)
62 {
63         /* TODO:
64          * - Search the correct hash table (tbl - IPFW_TABLES_MAX)
65          * - Search if the entry already exists
66          * - Insert the new entry in the table
67          * - Possibly reallocate the table if it is too small
68          */
69
70         struct t_o obj;
71         int ret;
72         int i = tbl - IPFW_TABLES_MAX;
73         int size = 128;
74         int obj_size = sizeof(struct t_o);
75
76         if (i < 0 || i > size-1) /* wrong table number */
77                 return 1;
78         if (ch->global_tables[i] == NULL) {
79                 ch->global_tables[i] = new_table_init(size, obj_size,
80                                 simple_hash32, cmp_func32, M_IPFW_HTBL);
81         }
82
83         obj.addr = addr;
84         obj.value = value;
85         obj.mask = mlen;
86
87         /* Insert the object in the table */
88         ret = new_table_insert_obj(ch->global_tables[i], &obj);
89         return ret;
90 }
91
92 int
93 new_del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr)
94 {
95         int ret;
96         int nr = tbl - IPFW_TABLES_MAX;
97
98         ret = new_table_delete_obj(ch->global_tables[nr], &addr);
99
100         return ret;
101 }
102
103 int
104 del_table_entry(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
105     uint8_t mlen)
106 {
107         if (tbl >= IPFW_TABLES_MAX && tbl < IPFW_NEWTABLES_MAX) {
108                 new_del_table_entry(ch, tbl, addr);
109                 return 0;
110         }
111         return (EINVAL);
112 }
113
114 int
115 new_flush_table(struct ip_fw_chain *ch, uint16_t tbl)
116 {
117         new_table_destroy(ch->global_tables[tbl - IPFW_TABLES_MAX]);
118         return 0;
119 }
120
121 int
122 flush_table(struct ip_fw_chain *ch, uint16_t tbl)
123 {
124         if (tbl >= IPFW_TABLES_MAX && tbl < IPFW_NEWTABLES_MAX)
125                 return new_flush_table(ch, tbl);
126         
127         return (EINVAL);
128 }
129
130 int
131 lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
132     uint32_t *val)
133 {
134         if (tbl >= IPFW_TABLES_MAX && tbl < IPFW_NEWTABLES_MAX) {
135                 struct new_hash_table *h;
136                 const struct t_o *obj;
137
138                 h = ch->global_tables[tbl - IPFW_TABLES_MAX];
139
140                 obj = new_table_extract_obj(h, (void *)&addr);
141                 if (obj == NULL)
142                         return 0; /* no match */
143
144                 *val = obj->value;
145                 return 1; /* match */
146         }
147         return 0;
148 }
149
150 int
151 new_count_table_entry(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
152 {
153         *cnt = new_table_get_element(ch->global_tables[tbl - IPFW_TABLES_MAX]);
154         return 0;
155 }
156
157 int
158 count_table(struct ip_fw_chain *ch, uint32_t tbl, uint32_t *cnt)
159 {
160         if (tbl >= IPFW_TABLES_MAX && tbl < IPFW_NEWTABLES_MAX) {
161                 new_count_table_entry(ch, tbl, cnt);
162                 return (0);
163         }
164         return (EINVAL);
165 }
166
167 int
168 new_dump_table_entry(struct ip_fw_chain *ch, ipfw_table *tbl)
169 {
170         /* fill the tbl with all entryes */
171         ipfw_table_entry *ent;
172         const struct t_o *obj;
173         int i;
174         int n_el;
175         int nr = tbl->tbl - IPFW_TABLES_MAX;
176         struct new_hash_table *t = ch->global_tables[nr];
177
178         i = 0;
179         tbl->cnt = 0;
180
181         /* XXX determine tbl->size */
182         n_el = new_table_get_element(t);
183         obj = NULL;
184         for (; n_el > 0; n_el--) {
185                 obj = table_next(t, obj);
186                 if (obj == NULL)
187                         break;
188                 ent = &tbl->ent[tbl->cnt];
189
190                 ent->addr = obj->addr;
191                 ent->value = obj->value;
192                 ent->masklen = obj->mask;
193                 tbl->cnt++;
194         }
195         return 0;
196 }
197
198 int
199 dump_table(struct ip_fw_chain *ch, ipfw_table *tbl)
200 {
201         if (tbl->tbl >= IPFW_TABLES_MAX && tbl->tbl < IPFW_NEWTABLES_MAX) {
202                 new_dump_table_entry(ch, tbl);
203                 return (0);
204         }
205         return (EINVAL);
206 }
207
208 int
209 init_tables(struct ip_fw_chain *ch)
210 {
211
212         int i;
213         /* Initialize new tables XXXMPD */
214         for (i = 0; i < IPFW_NEWTABLES_MAX - IPFW_TABLES_MAX; i++) {
215                 memset(&ch->global_tables[i], sizeof(struct new_hash_table*), 0);
216         }
217
218         return (0);
219 }