util.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. -- Writes all lines from the file input to the file output except those starting with prefix
  2. -- Doesn't close the output file, but returns the file object
  3. local function do_filter_prefix(input, output, prefix)
  4. local f = io.open(output, 'w+')
  5. local l = prefix:len()
  6. for line in io.lines(input) do
  7. if line:sub(1, l) ~= prefix then
  8. f:write(line, '\n')
  9. end
  10. end
  11. return f
  12. end
  13. local function escape_args(ret, arg0, ...)
  14. if not arg0 then
  15. return ret
  16. end
  17. return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...)
  18. end
  19. local os = os
  20. local string = string
  21. local tonumber = tonumber
  22. local ipairs = ipairs
  23. local table = table
  24. local nixio = require 'nixio'
  25. local hash = require 'hash'
  26. local sysconfig = require 'gluon.sysconfig'
  27. local site = require 'gluon.site_config'
  28. local uci = require('luci.model.uci').cursor()
  29. module 'gluon.util'
  30. function exec(...)
  31. return os.execute(escape_args('', 'exec', ...))
  32. end
  33. -- Removes all lines starting with a prefix from a file, optionally adding a new one
  34. function replace_prefix(file, prefix, add)
  35. local tmp = file .. '.tmp'
  36. local f = do_filter_prefix(file, tmp, prefix)
  37. if add then
  38. f:write(add)
  39. end
  40. f:close()
  41. os.rename(tmp, file)
  42. end
  43. function readline(fd)
  44. local line = fd:read('*l')
  45. fd:close()
  46. return line
  47. end
  48. function lock(file)
  49. exec('lock', file)
  50. end
  51. function unlock(file)
  52. exec('lock', '-u', file)
  53. end
  54. function node_id()
  55. return string.gsub(sysconfig.primary_mac, ':', '')
  56. end
  57. -- Generates a (hopefully) unique MAC address
  58. -- The parameter defines the ID to add to the mac addr
  59. --
  60. -- IDs defined so far:
  61. -- 0: client0; mesh-vpn
  62. -- 1: mesh0
  63. -- 2: ibss0
  64. -- 3: client1; mesh-on-wan
  65. -- 4: mesh1
  66. -- 5: ibss1
  67. -- 6: mesh-on-lan
  68. -- 7: unused
  69. function generate_mac(i)
  70. if i > 7 or i < 0 then return nil end -- max allowed id (0b111)
  71. local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12)
  72. local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)')
  73. m1 = tonumber(m1, 16)
  74. m6 = tonumber(m6, 16)
  75. m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit
  76. m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit
  77. -- It's necessary that the first 45 bits of the mac do
  78. -- not vary on a single hardware interface, since some chips are using
  79. -- a hardware mac filter. (e.g 'ramips-rt305x')
  80. m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting)
  81. m6 = m6 + i -- add virtual interface id
  82. return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6)
  83. end
  84. -- Iterate over all radios defined in UCI calling
  85. -- f(radio, index, site.wifiX) for each radio found while passing
  86. -- site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones.
  87. function iterate_radios(f)
  88. local radios = {}
  89. uci:foreach('wireless', 'wifi-device',
  90. function(s)
  91. table.insert(radios, s['.name'])
  92. end
  93. )
  94. for index, radio in ipairs(radios) do
  95. local hwmode = uci:get('wireless', radio, 'hwmode')
  96. if hwmode == '11g' or hwmode == '11ng' then
  97. f(radio, index, site.wifi24)
  98. elseif hwmode == '11a' or hwmode == '11na' then
  99. f(radio, index, site.wifi5)
  100. end
  101. end
  102. end