utils: define _GNU_SOURCE to get clearenv()
[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 = malloc(sizeof(*include));
51
52 if (!include)
53 continue;
54
55 memset(include, 0, sizeof(*include));
56
57 include->name = e->name;
58 include->enabled = true;
59
60 fw3_parse_options(include, fw3_include_opts, s);
61
62 if (!include->enabled)
63 {
64 fw3_free_include(include);
65 continue;
66 }
67
68 if (!include->path)
69 {
70 warn_elem(e, "must specify a path");
71 fw3_free_include(include);
72 continue;
73 }
74
75 if (include->type == FW3_INC_TYPE_RESTORE && !include->family)
76 warn_elem(e, "does not specify a family, include will get loaded "
77 "with both iptables-restore and ip6tables-restore!");
78
79 list_add_tail(&include->list, &state->includes);
80 continue;
81 }
82 }
83
84
85 static void
86 print_include(struct fw3_include *include)
87 {
88 FILE *f;
89 char line[1024];
90
91 info(" * Loading include '%s'", include->path);
92
93 if (!(f = fopen(include->path, "r")))
94 {
95 info(" ! Skipping due to open error: %s", strerror(errno));
96 return;
97 }
98
99 while (fgets(line, sizeof(line), f))
100 fw3_pr(line);
101
102 fclose(f);
103 }
104
105 void
106 fw3_print_includes(struct fw3_state *state, enum fw3_family family, bool reload)
107 {
108 struct fw3_include *include;
109
110 bool exec = false;
111 const char *restore = "iptables-restore";
112
113 if (family == FW3_FAMILY_V6)
114 restore = "ip6tables-restore";
115
116 list_for_each_entry(include, &state->includes, list)
117 {
118 if (reload && !include->reload)
119 continue;
120
121 if (include->type != FW3_INC_TYPE_RESTORE)
122 continue;
123
124 if (!fw3_is_family(include, family))
125 continue;
126
127 if (!exec)
128 {
129 exec = fw3_command_pipe(false, restore, "--noflush");
130
131 if (!exec)
132 return;
133 }
134
135 print_include(include);
136 }
137
138 if (exec)
139 fw3_command_close();
140 }
141
142
143 static void
144 run_include(struct fw3_include *include)
145 {
146 int rv;
147 struct stat s;
148 const char *tmpl =
149 "config() { "
150 "echo \"You cannot use UCI in firewall includes!\" >&2; "
151 "exit 1; "
152 "}; . %s";
153
154 char buf[PATH_MAX + sizeof(tmpl)];
155
156 info(" * Running script '%s'", include->path);
157
158 if (stat(include->path, &s))
159 {
160 info(" ! Skipping due to path error: %s", strerror(errno));
161 return;
162 }
163
164 snprintf(buf, sizeof(buf), tmpl, include->path);
165 rv = system(buf);
166
167 if (rv)
168 info(" ! Failed with exit code %u", WEXITSTATUS(rv));
169 }
170
171 void
172 fw3_run_includes(struct fw3_state *state, bool reload)
173 {
174 struct fw3_include *include;
175
176 list_for_each_entry(include, &state->includes, list)
177 {
178 if (reload && !include->reload)
179 continue;
180
181 if (include->type == FW3_INC_TYPE_SCRIPT)
182 run_include(include);
183 }
184 }