Install a moduli(5) manual page.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / backend / lua / lib / network.lua
1 -- lib/network.lua
2 -- $Id: network.lua,v 1.10 2005/03/27 01:19:41 cpressey Exp $
3 -- Lua abstraction for the Network Interfaces of a system.
4
5 -- BEGIN lib/network.lua --
6
7 require "app"
8 require "cmdchain"
9
10 --[[------------------]]--
11 --[[ NetworkInterface ]]--
12 --[[------------------]]--
13
14 --
15 -- This class returns an object which represents one of the system's
16 -- network interfaces.
17 --
18 -- This class is not typically instantiated directly by client code.
19 -- Instead, the user should call NetworkInterface.all() to get a table
20 -- of all network interfaces present in the system, and choose one.
21 --
22 NetworkInterface = {}
23 NetworkInterface.new = function(name)
24         local ni = {}                   -- instance variable
25         local desc = name               -- description of device
26         local up                        -- internal state...
27         local mtu
28         local inet6, prefixlen, scopeid
29         local inet, netmask, broadcast
30         local ether
31
32         local toboolean = function(x)
33                 if x then
34                         return true
35                 else
36                         return false
37                 end
38         end
39
40         --
41         -- Probe this network interface for its current state.
42         --
43         -- dc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
44         -- inet6 fe80::250:bfff:fe96:cf68%dc0 prefixlen 64 scopeid 0x1 
45         -- inet 10.0.0.19 netmask 0xffffff00 broadcast 10.0.0.255
46         -- ether 00:50:bf:96:cf:68
47         -- media: Ethernet autoselect (10baseT/UTP)
48         --
49         ni.probe = function(ni)
50                 local found, len, cap, flagstring
51                 local pty
52
53                 up = nil
54                 mtu = nil
55                 inet6, prefixlen, scopeid = nil, nil, nil
56                 inet, netmask, broadcast = nil, nil, nil
57
58                 pty = Pty.open(App.expand("${root}${IFCONFIG} ${name}", { name = name }))
59                 if not pty then
60                         return nil, "could not open pty"
61                 end
62                 line = pty:readline()
63                 while line do
64                         found, len, cap, flagstring =
65                             string.find(line, "flags%s*=%s*(%d+)%s*%<([^%>]*)%>")
66                         if found then
67                                 flagstring = "," .. flagstring .. ","
68                                 up = toboolean(string.find(flagstring, ",UP,"))
69                         end
70
71                         found, len, cap = string.find(line, "mtu%s*(%d+)")
72                         if found then
73                                 mtu = tonumber(cap)
74                         end
75                         found, len, cap = string.find(line, "inet6%s*([^%s]+)")
76                         if found then
77                                 inet6 = cap
78                         end
79                         found, len, cap = string.find(line, "prefixlen%s*(%d+)")
80                         if found then
81                                 prefixlen = tonumber(cap)
82                         end
83                         found, len, cap = string.find(line, "scopeid%s*0x(%x+)")
84                         if found then
85                                 scopeid = cap
86                         end
87                         found, len, cap = string.find(line, "inet%s*(%d+%.%d+%.%d+%.%d+)")
88                         if found then
89                                 inet = cap
90                         end
91                         found, len, cap = string.find(line, "netmask%s*0x(%x+)")
92                         if found then
93                                 netmask = cap
94                         end
95                         found, len, cap = string.find(line, "broadcast%s*(%d+%.%d+%.%d+%.%d+)")
96                         if found then
97                                 broadcast = cap
98                         end
99                         found, len, cap = string.find(line, "ether%s*(%x%x%:%x%x%:%x%x%:%x%x%:%x%x%:%x%x%)")
100                         if found then
101                                 ether = cap
102                         end
103                         line = pty:readline()
104                 end
105                 pty:close()
106         end
107
108         --
109         -- Accessor methods.
110         --
111
112         ni.is_up = function(ni)
113                 return up
114         end
115
116         ni.get_name = function(ni)
117                 return name
118         end
119
120         ni.get_inet_addr = function(ni)
121                 return inet
122         end
123
124         ni.get_netmask = function(ni)
125                 return netmask
126         end
127
128         ni.get_broadcast_addr = function(ni)
129                 return broadcast
130         end
131
132         ni.get_ether_addr = function(ni)
133                 return ether
134         end
135
136         ni.get_desc = function(ni)
137                 return desc
138         end
139
140         ni.set_desc = function(ni, new_desc)
141                 --
142                 -- Calculate a score for how well this string describes
143                 -- a network interface.  Reject obviously bogus descriptions
144                 -- (usually harvested from error messages in dmesg.)
145                 --
146                 local calculate_score = function(s)
147                         local score = 0
148
149                         -- In the absence of any good discriminator,
150                         -- the longest description wins.
151                         score = string.len(s)
152
153                         -- Look for clues
154                         if string.find(s, "%<.*%>") then
155                                 score = score + 10
156                         end
157
158                         -- Look for irrelevancies
159                         if string.find(s, "MII bus") then
160                                 score = 0
161                         end
162
163                         return score
164                 end
165
166                 if calculate_score(new_desc) > calculate_score(desc) then
167                         desc = new_desc
168                 end
169         end
170
171         --
172         -- Set the description of a device, as best we can, based on
173         -- the available system information.
174         --
175         ni.auto_describe = function(ni)
176                 --
177                 -- First give some common pseudo-devices some
178                 -- reasonable 'canned' descriptions.
179                 --
180                 local descs = {
181                     ["ppp%d+"] = "Point-to-Point Protocol device",
182                     ["sl%d+"] = "Serial Line IP device",
183                     ["faith%d+"] = "IPv6-to-IPv4 Tunnel device",
184                     ["lp%d+"] = "Network Line Printer device",
185                     ["lo%d+"] = "Loopback device"
186                 }
187                 for pat, desc in descs do
188                         if string.find(name, "^" .. pat .. "$") then
189                                 ni:set_desc(name .. ": " .. desc)
190                         end
191                 end
192
193                 --
194                 -- Now look through dmesg.boot for the names of
195                 -- physical network interface hardware.
196                 --
197                 for line in io.lines("/var/run/dmesg.boot") do
198                         local found, len, cap =
199                             string.find(line, "^" .. name .. ":.*(%<.*%>).*$")
200                         if found then
201                                 ni:set_desc(name .. ": " .. cap)
202                         end
203                 end
204         end
205
206         --
207         -- CmdChain-creating methods.
208         --
209
210         ni.cmds_assign_inet_addr = function(ni, cmds, addr)
211                 cmds:add({
212                     cmdline = "${root}${IFCONFIG} ${name} ${addr}",
213                     replacements = {
214                         name = name,
215                         addr = addr
216                     }
217                 })
218         end
219
220         ni.cmds_assign_netmask = function(ni, cmds, netmask)
221                 cmds:add({
222                     cmdline = "${root}${IFCONFIG} ${name} netmask ${netmask}",
223                     replacements = {
224                         name = name,
225                         netmask = netmask
226                     }
227                 })
228         end
229
230         ni.cmds_dhcp_configure = function(ni, cmds)
231                 cmds:add(
232                     {
233                         cmdline = "${root}${KILLALL} dhclient",
234                         failure_mode = CmdChain.FAILURE_IGNORE
235                     },
236                     {
237                         cmdline = "${root}${DHCLIENT} -1 ${name}",
238                         replacements = {
239                             name = name
240                         }
241                     }
242                 )
243         end
244
245         return ni
246 end
247
248 --[[-------------------]]--
249 --[[ NetworkInterfaces ]]--
250 --[[-------------------]]--
251
252 --
253 -- A container/aggregate class.  Contains a bunch of NetworkInterface
254 -- objects, typically the set of those available on a given system.
255 --
256
257 NetworkInterfaces = {}
258
259 NetworkInterfaces.new = function()
260         local ni_tab = {}
261         local method = {}
262
263         method.add = function(nis)
264                 ni_tab[ni.name] = ni
265         end
266
267         method.get = function(nis, name)
268                 return ni_tab[name]
269         end
270
271         -- Iterator, typically used in for loops.
272         method.each = function(nis)
273                 local name, ni
274                 local list = {}
275                 local i, n = 0, 0
276                 
277                 for name, ni in ni_tab do
278                         table.insert(list, ni)
279                         n = n + 1
280                 end
281
282                 table.sort(list, function(a, b)
283                         return a:get_name() < b:get_name()
284                 end)
285
286                 return function()
287                         if i <= n then
288                                 i = i + 1
289                                 return list[i]
290                         end
291                 end
292         end
293
294         --
295         -- Populate the NetworkInterface collection with all the
296         -- network interfaces detected as present in the system.
297         --
298         method.probe = function(nis)
299                 local pty, line, name, ni, line, pat, desc
300
301                 pty = Pty.open(App.expand("${root}${IFCONFIG} -l"))
302                 if not pty then
303                         return nil, "could not open pty"
304                 end
305                 line = pty:readline()
306                 pty:close()
307
308                 ni_tab = {}
309
310                 for name in string.gfind(line, "%s*([^%s]+)%s*") do
311                         ni = NetworkInterface.new(name)
312                         ni:probe()
313                         ni:auto_describe()
314                         ni_tab[name] = ni
315                 end
316
317                 return nis
318         end
319
320         --
321         -- Returns the number of configured IP addresses of all the
322         -- NetworkInterface objects in this NetworkInterfaces object.
323         --
324         -- Practically, used for asking "Uh, is the network on?"  :)
325         --
326         method.ip_addr_count = function(nis)
327                 local name, ni
328                 local num = 0
329
330                 for name, ni in ni_tab do
331                         ip_addr = ni:get_inet_addr()
332                         if ip_addr and not string.find(ip_addr, "^127%..*$") then
333                                 num = num + 1
334                         end
335                 end
336
337                 return num
338         end
339
340         --
341         -- User-interface methods.
342         --
343
344         --
345         -- Display a dialog box, allow the user to select which
346         -- network interface they want to use.
347         --
348         method.ui_select_interface = function(nis, tab)
349                 local actions, ni, ifname
350                 if not tab then tab = {} end
351                 local ui = tab.ui or App.ui
352                 local id = tab.id or "select_interface"
353                 local name = tab.name or _("Select Network Interface")
354                 local short_desc = tab.short_desc or _(
355                     "Please select the network interface you wish to configure."
356                 )
357
358                 --
359                 -- Get interface list.
360                 --
361                 actions = {}
362                 for ni in nis:each() do
363                         table.insert(actions, {
364                             id = ni:get_name(),
365                             name = ni:get_desc()
366                         })
367                 end
368                 table.insert(actions, {
369                     id = "cancel",
370                     name = "Cancel"
371                 })
372         
373                 ifname = App.ui:present({
374                     id = id,
375                     name =  name,
376                     short_desc = short_desc,
377                     role = "menu",
378                     actions = actions
379                 }).action_id
380         
381                 if ifname == "cancel" then
382                         return nil
383                 else
384                         return nis:get(ifname)
385                 end
386         end
387
388         return method
389 end
390
391 -- END of lib/network.lua --