79604c263f61eb542eee94cdbcd256e0e3091a2a
[project/luci.git] / applications / luci-firewall / luasrc / model / cbi / luci_fw / zones.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10         http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13 ]]--
14
15 local nw = require "luci.model.network"
16 local fw = require "luci.model.firewall"
17 local ds = require "luci.dispatcher"
18
19 local has_v2 = nixio.fs.access("/lib/firewall/fw.sh")
20
21 require("luci.tools.webadmin")
22 m = Map("firewall", translate("Firewall"), translate("The firewall creates zones over your network interfaces to control network traffic flow."))
23
24 fw.init(m.uci)
25 nw.init(m.uci)
26
27 s = m:section(TypedSection, "defaults")
28 s.anonymous = true
29 s.addremove = false
30
31 s:tab("general", translate("General Settings"))
32 s:tab("custom", translate("Custom Rules"))
33
34
35 s:taboption("general", Flag, "syn_flood", translate("Enable SYN-flood protection"))
36
37 local di = s:taboption("general", Flag, "drop_invalid", translate("Drop invalid packets"))
38 di.rmempty = false
39 function di.cfgvalue(...)
40         return AbstractValue.cfgvalue(...) or "1"
41 end
42
43 p = {}
44 p[1] = s:taboption("general", ListValue, "input", translate("Input"))
45 p[2] = s:taboption("general", ListValue, "output", translate("Output"))
46 p[3] = s:taboption("general", ListValue, "forward", translate("Forward"))
47
48 for i, v in ipairs(p) do
49         v:value("REJECT", translate("reject"))
50         v:value("DROP", translate("drop"))
51         v:value("ACCEPT", translate("accept"))
52 end
53
54 custom = s:taboption("custom", Value, "_custom",
55         translate("Custom Rules (/etc/firewall.user)"))
56
57 custom.template = "cbi/tvalue"
58 custom.rows = 20
59
60 function custom.cfgvalue(self, section)
61         return nixio.fs.readfile("/etc/firewall.user")
62 end
63
64 function custom.write(self, section, value)
65         value = value:gsub("\r\n?", "\n")
66         nixio.fs.writefile("/etc/firewall.user", value)
67 end
68
69
70 s = m:section(TypedSection, "zone", translate("Zones"))
71 s.template = "cbi/tblsection"
72 s.anonymous = true
73 s.addremove = true
74 s.extedit   = ds.build_url("admin", "network", "firewall", "zones", "%s")
75
76 function s.create(self)
77         local z = fw:new_zone()
78         if z then
79                 luci.http.redirect(
80                         ds.build_url("admin", "network", "firewall", "zones", z.sid)
81                 )
82         end
83 end
84
85 function s.remove(self, section)
86         return fw:del_zone(section)
87 end
88
89 info = s:option(DummyValue, "_info", translate("Zone ⇒ Forwardings"))
90 info.template = "cbi/firewall_zoneforwards"
91 function info.cfgvalue(self, section)
92         return self.map:get(section, "name")
93 end
94
95 p = {}
96 p[1] = s:option(ListValue, "input", translate("Input"))
97 p[2] = s:option(ListValue, "output", translate("Output"))
98 p[3] = s:option(ListValue, "forward", translate("Forward"))
99
100 for i, v in ipairs(p) do
101         v:value("REJECT", translate("reject"))
102         v:value("DROP", translate("drop"))
103         v:value("ACCEPT", translate("accept"))
104 end
105
106 s:option(Flag, "masq", translate("Masquerading"))
107 s:option(Flag, "mtu_fix", translate("MSS clamping"))
108
109
110 local created = nil
111
112 --
113 -- Redirects
114 --
115
116 s = m:section(TypedSection, "redirect", translate("Redirections"))
117 s.template  = "cbi/tblsection"
118 s.addremove = true
119 s.anonymous = true
120 s.sortable  = true
121 s.extedit   = ds.build_url("admin", "network", "firewall", "redirect", "%s")
122
123 function s.create(self, section)
124         created = TypedSection.create(self, section)
125 end
126
127 function s.parse(self, ...)
128         TypedSection.parse(self, ...)
129         if created then
130                 m.uci:save("firewall")
131                 luci.http.redirect(ds.build_url(
132                         "admin", "network", "firewall", "redirect", created
133                 ))
134         end
135 end
136
137 name = s:option(DummyValue, "_name", translate("Name"))
138 function name.cfgvalue(self, s)
139         return self.map:get(s, "_name") or "-"
140 end
141
142 proto = s:option(DummyValue, "proto", translate("Protocol"))
143 function proto.cfgvalue(self, s)
144         local p = self.map:get(s, "proto")
145         if not p or p == "tcpudp" then
146                 return "TCP+UDP"
147         else
148                 return p:upper()
149         end
150 end
151
152 src = s:option(DummyValue, "src", translate("Source"))
153 function src.cfgvalue(self, s)
154         local rv = "%s:%s:%s" % {
155                 self.map:get(s, "src") or "*",
156                 self.map:get(s, "src_ip") or "0.0.0.0/0",
157                 self.map:get(s, "src_port") or "*"
158         }
159
160         local mac = self.map:get(s, "src_mac")
161         if mac then
162                 rv = rv .. ", MAC " .. mac
163         end
164
165         return rv
166 end
167
168 via = s:option(DummyValue, "via", translate("Via"))
169 function via.cfgvalue(self, s)
170         return "%s:%s:%s" % {
171                 translate("Device"),
172                 self.map:get(s, "src_dip") or "0.0.0.0/0",
173                 self.map:get(s, "src_dport") or "*"
174         }
175 end
176
177 dest = s:option(DummyValue, "dest", translate("Destination"))
178 function dest.cfgvalue(self, s)
179         return "%s:%s:%s" % {
180                 self.map:get(s, "dest") or "*",
181                 self.map:get(s, "dest_ip") or "0.0.0.0/0",
182                 self.map:get(s, "dest_port") or "*"
183         }
184 end
185
186 target = s:option(DummyValue, "target", translate("Action"))
187 function target.cfgvalue(self, s)
188         return self.map:get(s, "target") or "DNAT"
189 end
190
191
192 --
193 -- Rules
194 --
195
196 s = m:section(TypedSection, "rule", translate("Rules"))
197 s.addremove = true
198 s.anonymous = true
199 s.sortable  = true
200 s.template = "cbi/tblsection"
201 s.extedit   = ds.build_url("admin", "network", "firewall", "rule", "%s")
202 s.defaults.target = "ACCEPT"
203
204 function s.create(self, section)
205         local created = TypedSection.create(self, section)
206         m.uci:save("firewall")
207         luci.http.redirect(ds.build_url(
208                 "admin", "network", "firewall", "rule", created
209         ))
210         return
211 end
212
213 name = s:option(DummyValue, "_name", translate("Name"))
214 function name.cfgvalue(self, s)
215         return self.map:get(s, "_name") or "-"
216 end
217
218 if has_v2 then
219         family = s:option(DummyValue, "family", translate("Family"))
220         function family.cfgvalue(self, s)
221                 local f = self.map:get(s, "family")
222                 if f and f:match("4") then
223                         return translate("IPv4 only")
224                 elseif f and f:match("6") then
225                         return translate("IPv6 only")
226                 else
227                         return translate("IPv4 and IPv6")
228                 end
229         end
230 end
231
232 proto = s:option(DummyValue, "proto", translate("Protocol"))
233 function proto.cfgvalue(self, s)
234         local p = self.map:get(s, "proto")
235         local t = self.map:get(s, "icmp_type")
236         if p == "icmp" and t then
237                 return "ICMP (%s)" % t
238         elseif p == "tcpudp" or not p then
239                 return "TCP+UDP"
240         else
241                 return p:upper()
242         end
243 end
244
245 src = s:option(DummyValue, "src", translate("Source"))
246 function src.cfgvalue(self, s)
247         local rv = "%s:%s:%s" % {
248                 self.map:get(s, "src") or "*",
249                 self.map:get(s, "src_ip") or "0.0.0.0/0",
250                 self.map:get(s, "src_port") or "*"
251         }
252
253         local mac = self.map:get(s, "src_mac")
254         if mac then
255                 rv = rv .. ", MAC " .. mac
256         end
257
258         return rv
259 end
260
261 dest = s:option(DummyValue, "dest", translate("Destination"))
262 function dest.cfgvalue(self, s)
263         return "%s:%s:%s" % {
264                 self.map:get(s, "dest") or translate("Device"),
265                 self.map:get(s, "dest_ip") or "0.0.0.0/0",
266                 self.map:get(s, "dest_port") or "*"
267         }
268 end
269
270
271 s:option(DummyValue, "target", translate("Action"))
272
273 return m