ubus: allow proto handlers to override device in announced rules
[project/firewall3.git] / includes.c
1 /*
2  * firewall3 - 3rd OpenWrt UCI firewall implementation
3  *
4  *   Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 #include "includes.h"
20
21
22 const struct fw3_option fw3_include_opts[] = {
23         FW3_OPT("enabled",             bool,           include,     enabled),
24
25         FW3_OPT("path",                string,         include,     path),
26         FW3_OPT("type",                include_type,   include,     type),
27         FW3_OPT("family",              family,         include,     family),
28         FW3_OPT("reload",              bool,           include,     reload),
29
30         { }
31 };
32
33
34 void
35 fw3_load_includes(struct fw3_state *state, struct uci_package *p)
36 {
37         struct uci_section *s;
38         struct uci_element *e;
39         struct fw3_include *include;
40
41         INIT_LIST_HEAD(&state->includes);
42
43         uci_foreach_element(&p->sections, e)
44         {
45                 s = uci_to_section(e);
46
47                 if (strcmp(s->type, "include"))
48                         continue;
49
50                 include = calloc(1, sizeof(*include));
51                 if (!include)
52                         continue;
53
54                 include->name = e->name;
55                 include->enabled = true;
56
57                 fw3_parse_options(include, fw3_include_opts, s);
58
59                 if (!include->enabled)
60                 {
61                         fw3_free_include(include);
62                         continue;
63                 }
64
65                 if (!include->path)
66                 {
67                         warn_elem(e, "must specify a path");
68                         fw3_free_include(include);
69                         continue;
70                 }
71
72                 if (include->type == FW3_INC_TYPE_RESTORE && !include->family)
73                         warn_elem(e, "does not specify a family, include will get loaded "
74                                      "with both iptables-restore and ip6tables-restore!");
75
76                 list_add_tail(&include->list, &state->includes);
77                 continue;
78         }
79 }
80
81
82 static void
83 print_include(struct fw3_include *include)
84 {
85         FILE *f;
86         char line[1024];
87
88         info(" * Loading include '%s'", include->path);
89
90         if (!(f = fopen(include->path, "r")))
91         {
92                 info("   ! Skipping due to open error: %s", strerror(errno));
93                 return;
94         }
95
96         while (fgets(line, sizeof(line), f))
97                 fw3_pr(line);
98
99         fclose(f);
100 }
101
102 void
103 fw3_print_includes(struct fw3_state *state, enum fw3_family family, bool reload)
104 {
105         struct fw3_include *include;
106
107         bool exec = false;
108         const char *restore = "iptables-restore";
109
110         if (family == FW3_FAMILY_V6)
111                 restore = "ip6tables-restore";
112
113         list_for_each_entry(include, &state->includes, list)
114         {
115                 if (reload && !include->reload)
116                         continue;
117
118                 if (include->type != FW3_INC_TYPE_RESTORE)
119                         continue;
120
121                 if (!fw3_is_family(include, family))
122                         continue;
123
124                 if (!exec)
125                 {
126                         exec = fw3_command_pipe(false, restore, "--noflush");
127
128                         if (!exec)
129                                 return;
130                 }
131
132                 print_include(include);
133         }
134
135         if (exec)
136                 fw3_command_close();
137 }
138
139
140 static void
141 run_include(struct fw3_include *include)
142 {
143         int rv;
144         struct stat s;
145         const char *tmpl =
146                 "config() { "
147                         "echo \"You cannot use UCI in firewall includes!\" >&2; "
148                         "exit 1; "
149                 "}; . %s";
150
151         char buf[PATH_MAX + sizeof(tmpl)];
152
153         info(" * Running script '%s'", include->path);
154
155         if (stat(include->path, &s))
156         {
157                 info("   ! Skipping due to path error: %s", strerror(errno));
158                 return;
159         }
160
161         snprintf(buf, sizeof(buf), tmpl, include->path);
162         rv = system(buf);
163
164         if (rv)
165                 info("   ! Failed with exit code %u", WEXITSTATUS(rv));
166 }
167
168 void
169 fw3_run_includes(struct fw3_state *state, bool reload)
170 {
171         struct fw3_include *include;
172
173         list_for_each_entry(include, &state->includes, list)
174         {
175                 if (reload && !include->reload)
176                         continue;
177
178                 if (include->type == FW3_INC_TYPE_SCRIPT)
179                         run_include(include);
180         }
181 }