upnp.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. 'use strict';
  2. 'require uci';
  3. 'require rpc';
  4. 'require form';
  5. var callInitAction, callUpnpGetStatus, callUpnpDeleteRule, handleDelRule;
  6. callInitAction = rpc.declare({
  7. object: 'luci',
  8. method: 'setInitAction',
  9. params: [ 'name', 'action' ],
  10. expect: { result: false }
  11. });
  12. callUpnpGetStatus = rpc.declare({
  13. object: 'luci.upnp',
  14. method: 'get_status',
  15. expect: { }
  16. });
  17. callUpnpDeleteRule = rpc.declare({
  18. object: 'luci.upnp',
  19. method: 'delete_rule',
  20. params: [ 'token' ],
  21. expect: { result : "OK" },
  22. });
  23. handleDelRule = function(num, ev) {
  24. L.dom.parent(ev.currentTarget, '.tr').style.opacity = 0.5;
  25. ev.currentTarget.classList.add('spinning');
  26. ev.currentTarget.disabled = true;
  27. ev.currentTarget.blur();
  28. callUpnpDeleteRule(num);
  29. };
  30. return L.view.extend({
  31. load: function() {
  32. return Promise.all([
  33. callUpnpGetStatus(),
  34. uci.load('upnpd')
  35. ]);
  36. },
  37. poll_status: function(nodes, data) {
  38. var rules = Array.isArray(data[0].rules) ? data[0].rules : [];
  39. var rows = rules.map(function(rule) {
  40. return [
  41. rule.proto,
  42. rule.extport,
  43. rule.intaddr,
  44. rule.host_hint || _('Unknown'),
  45. rule.intport,
  46. rule.descr,
  47. E('button', {
  48. 'class': 'btn cbi-button-remove',
  49. 'click': L.bind(handleDelRule, this, rule.num)
  50. }, [ _('Delete') ])
  51. ];
  52. });
  53. cbi_update_table(nodes.querySelector('#upnp_status_table'), rows, E('em', _('There are no active redirects.')));
  54. return;
  55. },
  56. render: function(data) {
  57. var m, s, o;
  58. m = new form.Map('upnpd', _('Universal Plug & Play'),
  59. _('UPnP allows clients in the local network to automatically configure the router.'));
  60. s = m.section(form.GridSection, '_active_rules');
  61. s.render = L.bind(function(view, section_id) {
  62. var table = E('div', { 'class': 'table cbi-section-table', 'id': 'upnp_status_table' }, [
  63. E('div', { 'class': 'tr table-titles' }, [
  64. E('div', { 'class': 'th' }, _('Protocol')),
  65. E('div', { 'class': 'th' }, _('External Port')),
  66. E('div', { 'class': 'th' }, _('Client Address')),
  67. E('div', { 'class': 'th' }, _('Host')),
  68. E('div', { 'class': 'th' }, _('Client Port')),
  69. E('div', { 'class': 'th' }, _('Description')),
  70. E('div', { 'class': 'th cbi-section-actions' }, '')
  71. ])
  72. ]);
  73. var rules = Array.isArray(data[0].rules) ? data[0].rules : [];
  74. var rows = rules.map(function(rule) {
  75. return [
  76. rule.proto,
  77. rule.extport,
  78. rule.intaddr,
  79. rule.host_hint || _('Unknown'),
  80. rule.intport,
  81. rule.descr,
  82. E('button', {
  83. 'class': 'btn cbi-button-remove',
  84. 'click': L.bind(handleDelRule, this, rule.num)
  85. }, [ _('Delete') ])
  86. ];
  87. });
  88. cbi_update_table(table, rows, E('em', _('There are no active redirects.')));
  89. return E('div', { 'class': 'cbi-section cbi-tblsection' }, [
  90. E('h3', _('Active UPnP Redirects')), table ]);
  91. }, o, this);
  92. s = m.section(form.NamedSection, 'config', 'upnpd', _('MiniUPnP settings'));
  93. s.addremove = false;
  94. s.tab('general', _('General Settings'));
  95. s.tab('advanced', _('Advanced Settings'));
  96. o = s.taboption('general', form.Flag, 'enabled', _('Start UPnP and NAT-PMP service'));
  97. o.rmempty = false;
  98. s.taboption('general', form.Flag, 'enable_upnp', _('Enable UPnP functionality')).default = '1'
  99. s.taboption('general', form.Flag, 'enable_natpmp', _('Enable NAT-PMP functionality')).default = '1'
  100. s.taboption('general', form.Flag, 'secure_mode', _('Enable secure mode'),
  101. _('Allow adding forwards only to requesting ip addresses')).default = '1'
  102. s.taboption('general', form.Flag, 'igdv1', _('Enable IGDv1 mode'),
  103. _('Advertise as IGDv1 device instead of IGDv2')).default = '0'
  104. s.taboption('general', form.Flag, 'log_output', _('Enable additional logging'),
  105. _('Puts extra debugging information into the system log'))
  106. s.taboption('general', form.Value, 'download', _('Downlink'),
  107. _('Value in KByte/s, informational only')).rmempty = true
  108. s.taboption('general', form.Value, 'upload', _('Uplink'),
  109. _('Value in KByte/s, informational only')).rmempty = true
  110. o = s.taboption('general', form.Value, 'port', _('Port'))
  111. o.datatype = 'port'
  112. o.default = 5000
  113. s.taboption('advanced', form.Flag, 'system_uptime', _('Report system instead of daemon uptime')).default = '1'
  114. s.taboption('advanced', form.Value, 'uuid', _('Device UUID'))
  115. s.taboption('advanced', form.Value, 'serial_number', _('Announced serial number'))
  116. s.taboption('advanced', form.Value, 'model_number', _('Announced model number'))
  117. o = s.taboption('advanced', form.Value, 'notify_interval', _('Notify interval'))
  118. o.datatype = 'uinteger'
  119. o.placeholder = 30
  120. o = s.taboption('advanced', form.Value, 'clean_ruleset_threshold', _('Clean rules threshold'))
  121. o.datatype = 'uinteger'
  122. o.placeholder = 20
  123. o = s.taboption('advanced', form.Value, 'clean_ruleset_interval', _('Clean rules interval'))
  124. o.datatype = 'uinteger'
  125. o.placeholder = 600
  126. o = s.taboption('advanced', form.Value, 'presentation_url', _('Presentation URL'))
  127. o.placeholder = 'http://192.168.1.1/'
  128. o = s.taboption('advanced', form.Value, 'upnp_lease_file', _('UPnP lease file'))
  129. o.placeholder = '/var/run/miniupnpd.leases'
  130. s = m.section(form.GridSection, 'perm_rule', _('MiniUPnP ACLs'),
  131. _('ACLs specify which external ports may be redirected to which internal addresses and ports'))
  132. s.sortable = true
  133. s.anonymous = true
  134. s.addremove = true
  135. s.option(form.Value, 'comment', _('Comment'))
  136. o = s.option(form.Value, 'ext_ports', _('External ports'))
  137. o.datatype = 'portrange'
  138. o.placeholder = '0-65535'
  139. o = s.option(form.Value, 'int_addr', _('Internal addresses'))
  140. o.datatype = 'ip4addr'
  141. o.placeholder = '0.0.0.0/0'
  142. o = s.option(form.Value, 'int_ports', _('Internal ports'))
  143. o.datatype = 'portrange'
  144. o.placeholder = '0-65535'
  145. o = s.option(form.ListValue, 'action', _('Action'))
  146. o.value('allow')
  147. o.value('deny')
  148. return m.render().then(L.bind(function(m, nodes) {
  149. L.Poll.add(L.bind(function() {
  150. return Promise.all([
  151. callUpnpGetStatus()
  152. ]).then(L.bind(this.poll_status, this, nodes));
  153. }, this), 5);
  154. return nodes;
  155. }, this, m));
  156. }
  157. });