prevent source code corruption with static build (reported by Tino Keitel)
[jleu-ebtables.git] / libebtc.c
blobf76a04c61f97e4180eb9eee47a59fae30857a080
1 /*
2 * libebtc.c, January 2004
4 * Contains the functions with which to make a table in userspace.
6 * Author: Bart De Schuymer
8 * This code is stongly inspired on the iptables code which is
9 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
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.
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.
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.
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdarg.h>
30 #include "include/ebtables_u.h"
31 #include "include/ethernetdb.h"
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <sys/wait.h>
36 static void decrease_chain_jumps(struct ebt_u_replace *replace);
37 static int iterate_entries(struct ebt_u_replace *replace, int type);
39 /* The standard names */
40 const char *ebt_hooknames[NF_BR_NUMHOOKS] =
42 [NF_BR_PRE_ROUTING]"PREROUTING",
43 [NF_BR_LOCAL_IN]"INPUT",
44 [NF_BR_FORWARD]"FORWARD",
45 [NF_BR_LOCAL_OUT]"OUTPUT",
46 [NF_BR_POST_ROUTING]"POSTROUTING",
47 [NF_BR_BROUTING]"BROUTING"
50 /* The four target names */
51 const char* ebt_standard_targets[NUM_STANDARD_TARGETS] =
53 "ACCEPT",
54 "DROP",
55 "CONTINUE",
56 "RETURN",
59 /* The lists of supported tables, matches, watchers and targets */
60 struct ebt_u_table *ebt_tables;
61 struct ebt_u_match *ebt_matches;
62 struct ebt_u_watcher *ebt_watchers;
63 struct ebt_u_target *ebt_targets;
65 /* Find the right structure belonging to a name */
66 struct ebt_u_target *ebt_find_target(const char *name)
68 struct ebt_u_target *t = ebt_targets;
70 while (t && strcmp(t->name, name))
71 t = t->next;
72 return t;
75 struct ebt_u_match *ebt_find_match(const char *name)
77 struct ebt_u_match *m = ebt_matches;
79 while (m && strcmp(m->name, name))
80 m = m->next;
81 return m;
84 struct ebt_u_watcher *ebt_find_watcher(const char *name)
86 struct ebt_u_watcher *w = ebt_watchers;
88 while (w && strcmp(w->name, name))
89 w = w->next;
90 return w;
93 struct ebt_u_table *ebt_find_table(const char *name)
95 struct ebt_u_table *t = ebt_tables;
97 while (t && strcmp(t->name, name))
98 t = t->next;
99 return t;
102 /* Prints all registered extensions */
103 void ebt_list_extensions()
105 struct ebt_u_table *tbl = ebt_tables;
106 struct ebt_u_target *t = ebt_targets;
107 struct ebt_u_match *m = ebt_matches;
108 struct ebt_u_watcher *w = ebt_watchers;
110 PRINT_VERSION;
111 printf("Loaded userspace extensions:\n\nLoaded tables:\n");
112 while (tbl) {
113 printf("%s\n", tbl->name);
114 tbl = tbl->next;
116 printf("\nLoaded targets:\n");
117 while (t) {
118 printf("%s\n", t->name);
119 t = t->next;
121 printf("\nLoaded matches:\n");
122 while (m) {
123 printf("%s\n", m->name);
124 m = m->next;
126 printf("\nLoaded watchers:\n");
127 while (w) {
128 printf("%s\n", w->name);
129 w = w->next;
133 /* Get the table from the kernel or from a binary file
134 * init: 1 = ask the kernel for the initial contents of a table, i.e. the
135 * way it looks when the table is insmod'ed
136 * 0 = get the current data in the table */
137 int ebt_get_kernel_table(struct ebt_u_replace *replace, int init)
139 if (!ebt_find_table(replace->name)) {
140 ebt_print_error("Bad table name '%s'", replace->name);
141 return -1;
143 /* Get the kernel's information */
144 if (ebt_get_table(replace, init)) {
145 if (ebt_errormsg[0] != '\0')
146 return -1;
147 ebtables_insmod("ebtables");
148 if (ebt_get_table(replace, init)) {
149 ebt_print_error("The kernel doesn't support the ebtables '%s' table", replace->name);
150 return -1;
153 return 0;
156 /* Put sane values into a new entry */
157 void ebt_initialize_entry(struct ebt_u_entry *e)
159 e->bitmask = EBT_NOPROTO;
160 e->invflags = 0;
161 e->ethproto = 0;
162 strcpy(e->in, "");
163 strcpy(e->out, "");
164 strcpy(e->logical_in, "");
165 strcpy(e->logical_out, "");
166 e->m_list = NULL;
167 e->w_list = NULL;
168 e->t = (struct ebt_entry_target *)ebt_find_target(EBT_STANDARD_TARGET);
169 ebt_find_target(EBT_STANDARD_TARGET)->used = 1;
170 e->cnt.pcnt = e->cnt.bcnt = e->cnt_surplus.pcnt = e->cnt_surplus.bcnt = 0;
172 if (!e->t)
173 ebt_print_bug("Couldn't load standard target");
174 ((struct ebt_standard_target *)((struct ebt_u_target *)e->t)->t)->verdict = EBT_CONTINUE;
177 /* Free up the memory of the table held in userspace, *replace can be reused */
178 void ebt_cleanup_replace(struct ebt_u_replace *replace)
180 int i;
181 struct ebt_u_entries *entries;
182 struct ebt_cntchanges *cc1, *cc2;
183 struct ebt_u_entry *u_e1, *u_e2;
185 replace->name[0] = '\0';
186 replace->valid_hooks = 0;
187 replace->nentries = 0;
188 replace->num_counters = 0;
189 replace->flags = 0;
190 replace->command = 0;
191 replace->selected_chain = -1;
192 free(replace->filename);
193 replace->filename = NULL;
194 free(replace->counters);
195 replace->counters = NULL;
197 for (i = 0; i < replace->num_chains; i++) {
198 if (!(entries = replace->chains[i]))
199 continue;
200 u_e1 = entries->entries->next;
201 while (u_e1 != entries->entries) {
202 ebt_free_u_entry(u_e1);
203 u_e2 = u_e1->next;
204 free(u_e1);
205 u_e1 = u_e2;
207 free(entries->entries);
208 free(entries);
209 replace->chains[i] = NULL;
211 cc1 = replace->cc->next;
212 while (cc1 != replace->cc) {
213 cc2 = cc1->next;
214 free(cc1);
215 cc1 = cc2;
217 replace->cc->next = replace->cc->prev = replace->cc;
220 /* Should be called, e.g., between 2 rule adds */
221 void ebt_reinit_extensions()
223 struct ebt_u_match *m;
224 struct ebt_u_watcher *w;
225 struct ebt_u_target *t;
226 int size;
228 /* The init functions should determine by themselves whether they are
229 * called for the first time or not (when necessary). */
230 for (m = ebt_matches; m; m = m->next) {
231 if (m->used) {
232 size = EBT_ALIGN(m->size) + sizeof(struct ebt_entry_match);
233 m->m = (struct ebt_entry_match *)malloc(size);
234 if (!m->m)
235 ebt_print_memory();
236 strcpy(m->m->u.name, m->name);
237 m->m->match_size = EBT_ALIGN(m->size);
238 m->used = 0;
240 m->flags = 0; /* An error can occur before used is set, while flags is changed. */
241 m->init(m->m);
243 for (w = ebt_watchers; w; w = w->next) {
244 if (w->used) {
245 size = EBT_ALIGN(w->size) + sizeof(struct ebt_entry_watcher);
246 w->w = (struct ebt_entry_watcher *)malloc(size);
247 if (!w->w)
248 ebt_print_memory();
249 strcpy(w->w->u.name, w->name);
250 w->w->watcher_size = EBT_ALIGN(w->size);
251 w->used = 0;
253 w->flags = 0;
254 w->init(w->w);
256 for (t = ebt_targets; t; t = t->next) {
257 if (t->used) {
258 size = EBT_ALIGN(t->size) + sizeof(struct ebt_entry_target);
259 t->t = (struct ebt_entry_target *)malloc(size);
260 if (!t->t)
261 ebt_print_memory();
262 strcpy(t->t->u.name, t->name);
263 t->t->target_size = EBT_ALIGN(t->size);
264 t->used = 0;
266 t->flags = 0;
267 t->init(t->t);
271 /* This doesn't free e, because the calling function might need e->next */
272 void ebt_free_u_entry(struct ebt_u_entry *e)
274 struct ebt_u_match_list *m_l, *m_l2;
275 struct ebt_u_watcher_list *w_l, *w_l2;
277 m_l = e->m_list;
278 while (m_l) {
279 m_l2 = m_l->next;
280 free(m_l->m);
281 free(m_l);
282 m_l = m_l2;
284 w_l = e->w_list;
285 while (w_l) {
286 w_l2 = w_l->next;
287 free(w_l->w);
288 free(w_l);
289 w_l = w_l2;
291 free(e->t);
294 static char *get_modprobe(void)
296 int procfile;
297 char *ret;
299 procfile = open(PROC_SYS_MODPROBE, O_RDONLY);
300 if (procfile < 0)
301 return NULL;
303 ret = malloc(1024);
304 if (ret) {
305 if (read(procfile, ret, 1024) == -1)
306 goto fail;
307 /* The kernel adds a '\n' */
308 ret[1023] = '\n';
309 *strchr(ret, '\n') = '\0';
310 close(procfile);
311 return ret;
313 fail:
314 free(ret);
315 close(procfile);
316 return NULL;
319 char *ebt_modprobe;
320 /* Try to load the kernel module, analogous to ip_tables.c */
321 int ebtables_insmod(const char *modname)
323 char *buf = NULL;
324 char *argv[3];
326 /* If they don't explicitly set it, read out of /proc */
327 if (!ebt_modprobe) {
328 buf = get_modprobe();
329 if (!buf)
330 return -1;
331 ebt_modprobe = buf; /* Keep the value for possible later use */
334 switch (fork()) {
335 case 0:
336 argv[0] = (char *)ebt_modprobe;
337 argv[1] = (char *)modname;
338 argv[2] = NULL;
339 execv(argv[0], argv);
341 /* Not usually reached */
342 exit(0);
343 case -1:
344 return -1;
346 default: /* Parent */
347 wait(NULL);
350 return 0;
353 /* Parse the chain name and return a pointer to the chain base.
354 * Returns NULL on failure. */
355 struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace, const char* arg)
357 int i;
358 struct ebt_u_entries *chain;
360 for (i = 0; i < replace->num_chains; i++) {
361 if (!(chain = replace->chains[i]))
362 continue;
363 if (!strcmp(arg, chain->name))
364 return chain;
366 return NULL;
369 /* Parse the chain name and return the corresponding chain nr
370 * returns -1 on failure */
371 int ebt_get_chainnr(const struct ebt_u_replace *replace, const char* arg)
373 int i;
375 for (i = 0; i < replace->num_chains; i++) {
376 if (!replace->chains[i])
377 continue;
378 if (!strcmp(arg, replace->chains[i]->name))
379 return i;
381 return -1;
385 ************
386 ************
387 **COMMANDS**
388 ************
389 ************
392 /* Change the policy of selected_chain.
393 * Handing a bad policy to this function is a bug. */
394 void ebt_change_policy(struct ebt_u_replace *replace, int policy)
396 struct ebt_u_entries *entries = ebt_to_chain(replace);
398 if (policy < -NUM_STANDARD_TARGETS || policy == EBT_CONTINUE)
399 ebt_print_bug("Wrong policy: %d", policy);
400 entries->policy = policy;
403 void ebt_delete_cc(struct ebt_cntchanges *cc)
405 if (cc->type == CNT_ADD) {
406 cc->prev->next = cc->next;
407 cc->next->prev = cc->prev;
408 free(cc);
410 cc->type = CNT_DEL;
413 void ebt_empty_chain(struct ebt_u_entries *entries)
415 struct ebt_u_entry *u_e = entries->entries->next, *tmp;
416 while (u_e != entries->entries) {
417 ebt_delete_cc(u_e->cc);
418 ebt_free_u_entry(u_e);
419 tmp = u_e->next;
420 free(u_e);
421 u_e = tmp;
423 entries->entries->next = entries->entries->prev = entries->entries;
424 entries->nentries = 0;
427 /* Flush one chain or the complete table
428 * If selected_chain == -1 then flush the complete table */
429 void ebt_flush_chains(struct ebt_u_replace *replace)
431 int i, numdel;
432 struct ebt_u_entries *entries = ebt_to_chain(replace);
434 /* Flush whole table */
435 if (!entries) {
436 if (replace->nentries == 0)
437 return;
438 replace->nentries = 0;
440 /* Free everything and zero (n)entries */
441 for (i = 0; i < replace->num_chains; i++) {
442 if (!(entries = replace->chains[i]))
443 continue;
444 entries->counter_offset = 0;
445 ebt_empty_chain(entries);
447 return;
450 if (entries->nentries == 0)
451 return;
452 replace->nentries -= entries->nentries;
453 numdel = entries->nentries;
455 /* Update counter_offset */
456 for (i = replace->selected_chain+1; i < replace->num_chains; i++) {
457 if (!(entries = replace->chains[i]))
458 continue;
459 entries->counter_offset -= numdel;
462 entries = ebt_to_chain(replace);
463 ebt_empty_chain(entries);
466 #define OPT_COUNT 0x1000 /* This value is also defined in ebtables.c */
467 /* Returns the rule number on success (starting from 0), -1 on failure
469 * This function expects the ebt_{match,watcher,target} members of new_entry
470 * to contain pointers to ebt_u_{match,watcher,target} */
471 int ebt_check_rule_exists(struct ebt_u_replace *replace,
472 struct ebt_u_entry *new_entry)
474 struct ebt_u_entry *u_e;
475 struct ebt_u_match_list *m_l, *m_l2;
476 struct ebt_u_match *m;
477 struct ebt_u_watcher_list *w_l, *w_l2;
478 struct ebt_u_watcher *w;
479 struct ebt_u_target *t = (struct ebt_u_target *)new_entry->t;
480 struct ebt_u_entries *entries = ebt_to_chain(replace);
481 int i, j, k;
483 u_e = entries->entries->next;
484 /* Check for an existing rule (if there are duplicate rules,
485 * take the first occurance) */
486 for (i = 0; i < entries->nentries; i++, u_e = u_e->next) {
487 if (u_e->ethproto != new_entry->ethproto)
488 continue;
489 if (strcmp(u_e->in, new_entry->in))
490 continue;
491 if (strcmp(u_e->out, new_entry->out))
492 continue;
493 if (strcmp(u_e->logical_in, new_entry->logical_in))
494 continue;
495 if (strcmp(u_e->logical_out, new_entry->logical_out))
496 continue;
497 if (new_entry->bitmask & EBT_SOURCEMAC &&
498 memcmp(u_e->sourcemac, new_entry->sourcemac, ETH_ALEN))
499 continue;
500 if (new_entry->bitmask & EBT_DESTMAC &&
501 memcmp(u_e->destmac, new_entry->destmac, ETH_ALEN))
502 continue;
503 if (new_entry->bitmask != u_e->bitmask ||
504 new_entry->invflags != u_e->invflags)
505 continue;
506 if (replace->flags & OPT_COUNT && (new_entry->cnt.pcnt !=
507 u_e->cnt.pcnt || new_entry->cnt.bcnt != u_e->cnt.bcnt))
508 continue;
509 /* Compare all matches */
510 m_l = new_entry->m_list;
511 j = 0;
512 while (m_l) {
513 m = (struct ebt_u_match *)(m_l->m);
514 m_l2 = u_e->m_list;
515 while (m_l2 && strcmp(m_l2->m->u.name, m->m->u.name))
516 m_l2 = m_l2->next;
517 if (!m_l2 || !m->compare(m->m, m_l2->m))
518 goto letscontinue;
519 j++;
520 m_l = m_l->next;
522 /* Now be sure they have the same nr of matches */
523 k = 0;
524 m_l = u_e->m_list;
525 while (m_l) {
526 k++;
527 m_l = m_l->next;
529 if (j != k)
530 continue;
532 /* Compare all watchers */
533 w_l = new_entry->w_list;
534 j = 0;
535 while (w_l) {
536 w = (struct ebt_u_watcher *)(w_l->w);
537 w_l2 = u_e->w_list;
538 while (w_l2 && strcmp(w_l2->w->u.name, w->w->u.name))
539 w_l2 = w_l2->next;
540 if (!w_l2 || !w->compare(w->w, w_l2->w))
541 goto letscontinue;
542 j++;
543 w_l = w_l->next;
545 k = 0;
546 w_l = u_e->w_list;
547 while (w_l) {
548 k++;
549 w_l = w_l->next;
551 if (j != k)
552 continue;
553 if (strcmp(t->t->u.name, u_e->t->u.name))
554 continue;
555 if (!t->compare(t->t, u_e->t))
556 continue;
557 return i;
558 letscontinue:;
560 return -1;
563 /* Add a rule, rule_nr is the rule to update
564 * rule_nr specifies where the rule should be inserted
565 * rule_nr > 0 : insert the rule right before the rule_nr'th rule
566 * (the first rule is rule 1)
567 * rule_nr < 0 : insert the rule right before the (n+rule_nr+1)'th rule,
568 * where n denotes the number of rules in the chain
569 * rule_nr == 0: add a new rule at the end of the chain
571 * This function expects the ebt_{match,watcher,target} members of new_entry
572 * to contain pointers to ebt_u_{match,watcher,target} and updates these
573 * pointers so that they point to ebt_{match,watcher,target}, before adding
574 * the rule to the chain. Don't free() the ebt_{match,watcher,target} and
575 * don't reuse the new_entry after a successful call to ebt_add_rule() */
576 void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry, int rule_nr)
578 int i;
579 struct ebt_u_entry *u_e;
580 struct ebt_u_match_list *m_l;
581 struct ebt_u_watcher_list *w_l;
582 struct ebt_u_entries *entries = ebt_to_chain(replace);
583 struct ebt_cntchanges *cc, *new_cc;
585 if (rule_nr <= 0)
586 rule_nr += entries->nentries;
587 else
588 rule_nr--;
589 if (rule_nr > entries->nentries || rule_nr < 0) {
590 ebt_print_error("The specified rule number is incorrect");
591 return;
593 /* Go to the right position in the chain */
594 if (rule_nr == entries->nentries)
595 u_e = entries->entries;
596 else {
597 u_e = entries->entries->next;
598 for (i = 0; i < rule_nr; i++)
599 u_e = u_e->next;
601 /* We're adding one rule */
602 replace->nentries++;
603 entries->nentries++;
604 /* Insert the rule */
605 new_entry->next = u_e;
606 new_entry->prev = u_e->prev;
607 u_e->prev->next = new_entry;
608 u_e->prev = new_entry;
609 new_cc = (struct ebt_cntchanges *)malloc(sizeof(struct ebt_cntchanges));
610 if (!new_cc)
611 ebt_print_memory();
612 new_cc->type = CNT_ADD;
613 new_cc->change = 0;
614 if (new_entry->next == entries->entries) {
615 for (i = replace->selected_chain+1; i < replace->num_chains; i++)
616 if (!replace->chains[i] || replace->chains[i]->nentries == 0)
617 continue;
618 else
619 break;
620 if (i == replace->num_chains)
621 cc = replace->cc;
622 else
623 cc = replace->chains[i]->entries->next->cc;
624 } else
625 cc = new_entry->next->cc;
626 new_cc->next = cc;
627 new_cc->prev = cc->prev;
628 cc->prev->next = new_cc;
629 cc->prev = new_cc;
630 new_entry->cc = new_cc;
632 /* Put the ebt_{match, watcher, target} pointers in place */
633 m_l = new_entry->m_list;
634 while (m_l) {
635 m_l->m = ((struct ebt_u_match *)m_l->m)->m;
636 m_l = m_l->next;
638 w_l = new_entry->w_list;
639 while (w_l) {
640 w_l->w = ((struct ebt_u_watcher *)w_l->w)->w;
641 w_l = w_l->next;
643 new_entry->t = ((struct ebt_u_target *)new_entry->t)->t;
644 /* Update the counter_offset of chains behind this one */
645 for (i = replace->selected_chain+1; i < replace->num_chains; i++) {
646 entries = replace->chains[i];
647 if (!(entries = replace->chains[i]))
648 continue;
649 entries->counter_offset++;
653 /* If *begin==*end==0 then find the rule corresponding to new_entry,
654 * else make the rule numbers positive (starting from 0) and check
655 * for bad rule numbers. */
656 static int check_and_change_rule_number(struct ebt_u_replace *replace,
657 struct ebt_u_entry *new_entry, int *begin, int *end)
659 struct ebt_u_entries *entries = ebt_to_chain(replace);
661 if (*begin < 0)
662 *begin += entries->nentries + 1;
663 if (*end < 0)
664 *end += entries->nentries + 1;
666 if (*begin < 0 || *begin > *end || *end > entries->nentries) {
667 ebt_print_error("Sorry, wrong rule numbers");
668 return -1;
671 if ((*begin * *end == 0) && (*begin + *end != 0))
672 ebt_print_bug("begin and end should be either both zero, "
673 "either both non-zero");
674 if (*begin != 0) {
675 (*begin)--;
676 (*end)--;
677 } else {
678 *begin = ebt_check_rule_exists(replace, new_entry);
679 *end = *begin;
680 if (*begin == -1) {
681 ebt_print_error("Sorry, rule does not exist");
682 return -1;
685 return 0;
688 /* Delete a rule or rules
689 * begin == end == 0: delete the rule corresponding to new_entry
691 * The first rule has rule nr 1, the last rule has rule nr -1, etc.
692 * This function expects the ebt_{match,watcher,target} members of new_entry
693 * to contain pointers to ebt_u_{match,watcher,target}. */
694 void ebt_delete_rule(struct ebt_u_replace *replace,
695 struct ebt_u_entry *new_entry, int begin, int end)
697 int i, nr_deletes;
698 struct ebt_u_entry *u_e, *u_e2, *u_e3;
699 struct ebt_u_entries *entries = ebt_to_chain(replace);
701 if (check_and_change_rule_number(replace, new_entry, &begin, &end))
702 return;
703 /* We're deleting rules */
704 nr_deletes = end - begin + 1;
705 replace->nentries -= nr_deletes;
706 entries->nentries -= nr_deletes;
707 /* Go to the right position in the chain */
708 u_e = entries->entries->next;
709 for (i = 0; i < begin; i++)
710 u_e = u_e->next;
711 u_e3 = u_e->prev;
712 /* Remove the rules */
713 for (i = 0; i < nr_deletes; i++) {
714 u_e2 = u_e;
715 ebt_delete_cc(u_e2->cc);
716 u_e = u_e->next;
717 /* Free everything */
718 ebt_free_u_entry(u_e2);
719 free(u_e2);
721 u_e3->next = u_e;
722 u_e->prev = u_e3;
723 /* Update the counter_offset of chains behind this one */
724 for (i = replace->selected_chain+1; i < replace->num_chains; i++) {
725 if (!(entries = replace->chains[i]))
726 continue;
727 entries->counter_offset -= nr_deletes;
731 /* Change the counters of a rule or rules
732 * begin == end == 0: change counters of the rule corresponding to new_entry
734 * The first rule has rule nr 1, the last rule has rule nr -1, etc.
735 * This function expects the ebt_{match,watcher,target} members of new_entry
736 * to contain pointers to ebt_u_{match,watcher,target}.
737 * The mask denotes the following:
738 * pcnt: mask % 3 = 0 : change; = 1: increment; = 2: decrement
739 * bcnt: mask / 3 = 0 : change; = 1: increment = 2: increment
740 * In daemon mode, mask==0 must hold */
741 void ebt_change_counters(struct ebt_u_replace *replace,
742 struct ebt_u_entry *new_entry, int begin, int end,
743 struct ebt_counter *cnt, int mask)
745 int i;
746 struct ebt_u_entry *u_e;
747 struct ebt_u_entries *entries = ebt_to_chain(replace);
749 if (check_and_change_rule_number(replace, new_entry, &begin, &end))
750 return;
751 u_e = entries->entries->next;
752 for (i = 0; i < begin; i++)
753 u_e = u_e->next;
754 for (i = end-begin+1; i > 0; i--) {
755 if (mask % 3 == 0) {
756 u_e->cnt.pcnt = (*cnt).pcnt;
757 u_e->cnt_surplus.pcnt = 0;
758 } else {
759 #ifdef EBT_DEBUG
760 if (u_e->cc->type != CNT_NORM)
761 ebt_print_bug("cc->type != CNT_NORM");
762 #endif
763 u_e->cnt_surplus.pcnt = (*cnt).pcnt;
766 if (mask / 3 == 0) {
767 u_e->cnt.bcnt = (*cnt).bcnt;
768 u_e->cnt_surplus.bcnt = 0;
769 } else {
770 #ifdef EBT_DEBUG
771 if (u_e->cc->type != CNT_NORM)
772 ebt_print_bug("cc->type != CNT_NORM");
773 #endif
774 u_e->cnt_surplus.bcnt = (*cnt).bcnt;
776 if (u_e->cc->type != CNT_ADD)
777 u_e->cc->type = CNT_CHANGE;
778 u_e->cc->change = mask;
779 u_e = u_e->next;
783 /* If selected_chain == -1 then zero all counters,
784 * otherwise, zero the counters of selected_chain */
785 void ebt_zero_counters(struct ebt_u_replace *replace)
787 struct ebt_u_entries *entries = ebt_to_chain(replace);
788 struct ebt_u_entry *next;
789 int i;
791 if (!entries) {
792 for (i = 0; i < replace->num_chains; i++) {
793 if (!(entries = replace->chains[i]))
794 continue;
795 next = entries->entries->next;
796 while (next != entries->entries) {
797 if (next->cc->type == CNT_NORM)
798 next->cc->type = CNT_CHANGE;
799 next->cnt.bcnt = next->cnt.pcnt = 0;
800 next->cc->change = 0;
801 next = next->next;
804 } else {
805 if (entries->nentries == 0)
806 return;
808 next = entries->entries->next;
809 while (next != entries->entries) {
810 if (next->cc->type == CNT_NORM)
811 next->cc->type = CNT_CHANGE;
812 next->cnt.bcnt = next->cnt.pcnt = 0;
813 next = next->next;
818 /* Add a new chain and specify its policy */
819 void ebt_new_chain(struct ebt_u_replace *replace, const char *name, int policy)
821 struct ebt_u_entries *new;
823 if (replace->num_chains == replace->max_chains)
824 ebt_double_chains(replace);
825 new = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
826 if (!new)
827 ebt_print_memory();
828 replace->chains[replace->num_chains++] = new;
829 new->nentries = 0;
830 new->policy = policy;
831 new->counter_offset = replace->nentries;
832 new->hook_mask = 0;
833 strcpy(new->name, name);
834 new->entries = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
835 if (!new->entries)
836 ebt_print_memory();
837 new->entries->next = new->entries->prev = new->entries;
838 new->kernel_start = NULL;
841 /* returns -1 if the chain is referenced, 0 on success */
842 static int ebt_delete_a_chain(struct ebt_u_replace *replace, int chain, int print_err)
844 int tmp = replace->selected_chain;
845 /* If the chain is referenced, don't delete it,
846 * also decrement jumps to a chain behind the
847 * one we're deleting */
848 replace->selected_chain = chain;
849 if (ebt_check_for_references(replace, print_err))
850 return -1;
851 decrease_chain_jumps(replace);
852 ebt_flush_chains(replace);
853 replace->selected_chain = tmp;
854 free(replace->chains[chain]->entries);
855 free(replace->chains[chain]);
856 memmove(replace->chains+chain, replace->chains+chain+1, (replace->num_chains-chain-1)*sizeof(void *));
857 replace->num_chains--;
858 return 0;
861 /* Selected_chain == -1: delete all non-referenced udc
862 * selected_chain < NF_BR_NUMHOOKS is illegal */
863 void ebt_delete_chain(struct ebt_u_replace *replace)
865 if (replace->selected_chain != -1 && replace->selected_chain < NF_BR_NUMHOOKS)
866 ebt_print_bug("You can't remove a standard chain");
867 if (replace->selected_chain == -1) {
868 int i = NF_BR_NUMHOOKS;
870 while (i < replace->num_chains)
871 if (ebt_delete_a_chain(replace, i, 0))
872 i++;
873 } else
874 ebt_delete_a_chain(replace, replace->selected_chain, 1);
877 /* Rename an existing chain. */
878 void ebt_rename_chain(struct ebt_u_replace *replace, const char *name)
880 struct ebt_u_entries *entries = ebt_to_chain(replace);
882 if (!entries)
883 ebt_print_bug("ebt_rename_chain: entries == NULL");
884 strcpy(entries->name, name);
889 *************************
890 *************************
891 **SPECIALIZED*FUNCTIONS**
892 *************************
893 *************************
897 void ebt_double_chains(struct ebt_u_replace *replace)
899 struct ebt_u_entries **new;
901 replace->max_chains *= 2;
902 new = (struct ebt_u_entries **)malloc(replace->max_chains*sizeof(void *));
903 if (!new)
904 ebt_print_memory();
905 memcpy(new, replace->chains, replace->max_chains/2*sizeof(void *));
906 free(replace->chains);
907 replace->chains = new;
910 /* Executes the final_check() function for all extensions used by the rule
911 * ebt_check_for_loops should have been executed earlier, to make sure the
912 * hook_mask is correct. The time argument to final_check() is set to 1,
913 * meaning it's the second time the final_check() function is executed. */
914 void ebt_do_final_checks(struct ebt_u_replace *replace, struct ebt_u_entry *e,
915 struct ebt_u_entries *entries)
917 struct ebt_u_match_list *m_l;
918 struct ebt_u_watcher_list *w_l;
919 struct ebt_u_target *t;
920 struct ebt_u_match *m;
921 struct ebt_u_watcher *w;
923 m_l = e->m_list;
924 w_l = e->w_list;
925 while (m_l) {
926 m = ebt_find_match(m_l->m->u.name);
927 m->final_check(e, m_l->m, replace->name,
928 entries->hook_mask, 1);
929 if (ebt_errormsg[0] != '\0')
930 return;
931 m_l = m_l->next;
933 while (w_l) {
934 w = ebt_find_watcher(w_l->w->u.name);
935 w->final_check(e, w_l->w, replace->name,
936 entries->hook_mask, 1);
937 if (ebt_errormsg[0] != '\0')
938 return;
939 w_l = w_l->next;
941 t = ebt_find_target(e->t->u.name);
942 t->final_check(e, e->t, replace->name,
943 entries->hook_mask, 1);
946 /* Returns 1 (if it returns) when the chain is referenced, 0 when it isn't.
947 * print_err: 0 (resp. 1) = don't (resp. do) print error when referenced */
948 int ebt_check_for_references(struct ebt_u_replace *replace, int print_err)
950 if (print_err)
951 return iterate_entries(replace, 1);
952 else
953 return iterate_entries(replace, 2);
956 /* chain_nr: nr of the udc (>= NF_BR_NUMHOOKS)
957 * Returns 1 (if it returns) when the chain is referenced, 0 when it isn't.
958 * print_err: 0 (resp. 1) = don't (resp. do) print error when referenced */
959 int ebt_check_for_references2(struct ebt_u_replace *replace, int chain_nr,
960 int print_err)
962 int tmp = replace->selected_chain, ret;
964 replace->selected_chain = chain_nr;
965 if (print_err)
966 ret = iterate_entries(replace, 1);
967 else
968 ret = iterate_entries(replace, 2);
969 replace->selected_chain = tmp;
970 return ret;
973 struct ebt_u_stack
975 int chain_nr;
976 int n;
977 struct ebt_u_entry *e;
978 struct ebt_u_entries *entries;
981 /* Checks for loops
982 * As a by-product, the hook_mask member of each chain is filled in
983 * correctly. The check functions of the extensions need this hook_mask
984 * to know from which standard chains they can be called. */
985 void ebt_check_for_loops(struct ebt_u_replace *replace)
987 int chain_nr , i, j , k, sp = 0, verdict;
988 struct ebt_u_entries *entries, *entries2;
989 struct ebt_u_stack *stack = NULL;
990 struct ebt_u_entry *e;
992 /* Initialize hook_mask to 0 */
993 for (i = 0; i < replace->num_chains; i++) {
994 if (!(entries = replace->chains[i]))
995 continue;
996 if (i < NF_BR_NUMHOOKS)
997 /* (1 << NF_BR_NUMHOOKS) implies it's a standard chain
998 * (usefull in the final_check() funtions) */
999 entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
1000 else
1001 entries->hook_mask = 0;
1003 if (replace->num_chains == NF_BR_NUMHOOKS)
1004 return;
1005 stack = (struct ebt_u_stack *)malloc((replace->num_chains - NF_BR_NUMHOOKS) * sizeof(struct ebt_u_stack));
1006 if (!stack)
1007 ebt_print_memory();
1009 /* Check for loops, starting from every base chain */
1010 for (i = 0; i < NF_BR_NUMHOOKS; i++) {
1011 if (!(entries = replace->chains[i]))
1012 continue;
1013 chain_nr = i;
1015 e = entries->entries->next;
1016 for (j = 0; j < entries->nentries; j++) {
1017 if (strcmp(e->t->u.name, EBT_STANDARD_TARGET))
1018 goto letscontinue;
1019 verdict = ((struct ebt_standard_target *)(e->t))->verdict;
1020 if (verdict < 0)
1021 goto letscontinue;
1022 /* Now see if we've been here before */
1023 for (k = 0; k < sp; k++)
1024 if (stack[k].chain_nr == verdict + NF_BR_NUMHOOKS) {
1025 ebt_print_error("Loop from chain '%s' to chain '%s'",
1026 replace->chains[chain_nr]->name,
1027 replace->chains[stack[k].chain_nr]->name);
1028 goto free_stack;
1030 entries2 = replace->chains[verdict + NF_BR_NUMHOOKS];
1031 /* check if we've dealt with this chain already */
1032 if (entries2->hook_mask & (1<<i))
1033 goto letscontinue;
1034 entries2->hook_mask |= entries->hook_mask;
1035 /* Jump to the chain, make sure we know how to get back */
1036 stack[sp].chain_nr = chain_nr;
1037 stack[sp].n = j;
1038 stack[sp].entries = entries;
1039 stack[sp].e = e;
1040 sp++;
1041 j = -1;
1042 e = entries2->entries->next;
1043 chain_nr = verdict + NF_BR_NUMHOOKS;
1044 entries = entries2;
1045 continue;
1046 letscontinue:
1047 e = e->next;
1049 /* We are at the end of a standard chain */
1050 if (sp == 0)
1051 continue;
1052 /* Go back to the chain one level higher */
1053 sp--;
1054 j = stack[sp].n;
1055 chain_nr = stack[sp].chain_nr;
1056 e = stack[sp].e;
1057 entries = stack[sp].entries;
1058 goto letscontinue;
1060 free_stack:
1061 free(stack);
1062 return;
1065 /* The user will use the match, so put it in new_entry. The ebt_u_match
1066 * pointer is put in the ebt_entry_match pointer. ebt_add_rule will
1067 * fill in the final value for new->m. Unless the rule is added to a chain,
1068 * the pointer will keep pointing to the ebt_u_match (until the new_entry
1069 * is freed). I know, I should use a union for these 2 pointer types... */
1070 void ebt_add_match(struct ebt_u_entry *new_entry, struct ebt_u_match *m)
1072 struct ebt_u_match_list **m_list, *new;
1074 for (m_list = &new_entry->m_list; *m_list; m_list = &(*m_list)->next);
1075 new = (struct ebt_u_match_list *)
1076 malloc(sizeof(struct ebt_u_match_list));
1077 if (!new)
1078 ebt_print_memory();
1079 *m_list = new;
1080 new->next = NULL;
1081 new->m = (struct ebt_entry_match *)m;
1084 void ebt_add_watcher(struct ebt_u_entry *new_entry, struct ebt_u_watcher *w)
1086 struct ebt_u_watcher_list **w_list;
1087 struct ebt_u_watcher_list *new;
1089 for (w_list = &new_entry->w_list; *w_list; w_list = &(*w_list)->next);
1090 new = (struct ebt_u_watcher_list *)
1091 malloc(sizeof(struct ebt_u_watcher_list));
1092 if (!new)
1093 ebt_print_memory();
1094 *w_list = new;
1095 new->next = NULL;
1096 new->w = (struct ebt_entry_watcher *)w;
1101 *******************
1102 *******************
1103 **OTHER*FUNCTIONS**
1104 *******************
1105 *******************
1109 /* type = 0 => update chain jumps
1110 * type = 1 => check for reference, print error when referenced
1111 * type = 2 => check for reference, don't print error when referenced
1113 * Returns 1 when type == 1 and the chain is referenced
1114 * returns 0 otherwise */
1115 static int iterate_entries(struct ebt_u_replace *replace, int type)
1117 int i, j, chain_nr = replace->selected_chain - NF_BR_NUMHOOKS;
1118 struct ebt_u_entries *entries;
1119 struct ebt_u_entry *e;
1121 if (chain_nr < 0)
1122 ebt_print_bug("iterate_entries: udc = %d < 0", chain_nr);
1123 for (i = 0; i < replace->num_chains; i++) {
1124 if (!(entries = replace->chains[i]))
1125 continue;
1126 e = entries->entries->next;
1127 for (j = 0; j < entries->nentries; j++) {
1128 int chain_jmp;
1130 if (strcmp(e->t->u.name, EBT_STANDARD_TARGET)) {
1131 e = e->next;
1132 continue;
1134 chain_jmp = ((struct ebt_standard_target *)e->t)->
1135 verdict;
1136 switch (type) {
1137 case 1:
1138 case 2:
1139 if (chain_jmp == chain_nr) {
1140 if (type == 2)
1141 return 1;
1142 ebt_print_error("Can't delete the chain '%s', it's referenced in chain '%s', rule %d",
1143 replace->chains[chain_nr + NF_BR_NUMHOOKS]->name, entries->name, j);
1144 return 1;
1146 break;
1147 case 0:
1148 /* Adjust the chain jumps when necessary */
1149 if (chain_jmp > chain_nr)
1150 ((struct ebt_standard_target *)e->t)->verdict--;
1151 break;
1152 } /* End switch */
1153 e = e->next;
1156 return 0;
1159 static void decrease_chain_jumps(struct ebt_u_replace *replace)
1161 iterate_entries(replace, 0);
1164 /* Used in initialization code of modules */
1165 void ebt_register_match(struct ebt_u_match *m)
1167 int size = EBT_ALIGN(m->size) + sizeof(struct ebt_entry_match);
1168 struct ebt_u_match **i;
1170 m->m = (struct ebt_entry_match *)malloc(size);
1171 if (!m->m)
1172 ebt_print_memory();
1173 strcpy(m->m->u.name, m->name);
1174 m->m->match_size = EBT_ALIGN(m->size);
1175 m->init(m->m);
1177 for (i = &ebt_matches; *i; i = &((*i)->next));
1178 m->next = NULL;
1179 *i = m;
1182 void ebt_register_watcher(struct ebt_u_watcher *w)
1184 int size = EBT_ALIGN(w->size) + sizeof(struct ebt_entry_watcher);
1185 struct ebt_u_watcher **i;
1187 w->w = (struct ebt_entry_watcher *)malloc(size);
1188 if (!w->w)
1189 ebt_print_memory();
1190 strcpy(w->w->u.name, w->name);
1191 w->w->watcher_size = EBT_ALIGN(w->size);
1192 w->init(w->w);
1194 for (i = &ebt_watchers; *i; i = &((*i)->next));
1195 w->next = NULL;
1196 *i = w;
1199 void ebt_register_target(struct ebt_u_target *t)
1201 int size = EBT_ALIGN(t->size) + sizeof(struct ebt_entry_target);
1202 struct ebt_u_target **i;
1204 t->t = (struct ebt_entry_target *)malloc(size);
1205 if (!t->t)
1206 ebt_print_memory();
1207 strcpy(t->t->u.name, t->name);
1208 t->t->target_size = EBT_ALIGN(t->size);
1209 t->init(t->t);
1211 for (i = &ebt_targets; *i; i = &((*i)->next));
1212 t->next = NULL;
1213 *i = t;
1216 void ebt_register_table(struct ebt_u_table *t)
1218 t->next = ebt_tables;
1219 ebt_tables = t;
1222 void ebt_iterate_matches(void (*f)(struct ebt_u_match *))
1224 struct ebt_u_match *i;
1226 for (i = ebt_matches; i; i = i->next)
1227 f(i);
1230 void ebt_iterate_watchers(void (*f)(struct ebt_u_watcher *))
1232 struct ebt_u_watcher *i;
1234 for (i = ebt_watchers; i; i = i->next)
1235 f(i);
1238 void ebt_iterate_targets(void (*f)(struct ebt_u_target *))
1240 struct ebt_u_target *i;
1242 for (i = ebt_targets; i; i = i->next)
1243 f(i);
1246 /* Don't use this function, use ebt_print_bug() */
1247 void __ebt_print_bug(char *file, int line, char *format, ...)
1249 va_list l;
1251 va_start(l, format);
1252 fprintf(stderr, PROGNAME" v"PROGVERSION":%s:%d:--BUG--: \n", file, line);
1253 vfprintf(stderr, format, l);
1254 fprintf(stderr, "\n");
1255 va_end(l);
1256 exit (-1);
1259 /* The error messages are put in here when ebt_silent == 1
1260 * ebt_errormsg[0] == '\0' implies there was no error */
1261 char ebt_errormsg[ERRORMSG_MAXLEN];
1262 /* When error messages should not be printed on the screen, after which
1263 * the program exit()s, set ebt_silent to 1. */
1264 int ebt_silent;
1265 /* Don't use this function, use ebt_print_error() */
1266 void __ebt_print_error(char *format, ...)
1268 va_list l;
1270 va_start(l, format);
1271 if (ebt_silent && ebt_errormsg[0] == '\0') {
1272 vsnprintf(ebt_errormsg, ERRORMSG_MAXLEN, format, l);
1273 va_end(l);
1274 } else {
1275 vfprintf(stderr, format, l);
1276 fprintf(stderr, ".\n");
1277 va_end(l);
1278 exit (-1);