network.lua 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700
  1. -- Copyright 2009-2015 Jo-Philipp Wich <jow@openwrt.org>
  2. -- Licensed to the public under the Apache License 2.0.
  3. local type, next, pairs, ipairs, loadfile, table, select
  4. = type, next, pairs, ipairs, loadfile, table, select
  5. local tonumber, tostring, math = tonumber, tostring, math
  6. local require = require
  7. local nxo = require "nixio"
  8. local nfs = require "nixio.fs"
  9. local ipc = require "luci.ip"
  10. local sys = require "luci.sys"
  11. local utl = require "luci.util"
  12. local dsp = require "luci.dispatcher"
  13. local uci = require "luci.model.uci"
  14. local lng = require "luci.i18n"
  15. local jsc = require "luci.jsonc"
  16. module "luci.model.network"
  17. IFACE_PATTERNS_VIRTUAL = { }
  18. IFACE_PATTERNS_IGNORE = { "^wmaster%d", "^wifi%d", "^hwsim%d", "^imq%d", "^ifb%d", "^mon%.wlan%d", "^sit%d", "^gre%d", "^gretap%d", "^ip6gre%d", "^ip6tnl%d", "^tunl%d", "^lo$" }
  19. IFACE_PATTERNS_WIRELESS = { "^wlan%d", "^wl%d", "^ath%d", "^%w+%.network%d" }
  20. protocol = utl.class()
  21. local _protocols = { }
  22. local _interfaces, _bridge, _switch, _tunnel, _swtopo
  23. local _ubusnetcache, _ubusdevcache, _ubuswificache
  24. local _uci
  25. function _filter(c, s, o, r)
  26. local val = _uci:get(c, s, o)
  27. if val then
  28. local l = { }
  29. if type(val) == "string" then
  30. for val in val:gmatch("%S+") do
  31. if val ~= r then
  32. l[#l+1] = val
  33. end
  34. end
  35. if #l > 0 then
  36. _uci:set(c, s, o, table.concat(l, " "))
  37. else
  38. _uci:delete(c, s, o)
  39. end
  40. elseif type(val) == "table" then
  41. for _, val in ipairs(val) do
  42. if val ~= r then
  43. l[#l+1] = val
  44. end
  45. end
  46. if #l > 0 then
  47. _uci:set(c, s, o, l)
  48. else
  49. _uci:delete(c, s, o)
  50. end
  51. end
  52. end
  53. end
  54. function _append(c, s, o, a)
  55. local val = _uci:get(c, s, o) or ""
  56. if type(val) == "string" then
  57. local l = { }
  58. for val in val:gmatch("%S+") do
  59. if val ~= a then
  60. l[#l+1] = val
  61. end
  62. end
  63. l[#l+1] = a
  64. _uci:set(c, s, o, table.concat(l, " "))
  65. elseif type(val) == "table" then
  66. local l = { }
  67. for _, val in ipairs(val) do
  68. if val ~= a then
  69. l[#l+1] = val
  70. end
  71. end
  72. l[#l+1] = a
  73. _uci:set(c, s, o, l)
  74. end
  75. end
  76. function _stror(s1, s2)
  77. if not s1 or #s1 == 0 then
  78. return s2 and #s2 > 0 and s2
  79. else
  80. return s1
  81. end
  82. end
  83. function _get(c, s, o)
  84. return _uci:get(c, s, o)
  85. end
  86. function _set(c, s, o, v)
  87. if v ~= nil then
  88. if type(v) == "boolean" then v = v and "1" or "0" end
  89. return _uci:set(c, s, o, v)
  90. else
  91. return _uci:delete(c, s, o)
  92. end
  93. end
  94. function _wifi_iface(x)
  95. local _, p
  96. for _, p in ipairs(IFACE_PATTERNS_WIRELESS) do
  97. if x:match(p) then
  98. return true
  99. end
  100. end
  101. return false
  102. end
  103. function _wifi_state(key, val, field)
  104. local radio, radiostate, ifc, ifcstate
  105. if not next(_ubuswificache) then
  106. _ubuswificache = utl.ubus("network.wireless", "status", {}) or {}
  107. -- workaround extended section format
  108. for radio, radiostate in pairs(_ubuswificache) do
  109. for ifc, ifcstate in pairs(radiostate.interfaces) do
  110. if ifcstate.section and ifcstate.section:sub(1, 1) == '@' then
  111. local s = _uci:get_all('wireless.%s' % ifcstate.section)
  112. if s then
  113. ifcstate.section = s['.name']
  114. end
  115. end
  116. end
  117. end
  118. end
  119. for radio, radiostate in pairs(_ubuswificache) do
  120. for ifc, ifcstate in pairs(radiostate.interfaces) do
  121. if ifcstate[key] == val then
  122. return ifcstate[field]
  123. end
  124. end
  125. end
  126. end
  127. function _wifi_lookup(ifn)
  128. -- got a radio#.network# pseudo iface, locate the corresponding section
  129. local radio, ifnidx = ifn:match("^(%w+)%.network(%d+)$")
  130. if radio and ifnidx then
  131. local sid = nil
  132. local num = 0
  133. ifnidx = tonumber(ifnidx)
  134. _uci:foreach("wireless", "wifi-iface",
  135. function(s)
  136. if s.device == radio then
  137. num = num + 1
  138. if num == ifnidx then
  139. sid = s['.name']
  140. return false
  141. end
  142. end
  143. end)
  144. return sid
  145. -- looks like wifi, try to locate the section via ubus state
  146. elseif _wifi_iface(ifn) then
  147. return _wifi_state("ifname", ifn, "section")
  148. end
  149. end
  150. function _iface_virtual(x)
  151. local _, p
  152. for _, p in ipairs(IFACE_PATTERNS_VIRTUAL) do
  153. if x:match(p) then
  154. return true
  155. end
  156. end
  157. return false
  158. end
  159. function _iface_ignore(x)
  160. local _, p
  161. for _, p in ipairs(IFACE_PATTERNS_IGNORE) do
  162. if x:match(p) then
  163. return true
  164. end
  165. end
  166. return false
  167. end
  168. function init(cursor)
  169. _uci = cursor or _uci or uci.cursor()
  170. _interfaces = { }
  171. _bridge = { }
  172. _switch = { }
  173. _tunnel = { }
  174. _swtopo = { }
  175. _ubusnetcache = { }
  176. _ubusdevcache = { }
  177. _ubuswificache = { }
  178. -- read interface information
  179. local n, i
  180. for n, i in ipairs(nxo.getifaddrs()) do
  181. local name = i.name:match("[^:]+")
  182. if _iface_virtual(name) then
  183. _tunnel[name] = true
  184. end
  185. if _tunnel[name] or not (_iface_ignore(name) or _iface_virtual(name)) then
  186. _interfaces[name] = _interfaces[name] or {
  187. idx = i.ifindex or n,
  188. name = name,
  189. rawname = i.name,
  190. flags = { },
  191. ipaddrs = { },
  192. ip6addrs = { }
  193. }
  194. if i.family == "packet" then
  195. _interfaces[name].flags = i.flags
  196. _interfaces[name].stats = i.data
  197. _interfaces[name].macaddr = i.addr
  198. elseif i.family == "inet" then
  199. _interfaces[name].ipaddrs[#_interfaces[name].ipaddrs+1] = ipc.IPv4(i.addr, i.netmask)
  200. elseif i.family == "inet6" then
  201. _interfaces[name].ip6addrs[#_interfaces[name].ip6addrs+1] = ipc.IPv6(i.addr, i.netmask)
  202. end
  203. end
  204. end
  205. -- read bridge informaton
  206. local b, l
  207. for l in utl.execi("brctl show") do
  208. if not l:match("STP") then
  209. local r = utl.split(l, "%s+", nil, true)
  210. if #r == 4 then
  211. b = {
  212. name = r[1],
  213. id = r[2],
  214. stp = r[3] == "yes",
  215. ifnames = { _interfaces[r[4]] }
  216. }
  217. if b.ifnames[1] then
  218. b.ifnames[1].bridge = b
  219. end
  220. _bridge[r[1]] = b
  221. elseif b then
  222. b.ifnames[#b.ifnames+1] = _interfaces[r[2]]
  223. b.ifnames[#b.ifnames].bridge = b
  224. end
  225. end
  226. end
  227. -- read switch topology
  228. local boardinfo = jsc.parse(nfs.readfile("/etc/board.json") or "")
  229. if type(boardinfo) == "table" and type(boardinfo.switch) == "table" then
  230. local switch, layout
  231. for switch, layout in pairs(boardinfo.switch) do
  232. if type(layout) == "table" and type(layout.ports) == "table" then
  233. local _, port
  234. local ports = { }
  235. local nports = { }
  236. local netdevs = { }
  237. for _, port in ipairs(layout.ports) do
  238. if type(port) == "table" and
  239. type(port.num) == "number" and
  240. (type(port.role) == "string" or
  241. type(port.device) == "string")
  242. then
  243. local spec = {
  244. num = port.num,
  245. role = port.role or "cpu",
  246. index = port.index or port.num
  247. }
  248. if port.device then
  249. spec.device = port.device
  250. spec.tagged = port.need_tag
  251. netdevs[tostring(port.num)] = port.device
  252. end
  253. ports[#ports+1] = spec
  254. if port.role then
  255. nports[port.role] = (nports[port.role] or 0) + 1
  256. end
  257. end
  258. end
  259. table.sort(ports, function(a, b)
  260. if a.role ~= b.role then
  261. return (a.role < b.role)
  262. end
  263. return (a.index < b.index)
  264. end)
  265. local pnum, role
  266. for _, port in ipairs(ports) do
  267. if port.role ~= role then
  268. role = port.role
  269. pnum = 1
  270. end
  271. if role == "cpu" then
  272. port.label = "CPU (%s)" % port.device
  273. elseif nports[role] > 1 then
  274. port.label = "%s %d" %{ role:upper(), pnum }
  275. pnum = pnum + 1
  276. else
  277. port.label = role:upper()
  278. end
  279. port.role = nil
  280. port.index = nil
  281. end
  282. _swtopo[switch] = {
  283. ports = ports,
  284. netdevs = netdevs
  285. }
  286. end
  287. end
  288. end
  289. return _M
  290. end
  291. function save(self, ...)
  292. _uci:save(...)
  293. _uci:load(...)
  294. end
  295. function commit(self, ...)
  296. _uci:commit(...)
  297. _uci:load(...)
  298. end
  299. function ifnameof(self, x)
  300. if utl.instanceof(x, interface) then
  301. return x:name()
  302. elseif utl.instanceof(x, protocol) then
  303. return x:ifname()
  304. elseif type(x) == "string" then
  305. return x:match("^[^:]+")
  306. end
  307. end
  308. function get_protocol(self, protoname, netname)
  309. local v = _protocols[protoname]
  310. if v then
  311. return v(netname or "__dummy__")
  312. end
  313. end
  314. function get_protocols(self)
  315. local p = { }
  316. local _, v
  317. for _, v in ipairs(_protocols) do
  318. p[#p+1] = v("__dummy__")
  319. end
  320. return p
  321. end
  322. function register_protocol(self, protoname)
  323. local proto = utl.class(protocol)
  324. function proto.__init__(self, name)
  325. self.sid = name
  326. end
  327. function proto.proto(self)
  328. return protoname
  329. end
  330. _protocols[#_protocols+1] = proto
  331. _protocols[protoname] = proto
  332. return proto
  333. end
  334. function register_pattern_virtual(self, pat)
  335. IFACE_PATTERNS_VIRTUAL[#IFACE_PATTERNS_VIRTUAL+1] = pat
  336. end
  337. function has_ipv6(self)
  338. return nfs.access("/proc/net/ipv6_route")
  339. end
  340. function add_network(self, n, options)
  341. local oldnet = self:get_network(n)
  342. if n and #n > 0 and n:match("^[a-zA-Z0-9_]+$") and not oldnet then
  343. if _uci:section("network", "interface", n, options) then
  344. return network(n)
  345. end
  346. elseif oldnet and oldnet:is_empty() then
  347. if options then
  348. local k, v
  349. for k, v in pairs(options) do
  350. oldnet:set(k, v)
  351. end
  352. end
  353. return oldnet
  354. end
  355. end
  356. function get_network(self, n)
  357. if n and _uci:get("network", n) == "interface" then
  358. return network(n)
  359. end
  360. end
  361. function get_networks(self)
  362. local nets = { }
  363. local nls = { }
  364. _uci:foreach("network", "interface",
  365. function(s)
  366. nls[s['.name']] = network(s['.name'])
  367. end)
  368. local n
  369. for n in utl.kspairs(nls) do
  370. nets[#nets+1] = nls[n]
  371. end
  372. return nets
  373. end
  374. function del_network(self, n)
  375. local r = _uci:delete("network", n)
  376. if r then
  377. _uci:delete_all("network", "alias",
  378. function(s) return (s.interface == n) end)
  379. _uci:delete_all("network", "route",
  380. function(s) return (s.interface == n) end)
  381. _uci:delete_all("network", "route6",
  382. function(s) return (s.interface == n) end)
  383. _uci:foreach("wireless", "wifi-iface",
  384. function(s)
  385. local net
  386. local rest = { }
  387. for net in utl.imatch(s.network) do
  388. if net ~= n then
  389. rest[#rest+1] = net
  390. end
  391. end
  392. if #rest > 0 then
  393. _uci:set("wireless", s['.name'], "network",
  394. table.concat(rest, " "))
  395. else
  396. _uci:delete("wireless", s['.name'], "network")
  397. end
  398. end)
  399. end
  400. return r
  401. end
  402. function rename_network(self, old, new)
  403. local r
  404. if new and #new > 0 and new:match("^[a-zA-Z0-9_]+$") and not self:get_network(new) then
  405. r = _uci:section("network", "interface", new, _uci:get_all("network", old))
  406. if r then
  407. _uci:foreach("network", "alias",
  408. function(s)
  409. if s.interface == old then
  410. _uci:set("network", s['.name'], "interface", new)
  411. end
  412. end)
  413. _uci:foreach("network", "route",
  414. function(s)
  415. if s.interface == old then
  416. _uci:set("network", s['.name'], "interface", new)
  417. end
  418. end)
  419. _uci:foreach("network", "route6",
  420. function(s)
  421. if s.interface == old then
  422. _uci:set("network", s['.name'], "interface", new)
  423. end
  424. end)
  425. _uci:foreach("wireless", "wifi-iface",
  426. function(s)
  427. local net
  428. local list = { }
  429. for net in utl.imatch(s.network) do
  430. if net == old then
  431. list[#list+1] = new
  432. else
  433. list[#list+1] = net
  434. end
  435. end
  436. if #list > 0 then
  437. _uci:set("wireless", s['.name'], "network",
  438. table.concat(list, " "))
  439. end
  440. end)
  441. _uci:delete("network", old)
  442. end
  443. end
  444. return r or false
  445. end
  446. function get_interface(self, i)
  447. if _interfaces[i] or _wifi_iface(i) then
  448. return interface(i)
  449. else
  450. local ifc
  451. local num = { }
  452. _uci:foreach("wireless", "wifi-iface",
  453. function(s)
  454. if s.device then
  455. num[s.device] = num[s.device] and num[s.device] + 1 or 1
  456. if s['.name'] == i then
  457. ifc = interface(
  458. "%s.network%d" %{s.device, num[s.device] })
  459. return false
  460. end
  461. end
  462. end)
  463. return ifc
  464. end
  465. end
  466. function get_interfaces(self)
  467. local iface
  468. local ifaces = { }
  469. local nfs = { }
  470. -- find normal interfaces
  471. _uci:foreach("network", "interface",
  472. function(s)
  473. for iface in utl.imatch(s.ifname) do
  474. if not _iface_ignore(iface) and not _iface_virtual(iface) and not _wifi_iface(iface) then
  475. nfs[iface] = interface(iface)
  476. end
  477. end
  478. end)
  479. for iface in utl.kspairs(_interfaces) do
  480. if not (nfs[iface] or _iface_ignore(iface) or _iface_virtual(iface) or _wifi_iface(iface)) then
  481. nfs[iface] = interface(iface)
  482. end
  483. end
  484. -- find vlan interfaces
  485. _uci:foreach("network", "switch_vlan",
  486. function(s)
  487. if type(s.ports) ~= "string" or
  488. type(s.device) ~= "string" or
  489. type(_swtopo[s.device]) ~= "table"
  490. then
  491. return
  492. end
  493. local pnum, ptag
  494. for pnum, ptag in s.ports:gmatch("(%d+)([tu]?)") do
  495. local netdev = _swtopo[s.device].netdevs[pnum]
  496. if netdev then
  497. if not nfs[netdev] then
  498. nfs[netdev] = interface(netdev)
  499. end
  500. _switch[netdev] = true
  501. if ptag == "t" then
  502. local vid = tonumber(s.vid or s.vlan)
  503. if vid ~= nil and vid >= 0 and vid <= 4095 then
  504. local iface = "%s.%d" %{ netdev, vid }
  505. if not nfs[iface] then
  506. nfs[iface] = interface(iface)
  507. end
  508. _switch[iface] = true
  509. end
  510. end
  511. end
  512. end
  513. end)
  514. for iface in utl.kspairs(nfs) do
  515. ifaces[#ifaces+1] = nfs[iface]
  516. end
  517. -- find wifi interfaces
  518. local num = { }
  519. local wfs = { }
  520. _uci:foreach("wireless", "wifi-iface",
  521. function(s)
  522. if s.device then
  523. num[s.device] = num[s.device] and num[s.device] + 1 or 1
  524. local i = "%s.network%d" %{ s.device, num[s.device] }
  525. wfs[i] = interface(i)
  526. end
  527. end)
  528. for iface in utl.kspairs(wfs) do
  529. ifaces[#ifaces+1] = wfs[iface]
  530. end
  531. return ifaces
  532. end
  533. function ignore_interface(self, x)
  534. return _iface_ignore(x)
  535. end
  536. function get_wifidev(self, dev)
  537. if _uci:get("wireless", dev) == "wifi-device" then
  538. return wifidev(dev)
  539. end
  540. end
  541. function get_wifidevs(self)
  542. local devs = { }
  543. local wfd = { }
  544. _uci:foreach("wireless", "wifi-device",
  545. function(s) wfd[#wfd+1] = s['.name'] end)
  546. local dev
  547. for _, dev in utl.vspairs(wfd) do
  548. devs[#devs+1] = wifidev(dev)
  549. end
  550. return devs
  551. end
  552. function get_wifinet(self, net)
  553. local wnet = _wifi_lookup(net)
  554. if wnet then
  555. return wifinet(wnet)
  556. end
  557. end
  558. function add_wifinet(self, net, options)
  559. if type(options) == "table" and options.device and
  560. _uci:get("wireless", options.device) == "wifi-device"
  561. then
  562. local wnet = _uci:section("wireless", "wifi-iface", nil, options)
  563. return wifinet(wnet)
  564. end
  565. end
  566. function del_wifinet(self, net)
  567. local wnet = _wifi_lookup(net)
  568. if wnet then
  569. _uci:delete("wireless", wnet)
  570. return true
  571. end
  572. return false
  573. end
  574. function get_status_by_route(self, addr, mask)
  575. local _, object
  576. for _, object in ipairs(utl.ubus()) do
  577. local net = object:match("^network%.interface%.(.+)")
  578. if net then
  579. local s = utl.ubus(object, "status", {})
  580. if s and s.route then
  581. local rt
  582. for _, rt in ipairs(s.route) do
  583. if not rt.table and rt.target == addr and rt.mask == mask then
  584. return net, s
  585. end
  586. end
  587. end
  588. end
  589. end
  590. end
  591. function get_status_by_address(self, addr)
  592. local _, object
  593. for _, object in ipairs(utl.ubus()) do
  594. local net = object:match("^network%.interface%.(.+)")
  595. if net then
  596. local s = utl.ubus(object, "status", {})
  597. if s and s['ipv4-address'] then
  598. local a
  599. for _, a in ipairs(s['ipv4-address']) do
  600. if a.address == addr then
  601. return net, s
  602. end
  603. end
  604. end
  605. if s and s['ipv6-address'] then
  606. local a
  607. for _, a in ipairs(s['ipv6-address']) do
  608. if a.address == addr then
  609. return net, s
  610. end
  611. end
  612. end
  613. end
  614. end
  615. end
  616. function get_wannet(self)
  617. local net, stat = self:get_status_by_route("0.0.0.0", 0)
  618. return net and network(net, stat.proto)
  619. end
  620. function get_wandev(self)
  621. local _, stat = self:get_status_by_route("0.0.0.0", 0)
  622. return stat and interface(stat.l3_device or stat.device)
  623. end
  624. function get_wan6net(self)
  625. local net, stat = self:get_status_by_route("::", 0)
  626. return net and network(net, stat.proto)
  627. end
  628. function get_wan6dev(self)
  629. local _, stat = self:get_status_by_route("::", 0)
  630. return stat and interface(stat.l3_device or stat.device)
  631. end
  632. function get_switch_topologies(self)
  633. return _swtopo
  634. end
  635. function network(name, proto)
  636. if name then
  637. local p = proto or _uci:get("network", name, "proto")
  638. local c = p and _protocols[p] or protocol
  639. return c(name)
  640. end
  641. end
  642. function protocol.__init__(self, name)
  643. self.sid = name
  644. end
  645. function protocol._get(self, opt)
  646. local v = _uci:get("network", self.sid, opt)
  647. if type(v) == "table" then
  648. return table.concat(v, " ")
  649. end
  650. return v or ""
  651. end
  652. function protocol._ubus(self, field)
  653. if not _ubusnetcache[self.sid] then
  654. _ubusnetcache[self.sid] = utl.ubus("network.interface.%s" % self.sid,
  655. "status", { })
  656. end
  657. if _ubusnetcache[self.sid] and field then
  658. return _ubusnetcache[self.sid][field]
  659. end
  660. return _ubusnetcache[self.sid]
  661. end
  662. function protocol.get(self, opt)
  663. return _get("network", self.sid, opt)
  664. end
  665. function protocol.set(self, opt, val)
  666. return _set("network", self.sid, opt, val)
  667. end
  668. function protocol.ifname(self)
  669. local ifname
  670. if self:is_floating() then
  671. ifname = self:_ubus("l3_device")
  672. else
  673. ifname = self:_ubus("device")
  674. end
  675. if not ifname then
  676. local num = { }
  677. _uci:foreach("wireless", "wifi-iface",
  678. function(s)
  679. if s.device then
  680. num[s.device] = num[s.device]
  681. and num[s.device] + 1 or 1
  682. local net
  683. for net in utl.imatch(s.network) do
  684. if net == self.sid then
  685. ifname = "%s.network%d" %{ s.device, num[s.device] }
  686. return false
  687. end
  688. end
  689. end
  690. end)
  691. end
  692. return ifname
  693. end
  694. function protocol.proto(self)
  695. return "none"
  696. end
  697. function protocol.get_i18n(self)
  698. local p = self:proto()
  699. if p == "none" then
  700. return lng.translate("Unmanaged")
  701. elseif p == "static" then
  702. return lng.translate("Static address")
  703. elseif p == "dhcp" then
  704. return lng.translate("DHCP client")
  705. else
  706. return lng.translate("Unknown")
  707. end
  708. end
  709. function protocol.type(self)
  710. return self:_get("type")
  711. end
  712. function protocol.name(self)
  713. return self.sid
  714. end
  715. function protocol.uptime(self)
  716. return self:_ubus("uptime") or 0
  717. end
  718. function protocol.expires(self)
  719. local u = self:_ubus("uptime")
  720. local d = self:_ubus("data")
  721. if type(u) == "number" and type(d) == "table" and
  722. type(d.leasetime) == "number"
  723. then
  724. local r = (d.leasetime - (u % d.leasetime))
  725. return r > 0 and r or 0
  726. end
  727. return -1
  728. end
  729. function protocol.metric(self)
  730. return self:_ubus("metric") or 0
  731. end
  732. function protocol.ipaddr(self)
  733. local addrs = self:_ubus("ipv4-address")
  734. return addrs and #addrs > 0 and addrs[1].address
  735. end
  736. function protocol.ipaddrs(self)
  737. local addrs = self:_ubus("ipv4-address")
  738. local rv = { }
  739. if type(addrs) == "table" then
  740. local n, addr
  741. for n, addr in ipairs(addrs) do
  742. rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
  743. end
  744. end
  745. return rv
  746. end
  747. function protocol.netmask(self)
  748. local addrs = self:_ubus("ipv4-address")
  749. return addrs and #addrs > 0 and
  750. ipc.IPv4("0.0.0.0/%d" % addrs[1].mask):mask():string()
  751. end
  752. function protocol.gwaddr(self)
  753. local _, route
  754. for _, route in ipairs(self:_ubus("route") or { }) do
  755. if route.target == "0.0.0.0" and route.mask == 0 then
  756. return route.nexthop
  757. end
  758. end
  759. end
  760. function protocol.dnsaddrs(self)
  761. local dns = { }
  762. local _, addr
  763. for _, addr in ipairs(self:_ubus("dns-server") or { }) do
  764. if not addr:match(":") then
  765. dns[#dns+1] = addr
  766. end
  767. end
  768. return dns
  769. end
  770. function protocol.ip6addr(self)
  771. local addrs = self:_ubus("ipv6-address")
  772. if addrs and #addrs > 0 then
  773. return "%s/%d" %{ addrs[1].address, addrs[1].mask }
  774. else
  775. addrs = self:_ubus("ipv6-prefix-assignment")
  776. if addrs and #addrs > 0 then
  777. return "%s/%d" %{ addrs[1].address, addrs[1].mask }
  778. end
  779. end
  780. end
  781. function protocol.ip6addrs(self)
  782. local addrs = self:_ubus("ipv6-address")
  783. local rv = { }
  784. local n, addr
  785. if type(addrs) == "table" then
  786. for n, addr in ipairs(addrs) do
  787. rv[#rv+1] = "%s/%d" %{ addr.address, addr.mask }
  788. end
  789. end
  790. addrs = self:_ubus("ipv6-prefix-assignment")
  791. if type(addrs) == "table" then
  792. for n, addr in ipairs(addrs) do
  793. rv[#rv+1] = "%s1/%d" %{ addr.address, addr.mask }
  794. end
  795. end
  796. return rv
  797. end
  798. function protocol.gw6addr(self)
  799. local _, route
  800. for _, route in ipairs(self:_ubus("route") or { }) do
  801. if route.target == "::" and route.mask == 0 then
  802. return ipc.IPv6(route.nexthop):string()
  803. end
  804. end
  805. end
  806. function protocol.dns6addrs(self)
  807. local dns = { }
  808. local _, addr
  809. for _, addr in ipairs(self:_ubus("dns-server") or { }) do
  810. if addr:match(":") then
  811. dns[#dns+1] = addr
  812. end
  813. end
  814. return dns
  815. end
  816. function protocol.is_bridge(self)
  817. return (not self:is_virtual() and self:type() == "bridge")
  818. end
  819. function protocol.opkg_package(self)
  820. return nil
  821. end
  822. function protocol.is_installed(self)
  823. return true
  824. end
  825. function protocol.is_virtual(self)
  826. return false
  827. end
  828. function protocol.is_floating(self)
  829. return false
  830. end
  831. function protocol.is_empty(self)
  832. if self:is_floating() then
  833. return false
  834. else
  835. local rv = true
  836. if (self:_get("ifname") or ""):match("%S+") then
  837. rv = false
  838. end
  839. _uci:foreach("wireless", "wifi-iface",
  840. function(s)
  841. local n
  842. for n in utl.imatch(s.network) do
  843. if n == self.sid then
  844. rv = false
  845. return false
  846. end
  847. end
  848. end)
  849. return rv
  850. end
  851. end
  852. function protocol.add_interface(self, ifname)
  853. ifname = _M:ifnameof(ifname)
  854. if ifname and not self:is_floating() then
  855. -- if its a wifi interface, change its network option
  856. local wif = _wifi_lookup(ifname)
  857. if wif then
  858. _append("wireless", wif, "network", self.sid)
  859. -- add iface to our iface list
  860. else
  861. _append("network", self.sid, "ifname", ifname)
  862. end
  863. end
  864. end
  865. function protocol.del_interface(self, ifname)
  866. ifname = _M:ifnameof(ifname)
  867. if ifname and not self:is_floating() then
  868. -- if its a wireless interface, clear its network option
  869. local wif = _wifi_lookup(ifname)
  870. if wif then _filter("wireless", wif, "network", self.sid) end
  871. -- remove the interface
  872. _filter("network", self.sid, "ifname", ifname)
  873. end
  874. end
  875. function protocol.get_interface(self)
  876. if self:is_virtual() then
  877. _tunnel[self:proto() .. "-" .. self.sid] = true
  878. return interface(self:proto() .. "-" .. self.sid, self)
  879. elseif self:is_bridge() then
  880. _bridge["br-" .. self.sid] = true
  881. return interface("br-" .. self.sid, self)
  882. else
  883. local ifn = nil
  884. local num = { }
  885. for ifn in utl.imatch(_uci:get("network", self.sid, "ifname")) do
  886. ifn = ifn:match("^[^:/]+")
  887. return ifn and interface(ifn, self)
  888. end
  889. ifn = nil
  890. _uci:foreach("wireless", "wifi-iface",
  891. function(s)
  892. if s.device then
  893. num[s.device] = num[s.device] and num[s.device] + 1 or 1
  894. local net
  895. for net in utl.imatch(s.network) do
  896. if net == self.sid then
  897. ifn = "%s.network%d" %{ s.device, num[s.device] }
  898. return false
  899. end
  900. end
  901. end
  902. end)
  903. return ifn and interface(ifn, self)
  904. end
  905. end
  906. function protocol.get_interfaces(self)
  907. if self:is_bridge() or (self:is_virtual() and not self:is_floating()) then
  908. local ifaces = { }
  909. local ifn
  910. local nfs = { }
  911. for ifn in utl.imatch(self:get("ifname")) do
  912. ifn = ifn:match("^[^:/]+")
  913. nfs[ifn] = interface(ifn, self)
  914. end
  915. for ifn in utl.kspairs(nfs) do
  916. ifaces[#ifaces+1] = nfs[ifn]
  917. end
  918. local num = { }
  919. local wfs = { }
  920. _uci:foreach("wireless", "wifi-iface",
  921. function(s)
  922. if s.device then
  923. num[s.device] = num[s.device] and num[s.device] + 1 or 1
  924. local net
  925. for net in utl.imatch(s.network) do
  926. if net == self.sid then
  927. ifn = "%s.network%d" %{ s.device, num[s.device] }
  928. wfs[ifn] = interface(ifn, self)
  929. end
  930. end
  931. end
  932. end)
  933. for ifn in utl.kspairs(wfs) do
  934. ifaces[#ifaces+1] = wfs[ifn]
  935. end
  936. return ifaces
  937. end
  938. end
  939. function protocol.contains_interface(self, ifname)
  940. ifname = _M:ifnameof(ifname)
  941. if not ifname then
  942. return false
  943. elseif self:is_virtual() and self:proto() .. "-" .. self.sid == ifname then
  944. return true
  945. elseif self:is_bridge() and "br-" .. self.sid == ifname then
  946. return true
  947. else
  948. local ifn
  949. for ifn in utl.imatch(self:get("ifname")) do
  950. ifn = ifn:match("[^:]+")
  951. if ifn == ifname then
  952. return true
  953. end
  954. end
  955. local wif = _wifi_lookup(ifname)
  956. if wif then
  957. local n
  958. for n in utl.imatch(_uci:get("wireless", wif, "network")) do
  959. if n == self.sid then
  960. return true
  961. end
  962. end
  963. end
  964. end
  965. return false
  966. end
  967. function protocol.adminlink(self)
  968. return dsp.build_url("admin", "network", "network", self.sid)
  969. end
  970. interface = utl.class()
  971. function interface.__init__(self, ifname, network)
  972. local wif = _wifi_lookup(ifname)
  973. if wif then
  974. self.wif = wifinet(wif)
  975. self.ifname = _wifi_state("section", wif, "ifname")
  976. end
  977. self.ifname = self.ifname or ifname
  978. self.dev = _interfaces[self.ifname]
  979. self.network = network
  980. end
  981. function interface._ubus(self, field)
  982. if not _ubusdevcache[self.ifname] then
  983. _ubusdevcache[self.ifname] = utl.ubus("network.device", "status",
  984. { name = self.ifname })
  985. end
  986. if _ubusdevcache[self.ifname] and field then
  987. return _ubusdevcache[self.ifname][field]
  988. end
  989. return _ubusdevcache[self.ifname]
  990. end
  991. function interface.name(self)
  992. return self.wif and self.wif:ifname() or self.ifname
  993. end
  994. function interface.mac(self)
  995. local mac = self:_ubus("macaddr")
  996. return mac and mac:upper()
  997. end
  998. function interface.ipaddrs(self)
  999. return self.dev and self.dev.ipaddrs or { }
  1000. end
  1001. function interface.ip6addrs(self)
  1002. return self.dev and self.dev.ip6addrs or { }
  1003. end
  1004. function interface.type(self)
  1005. if self.wif or _wifi_iface(self.ifname) then
  1006. return "wifi"
  1007. elseif _bridge[self.ifname] then
  1008. return "bridge"
  1009. elseif _tunnel[self.ifname] then
  1010. return "tunnel"
  1011. elseif self.ifname:match("%.") then
  1012. return "vlan"
  1013. elseif _switch[self.ifname] then
  1014. return "switch"
  1015. else
  1016. return "ethernet"
  1017. end
  1018. end
  1019. function interface.shortname(self)
  1020. if self.wif then
  1021. return self.wif:shortname()
  1022. else
  1023. return self.ifname
  1024. end
  1025. end
  1026. function interface.get_i18n(self)
  1027. if self.wif then
  1028. return "%s: %s %q" %{
  1029. lng.translate("Wireless Network"),
  1030. self.wif:active_mode(),
  1031. self.wif:active_ssid() or self.wif:active_bssid() or self.wif:id()
  1032. }
  1033. else
  1034. return "%s: %q" %{ self:get_type_i18n(), self:name() }
  1035. end
  1036. end
  1037. function interface.get_type_i18n(self)
  1038. local x = self:type()
  1039. if x == "wifi" then
  1040. return lng.translate("Wireless Adapter")
  1041. elseif x == "bridge" then
  1042. return lng.translate("Bridge")
  1043. elseif x == "switch" then
  1044. return lng.translate("Ethernet Switch")
  1045. elseif x == "vlan" then
  1046. if _switch[self.ifname] then
  1047. return lng.translate("Switch VLAN")
  1048. else
  1049. return lng.translate("Software VLAN")
  1050. end
  1051. elseif x == "tunnel" then
  1052. return lng.translate("Tunnel Interface")
  1053. else
  1054. return lng.translate("Ethernet Adapter")
  1055. end
  1056. end
  1057. function interface.adminlink(self)
  1058. if self.wif then
  1059. return self.wif:adminlink()
  1060. end
  1061. end
  1062. function interface.ports(self)
  1063. local members = self:_ubus("bridge-members")
  1064. if members then
  1065. local _, iface
  1066. local ifaces = { }
  1067. for _, iface in ipairs(members) do
  1068. ifaces[#ifaces+1] = interface(iface)
  1069. end
  1070. end
  1071. end
  1072. function interface.bridge_id(self)
  1073. if self.br then
  1074. return self.br.id
  1075. else
  1076. return nil
  1077. end
  1078. end
  1079. function interface.bridge_stp(self)
  1080. if self.br then
  1081. return self.br.stp
  1082. else
  1083. return false
  1084. end
  1085. end
  1086. function interface.is_up(self)
  1087. return self:_ubus("up") or false
  1088. end
  1089. function interface.is_bridge(self)
  1090. return (self:type() == "bridge")
  1091. end
  1092. function interface.is_bridgeport(self)
  1093. return self.dev and self.dev.bridge and true or false
  1094. end
  1095. function interface.tx_bytes(self)
  1096. local stat = self:_ubus("statistics")
  1097. return stat and stat.tx_bytes or 0
  1098. end
  1099. function interface.rx_bytes(self)
  1100. local stat = self:_ubus("statistics")
  1101. return stat and stat.rx_bytes or 0
  1102. end
  1103. function interface.tx_packets(self)
  1104. local stat = self:_ubus("statistics")
  1105. return stat and stat.tx_packets or 0
  1106. end
  1107. function interface.rx_packets(self)
  1108. local stat = self:_ubus("statistics")
  1109. return stat and stat.rx_packets or 0
  1110. end
  1111. function interface.get_network(self)
  1112. return self:get_networks()[1]
  1113. end
  1114. function interface.get_networks(self)
  1115. if not self.networks then
  1116. local nets = { }
  1117. local _, net
  1118. for _, net in ipairs(_M:get_networks()) do
  1119. if net:contains_interface(self.ifname) or
  1120. net:ifname() == self.ifname
  1121. then
  1122. nets[#nets+1] = net
  1123. end
  1124. end
  1125. table.sort(nets, function(a, b) return a.sid < b.sid end)
  1126. self.networks = nets
  1127. return nets
  1128. else
  1129. return self.networks
  1130. end
  1131. end
  1132. function interface.get_wifinet(self)
  1133. return self.wif
  1134. end
  1135. wifidev = utl.class()
  1136. function wifidev.__init__(self, dev)
  1137. self.sid = dev
  1138. self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
  1139. end
  1140. function wifidev.get(self, opt)
  1141. return _get("wireless", self.sid, opt)
  1142. end
  1143. function wifidev.set(self, opt, val)
  1144. return _set("wireless", self.sid, opt, val)
  1145. end
  1146. function wifidev.name(self)
  1147. return self.sid
  1148. end
  1149. function wifidev.hwmodes(self)
  1150. local l = self.iwinfo.hwmodelist
  1151. if l and next(l) then
  1152. return l
  1153. else
  1154. return { b = true, g = true }
  1155. end
  1156. end
  1157. function wifidev.get_i18n(self)
  1158. local t = "Generic"
  1159. if self.iwinfo.type == "wl" then
  1160. t = "Broadcom"
  1161. elseif self.iwinfo.type == "madwifi" then
  1162. t = "Atheros"
  1163. end
  1164. local m = ""
  1165. local l = self:hwmodes()
  1166. if l.a then m = m .. "a" end
  1167. if l.b then m = m .. "b" end
  1168. if l.g then m = m .. "g" end
  1169. if l.n then m = m .. "n" end
  1170. if l.ac then m = "ac" end
  1171. return "%s 802.11%s Wireless Controller (%s)" %{ t, m, self:name() }
  1172. end
  1173. function wifidev.is_up(self)
  1174. if _ubuswificache[self.sid] then
  1175. return (_ubuswificache[self.sid].up == true)
  1176. end
  1177. return false
  1178. end
  1179. function wifidev.get_wifinet(self, net)
  1180. if _uci:get("wireless", net) == "wifi-iface" then
  1181. return wifinet(net)
  1182. else
  1183. local wnet = _wifi_lookup(net)
  1184. if wnet then
  1185. return wifinet(wnet)
  1186. end
  1187. end
  1188. end
  1189. function wifidev.get_wifinets(self)
  1190. local nets = { }
  1191. _uci:foreach("wireless", "wifi-iface",
  1192. function(s)
  1193. if s.device == self.sid then
  1194. nets[#nets+1] = wifinet(s['.name'])
  1195. end
  1196. end)
  1197. return nets
  1198. end
  1199. function wifidev.add_wifinet(self, options)
  1200. options = options or { }
  1201. options.device = self.sid
  1202. local wnet = _uci:section("wireless", "wifi-iface", nil, options)
  1203. if wnet then
  1204. return wifinet(wnet, options)
  1205. end
  1206. end
  1207. function wifidev.del_wifinet(self, net)
  1208. if utl.instanceof(net, wifinet) then
  1209. net = net.sid
  1210. elseif _uci:get("wireless", net) ~= "wifi-iface" then
  1211. net = _wifi_lookup(net)
  1212. end
  1213. if net and _uci:get("wireless", net, "device") == self.sid then
  1214. _uci:delete("wireless", net)
  1215. return true
  1216. end
  1217. return false
  1218. end
  1219. wifinet = utl.class()
  1220. function wifinet.__init__(self, net, data)
  1221. self.sid = net
  1222. local n = 0
  1223. local num = { }
  1224. local netid, sid
  1225. _uci:foreach("wireless", "wifi-iface",
  1226. function(s)
  1227. n = n + 1
  1228. if s.device then
  1229. num[s.device] = num[s.device] and num[s.device] + 1 or 1
  1230. if s['.name'] == self.sid then
  1231. sid = "@wifi-iface[%d]" % n
  1232. netid = "%s.network%d" %{ s.device, num[s.device] }
  1233. return false
  1234. end
  1235. end
  1236. end)
  1237. if sid then
  1238. local _, k, r, i
  1239. for k, r in pairs(_ubuswificache) do
  1240. if type(r) == "table" and
  1241. type(r.interfaces) == "table"
  1242. then
  1243. for _, i in ipairs(r.interfaces) do
  1244. if type(i) == "table" and i.section == sid then
  1245. self._ubusdata = {
  1246. radio = k,
  1247. dev = r,
  1248. net = i
  1249. }
  1250. end
  1251. end
  1252. end
  1253. end
  1254. end
  1255. local dev = _wifi_state("section", self.sid, "ifname") or netid
  1256. self.netid = netid
  1257. self.wdev = dev
  1258. self.iwinfo = dev and sys.wifi.getiwinfo(dev) or { }
  1259. end
  1260. function wifinet.ubus(self, ...)
  1261. local n, v = self._ubusdata
  1262. for n = 1, select('#', ...) do
  1263. if type(v) == "table" then
  1264. v = v[select(n, ...)]
  1265. else
  1266. return nil
  1267. end
  1268. end
  1269. return v
  1270. end
  1271. function wifinet.get(self, opt)
  1272. return _get("wireless", self.sid, opt)
  1273. end
  1274. function wifinet.set(self, opt, val)
  1275. return _set("wireless", self.sid, opt, val)
  1276. end
  1277. function wifinet.mode(self)
  1278. return self:ubus("net", "config", "mode") or self:get("mode") or "ap"
  1279. end
  1280. function wifinet.ssid(self)
  1281. return self:ubus("net", "config", "ssid") or self:get("ssid")
  1282. end
  1283. function wifinet.bssid(self)
  1284. return self:ubus("net", "config", "bssid") or self:get("bssid")
  1285. end
  1286. function wifinet.network(self)
  1287. local net, networks = nil, { }
  1288. for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
  1289. networks[#networks+1] = net
  1290. end
  1291. return networks
  1292. end
  1293. function wifinet.id(self)
  1294. return self.netid
  1295. end
  1296. function wifinet.name(self)
  1297. return self.sid
  1298. end
  1299. function wifinet.ifname(self)
  1300. local ifname = self:ubus("net", "ifname") or self.iwinfo.ifname
  1301. if not ifname or ifname:match("^wifi%d") or ifname:match("^radio%d") then
  1302. ifname = self.wdev
  1303. end
  1304. return ifname
  1305. end
  1306. function wifinet.get_device(self)
  1307. local dev = self:ubus("radio") or self:get("device")
  1308. return dev and wifidev(dev) or nil
  1309. end
  1310. function wifinet.is_up(self)
  1311. local ifc = self:get_interface()
  1312. return (ifc and ifc:is_up() or false)
  1313. end
  1314. function wifinet.active_mode(self)
  1315. local m = self.iwinfo.mode or self:ubus("net", "config", "mode") or self:get("mode") or "ap"
  1316. if m == "ap" then m = "Master"
  1317. elseif m == "sta" then m = "Client"
  1318. elseif m == "adhoc" then m = "Ad-Hoc"
  1319. elseif m == "mesh" then m = "Mesh"
  1320. elseif m == "monitor" then m = "Monitor"
  1321. end
  1322. return m
  1323. end
  1324. function wifinet.active_mode_i18n(self)
  1325. return lng.translate(self:active_mode())
  1326. end
  1327. function wifinet.active_ssid(self)
  1328. return self.iwinfo.ssid or self:ubus("net", "config", "ssid") or self:get("ssid")
  1329. end
  1330. function wifinet.active_bssid(self)
  1331. return self.iwinfo.bssid or self:ubus("net", "config", "bssid") or self:get("bssid")
  1332. end
  1333. function wifinet.active_encryption(self)
  1334. local enc = self.iwinfo and self.iwinfo.encryption
  1335. return enc and enc.description or "-"
  1336. end
  1337. function wifinet.assoclist(self)
  1338. return self.iwinfo.assoclist or { }
  1339. end
  1340. function wifinet.frequency(self)
  1341. local freq = self.iwinfo.frequency
  1342. if freq and freq > 0 then
  1343. return "%.03f" % (freq / 1000)
  1344. end
  1345. end
  1346. function wifinet.bitrate(self)
  1347. local rate = self.iwinfo.bitrate
  1348. if rate and rate > 0 then
  1349. return (rate / 1000)
  1350. end
  1351. end
  1352. function wifinet.channel(self)
  1353. return self.iwinfo.channel or self:ubus("dev", "config", "channel") or
  1354. tonumber(self:get("channel"))
  1355. end
  1356. function wifinet.signal(self)
  1357. return self.iwinfo.signal or 0
  1358. end
  1359. function wifinet.noise(self)
  1360. return self.iwinfo.noise or 0
  1361. end
  1362. function wifinet.country(self)
  1363. return self.iwinfo.country or self:ubus("dev", "config", "country") or "00"
  1364. end
  1365. function wifinet.txpower(self)
  1366. local pwr = (self.iwinfo.txpower or 0)
  1367. return pwr + self:txpower_offset()
  1368. end
  1369. function wifinet.txpower_offset(self)
  1370. return self.iwinfo.txpower_offset or 0
  1371. end
  1372. function wifinet.signal_level(self, s, n)
  1373. if self:active_bssid() ~= "00:00:00:00:00:00" then
  1374. local signal = s or self:signal()
  1375. local noise = n or self:noise()
  1376. if signal < 0 and noise < 0 then
  1377. local snr = -1 * (noise - signal)
  1378. return math.floor(snr / 5)
  1379. else
  1380. return 0
  1381. end
  1382. else
  1383. return -1
  1384. end
  1385. end
  1386. function wifinet.signal_percent(self)
  1387. local qc = self.iwinfo.quality or 0
  1388. local qm = self.iwinfo.quality_max or 0
  1389. if qc > 0 and qm > 0 then
  1390. return math.floor((100 / qm) * qc)
  1391. else
  1392. return 0
  1393. end
  1394. end
  1395. function wifinet.shortname(self)
  1396. return "%s %q" %{
  1397. lng.translate(self:active_mode()),
  1398. self:active_ssid() or self:active_bssid() or self:id()
  1399. }
  1400. end
  1401. function wifinet.get_i18n(self)
  1402. return "%s: %s %q (%s)" %{
  1403. lng.translate("Wireless Network"),
  1404. lng.translate(self:active_mode()),
  1405. self:active_ssid() or self:active_bssid() or self:id(),
  1406. self:ifname()
  1407. }
  1408. end
  1409. function wifinet.adminlink(self)
  1410. return dsp.build_url("admin", "network", "wireless", self.netid)
  1411. end
  1412. function wifinet.get_network(self)
  1413. return self:get_networks()[1]
  1414. end
  1415. function wifinet.get_networks(self)
  1416. local nets = { }
  1417. local net
  1418. for net in utl.imatch(self:ubus("net", "config", "network") or self:get("network")) do
  1419. if _uci:get("network", net) == "interface" then
  1420. nets[#nets+1] = network(net)
  1421. end
  1422. end
  1423. table.sort(nets, function(a, b) return a.sid < b.sid end)
  1424. return nets
  1425. end
  1426. function wifinet.get_interface(self)
  1427. return interface(self:ifname())
  1428. end
  1429. -- setup base protocols
  1430. _M:register_protocol("static")
  1431. _M:register_protocol("dhcp")
  1432. _M:register_protocol("none")
  1433. -- load protocol extensions
  1434. local exts = nfs.dir(utl.libpath() .. "/model/network")
  1435. if exts then
  1436. local ext
  1437. for ext in exts do
  1438. if ext:match("%.lua$") then
  1439. require("luci.model.network." .. ext:gsub("%.lua$", ""))
  1440. end
  1441. end
  1442. end