mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-30 00:23:21 +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