Add luci, based upon commit : ae8ddb0ca6dfe98cb842fe2c01b36c4df55a0894
[librecmc/librecmc.git] / package / luci / applications / luci-app-openvpn / luasrc / model / cbi / openvpn.lua
1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Licensed to the public under the Apache License 2.0.
3
4 local fs  = require "nixio.fs"
5 local sys = require "luci.sys"
6 local uci = require "luci.model.uci".cursor()
7 local testfullps = sys.exec("ps --help 2>&1 | grep BusyBox") --check which ps do we have
8 local psstring = (string.len(testfullps)>0) and  "ps w" or  "ps axfw" --set command we use to get pid
9
10 local m = Map("openvpn", translate("OpenVPN"))
11 local s = m:section( TypedSection, "openvpn", translate("OpenVPN instances"), translate("Below is a list of configured OpenVPN instances and their current state") )
12 s.template = "cbi/tblsection"
13 s.template_addremove = "openvpn/cbi-select-input-add"
14 s.addremove = true
15 s.add_select_options = { }
16
17 local cfg = s:option(DummyValue, "config")
18 function cfg.cfgvalue(self, section)
19         local file_cfg = self.map:get(section, "config")
20         if file_cfg then
21                 s.extedit = luci.dispatcher.build_url("admin", "services", "openvpn", "file", "%s")
22         else
23                 s.extedit = luci.dispatcher.build_url("admin", "services", "openvpn", "basic", "%s")
24         end
25 end
26
27 uci:load("openvpn_recipes")
28 uci:foreach( "openvpn_recipes", "openvpn_recipe",
29         function(section)
30                 s.add_select_options[section['.name']] =
31                         section['_description'] or section['.name']
32         end
33 )
34
35 function s.getPID(section) -- Universal function which returns valid pid # or nil
36         local pid = sys.exec("%s | grep -w '[o]penvpn(%s)'" % { psstring, section })
37         if pid and #pid > 0 then
38                 return tonumber(pid:match("^%s*(%d+)"))
39         else
40                 return nil
41         end
42 end
43
44 function s.parse(self, section)
45         local recipe = luci.http.formvalue(
46                 luci.cbi.CREATE_PREFIX .. self.config .. "." ..
47                 self.sectiontype .. ".select"
48         )
49
50         if recipe and not s.add_select_options[recipe] then
51                 self.invalid_cts = true
52         else
53                 TypedSection.parse( self, section )
54         end
55 end
56
57 function s.create(self, name)
58         local recipe = luci.http.formvalue(
59                 luci.cbi.CREATE_PREFIX .. self.config .. "." ..
60                 self.sectiontype .. ".select"
61         )
62         local name = luci.http.formvalue(
63                 luci.cbi.CREATE_PREFIX .. self.config .. "." ..
64                 self.sectiontype .. ".text"
65         )
66         if #name > 3 and not name:match("[^a-zA-Z0-9_]") then
67                 local s = uci:section("openvpn", "openvpn", name)
68                 if s then
69                         local options = uci:get_all("openvpn_recipes", recipe)
70                         for k, v in pairs(options) do
71                                 if k ~= "_role" and k ~= "_description" then
72                                         if type(v) == "boolean" then
73                                                 v = v and "1" or "0"
74                                         end
75                                         uci:set("openvpn", name, k, v)
76                                 end
77                         end
78                         uci:save("openvpn")
79                         uci:commit("openvpn")
80                         if extedit then
81                                 luci.http.redirect( self.extedit:format(name) )
82                         end
83                 end
84         elseif #name > 0 then
85                 self.invalid_cts = true
86         end
87         return 0
88 end
89
90 function s.remove(self, name)
91         local cfg_file  = "/etc/openvpn/" ..name.. ".ovpn"
92         local auth_file = "/etc/openvpn/" ..name.. ".auth"
93         if fs.access(cfg_file) then
94                 fs.unlink(cfg_file)
95         end
96         if fs.access(auth_file) then
97                 fs.unlink(auth_file)
98         end
99         uci:delete("openvpn", name)
100         uci:save("openvpn")
101         uci:commit("openvpn")
102 end
103
104 s:option( Flag, "enabled", translate("Enabled") )
105
106 local active = s:option( DummyValue, "_active", translate("Started") )
107 function active.cfgvalue(self, section)
108         local pid = s.getPID(section)
109         if pid ~= nil then
110                 return (sys.process.signal(pid, 0))
111                         and translatef("yes (%i)", pid)
112                         or  translate("no")
113         end
114         return translate("no")
115 end
116
117 local updown = s:option( Button, "_updown", translate("Start/Stop") )
118 updown._state = false
119 updown.redirect = luci.dispatcher.build_url(
120         "admin", "services", "openvpn"
121 )
122 function updown.cbid(self, section)
123         local pid = s.getPID(section)
124         self._state = pid ~= nil and sys.process.signal(pid, 0)
125         self.option = self._state and "stop" or "start"
126         return AbstractValue.cbid(self, section)
127 end
128 function updown.cfgvalue(self, section)
129         self.title = self._state and "stop" or "start"
130         self.inputstyle = self._state and "reset" or "reload"
131 end
132 function updown.write(self, section, value)
133         if self.option == "stop" then
134                 sys.call("/etc/init.d/openvpn stop %s" % section)
135         else
136                 sys.call("/etc/init.d/openvpn start %s" % section)
137         end
138         luci.http.redirect( self.redirect )
139 end
140
141 local port = s:option( DummyValue, "port", translate("Port") )
142 function port.cfgvalue(self, section)
143         local val = AbstractValue.cfgvalue(self, section)
144         if not val then
145                 local file_cfg = self.map:get(section, "config")
146                 if file_cfg  and fs.access(file_cfg) then
147                         val = sys.exec("awk '{if(match(tolower($1),/^port$/)&&match($2,/[0-9]+/)){cnt++;printf $2;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
148                         if val == "-" then
149                                 val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match($3,/[0-9]+/)){cnt++;printf $3;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
150                         end
151                 end
152         end
153         return val or "-"
154 end
155
156 local proto = s:option( DummyValue, "proto", translate("Protocol") )
157 function proto.cfgvalue(self, section)
158         local val = AbstractValue.cfgvalue(self, section)
159         if not val then
160                 local file_cfg = self.map:get(section, "config")
161                 if file_cfg and fs.access(file_cfg) then
162                         val = sys.exec("awk '{if(match(tolower($1),/^proto$/)&&match(tolower($2),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf tolower($2);exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
163                         if val == "-" then
164                                 val = sys.exec("awk '{if(match(tolower($1),/^remote$/)&&match(tolower($4),/^udp[46]*$|^tcp[46]*-server$|^tcp[46]*-client$/)){cnt++;printf $4;exit}}END{if(cnt==0)printf \"-\"}' " ..file_cfg)
165                         end
166                 end
167         end
168         return val or "-"
169 end
170
171 function m.on_after_apply(self,map)
172         sys.call('/etc/init.d/openvpn reload')
173 end
174
175 return m