common.uc 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. import * as nl80211 from "nl80211";
  2. import * as rtnl from "rtnl";
  3. import { readfile } from "fs";
  4. const iftypes = {
  5. ap: nl80211.const.NL80211_IFTYPE_AP,
  6. mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
  7. sta: nl80211.const.NL80211_IFTYPE_STATION,
  8. adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
  9. monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
  10. };
  11. function wdev_remove(name)
  12. {
  13. nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
  14. }
  15. function __phy_is_fullmac(phyidx)
  16. {
  17. let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
  18. return !data.software_iftypes.ap_vlan;
  19. }
  20. function phy_is_fullmac(phy)
  21. {
  22. let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
  23. return __phy_is_fullmac(phyidx);
  24. }
  25. function find_reusable_wdev(phyidx)
  26. {
  27. if (!__phy_is_fullmac(phyidx))
  28. return null;
  29. let data = nl80211.request(
  30. nl80211.const.NL80211_CMD_GET_INTERFACE,
  31. nl80211.const.NLM_F_DUMP,
  32. { wiphy: phyidx });
  33. for (let res in data)
  34. if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
  35. return res.ifname;
  36. return null;
  37. }
  38. function wdev_create(phy, name, data)
  39. {
  40. let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
  41. wdev_remove(name);
  42. if (!iftypes[data.mode])
  43. return `Invalid mode: ${data.mode}`;
  44. let req = {
  45. wiphy: phyidx,
  46. ifname: name,
  47. iftype: iftypes[data.mode],
  48. };
  49. if (data["4addr"])
  50. req["4addr"] = data["4addr"];
  51. if (data.macaddr)
  52. req.mac = data.macaddr;
  53. nl80211.error();
  54. let reuse_ifname = find_reusable_wdev(phyidx);
  55. if (reuse_ifname &&
  56. (reuse_ifname == name ||
  57. rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
  58. nl80211.request(
  59. nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
  60. wiphy: phyidx,
  61. dev: name,
  62. iftype: iftypes[data.mode],
  63. });
  64. else
  65. nl80211.request(
  66. nl80211.const.NL80211_CMD_NEW_INTERFACE,
  67. nl80211.const.NLM_F_CREATE,
  68. req);
  69. let error = nl80211.error();
  70. if (error)
  71. return error;
  72. if (data.powersave != null) {
  73. nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
  74. { dev: name, ps_state: data.powersave ? 1 : 0});
  75. }
  76. return null;
  77. }
  78. const vlist_proto = {
  79. update: function(values, arg) {
  80. let data = this.data;
  81. let cb = this.cb;
  82. let seq = { };
  83. let new_data = {};
  84. let old_data = {};
  85. this.data = new_data;
  86. if (type(values) == "object") {
  87. for (let key in values) {
  88. old_data[key] = data[key];
  89. new_data[key] = values[key];
  90. delete data[key];
  91. }
  92. } else {
  93. for (let val in values) {
  94. let cur_key = val[0];
  95. let cur_obj = val[1];
  96. old_data[cur_key] = data[cur_key];
  97. new_data[cur_key] = val[1];
  98. delete data[cur_key];
  99. }
  100. }
  101. for (let key in data) {
  102. cb(null, data[key], arg);
  103. delete data[key];
  104. }
  105. for (let key in new_data)
  106. cb(new_data[key], old_data[key], arg);
  107. }
  108. };
  109. function is_equal(val1, val2) {
  110. let t1 = type(val1);
  111. if (t1 != type(val2))
  112. return false;
  113. if (t1 == "array") {
  114. if (length(val1) != length(val2))
  115. return false;
  116. for (let i = 0; i < length(val1); i++)
  117. if (!is_equal(val1[i], val2[i]))
  118. return false;
  119. return true;
  120. } else if (t1 == "object") {
  121. for (let key in val1)
  122. if (!is_equal(val1[key], val2[key]))
  123. return false;
  124. for (let key in val2)
  125. if (!val1[key])
  126. return false;
  127. return true;
  128. } else {
  129. return val1 == val2;
  130. }
  131. }
  132. function vlist_new(cb) {
  133. return proto({
  134. cb: cb,
  135. data: {}
  136. }, vlist_proto);
  137. }
  138. export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };