add support for includes
[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("path", string, include, path),
24 FW3_OPT("type", include_type, include, type),
25 FW3_OPT("family", family, include, family),
26
27 { }
28 };
29
30
31 void
32 fw3_load_includes(struct fw3_state *state, struct uci_package *p)
33 {
34 struct uci_section *s;
35 struct uci_element *e;
36 struct fw3_include *include;
37
38 INIT_LIST_HEAD(&state->includes);
39
40 uci_foreach_element(&p->sections, e)
41 {
42 s = uci_to_section(e);
43
44 if (strcmp(s->type, "include"))
45 continue;
46
47 include = malloc(sizeof(*include));
48
49 if (!include)
50 continue;
51
52 memset(include, 0, sizeof(*include));
53 include->name = e->name;
54
55 fw3_parse_options(include, fw3_include_opts, s);
56
57 if (!include->path)
58 {
59 warn_elem(e, "must specify a path");
60 fw3_free_include(include);
61 continue;
62 }
63
64 if (include->type == FW3_INC_TYPE_RESTORE && !include->family)
65 warn_elem(e, "does not specify a family, include will get loaded "
66 "with both iptables-restore and ip6tables-restore!");
67
68 list_add_tail(&include->list, &state->includes);
69 continue;
70 }
71 }
72
73
74 static void
75 print_include(enum fw3_family family, struct fw3_include *include)
76 {
77 FILE *f;
78 char line[1024];
79
80 if (!fw3_is_family(include, family))
81 return;
82
83 info(" * Loading include '%s'", include->path);
84
85 if (!(f = fopen(include->path, "r")))
86 {
87 info(" ! Skipping due to open error: %s", strerror(errno));
88 return;
89 }
90
91 while (fgets(line, sizeof(line), f))
92 fw3_pr(line);
93
94 fclose(f);
95 }
96
97 void
98 fw3_print_includes(enum fw3_family family, struct fw3_state *state)
99 {
100 struct fw3_include *include;
101
102 list_for_each_entry(include, &state->includes, list)
103 if (include->type == FW3_INC_TYPE_RESTORE)
104 print_include(family, include);
105 }
106
107
108 static void
109 run_include(struct fw3_include *include)
110 {
111 int rv;
112 struct stat s;
113 const char *tmpl =
114 "config() { "
115 "echo \"You cannot use UCI in firewall includes!\" >&2; "
116 "exit 1; "
117 "}; . %s";
118
119 char buf[PATH_MAX + sizeof(tmpl)];
120
121 info(" * Running script '%s'", include->path);
122
123 if (stat(include->path, &s))
124 {
125 info(" ! Skipping due to path error: %s", strerror(errno));
126 return;
127 }
128
129 snprintf(buf, sizeof(buf), tmpl, include->path);
130 rv = system(buf);
131
132 if (rv)
133 info(" ! Failed with exit code %u", WEXITSTATUS(rv));
134 }
135
136 void
137 fw3_run_includes(struct fw3_state *state)
138 {
139 struct fw3_include *include;
140
141 list_for_each_entry(include, &state->includes, list)
142 if (include->type == FW3_INC_TYPE_SCRIPT)
143 run_include(include);
144 }