blob: 3e39512340dd24320f53148ee28636661117896e [file] [log] [blame]
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001/*
2 * libebtc.c, January 2004
3 *
4 * Contains the functions with which to make a table in userspace.
5 *
6 * Author: Bart De Schuymer
7 *
8 * This code is stongly inspired on the iptables code which is
9 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000026#include <string.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <stdarg.h>
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000030#include "include/ebtables_u.h"
31#include "include/ethernetdb.h"
32#include <unistd.h>
33#include <fcntl.h>
34#include <sys/wait.h>
35
36static void decrease_chain_jumps(struct ebt_u_replace *replace);
37static void remove_udc(struct ebt_u_replace *replace);
38static int iterate_entries(struct ebt_u_replace *replace, int type);
39
Bart De Schuymer6622a012005-01-19 21:09:05 +000040/* The standard names */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000041const char *ebt_hooknames[NF_BR_NUMHOOKS] =
42{
43 [NF_BR_PRE_ROUTING]"PREROUTING",
44 [NF_BR_LOCAL_IN]"INPUT",
45 [NF_BR_FORWARD]"FORWARD",
46 [NF_BR_LOCAL_OUT]"OUTPUT",
47 [NF_BR_POST_ROUTING]"POSTROUTING",
48 [NF_BR_BROUTING]"BROUTING"
49};
50
Bart De Schuymer6622a012005-01-19 21:09:05 +000051/* The four target names */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000052const char* ebt_standard_targets[NUM_STANDARD_TARGETS] =
53{
54 "ACCEPT",
55 "DROP",
56 "CONTINUE",
57 "RETURN",
58};
59
Bart De Schuymer6622a012005-01-19 21:09:05 +000060/* The lists of supported tables, matches, watchers and targets */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000061struct ebt_u_table *ebt_tables;
62struct ebt_u_match *ebt_matches;
63struct ebt_u_watcher *ebt_watchers;
64struct ebt_u_target *ebt_targets;
65
Bart De Schuymer6622a012005-01-19 21:09:05 +000066/* Find the right structure belonging to a name */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000067struct ebt_u_target *ebt_find_target(const char *name)
68{
69 struct ebt_u_target *t = ebt_targets;
70
Bart De Schuymer6622a012005-01-19 21:09:05 +000071 while (t && strcmp(t->name, name))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000072 t = t->next;
73 return t;
74}
75
76struct ebt_u_match *ebt_find_match(const char *name)
77{
78 struct ebt_u_match *m = ebt_matches;
79
Bart De Schuymer6622a012005-01-19 21:09:05 +000080 while (m && strcmp(m->name, name))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000081 m = m->next;
82 return m;
83}
84
85struct ebt_u_watcher *ebt_find_watcher(const char *name)
86{
87 struct ebt_u_watcher *w = ebt_watchers;
88
Bart De Schuymer6622a012005-01-19 21:09:05 +000089 while (w && strcmp(w->name, name))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +000090 w = w->next;
91 return w;
92}
93
94struct ebt_u_table *ebt_find_table(const char *name)
95{
96 struct ebt_u_table *t = ebt_tables;
97
98 while (t && strcmp(t->name, name))
99 t = t->next;
100 return t;
101}
102
Bart De Schuymer6622a012005-01-19 21:09:05 +0000103/* Prints all registered extensions */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000104void ebt_list_extensions()
105{
106 struct ebt_u_table *tbl = ebt_tables;
107 struct ebt_u_target *t = ebt_targets;
108 struct ebt_u_match *m = ebt_matches;
109 struct ebt_u_watcher *w = ebt_watchers;
110
111 PRINT_VERSION;
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000112 printf("Loaded userspace extensions:\n\nLoaded tables:\n");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000113 while (tbl) {
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000114 printf("%s\n", tbl->name);
115 tbl = tbl->next;
116 }
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000117 printf("\nLoaded targets:\n");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000118 while (t) {
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000119 printf("%s\n", t->name);
120 t = t->next;
121 }
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000122 printf("\nLoaded matches:\n");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000123 while (m) {
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000124 printf("%s\n", m->name);
125 m = m->next;
126 }
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000127 printf("\nLoaded watchers:\n");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000128 while (w) {
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000129 printf("%s\n", w->name);
130 w = w->next;
131 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000132}
133
Bart De Schuymer6622a012005-01-19 21:09:05 +0000134/* Get the table from the kernel or from a binary file
Bart De Schuymer64182a32004-01-21 20:39:54 +0000135 * init: 1 = ask the kernel for the initial contents of a table, i.e. the
136 * way it looks when the table is insmod'ed
Bart De Schuymer6622a012005-01-19 21:09:05 +0000137 * 0 = get the current data in the table */
138int ebt_get_kernel_table(struct ebt_u_replace *replace, int init)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000139{
Bart De Schuymer6622a012005-01-19 21:09:05 +0000140 if (!ebt_find_table(replace->name)) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000141 ebt_print_error("Bad table name '%s'", replace->name);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000142 return -1;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000143 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000144 /* Get the kernel's information */
145 if (ebt_get_table(replace, init)) {
146 if (ebt_errormsg[0] != '\0')
147 return -1;
148 ebtables_insmod("ebtables");
149 if (ebt_get_table(replace, init)) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000150 ebt_print_error("The kernel doesn't support the ebtables '%s' table", replace->name);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000151 return -1;
152 }
153 }
154 return 0;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000155}
156
Bart De Schuymer6622a012005-01-19 21:09:05 +0000157/* Put sane values into a new entry */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000158void ebt_initialize_entry(struct ebt_u_entry *e)
159{
160 e->bitmask = EBT_NOPROTO;
161 e->invflags = 0;
162 e->ethproto = 0;
163 strcpy(e->in, "");
164 strcpy(e->out, "");
165 strcpy(e->logical_in, "");
166 strcpy(e->logical_out, "");
167 e->m_list = NULL;
168 e->w_list = NULL;
169 e->t = (struct ebt_entry_target *)ebt_find_target(EBT_STANDARD_TARGET);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000170 ebt_find_target(EBT_STANDARD_TARGET)->used = 1;
Bart De Schuymerab611e22005-02-14 20:20:03 +0000171 e->cnt.pcnt = e->cnt.bcnt = e->cnt_surplus.pcnt = e->cnt_surplus.bcnt = 0;
Bart De Schuymer64182a32004-01-21 20:39:54 +0000172
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000173 if (!e->t)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000174 ebt_print_bug("Couldn't load standard target");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000175 ((struct ebt_standard_target *)((struct ebt_u_target *)e->t)->t)->verdict = EBT_CONTINUE;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000176}
177
Bart De Schuymer6622a012005-01-19 21:09:05 +0000178/* Free up the memory of the table held in userspace, *replace can be reused */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000179void ebt_cleanup_replace(struct ebt_u_replace *replace)
180{
181 int i;
182 struct ebt_u_entries *entries;
183 struct ebt_u_chain_list *udc1, *udc2;
184 struct ebt_cntchanges *cc1, *cc2;
185 struct ebt_u_entry *u_e1, *u_e2;
186
187 replace->name[0] = '\0';
188 replace->valid_hooks = 0;
189 replace->nentries = 0;
190 replace->num_counters = 0;
191 replace->flags = 0;
192 replace->command = 0;
193 replace->selected_chain = -1;
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000194 free(replace->filename);
195 replace->filename = NULL;
196 free(replace->counters);
197 replace->counters = NULL;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000198
199 i = -1;
200 while (1) {
201 i++;
202 entries = ebt_nr_to_chain(replace, i);
203 if (!entries) {
204 if (i < NF_BR_NUMHOOKS)
205 continue;
206 else
207 break;
208 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000209 u_e1 = entries->entries;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000210 while (u_e1) {
211 ebt_free_u_entry(u_e1);
212 u_e2 = u_e1->next;
213 free(u_e1);
214 u_e1 = u_e2;
215 }
216 }
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000217 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
218 free(replace->hook_entry[i]);
219 replace->hook_entry[i] = NULL;
220 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000221 udc1 = replace->udc;
222 while (udc1) {
Bart De Schuymer6622a012005-01-19 21:09:05 +0000223 free(udc1->udc);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000224 udc2 = udc1->next;
225 free(udc1);
226 udc1 = udc2;
227 }
228 replace->udc = NULL;
229 cc1 = replace->counterchanges;
230 while (cc1) {
231 cc2 = cc1->next;
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000232 free(cc1);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000233 cc1 = cc2;
234 }
235 replace->counterchanges = NULL;
236}
237
Bart De Schuymer6622a012005-01-19 21:09:05 +0000238/* Should be called, e.g., between 2 rule adds */
239void ebt_reinit_extensions()
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000240{
241 struct ebt_u_match *m;
242 struct ebt_u_watcher *w;
243 struct ebt_u_target *t;
Bart De Schuymer64182a32004-01-21 20:39:54 +0000244 int size;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000245
246 /* The init functions should determine by themselves whether they are
247 * called for the first time or not (when necessary). */
248 for (m = ebt_matches; m; m = m->next) {
Bart De Schuymer6622a012005-01-19 21:09:05 +0000249 if (m->used) {
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000250 size = EBT_ALIGN(m->size) + sizeof(struct ebt_entry_match);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000251 m->m = (struct ebt_entry_match *)malloc(size);
252 if (!m->m)
253 ebt_print_memory();
254 strcpy(m->m->u.name, m->name);
255 m->m->match_size = EBT_ALIGN(m->size);
256 m->used = 0;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000257 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000258 m->flags = 0; /* An error can occur before used is set, while flags is changed. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000259 m->init(m->m);
260 }
261 for (w = ebt_watchers; w; w = w->next) {
Bart De Schuymer6622a012005-01-19 21:09:05 +0000262 if (w->used) {
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000263 size = EBT_ALIGN(w->size) + sizeof(struct ebt_entry_watcher);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000264 w->w = (struct ebt_entry_watcher *)malloc(size);
265 if (!w->w)
266 ebt_print_memory();
267 strcpy(w->w->u.name, w->name);
268 w->w->watcher_size = EBT_ALIGN(w->size);
269 w->used = 0;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000270 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000271 w->flags = 0;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000272 w->init(w->w);
273 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000274 for (t = ebt_targets; t; t = t->next) {
Bart De Schuymer6622a012005-01-19 21:09:05 +0000275 if (t->used) {
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000276 size = EBT_ALIGN(t->size) + sizeof(struct ebt_entry_target);
Bart De Schuymer6622a012005-01-19 21:09:05 +0000277 t->t = (struct ebt_entry_target *)malloc(size);
278 if (!t->t)
279 ebt_print_memory();
280 strcpy(t->t->u.name, t->name);
281 t->t->target_size = EBT_ALIGN(t->size);
282 t->used = 0;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000283 }
Bart De Schuymerff587202005-02-08 20:02:28 +0000284 t->flags = 0;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000285 t->init(t->t);
286 }
287}
288
Bart De Schuymer6622a012005-01-19 21:09:05 +0000289/* This doesn't free e, because the calling function might need e->next */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000290void ebt_free_u_entry(struct ebt_u_entry *e)
291{
292 struct ebt_u_match_list *m_l, *m_l2;
293 struct ebt_u_watcher_list *w_l, *w_l2;
294
295 m_l = e->m_list;
296 while (m_l) {
297 m_l2 = m_l->next;
298 free(m_l->m);
299 free(m_l);
300 m_l = m_l2;
301 }
302 w_l = e->w_list;
303 while (w_l) {
304 w_l2 = w_l->next;
305 free(w_l->w);
306 free(w_l);
307 w_l = w_l2;
308 }
309 free(e->t);
310}
311
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000312static char *get_modprobe(void)
313{
314 int procfile;
315 char *ret;
316
317 procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
318 if (procfile < 0)
319 return NULL;
320
321 ret = malloc(1024);
322 if (ret) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000323 if (read(procfile, ret, 1024) == -1)
324 goto fail;
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000325 /* The kernel adds a '\n' */
326 ret[1023] = '\n';
327 *strchr(ret, '\n') = '\0';
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000328 close(procfile);
329 return ret;
330 }
331 fail:
332 free(ret);
333 close(procfile);
334 return NULL;
335}
336
337char *ebt_modprobe;
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000338/* Try to load the kernel module, analogous to ip_tables.c */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000339int ebtables_insmod(const char *modname)
340{
341 char *buf = NULL;
342 char *argv[3];
343
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000344 /* If they don't explicitly set it, read out of /proc */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000345 if (!ebt_modprobe) {
346 buf = get_modprobe();
347 if (!buf)
348 return -1;
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000349 ebt_modprobe = buf; /* Keep the value for possible later use */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000350 }
351
352 switch (fork()) {
353 case 0:
354 argv[0] = (char *)ebt_modprobe;
355 argv[1] = (char *)modname;
356 argv[2] = NULL;
357 execv(argv[0], argv);
358
Bart De Schuymer6622a012005-01-19 21:09:05 +0000359 /* Not usually reached */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000360 exit(0);
361 case -1:
362 return -1;
363
Bart De Schuymer6622a012005-01-19 21:09:05 +0000364 default: /* Parent */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000365 wait(NULL);
366 }
367
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000368 return 0;
369}
370
Bart De Schuymer6622a012005-01-19 21:09:05 +0000371/* Gives back a pointer to the chain base, based on nr.
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000372 * If nr >= NF_BR_NUMHOOKS you'll get back a user-defined chain.
Bart De Schuymer6622a012005-01-19 21:09:05 +0000373 * Returns NULL on failure. */
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000374struct ebt_u_entries *ebt_nr_to_chain(const struct ebt_u_replace *replace, int nr)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000375{
376 if (nr == -1)
377 return NULL;
378 if (nr < NF_BR_NUMHOOKS)
379 return replace->hook_entry[nr];
380 else {
381 int i;
382 struct ebt_u_chain_list *cl = replace->udc;
383
384 i = nr - NF_BR_NUMHOOKS;
385 while (i > 0 && cl) {
386 cl = cl->next;
387 i--;
388 }
389 if (cl)
390 return cl->udc;
391 else
392 return NULL;
393 }
394}
395
Bart De Schuymer6622a012005-01-19 21:09:05 +0000396/* Gives back a pointer to the chain base of selected_chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000397struct ebt_u_entries *ebt_to_chain(const struct ebt_u_replace *replace)
398{
399 return ebt_nr_to_chain(replace, replace->selected_chain);
400}
401
Bart De Schuymer6622a012005-01-19 21:09:05 +0000402/* Parse the chain name and return a pointer to the chain base.
403 * Returns NULL on failure. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000404struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace,
Bart De Schuymer6622a012005-01-19 21:09:05 +0000405 const char* arg)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000406{
407 int i;
408 struct ebt_u_chain_list *cl = replace->udc;
409
410 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000411 if (!replace->hook_entry[i])
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000412 continue;
413 if (!strcmp(arg, replace->hook_entry[i]->name))
414 return replace->hook_entry[i];
415 }
416 while(cl) {
417 if (!strcmp(arg, cl->udc->name))
418 return cl->udc;
419 cl = cl->next;
420 }
421 return NULL;
422}
423
Bart De Schuymer6622a012005-01-19 21:09:05 +0000424/* Parse the chain name and return the corresponding chain nr
425 * returns -1 on failure */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000426int ebt_get_chainnr(const struct ebt_u_replace *replace, const char* arg)
427{
428 int i;
429 struct ebt_u_chain_list *cl = replace->udc;
430
431 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000432 if (!replace->hook_entry[i])
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000433 continue;
434 if (!strcmp(arg, replace->hook_entry[i]->name))
435 return i;
436 }
437 while(cl) {
438 if (!strcmp(arg, cl->udc->name))
439 return i;
440 i++;
441 cl = cl->next;
442 }
443 return -1;
444}
445
446 /*
447************
448************
449**COMMANDS**
450************
451************
452 */
453
Bart De Schuymer6622a012005-01-19 21:09:05 +0000454/* Change the policy of selected_chain.
455 * Handing a bad policy to this function is a bug. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000456void ebt_change_policy(struct ebt_u_replace *replace, int policy)
457{
458 struct ebt_u_entries *entries = ebt_to_chain(replace);
459
460 if (policy < -NUM_STANDARD_TARGETS || policy == EBT_CONTINUE)
Bart De Schuymer6622a012005-01-19 21:09:05 +0000461 ebt_print_bug("Wrong policy: %d", policy);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000462 entries->policy = policy;
463}
464
Bart De Schuymer6622a012005-01-19 21:09:05 +0000465/* Flush one chain or the complete table
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000466 * If selected_chain == -1 then flush the complete table */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000467void ebt_flush_chains(struct ebt_u_replace *replace)
468{
469 int i, j, numdel;
470 struct ebt_u_entry *u_e, *tmp;
471 struct ebt_u_entries *entries = ebt_to_chain(replace);
472 struct ebt_cntchanges *cc = replace->counterchanges;
473 struct ebt_cntchanges **prev_cc = &(replace->counterchanges);
474
Bart De Schuymer6622a012005-01-19 21:09:05 +0000475 /* Flush whole table */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000476 if (!entries) {
477 if (replace->nentries == 0)
478 return;
479 replace->nentries = 0;
480
Bart De Schuymer6622a012005-01-19 21:09:05 +0000481 /* Free everything and zero (n)entries */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000482 i = -1;
483 while (1) {
484 i++;
485 entries = ebt_nr_to_chain(replace, i);
486 if (!entries) {
487 if (i < NF_BR_NUMHOOKS)
488 continue;
489 else
490 break;
491 }
492 entries->nentries = 0;
493 entries->counter_offset = 0;
494 u_e = entries->entries;
495 entries->entries = NULL;
496 while (u_e) {
497 ebt_free_u_entry(u_e);
498 tmp = u_e->next;
499 free(u_e);
500 u_e = tmp;
501 }
502 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000503 /* Update the counters */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000504 while (cc) {
505 if (cc->type == CNT_ADD) {
506 *prev_cc = cc->next;
507 free(cc);
508 cc = *prev_cc;
509 continue;
510 }
511 cc->type = CNT_DEL;
512 prev_cc = &(cc->next);
513 cc = cc->next;
514 }
515 return;
516 }
517
518 if (entries->nentries == 0)
519 return;
520 replace->nentries -= entries->nentries;
521 numdel = entries->nentries;
522
Bart De Schuymer6622a012005-01-19 21:09:05 +0000523 /* Delete the counters belonging to the specified chain,
524 * update counter_offset */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000525 i = -1;
526 while (1) {
527 i++;
528 entries = ebt_nr_to_chain(replace, i);
529 if (!entries) {
530 if (i < NF_BR_NUMHOOKS)
531 continue;
532 else
533 break;
534 }
535 if (i > replace->selected_chain) {
536 entries->counter_offset -= numdel;
537 continue;
538 }
539 j = entries->nentries;
540 while (j) {
Bart De Schuymer6622a012005-01-19 21:09:05 +0000541 /* Don't count deleted entries */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000542 if (cc->type == CNT_DEL)
543 goto letscontinue;
544 if (i == replace->selected_chain) {
545 if (cc->type == CNT_ADD) {
546 *prev_cc = cc->next;
547 free(cc);
548 cc = *prev_cc;
549 j--;
550 continue;
551 }
552 cc->type = CNT_DEL;
553 }
554 j--;
555letscontinue:
556 prev_cc = &(cc->next);
557 cc = cc->next;
558 }
559 }
560
561 entries = ebt_to_chain(replace);
562 entries->nentries = 0;
563 u_e = entries->entries;
564 while (u_e) {
565 ebt_free_u_entry(u_e);
566 tmp = u_e->next;
567 free(u_e);
568 u_e = tmp;
569 }
570 entries->entries = NULL;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000571}
572
Bart De Schuymerab611e22005-02-14 20:20:03 +0000573#define OPT_COUNT 0x1000 /* This value is also defined in ebtables.c */
Bart De Schuymer6622a012005-01-19 21:09:05 +0000574/* Returns the rule number on success (starting from 0), -1 on failure
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000575 *
576 * This function expects the ebt_{match,watcher,target} members of new_entry
Bart De Schuymer6622a012005-01-19 21:09:05 +0000577 * to contain pointers to ebt_u_{match,watcher,target} */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000578int ebt_check_rule_exists(struct ebt_u_replace *replace,
579 struct ebt_u_entry *new_entry)
580{
581 struct ebt_u_entry *u_e;
582 struct ebt_u_match_list *m_l, *m_l2;
583 struct ebt_u_match *m;
584 struct ebt_u_watcher_list *w_l, *w_l2;
585 struct ebt_u_watcher *w;
586 struct ebt_u_target *t = (struct ebt_u_target *)new_entry->t;
587 struct ebt_u_entries *entries = ebt_to_chain(replace);
588 int i, j, k;
589
590 u_e = entries->entries;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000591 /* Check for an existing rule (if there are duplicate rules,
592 * take the first occurance) */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000593 for (i = 0; i < entries->nentries; i++, u_e = u_e->next) {
594 if (!u_e)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000595 ebt_print_bug("Hmm, trouble");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000596 if (u_e->ethproto != new_entry->ethproto)
597 continue;
598 if (strcmp(u_e->in, new_entry->in))
599 continue;
600 if (strcmp(u_e->out, new_entry->out))
601 continue;
602 if (strcmp(u_e->logical_in, new_entry->logical_in))
603 continue;
604 if (strcmp(u_e->logical_out, new_entry->logical_out))
605 continue;
606 if (new_entry->bitmask & EBT_SOURCEMAC &&
Bart De Schuymer6622a012005-01-19 21:09:05 +0000607 memcmp(u_e->sourcemac, new_entry->sourcemac, ETH_ALEN))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000608 continue;
609 if (new_entry->bitmask & EBT_DESTMAC &&
Bart De Schuymer6622a012005-01-19 21:09:05 +0000610 memcmp(u_e->destmac, new_entry->destmac, ETH_ALEN))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000611 continue;
612 if (new_entry->bitmask != u_e->bitmask ||
Bart De Schuymer6622a012005-01-19 21:09:05 +0000613 new_entry->invflags != u_e->invflags)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000614 continue;
Bart De Schuymerab611e22005-02-14 20:20:03 +0000615 if (replace->flags & OPT_COUNT && (new_entry->cnt.pcnt !=
616 u_e->cnt.pcnt || new_entry->cnt.bcnt != u_e->cnt.bcnt))
617 continue;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000618 /* Compare all matches */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000619 m_l = new_entry->m_list;
620 j = 0;
621 while (m_l) {
622 m = (struct ebt_u_match *)(m_l->m);
623 m_l2 = u_e->m_list;
624 while (m_l2 && strcmp(m_l2->m->u.name, m->m->u.name))
625 m_l2 = m_l2->next;
626 if (!m_l2 || !m->compare(m->m, m_l2->m))
627 goto letscontinue;
628 j++;
629 m_l = m_l->next;
630 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000631 /* Now be sure they have the same nr of matches */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000632 k = 0;
633 m_l = u_e->m_list;
634 while (m_l) {
635 k++;
636 m_l = m_l->next;
637 }
638 if (j != k)
639 continue;
640
Bart De Schuymer6622a012005-01-19 21:09:05 +0000641 /* Compare all watchers */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000642 w_l = new_entry->w_list;
643 j = 0;
644 while (w_l) {
645 w = (struct ebt_u_watcher *)(w_l->w);
646 w_l2 = u_e->w_list;
647 while (w_l2 && strcmp(w_l2->w->u.name, w->w->u.name))
648 w_l2 = w_l2->next;
649 if (!w_l2 || !w->compare(w->w, w_l2->w))
650 goto letscontinue;
651 j++;
652 w_l = w_l->next;
653 }
654 k = 0;
655 w_l = u_e->w_list;
656 while (w_l) {
657 k++;
658 w_l = w_l->next;
659 }
660 if (j != k)
661 continue;
662 if (strcmp(t->t->u.name, u_e->t->u.name))
663 continue;
664 if (!t->compare(t->t, u_e->t))
665 continue;
666 return i;
Bart De Schuymeraef08942004-09-09 21:41:29 +0000667letscontinue:;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000668 }
669 return -1;
670}
671
672/* Add a rule, rule_nr is the rule to update
673 * rule_nr specifies where the rule should be inserted
674 * rule_nr > 0 : insert the rule right before the rule_nr'th rule
675 * (the first rule is rule 1)
676 * rule_nr < 0 : insert the rule right before the (n+rule_nr+1)'th rule,
Bart De Schuymer6622a012005-01-19 21:09:05 +0000677 * where n denotes the number of rules in the chain
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000678 * rule_nr == 0: add a new rule at the end of the chain
679 *
680 * This function expects the ebt_{match,watcher,target} members of new_entry
681 * to contain pointers to ebt_u_{match,watcher,target} and updates these
Bart De Schuymer6622a012005-01-19 21:09:05 +0000682 * pointers so that they point to ebt_{match,watcher,target}, before adding
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000683 * the rule to the chain. Don't free() the ebt_{match,watcher,target} and
684 * don't reuse the new_entry after a successful call to ebt_add_rule() */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000685void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry,
686 int rule_nr)
687{
688 int i, j;
689 struct ebt_u_entry **u_e;
690 struct ebt_u_match_list *m_l;
691 struct ebt_u_watcher_list *w_l;
692 struct ebt_u_entries *entries = ebt_to_chain(replace);
693 struct ebt_cntchanges *cc = replace->counterchanges, *new_cc;
694 struct ebt_cntchanges **prev_cc = &(replace->counterchanges);
695
696 if (rule_nr <= 0)
697 rule_nr += entries->nentries;
698 else
699 rule_nr--;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000700 if (rule_nr > entries->nentries || rule_nr < 0) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000701 ebt_print_error("The specified rule number is incorrect");
Bart De Schuymer6622a012005-01-19 21:09:05 +0000702 return;
703 }
704 /* We're adding one rule */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000705 replace->nentries++;
706 entries->nentries++;
707
Bart De Schuymer6622a012005-01-19 21:09:05 +0000708 /* Handle counter stuff */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000709 for (i = 0; i < replace->selected_chain; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000710 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000711 continue;
712 j = ebt_nr_to_chain(replace, i)->nentries;
713 while (j) {
714 if (cc->type != CNT_DEL)
715 j--;
716 prev_cc = &(cc->next);
717 cc = cc->next;
718 }
719 }
720 j = rule_nr;
721 while (j) {
722 if (cc->type != CNT_DEL)
723 j--;
724 prev_cc = &(cc->next);
725 cc = cc->next;
726 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000727 if (cc && cc->type == CNT_DEL)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000728 cc->type = CNT_OWRITE;
729 else {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000730 new_cc = (struct ebt_cntchanges *)malloc(sizeof(struct ebt_cntchanges));
Bart De Schuymer6622a012005-01-19 21:09:05 +0000731 if (!new_cc)
732 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000733 new_cc->type = CNT_ADD;
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000734 new_cc->change = 0;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000735 new_cc->next = cc;
736 *prev_cc = new_cc;
737 }
Bart De Schuymer6622a012005-01-19 21:09:05 +0000738 /* Go to the right position in the chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000739 u_e = &entries->entries;
740 for (i = 0; i < rule_nr; i++)
741 u_e = &(*u_e)->next;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000742 /* Insert the rule */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000743 new_entry->next = *u_e;
744 *u_e = new_entry;
745
Bart De Schuymer6622a012005-01-19 21:09:05 +0000746 /* Put the ebt_{match, watcher, target} pointers in place */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000747 m_l = new_entry->m_list;
748 while (m_l) {
749 m_l->m = ((struct ebt_u_match *)m_l->m)->m;
750 m_l = m_l->next;
751 }
752 w_l = new_entry->w_list;
753 while (w_l) {
754 w_l->w = ((struct ebt_u_watcher *)w_l->w)->w;
755 w_l = w_l->next;
756 }
757 new_entry->t = ((struct ebt_u_target *)new_entry->t)->t;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000758 /* Update the counter_offset of chains behind this one */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000759 i = replace->selected_chain;
760 while (1) {
761 i++;
762 entries = ebt_nr_to_chain(replace, i);
763 if (!entries) {
764 if (i < NF_BR_NUMHOOKS)
765 continue;
766 else
767 break;
768 } else
769 entries->counter_offset++;
770 }
771}
772
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000773/* If *begin==*end==0 then find the rule corresponding to new_entry,
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000774 * else make the rule numbers positive (starting from 0) and check
775 * for bad rule numbers. */
Bart De Schuymerff587202005-02-08 20:02:28 +0000776static int check_and_change_rule_number(struct ebt_u_replace *replace,
777 struct ebt_u_entry *new_entry, int *begin, int *end)
778{
779 struct ebt_u_entries *entries = ebt_to_chain(replace);
780
781 if (*begin < 0)
782 *begin += entries->nentries + 1;
783 if (*end < 0)
784 *end += entries->nentries + 1;
785
786 if (*begin < 0 || *begin > *end || *end > entries->nentries) {
787 ebt_print_error("Sorry, wrong rule numbers");
788 return -1;
789 }
790
791 if ((*begin * *end == 0) && (*begin + *end != 0))
792 ebt_print_bug("begin and end should be either both zero, "
793 "either both non-zero");
Bart De Schuymerd5dc87d2005-07-16 22:35:32 +0000794 if (*begin != 0) {
Bart De Schuymerff587202005-02-08 20:02:28 +0000795 (*begin)--;
796 (*end)--;
797 } else {
798 *begin = ebt_check_rule_exists(replace, new_entry);
799 *end = *begin;
800 if (*begin == -1) {
801 ebt_print_error("Sorry, rule does not exist");
802 return -1;
803 }
804 }
805 return 0;
806}
807
Bart De Schuymer6622a012005-01-19 21:09:05 +0000808/* Delete a rule or rules
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000809 * begin == end == 0: delete the rule corresponding to new_entry
810 *
Bart De Schuymer6622a012005-01-19 21:09:05 +0000811 * The first rule has rule nr 1, the last rule has rule nr -1, etc.
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000812 * This function expects the ebt_{match,watcher,target} members of new_entry
Bart De Schuymer6622a012005-01-19 21:09:05 +0000813 * to contain pointers to ebt_u_{match,watcher,target}. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000814void ebt_delete_rule(struct ebt_u_replace *replace,
815 struct ebt_u_entry *new_entry, int begin, int end)
816{
817 int i, j, nr_deletes;
818 struct ebt_u_entry **u_e, *u_e2;
819 struct ebt_u_entries *entries = ebt_to_chain(replace);
820 struct ebt_cntchanges *cc = replace->counterchanges;
821 struct ebt_cntchanges **prev_cc = &(replace->counterchanges);
822
Bart De Schuymerff587202005-02-08 20:02:28 +0000823 if (check_and_change_rule_number(replace, new_entry, &begin, &end))
Bart De Schuymer6622a012005-01-19 21:09:05 +0000824 return;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000825
Bart De Schuymer6622a012005-01-19 21:09:05 +0000826 /* We're deleting rules */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000827 nr_deletes = end - begin + 1;
828 replace->nentries -= nr_deletes;
829 entries->nentries -= nr_deletes;
830
Bart De Schuymer6622a012005-01-19 21:09:05 +0000831 /* Handle counter stuff */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000832 for (i = 0; i < replace->selected_chain; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000833 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000834 continue;
835 j = ebt_nr_to_chain(replace, i)->nentries;
836 while (j) {
837 if (cc->type != CNT_DEL)
838 j--;
839 prev_cc = &(cc->next);
840 cc = cc->next;
841 }
842 }
843 j = begin;
844 while (j) {
845 if (cc->type != CNT_DEL)
846 j--;
847 prev_cc = &(cc->next);
848 cc = cc->next;
849 }
850 j = nr_deletes;
851 while (j) {
852 if (cc->type != CNT_DEL) {
853 j--;
854 if (cc->type == CNT_ADD) {
855 *prev_cc = cc->next;
856 free(cc);
857 cc = *prev_cc;
858 continue;
859 }
860 cc->type = CNT_DEL;
861 }
862 prev_cc = &(cc->next);
863 cc = cc->next;
864 }
865
Bart De Schuymer6622a012005-01-19 21:09:05 +0000866 /* Go to the right position in the chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000867 u_e = &entries->entries;
868 for (j = 0; j < begin; j++)
869 u_e = &(*u_e)->next;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000870 /* Remove the rules */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000871 j = nr_deletes;
872 while(j--) {
873 u_e2 = *u_e;
874 *u_e = (*u_e)->next;
Bart De Schuymer6622a012005-01-19 21:09:05 +0000875 /* Free everything */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000876 ebt_free_u_entry(u_e2);
877 free(u_e2);
878 }
879
Bart De Schuymer6622a012005-01-19 21:09:05 +0000880 /* Update the counter_offset of chains behind this one */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000881 j = replace->selected_chain;
882 while (1) {
883 j++;
884 entries = ebt_nr_to_chain(replace, j);
885 if (!entries) {
886 if (j < NF_BR_NUMHOOKS)
887 continue;
888 else
889 break;
890 } else
891 entries->counter_offset -= nr_deletes;
892 }
893}
894
Bart De Schuymerff587202005-02-08 20:02:28 +0000895/* Change the counters of a rule or rules
896 * begin == end == 0: change counters of the rule corresponding to new_entry
897 *
898 * The first rule has rule nr 1, the last rule has rule nr -1, etc.
899 * This function expects the ebt_{match,watcher,target} members of new_entry
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000900 * to contain pointers to ebt_u_{match,watcher,target}.
901 * The mask denotes the following:
902 * pcnt: mask % 3 = 0 : change; = 1: increment; = 2: decrement
903 * bcnt: mask / 3 = 0 : change; = 1: increment = 2: increment
904 * In daemon mode, mask==0 must hold */
Bart De Schuymerff587202005-02-08 20:02:28 +0000905void ebt_change_counters(struct ebt_u_replace *replace,
906 struct ebt_u_entry *new_entry, int begin, int end,
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000907 struct ebt_counter *cnt, int mask)
Bart De Schuymerff587202005-02-08 20:02:28 +0000908{
909 int i, j;
910 struct ebt_u_entry *u_e;
911 struct ebt_u_entries *entries = ebt_to_chain(replace);
912 struct ebt_cntchanges *cc = replace->counterchanges;
Bart De Schuymerff587202005-02-08 20:02:28 +0000913
914 if (check_and_change_rule_number(replace, new_entry, &begin, &end))
915 return;
916
917 for (i = 0; i < replace->selected_chain; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000918 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymerff587202005-02-08 20:02:28 +0000919 continue;
920 j = ebt_nr_to_chain(replace, i)->nentries;
921 while (j) {
922 if (cc->type != CNT_DEL)
923 j--;
Bart De Schuymerff587202005-02-08 20:02:28 +0000924 cc = cc->next;
925 }
926 }
927 i = begin;
928 while (i) {
929 if (cc->type != CNT_DEL)
930 i--;
Bart De Schuymerff587202005-02-08 20:02:28 +0000931 cc = cc->next;
932 }
933 u_e = entries->entries;
934 for (i = 0; i < begin; i++)
935 u_e = u_e->next;
936 i = end - begin + 1;
Bart De Schuymerab611e22005-02-14 20:20:03 +0000937 while (i) {
938 if (cc->type != CNT_DEL) {
939 i--;
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000940 if (mask % 3 == 0) {
941 u_e->cnt.pcnt = (*cnt).pcnt;
942 u_e->cnt_surplus.pcnt = 0;
943 } else {
944 if (cc->type != CNT_NORM)
945 ebt_print_bug("cc->type != CNT_NORM");
946 u_e->cnt_surplus.pcnt = (*cnt).pcnt;
Bart De Schuymerab611e22005-02-14 20:20:03 +0000947 }
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000948
949 if (mask / 3 == 0) {
950 u_e->cnt.bcnt = (*cnt).bcnt;
951 u_e->cnt_surplus.bcnt = 0;
952 } else {
953 if (cc->type != CNT_NORM)
954 ebt_print_bug("cc->type != CNT_NORM");
955 u_e->cnt_surplus.bcnt = (*cnt).bcnt;
956 }
957 if (cc->type == CNT_NORM || cc->type == CNT_ZERO)
958 cc->type = CNT_CHANGE;
959 cc->change = mask;
Bart De Schuymerab611e22005-02-14 20:20:03 +0000960 u_e = u_e->next;
961 }
962 cc = cc->next;
Bart De Schuymerff587202005-02-08 20:02:28 +0000963 }
964}
965
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000966/* If selected_chain == -1 then zero all counters,
967 * otherwise, zero the counters of selected_chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000968void ebt_zero_counters(struct ebt_u_replace *replace)
969{
970 struct ebt_u_entries *entries = ebt_to_chain(replace);
971 struct ebt_cntchanges *cc = replace->counterchanges;
Bart De Schuymer93f36ba2005-01-24 21:11:24 +0000972 struct ebt_u_entry *next;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000973 int i, j;
974
975 if (!entries) {
976 while (cc) {
977 if (cc->type == CNT_NORM)
978 cc->type = CNT_ZERO;
979 cc = cc->next;
980 }
Bart De Schuymer93f36ba2005-01-24 21:11:24 +0000981 i = -1;
982 while (1) {
983 i++;
Bart De Schuymer0436eda2005-03-28 20:29:37 +0000984 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymer93f36ba2005-01-24 21:11:24 +0000985 continue;
986 entries = ebt_nr_to_chain(replace, i);
987 if (!entries) {
988 if (i < NF_BR_NUMHOOKS)
989 ebt_print_bug("i < NF_BR_NUMHOOKS");
990 break;
991 }
992 next = entries->entries;
993 while (next) {
994 next->cnt.bcnt = next->cnt.pcnt = 0;
995 next = next->next;
996 }
997 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +0000998 } else {
Bart De Schuymer93f36ba2005-01-24 21:11:24 +0000999 next = entries->entries;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001000 if (entries->nentries == 0)
1001 return;
1002
1003 for (i = 0; i < replace->selected_chain; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +00001004 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001005 continue;
1006 j = ebt_nr_to_chain(replace, i)->nentries;
1007 while (j) {
1008 if (cc->type != CNT_DEL)
1009 j--;
1010 cc = cc->next;
1011 }
1012 }
1013 j = entries->nentries;
1014 while (j) {
1015 if (cc->type != CNT_DEL) {
1016 j--;
1017 if (cc->type == CNT_NORM)
1018 cc->type = CNT_ZERO;
1019 }
1020 cc = cc->next;
1021 }
Bart De Schuymer93f36ba2005-01-24 21:11:24 +00001022 while (next) {
1023 next->cnt.bcnt = next->cnt.pcnt = 0;
1024 next = next->next;
1025 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001026 }
1027}
1028
Bart De Schuymer6622a012005-01-19 21:09:05 +00001029/* Add a new chain and specify its policy */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001030void ebt_new_chain(struct ebt_u_replace *replace, const char *name, int policy)
1031{
1032 struct ebt_u_chain_list *cl, **cl2;
1033
Bart De Schuymer6622a012005-01-19 21:09:05 +00001034 if (ebt_get_chainnr(replace, name) != -1) {
Bart De Schuymer64182a32004-01-21 20:39:54 +00001035 ebt_print_error("Chain %s already exists", optarg);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001036 return;
1037 } else if (ebt_find_target(name)) {
Bart De Schuymer64182a32004-01-21 20:39:54 +00001038 ebt_print_error("Target with name %s exists", optarg);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001039 return;
1040 } else if (strlen(optarg) >= EBT_CHAIN_MAXNAMELEN) {
Bart De Schuymer64182a32004-01-21 20:39:54 +00001041 ebt_print_error("Chain name length can't exceed %d",
1042 EBT_CHAIN_MAXNAMELEN - 1);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001043 return;
1044 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001045 cl = (struct ebt_u_chain_list *)
1046 malloc(sizeof(struct ebt_u_chain_list));
1047 if (!cl)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001048 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001049 cl->next = NULL;
Bart De Schuymer0436eda2005-03-28 20:29:37 +00001050 cl->udc = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001051 if (!cl->udc)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001052 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001053 cl->udc->nentries = 0;
1054 cl->udc->policy = policy;
1055 cl->udc->counter_offset = replace->nentries;
1056 cl->udc->hook_mask = 0;
1057 strcpy(cl->udc->name, name);
1058 cl->udc->entries = NULL;
1059 cl->kernel_start = NULL;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001060 /* Put the new chain at the end */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001061 cl2 = &(replace->udc);
1062 while (*cl2)
1063 cl2 = &((*cl2)->next);
1064 *cl2 = cl;
1065}
1066
Bart De Schuymer6622a012005-01-19 21:09:05 +00001067/* Selected_chain == -1: delete all non-referenced udc
1068 * selected_chain < NF_BR_NUMHOOKS is illegal */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001069void ebt_delete_chain(struct ebt_u_replace *replace)
1070{
Bart De Schuymer6622a012005-01-19 21:09:05 +00001071 int chain_nr = replace->selected_chain, print_error = 1;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001072
1073 if (chain_nr != -1 && chain_nr < NF_BR_NUMHOOKS)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001074 ebt_print_bug("You can't remove a standard chain");
Bart De Schuymer6622a012005-01-19 21:09:05 +00001075 if (chain_nr == -1) {
1076 print_error = 0;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001077 replace->selected_chain = NF_BR_NUMHOOKS;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001078 }
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001079 do {
1080 if (ebt_to_chain(replace) == NULL) {
1081 if (chain_nr == -1)
1082 break;
Bart De Schuymer64182a32004-01-21 20:39:54 +00001083 ebt_print_bug("udc nr %d doesn't exist", chain_nr);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001084 }
Bart De Schuymer6622a012005-01-19 21:09:05 +00001085 /* If the chain is referenced, don't delete it,
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001086 * also decrement jumps to a chain behind the
Bart De Schuymer6622a012005-01-19 21:09:05 +00001087 * one we're deleting */
1088 if (ebt_check_for_references(replace, print_error)) {
1089 if (chain_nr != -1)
1090 break;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001091 replace->selected_chain++;
1092 continue;
1093 }
1094 decrease_chain_jumps(replace);
1095 ebt_flush_chains(replace);
1096 remove_udc(replace);
Bart De Schuymerc6c0dc32004-12-16 19:30:32 +00001097 } while (chain_nr == -1);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001098 replace->selected_chain = chain_nr; /* Put back to -1 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001099}
1100
Bart De Schuymer6622a012005-01-19 21:09:05 +00001101/* Rename an existing chain. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001102void ebt_rename_chain(struct ebt_u_replace *replace, const char *name)
1103{
1104 struct ebt_u_entries *entries = ebt_to_chain(replace);
1105
1106 if (!entries)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001107 ebt_print_bug("ebt_rename_chain: entries == NULL");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001108 strcpy(entries->name, name);
1109}
1110
1111
1112 /*
1113*************************
1114*************************
1115**SPECIALIZED*FUNCTIONS**
1116*************************
1117*************************
1118 */
1119
1120
Bart De Schuymer6622a012005-01-19 21:09:05 +00001121/* Executes the final_check() function for all extensions used by the rule
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001122 * ebt_check_for_loops should have been executed earlier, to make sure the
Bart De Schuymer6622a012005-01-19 21:09:05 +00001123 * hook_mask is correct. The time argument to final_check() is set to 1,
1124 * meaning it's the second time the final_check() function is executed. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001125void ebt_do_final_checks(struct ebt_u_replace *replace, struct ebt_u_entry *e,
1126 struct ebt_u_entries *entries)
1127{
1128 struct ebt_u_match_list *m_l;
1129 struct ebt_u_watcher_list *w_l;
1130 struct ebt_u_target *t;
1131 struct ebt_u_match *m;
1132 struct ebt_u_watcher *w;
1133
1134 m_l = e->m_list;
1135 w_l = e->w_list;
1136 while (m_l) {
1137 m = ebt_find_match(m_l->m->u.name);
1138 m->final_check(e, m_l->m, replace->name,
1139 entries->hook_mask, 1);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001140 if (ebt_errormsg[0] != '\0')
1141 return;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001142 m_l = m_l->next;
1143 }
1144 while (w_l) {
1145 w = ebt_find_watcher(w_l->w->u.name);
1146 w->final_check(e, w_l->w, replace->name,
1147 entries->hook_mask, 1);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001148 if (ebt_errormsg[0] != '\0')
1149 return;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001150 w_l = w_l->next;
1151 }
1152 t = ebt_find_target(e->t->u.name);
1153 t->final_check(e, e->t, replace->name,
1154 entries->hook_mask, 1);
1155}
1156
Bart De Schuymer6622a012005-01-19 21:09:05 +00001157/* Returns 1 (if it returns) when the chain is referenced, 0 when it isn't.
1158 * print_err: 0 (resp. 1) = don't (resp. do) print error when referenced */
1159int ebt_check_for_references(struct ebt_u_replace *replace, int print_err)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001160{
Bart De Schuymer6622a012005-01-19 21:09:05 +00001161 if (print_err)
1162 return iterate_entries(replace, 1);
1163 else
1164 return iterate_entries(replace, 2);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001165}
1166
Bart De Schuymer6622a012005-01-19 21:09:05 +00001167/* chain_nr: nr of the udc (>= NF_BR_NUMHOOKS)
1168 * Returns 1 (if it returns) when the chain is referenced, 0 when it isn't.
1169 * print_err: 0 (resp. 1) = don't (resp. do) print error when referenced */
1170int ebt_check_for_references2(struct ebt_u_replace *replace, int chain_nr,
1171 int print_err)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001172{
1173 int tmp = replace->selected_chain, ret;
1174
1175 replace->selected_chain = chain_nr;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001176 if (print_err)
1177 ret = iterate_entries(replace, 1);
1178 else
1179 ret = iterate_entries(replace, 2);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001180 replace->selected_chain = tmp;
1181 return ret;
1182}
1183
1184struct ebt_u_stack
1185{
1186 int chain_nr;
1187 int n;
1188 struct ebt_u_entry *e;
1189 struct ebt_u_entries *entries;
1190};
1191
Bart De Schuymer6622a012005-01-19 21:09:05 +00001192/* Checks for loops
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001193 * As a by-product, the hook_mask member of each chain is filled in
1194 * correctly. The check functions of the extensions need this hook_mask
Bart De Schuymer6622a012005-01-19 21:09:05 +00001195 * to know from which standard chains they can be called. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001196void ebt_check_for_loops(struct ebt_u_replace *replace)
1197{
1198 int chain_nr , i, j , k, sp = 0, verdict;
1199 struct ebt_u_entries *entries, *entries2;
1200 struct ebt_u_stack *stack = NULL;
1201 struct ebt_u_entry *e;
1202
1203 i = -1;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001204 /* Initialize hook_mask to 0 */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001205 while (1) {
1206 i++;
Bart De Schuymer0436eda2005-03-28 20:29:37 +00001207 if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001208 continue;
1209 entries = ebt_nr_to_chain(replace, i);
1210 if (!entries)
1211 break;
1212 entries->hook_mask = 0;
1213 }
1214 if (i > NF_BR_NUMHOOKS) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +00001215 stack = (struct ebt_u_stack *)malloc((i - NF_BR_NUMHOOKS) * sizeof(struct ebt_u_stack));
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001216 if (!stack)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001217 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001218 }
1219
Bart De Schuymer6622a012005-01-19 21:09:05 +00001220 /* Check for loops, starting from every base chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001221 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
Bart De Schuymer0436eda2005-03-28 20:29:37 +00001222 if (!(replace->hook_entry[i]))
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001223 continue;
1224 entries = ebt_nr_to_chain(replace, i);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001225 /* (1 << NF_BR_NUMHOOKS) implies it's a standard chain
1226 * (usefull in the final_check() funtions) */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001227 entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
1228 chain_nr = i;
1229
1230 e = entries->entries;
1231 for (j = 0; j < entries->nentries; j++) {
1232 if (strcmp(e->t->u.name, EBT_STANDARD_TARGET))
1233 goto letscontinue;
1234 verdict = ((struct ebt_standard_target *)(e->t))->verdict;
1235 if (verdict < 0)
1236 goto letscontinue;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001237 entries2 = ebt_nr_to_chain(replace, verdict + NF_BR_NUMHOOKS);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001238 entries2->hook_mask |= entries->hook_mask;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001239 /* Now see if we've been here before */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001240 for (k = 0; k < sp; k++)
Bart De Schuymer6622a012005-01-19 21:09:05 +00001241 if (stack[k].chain_nr == verdict + NF_BR_NUMHOOKS) {
1242 ebt_print_error("Loop from chain '%s' to chain '%s'",
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001243 ebt_nr_to_chain(replace, chain_nr)->name,
1244 ebt_nr_to_chain(replace, stack[k].chain_nr)->name);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001245 goto free_stack;
1246 }
1247 /* Jump to the chain, make sure we know how to get back */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001248 stack[sp].chain_nr = chain_nr;
1249 stack[sp].n = j;
1250 stack[sp].entries = entries;
1251 stack[sp].e = e;
1252 sp++;
1253 j = -1;
1254 e = entries2->entries;
1255 chain_nr = verdict + NF_BR_NUMHOOKS;
1256 entries = entries2;
1257 continue;
1258letscontinue:
1259 e = e->next;
1260 }
Bart De Schuymer6622a012005-01-19 21:09:05 +00001261 /* We are at the end of a standard chain */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001262 if (sp == 0)
1263 continue;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001264 /* Go back to the chain one level higher */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001265 sp--;
1266 j = stack[sp].n;
1267 chain_nr = stack[sp].chain_nr;
1268 e = stack[sp].e;
1269 entries = stack[sp].entries;
1270 goto letscontinue;
1271 }
Bart De Schuymer6622a012005-01-19 21:09:05 +00001272free_stack:
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001273 free(stack);
1274 return;
1275}
1276
Bart De Schuymer6622a012005-01-19 21:09:05 +00001277/* The user will use the match, so put it in new_entry. The ebt_u_match
1278 * pointer is put in the ebt_entry_match pointer. ebt_add_rule will
1279 * fill in the final value for new->m. Unless the rule is added to a chain,
1280 * the pointer will keep pointing to the ebt_u_match (until the new_entry
1281 * is freed). I know, I should use a union for these 2 pointer types... */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001282void ebt_add_match(struct ebt_u_entry *new_entry, struct ebt_u_match *m)
1283{
1284 struct ebt_u_match_list **m_list, *new;
1285
1286 for (m_list = &new_entry->m_list; *m_list; m_list = &(*m_list)->next);
1287 new = (struct ebt_u_match_list *)
1288 malloc(sizeof(struct ebt_u_match_list));
1289 if (!new)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001290 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001291 *m_list = new;
1292 new->next = NULL;
1293 new->m = (struct ebt_entry_match *)m;
1294}
1295
1296void ebt_add_watcher(struct ebt_u_entry *new_entry, struct ebt_u_watcher *w)
1297{
1298 struct ebt_u_watcher_list **w_list;
1299 struct ebt_u_watcher_list *new;
1300
1301 for (w_list = &new_entry->w_list; *w_list; w_list = &(*w_list)->next);
1302 new = (struct ebt_u_watcher_list *)
1303 malloc(sizeof(struct ebt_u_watcher_list));
1304 if (!new)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001305 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001306 *w_list = new;
1307 new->next = NULL;
1308 new->w = (struct ebt_entry_watcher *)w;
1309}
1310
1311
1312 /*
1313*******************
1314*******************
1315**OTHER*FUNCTIONS**
1316*******************
1317*******************
1318 */
1319
1320
Bart De Schuymer6622a012005-01-19 21:09:05 +00001321/* type = 0 => update chain jumps
1322 * type = 1 => check for reference, print error when referenced
1323 * type = 2 => check for reference, don't print error when referenced
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001324 *
Bart De Schuymer6622a012005-01-19 21:09:05 +00001325 * Returns 1 when type == 1 and the chain is referenced
1326 * returns 0 otherwise */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001327static int iterate_entries(struct ebt_u_replace *replace, int type)
1328{
1329 int i = -1, j, chain_nr = replace->selected_chain - NF_BR_NUMHOOKS;
1330 struct ebt_u_entries *entries;
1331 struct ebt_u_entry *e;
1332
1333 if (chain_nr < 0)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001334 ebt_print_bug("iterate_entries: udc = %d < 0", chain_nr);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001335 while (1) {
1336 i++;
1337 entries = ebt_nr_to_chain(replace, i);
1338 if (!entries) {
1339 if (i < NF_BR_NUMHOOKS)
1340 continue;
1341 else
1342 break;
1343 }
1344 e = entries->entries;
1345 j = 0;
1346 while (e) {
1347 int chain_jmp;
1348
1349 j++;
1350 if (strcmp(e->t->u.name, EBT_STANDARD_TARGET)) {
1351 e = e->next;
1352 continue;
1353 }
Bart De Schuymer64182a32004-01-21 20:39:54 +00001354 chain_jmp = ((struct ebt_standard_target *)e->t)->
1355 verdict;
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001356 switch (type) {
1357 case 1:
Bart De Schuymer6622a012005-01-19 21:09:05 +00001358 case 2:
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001359 if (chain_jmp == chain_nr) {
Bart De Schuymer6622a012005-01-19 21:09:05 +00001360 if (type == 2)
1361 return 1;
1362 ebt_print_error("Can't delete the chain '%s', it's referenced in chain '%s', rule %d",
1363 ebt_nr_to_chain(replace, chain_nr + NF_BR_NUMHOOKS)->name, entries->name, j);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001364 return 1;
1365 }
1366 break;
1367 case 0:
Bart De Schuymer6622a012005-01-19 21:09:05 +00001368 /* Adjust the chain jumps when necessary */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001369 if (chain_jmp > chain_nr)
1370 ((struct ebt_standard_target *)e->t)->verdict--;
1371 break;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001372 } /* End switch */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001373 e = e->next;
1374 }
1375 }
1376 return 0;
1377}
1378
1379static void decrease_chain_jumps(struct ebt_u_replace *replace)
1380{
1381 iterate_entries(replace, 0);
1382}
1383
Bart De Schuymer6622a012005-01-19 21:09:05 +00001384/* Selected_chain >= NF_BR_NUMHOOKS */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001385static void remove_udc(struct ebt_u_replace *replace)
1386{
1387 struct ebt_u_chain_list *cl, **cl2;
1388 struct ebt_u_entries *entries;
1389 struct ebt_u_entry *u_e, *tmp;
1390 int chain_nr = replace->selected_chain;
1391
1392 if (chain_nr < NF_BR_NUMHOOKS)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001393 ebt_print_bug("remove_udc: chain_nr = %d < %d", chain_nr,
1394 NF_BR_NUMHOOKS);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001395 /* First free the rules */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001396 entries = ebt_nr_to_chain(replace, chain_nr);
1397 u_e = entries->entries;
1398 while (u_e) {
1399 ebt_free_u_entry(u_e);
1400 tmp = u_e->next;
1401 free(u_e);
1402 u_e = tmp;
1403 }
1404
1405 /* next, remove the chain */
1406 cl2 = &(replace->udc);
1407 while ((*cl2)->udc != entries)
1408 cl2 = &((*cl2)->next);
1409 cl = (*cl2);
1410 (*cl2) = (*cl2)->next;
1411 free(cl->udc);
1412 free(cl);
1413}
1414
Bart De Schuymer6622a012005-01-19 21:09:05 +00001415/* Used in initialization code of modules */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001416void ebt_register_match(struct ebt_u_match *m)
1417{
1418 int size = EBT_ALIGN(m->size) + sizeof(struct ebt_entry_match);
1419 struct ebt_u_match **i;
1420
1421 m->m = (struct ebt_entry_match *)malloc(size);
1422 if (!m->m)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001423 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001424 strcpy(m->m->u.name, m->name);
1425 m->m->match_size = EBT_ALIGN(m->size);
1426 m->init(m->m);
1427
1428 for (i = &ebt_matches; *i; i = &((*i)->next));
1429 m->next = NULL;
1430 *i = m;
1431}
1432
1433void ebt_register_watcher(struct ebt_u_watcher *w)
1434{
1435 int size = EBT_ALIGN(w->size) + sizeof(struct ebt_entry_watcher);
1436 struct ebt_u_watcher **i;
1437
1438 w->w = (struct ebt_entry_watcher *)malloc(size);
1439 if (!w->w)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001440 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001441 strcpy(w->w->u.name, w->name);
1442 w->w->watcher_size = EBT_ALIGN(w->size);
1443 w->init(w->w);
1444
1445 for (i = &ebt_watchers; *i; i = &((*i)->next));
1446 w->next = NULL;
1447 *i = w;
1448}
1449
1450void ebt_register_target(struct ebt_u_target *t)
1451{
1452 int size = EBT_ALIGN(t->size) + sizeof(struct ebt_entry_target);
1453 struct ebt_u_target **i;
1454
1455 t->t = (struct ebt_entry_target *)malloc(size);
1456 if (!t->t)
Bart De Schuymer64182a32004-01-21 20:39:54 +00001457 ebt_print_memory();
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001458 strcpy(t->t->u.name, t->name);
1459 t->t->target_size = EBT_ALIGN(t->size);
1460 t->init(t->t);
1461
1462 for (i = &ebt_targets; *i; i = &((*i)->next));
1463 t->next = NULL;
1464 *i = t;
1465}
1466
1467void ebt_register_table(struct ebt_u_table *t)
1468{
1469 t->next = ebt_tables;
1470 ebt_tables = t;
1471}
1472
1473void ebt_iterate_matches(void (*f)(struct ebt_u_match *))
1474{
1475 struct ebt_u_match *i;
1476
1477 for (i = ebt_matches; i; i = i->next)
1478 f(i);
1479}
1480
1481void ebt_iterate_watchers(void (*f)(struct ebt_u_watcher *))
1482{
1483 struct ebt_u_watcher *i;
1484
1485 for (i = ebt_watchers; i; i = i->next)
1486 f(i);
1487}
1488
1489void ebt_iterate_targets(void (*f)(struct ebt_u_target *))
1490{
1491 struct ebt_u_target *i;
1492
1493 for (i = ebt_targets; i; i = i->next)
1494 f(i);
1495}
1496
Bart De Schuymer6622a012005-01-19 21:09:05 +00001497/* Don't use this function, use ebt_print_bug() */
Bart De Schuymer64182a32004-01-21 20:39:54 +00001498void __ebt_print_bug(char *file, int line, char *format, ...)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001499{
1500 va_list l;
1501
1502 va_start(l, format);
1503 printf(PROGNAME" v"PROGVERSION":%s:%d:--BUG--: \n", file, line);
1504 vprintf(format, l);
1505 printf("\n");
1506 va_end(l);
1507 exit (-1);
1508}
1509
Bart De Schuymer6622a012005-01-19 21:09:05 +00001510/* The error messages are put in here when ebt_silent == 1
1511 * ebt_errormsg[0] == '\0' implies there was no error */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001512char ebt_errormsg[ERRORMSG_MAXLEN];
Bart De Schuymer6622a012005-01-19 21:09:05 +00001513/* When error messages should not be printed on the screen, after which
1514 * the program exit()s, set ebt_silent to 1. */
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001515int ebt_silent;
Bart De Schuymer6622a012005-01-19 21:09:05 +00001516/* Don't use this function, use ebt_print_error() */
Bart De Schuymer64182a32004-01-21 20:39:54 +00001517void __ebt_print_error(char *format, ...)
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001518{
1519 va_list l;
1520
1521 va_start(l, format);
Bart De Schuymer6622a012005-01-19 21:09:05 +00001522 if (ebt_silent && ebt_errormsg[0] == '\0') {
1523 vsnprintf(ebt_errormsg, ERRORMSG_MAXLEN, format, l);
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001524 va_end(l);
1525 } else {
1526 vprintf(format, l);
Bart De Schuymer87889eb2005-01-24 22:25:27 +00001527 printf(".\n");
Bart De Schuymer80c82bb2004-01-14 20:06:44 +00001528 va_end(l);
1529 exit (-1);
1530 }
1531}