mirror of
https://github.com/gyurix1968/guacamole-client.git
synced 2025-09-07 05:31:22 +00:00
GUAC-1138: Add class for parsing and comparing IPv6 networks.
This commit is contained in:
230
guacamole/src/main/webapp/app/list/types/IPv6Network.js
Normal file
230
guacamole/src/main/webapp/app/list/types/IPv6Network.js
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Glyptodon LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A service for defining the IPv6Network class.
|
||||
*/
|
||||
angular.module('list').factory('IPv6Network', [
|
||||
function defineIPv6Network() {
|
||||
|
||||
/**
|
||||
* Represents an IPv6 network as a pairing of base address and netmask,
|
||||
* both of which are in binary form. To obtain an IPv6Network from
|
||||
* standard CIDR or dot-decimal notation, use IPv6Network.parse().
|
||||
*
|
||||
* @constructor
|
||||
* @param {Number[]} addressGroups
|
||||
* Array of eight IPv6 address groups in binary form, each group being
|
||||
* 16-bit number.
|
||||
*
|
||||
* @param {Number[]} netmaskGroups
|
||||
* Array of eight IPv6 netmask groups in binary form, each group being
|
||||
* 16-bit number.
|
||||
*/
|
||||
var IPv6Network = function IPv6Network(addressGroups, netmaskGroups) {
|
||||
|
||||
/**
|
||||
* Reference to this IPv6Network.
|
||||
*
|
||||
* @type IPv6Network
|
||||
*/
|
||||
var network = this;
|
||||
|
||||
/**
|
||||
* The 128-bit binary address of this network as an array of eight
|
||||
* 16-bit numbers.
|
||||
*
|
||||
* @type Number[]
|
||||
*/
|
||||
this.addressGroups = addressGroups;
|
||||
|
||||
/**
|
||||
* The 128-bit binary netmask of this network as an array of eight
|
||||
* 16-bit numbers.
|
||||
*
|
||||
* @type Number
|
||||
*/
|
||||
this.netmaskGroups = netmaskGroups;
|
||||
|
||||
/**
|
||||
* Tests whether the given network is entirely within this network,
|
||||
* taking into account the base addresses and netmasks of both.
|
||||
*
|
||||
* @param {IPv6Network} other
|
||||
* The network to test.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
* true if the other network is entirely within this network, false
|
||||
* otherwise.
|
||||
*/
|
||||
this.contains = function contains(other) {
|
||||
|
||||
// Test that each masked 16-bit quantity matches the address
|
||||
for (var i=0; i < 8; i++) {
|
||||
if (network.addressGroups[i] !== (other.addressGroups[i]
|
||||
& other.netmaskGroups[i]
|
||||
& network.netmaskGroups[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
// All 16-bit numbers match
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates a netmask having the given number of ones on the left side.
|
||||
* All other bits within the netmask will be zeroes. The resulting netmask
|
||||
* will be an array of eight numbers, where each number corresponds to a
|
||||
* 16-bit group of an IPv6 netmask.
|
||||
*
|
||||
* @param {Number} bits
|
||||
* The number of ones to include on the left side of the netmask. All
|
||||
* other bits will be zeroes.
|
||||
*
|
||||
* @returns {Number[]}
|
||||
* The generated netmask, having the given number of ones.
|
||||
*/
|
||||
var generateNetmask = function generateNetmask(bits) {
|
||||
|
||||
var netmask = [];
|
||||
|
||||
// Only generate up to 128 bits
|
||||
bits = Math.min(128, bits);
|
||||
|
||||
// Add any contiguous 16-bit sections of 1's
|
||||
while (bits >= 16) {
|
||||
netmask.push(0xFFFF);
|
||||
bits -= 16;
|
||||
}
|
||||
|
||||
// Add remaining 1's
|
||||
if (bits > 0 && bits <= 16)
|
||||
netmask.push(0xFFFF & (0xFFFF << (16 - bits)));
|
||||
|
||||
// Add remaining zeroes
|
||||
while (netmask.length < 8)
|
||||
netmask.push(0);
|
||||
|
||||
return netmask;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Splits the given IPv6 address or partial address into its corresponding
|
||||
* 16-bit groups.
|
||||
*
|
||||
* @param {String} str
|
||||
* The IPv6 address or partial address to split.
|
||||
*
|
||||
* @returns Number[]
|
||||
* The numeric values of all 16-bit groups within the given IPv6
|
||||
* address.
|
||||
*/
|
||||
var splitAddress = function splitAddress(str) {
|
||||
|
||||
var address = [];
|
||||
|
||||
// Split address into groups
|
||||
var groups = str.split(':');
|
||||
|
||||
// Parse the numeric value of each group
|
||||
angular.forEach(groups, function addGroup(group) {
|
||||
var value = parseInt(group || '0', 16);
|
||||
address.push(value);
|
||||
});
|
||||
|
||||
return address;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses the given string as an IPv6 address or subnet, returning an
|
||||
* IPv6Network object which describes that address or subnet.
|
||||
*
|
||||
* @param {String} str
|
||||
* The string to parse.
|
||||
*
|
||||
* @returns {IPv6Network}
|
||||
* The parsed network, or null if the given string is not valid.
|
||||
*/
|
||||
IPv6Network.parse = function parse(str) {
|
||||
|
||||
// Regex which matches the general form of IPv6 addresses
|
||||
var pattern = /^([0-9a-f]{0,4}(?::[0-9a-f]{0,4}){0,7})(?:\/([0-9]{1,3}))?$/;
|
||||
|
||||
// Parse rudimentary IPv6 address via regex
|
||||
var match = pattern.exec(str);
|
||||
if (!match)
|
||||
return null;
|
||||
|
||||
// Extract address and netmask from parse results
|
||||
var unparsedAddress = match[1];
|
||||
var unparsedNetmask = match[2];
|
||||
|
||||
// Parse netmask
|
||||
var netmask;
|
||||
if (unparsedNetmask)
|
||||
netmask = generateNetmask(parseInt(unparsedNetmask));
|
||||
else
|
||||
netmask = generateNetmask(128);
|
||||
|
||||
var address;
|
||||
|
||||
// Separate based on the double-colon, if present
|
||||
var doubleColon = unparsedAddress.indexOf('::');
|
||||
|
||||
// If no double colon, just split into groups
|
||||
if (doubleColon === -1)
|
||||
address = splitAddress(unparsedAddress);
|
||||
|
||||
// Otherwise, split either side of the double colon and pad with zeroes
|
||||
else {
|
||||
|
||||
// Parse either side of the double colon
|
||||
var leftAddress = splitAddress(unparsedAddress.substring(0, doubleColon));
|
||||
var rightAddress = splitAddress(unparsedAddress.substring(doubleColon + 2));
|
||||
|
||||
// Pad with zeroes up to address length
|
||||
var remaining = 8 - leftAddress.length - rightAddress.length;
|
||||
while (remaining > 0) {
|
||||
leftAddress.push(0);
|
||||
remaining--;
|
||||
}
|
||||
|
||||
address = leftAddress.concat(rightAddress);
|
||||
|
||||
}
|
||||
|
||||
// Validate length of address
|
||||
if (address.length !== 8)
|
||||
return null;
|
||||
|
||||
return new IPv6Network(address, netmask);
|
||||
|
||||
};
|
||||
|
||||
return IPv6Network;
|
||||
|
||||
}]);
|
Reference in New Issue
Block a user