Also add comments for unnamed 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 = 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, enum fw3_family family)
87 {
88         FILE *f;
89         char line[1024];
90
91         if (!fw3_is_family(include, family))
92                 return;
93
94         info(" * Loading include '%s'", include->path);
95
96         if (!(f = fopen(include->path, "r")))
97         {
98                 info("   ! Skipping due to open error: %s", strerror(errno));
99                 return;
100         }
101
102         while (fgets(line, sizeof(line), f))
103                 fw3_pr(line);
104
105         fclose(f);
106 }
107
108 void
109 fw3_print_includes(struct fw3_state *state, enum fw3_family family, bool reload)
110 {
111         struct fw3_include *include;
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                         print_include(include, family);
120         }
121 }
122
123
124 static void
125 run_include(struct fw3_include *include)
126 {
127         int rv;
128         struct stat s;
129         const char *tmpl =
130                 "config() { "
131                         "echo \"You cannot use UCI in firewall includes!\" >&2; "
132                         "exit 1; "
133                 "}; . %s";
134
135         char buf[PATH_MAX + sizeof(tmpl)];
136
137         info(" * Running script '%s'", include->path);
138
139         if (stat(include->path, &s))
140         {
141                 info("   ! Skipping due to path error: %s", strerror(errno));
142                 return;
143         }
144
145         snprintf(buf, sizeof(buf), tmpl, include->path);
146         rv = system(buf);
147
148         if (rv)
149                 info("   ! Failed with exit code %u", WEXITSTATUS(rv));
150 }
151
152 void
153 fw3_run_includes(struct fw3_state *state, bool reload)
154 {
155         struct fw3_include *include;
156
157         list_for_each_entry(include, &state->includes, list)
158         {
159                 if (reload && !include->reload)
160                         continue;
161
162                 if (include->type == FW3_INC_TYPE_SCRIPT)
163                         run_include(include);
164         }
165 }