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