123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- 'use strict';
- 'require uci';
- 'require rpc';
- 'require tools.prng as random';
- function initFirewallState() {
- return L.resolveDefault(uci.load('firewall'));
- }
- function parseEnum(s, values) {
- if (s == null)
- return null;
- s = String(s).toUpperCase();
- if (s == '')
- return null;
- for (var i = 0; i < values.length; i++)
- if (values[i].toUpperCase().indexOf(s) == 0)
- return values[i];
- return null;
- }
- function parsePolicy(s, defaultValue) {
- return parseEnum(s, ['DROP', 'REJECT', 'ACCEPT']) || (arguments.length < 2 ? null : defaultValue);
- }
- var Firewall, AbstractFirewallItem, Defaults, Zone, Forwarding, Redirect, Rule;
- function lookupZone(name) {
- var z = uci.get('firewall', name);
- if (z != null && z['.type'] == 'zone')
- return new Zone(z['.name']);
- var sections = uci.sections('firewall', 'zone');
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].name != name)
- continue;
- return new Zone(sections[i]['.name']);
- }
- return null;
- }
- function getColorForName(forName) {
- if (forName == null)
- return '#eeeeee';
- else if (forName == 'lan')
- return '#90f090';
- else if (forName == 'wan')
- return '#f09090';
- return random.derive_color(forName);
- }
- Firewall = L.Class.extend({
- getDefaults: function() {
- return initFirewallState().then(function() {
- return new Defaults();
- });
- },
- newZone: function() {
- return initFirewallState().then(L.bind(function() {
- var name = 'newzone',
- count = 1;
- while (this.getZone(name) != null)
- name = 'newzone%d'.format(++count);
- return this.addZone(name);
- }, this));
- },
- addZone: function(name) {
- return initFirewallState().then(L.bind(function() {
- if (name == null || !/^[a-zA-Z0-9_]+$/.test(name))
- return null;
- if (lookupZone(name) != null)
- return null;
- var d = new Defaults(),
- z = uci.add('firewall', 'zone');
- uci.set('firewall', z, 'name', name);
- uci.set('firewall', z, 'input', d.getInput() || 'DROP');
- uci.set('firewall', z, 'output', d.getOutput() || 'DROP');
- uci.set('firewall', z, 'forward', d.getForward() || 'DROP');
- return new Zone(z);
- }, this));
- },
- getZone: function(name) {
- return initFirewallState().then(function() {
- return lookupZone(name);
- });
- },
- getZones: function() {
- return initFirewallState().then(function() {
- var sections = uci.sections('firewall', 'zone'),
- zones = [];
- for (var i = 0; i < sections.length; i++)
- zones.push(new Zone(sections[i]['.name']));
- zones.sort(function(a, b) { return a.getName() > b.getName() });
- return zones;
- });
- },
- getZoneByNetwork: function(network) {
- return initFirewallState().then(function() {
- var sections = uci.sections('firewall', 'zone');
- for (var i = 0; i < sections.length; i++)
- if (L.toArray(sections[i].network).indexOf(network) != -1)
- return new Zone(sections[i]['.name']);
- return null;
- });
- },
- deleteZone: function(name) {
- return initFirewallState().then(function() {
- var section = uci.get('firewall', name),
- found = false;
- if (section != null && section['.type'] == 'zone') {
- found = true;
- name = section.name;
- uci.remove('firewall', section['.name']);
- }
- else if (name != null) {
- var sections = uci.sections('firewall', 'zone');
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].name != name)
- continue;
- found = true;
- uci.remove('firewall', sections[i]['.name']);
- }
- }
- if (found == true) {
- sections = uci.sections('firewall');
- for (var i = 0; i < sections.length; i++) {
- if (sections[i]['.type'] != 'rule' &&
- sections[i]['.type'] != 'redirect' &&
- sections[i]['.type'] != 'forwarding')
- continue;
- if (sections[i].src == name || sections[i].dest == name)
- uci.remove('firewall', sections[i]['.name']);
- }
- }
- return found;
- });
- },
- renameZone: function(oldName, newName) {
- return initFirewallState().then(L.bind(function() {
- if (oldName == null || newName == null || !/^[a-zA-Z0-9_]+$/.test(newName))
- return false;
- if (lookupZone(newName) != null)
- return false;
- var sections = uci.sections('firewall', 'zone'),
- found = false;
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].name != oldName)
- continue;
- uci.set('firewall', sections[i]['.name'], 'name', newName);
- found = true;
- }
- if (found == true) {
- sections = uci.sections('firewall');
- for (var i = 0; i < sections.length; i++) {
- if (sections[i]['.type'] != 'rule' &&
- sections[i]['.type'] != 'redirect' &&
- sections[i]['.type'] != 'forwarding')
- continue;
- if (sections[i].src == oldName)
- uci.set('firewall', sections[i]['.name'], 'src', newName);
- if (sections[i].dest == oldName)
- uci.set('firewall', sections[i]['.name'], 'dest', newName);
- }
- }
- return found;
- }, this));
- },
- deleteNetwork: function(network) {
- return this.getZones().then(L.bind(function(zones) {
- var rv = false;
- for (var i = 0; i < zones.length; i++)
- if (zones[i].deleteNetwork(network))
- rv = true;
- return rv;
- }, this));
- },
- getColorForName: getColorForName
- });
- AbstractFirewallItem = L.Class.extend({
- get: function(option) {
- return uci.get('firewall', this.sid, option);
- },
- set: function(option, value) {
- return uci.set('firewall', this.sid, option, value);
- }
- });
- Defaults = AbstractFirewallItem.extend({
- __init__: function() {
- var sections = uci.sections('firewall', 'defaults');
- for (var i = 0; i < sections.length; i++) {
- this.sid = sections[i]['.name'];
- break;
- }
- if (this.sid == null)
- this.sid = uci.add('firewall', 'defaults');
- },
- isSynFlood: function() {
- return (this.get('syn_flood') == '1');
- },
- isDropInvalid: function() {
- return (this.get('drop_invalid') == '1');
- },
- getInput: function() {
- return parsePolicy(this.get('input'), 'DROP');
- },
- getOutput: function() {
- return parsePolicy(this.get('output'), 'DROP');
- },
- getForward: function() {
- return parsePolicy(this.get('forward'), 'DROP');
- }
- });
- Zone = AbstractFirewallItem.extend({
- __init__: function(name) {
- var section = uci.get('firewall', name);
- if (section != null && section['.type'] == 'zone') {
- this.sid = name;
- this.data = section;
- }
- else if (name != null) {
- var sections = uci.get('firewall', 'zone');
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].name != name)
- continue;
- this.sid = sections[i]['.name'];
- this.data = sections[i];
- break;
- }
- }
- },
- isMasquerade: function() {
- return (this.get('masq') == '1');
- },
- getName: function() {
- return this.get('name');
- },
- getNetwork: function() {
- return this.get('network');
- },
- getInput: function() {
- return parsePolicy(this.get('input'), (new Defaults()).getInput());
- },
- getOutput: function() {
- return parsePolicy(this.get('output'), (new Defaults()).getOutput());
- },
- getForward: function() {
- return parsePolicy(this.get('forward'), (new Defaults()).getForward());
- },
- addNetwork: function(network) {
- var section = uci.get('network', network);
- if (section == null || section['.type'] != 'interface')
- return false;
- var newNetworks = this.getNetworks();
- if (newNetworks.filter(function(net) { return net == network }).length)
- return false;
- newNetworks.push(network);
- this.set('network', newNetworks);
- return true;
- },
- deleteNetwork: function(network) {
- var oldNetworks = this.getNetworks(),
- newNetworks = oldNetworks.filter(function(net) { return net != network });
- if (newNetworks.length > 0)
- this.set('network', newNetworks);
- else
- this.set('network', null);
- return (newNetworks.length < oldNetworks.length);
- },
- getNetworks: function() {
- return L.toArray(this.get('network'));
- },
- clearNetworks: function() {
- this.set('network', null);
- },
- getDevices: function() {
- return L.toArray(this.get('device'));
- },
- getSubnets: function() {
- return L.toArray(this.get('subnet'));
- },
- getForwardingsBy: function(what) {
- var sections = uci.sections('firewall', 'forwarding'),
- forwards = [];
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].src == null || sections[i].dest == null)
- continue;
- if (sections[i][what] != this.getName())
- continue;
- forwards.push(new Forwarding(sections[i]['.name']));
- }
- return forwards;
- },
- addForwardingTo: function(dest) {
- var forwards = this.getForwardingsBy('src'),
- zone = lookupZone(dest);
- if (zone == null || zone.getName() == this.getName())
- return null;
- for (var i = 0; i < forwards.length; i++)
- if (forwards[i].getDestination() == zone.getName())
- return null;
- var sid = uci.add('firewall', 'forwarding');
- uci.set('firewall', sid, 'src', this.getName());
- uci.set('firewall', sid, 'dest', zone.getName());
- return new Forwarding(sid);
- },
- addForwardingFrom: function(src) {
- var forwards = this.getForwardingsBy('dest'),
- zone = lookupZone(src);
- if (zone == null || zone.getName() == this.getName())
- return null;
- for (var i = 0; i < forwards.length; i++)
- if (forwards[i].getSource() == zone.getName())
- return null;
- var sid = uci.add('firewall', 'forwarding');
- uci.set('firewall', sid, 'src', zone.getName());
- uci.set('firewall', sid, 'dest', this.getName());
- return new Forwarding(sid);
- },
- deleteForwardingsBy: function(what) {
- var sections = uci.sections('firewall', 'forwarding'),
- found = false;
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].src == null || sections[i].dest == null)
- continue;
- if (sections[i][what] != this.getName())
- continue;
- uci.remove('firewall', sections[i]['.name']);
- found = true;
- }
- return found;
- },
- deleteForwarding: function(forwarding) {
- if (!(forwarding instanceof Forwarding))
- return false;
- var section = uci.get('firewall', forwarding.sid);
- if (!section || section['.type'] != 'forwarding')
- return false;
- uci.remove('firewall', section['.name']);
- return true;
- },
- addRedirect: function(options) {
- var sid = uci.add('firewall', 'redirect');
- if (options != null && typeof(options) == 'object')
- for (var key in options)
- if (options.hasOwnProperty(key))
- uci.set('firewall', sid, key, options[key]);
- uci.set('firewall', sid, 'src', this.getName());
- return new Redirect(sid);
- },
- addRule: function(options) {
- var sid = uci.add('firewall', 'rule');
- if (options != null && typeof(options) == 'object')
- for (var key in options)
- if (options.hasOwnProperty(key))
- uci.set('firewall', sid, key, options[key]);
- uci.set('firewall', sid, 'src', this.getName());
- return new Rule(sid);
- },
- getColor: function(forName) {
- var name = (arguments.length > 0 ? forName : this.getName());
- return getColorForName(name);
- }
- });
- Forwarding = AbstractFirewallItem.extend({
- __init__: function(sid) {
- this.sid = sid;
- },
- getSource: function() {
- return this.get('src');
- },
- getDestination: function() {
- return this.get('dest');
- },
- getSourceZone: function() {
- return lookupZone(this.getSource());
- },
- getDestinationZone: function() {
- return lookupZone(this.getDestination());
- }
- });
- Rule = AbstractFirewallItem.extend({
- getSource: function() {
- return this.get('src');
- },
- getDestination: function() {
- return this.get('dest');
- },
- getSourceZone: function() {
- return lookupZone(this.getSource());
- },
- getDestinationZone: function() {
- return lookupZone(this.getDestination());
- }
- });
- Redirect = AbstractFirewallItem.extend({
- getSource: function() {
- return this.get('src');
- },
- getDestination: function() {
- return this.get('dest');
- },
- getSourceZone: function() {
- return lookupZone(this.getSource());
- },
- getDestinationZone: function() {
- return lookupZone(this.getDestination());
- }
- });
- return Firewall;
|