From 1fa01d0dfa1b5ed65076672289dbe9be360b8e92 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sun, 22 Nov 2020 16:47:53 +0100 Subject: [PATCH 01/66] change version to 1.7 Start Swift code --- IPSubnetcalc.swift | 685 +++++++++++++++++++++++++++ README.md | 2 +- SubnetCalc-Bridging-Header.h | 4 + SubnetCalc-Info.plist | 4 +- SubnetCalc.xcodeproj/project.pbxproj | 21 +- 5 files changed, 710 insertions(+), 6 deletions(-) create mode 100644 IPSubnetcalc.swift create mode 100644 SubnetCalc-Bridging-Header.h diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift new file mode 100644 index 0000000..ed897d1 --- /dev/null +++ b/IPSubnetcalc.swift @@ -0,0 +1,685 @@ +// +// IPSubnetcalc.swift +// SubnetCalc +// +// Created by Julien Mulot on 22/11/2020. +// + +import Foundation +import Cocoa + + +//Const IPv6 +let addr16Full: UInt16 = 0xFFFF +let addr16Empty: UInt16 = 0x0000 +let addr128Full: [UInt16] = [addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full] +let addr128Empty: [UInt16] = [addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty] +let addr16Hex1: UInt16 = 0xF000 +let addr16Hex2: UInt16 = 0x0F00 +let addr16Hex3: UInt16 = 0x00F0 +let addr16Hex4: UInt16 = 0x000F + +let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", "::/128" : " Unspecified Address", "2001:db8::/32" : "Documentation"] + +//Const IPv4 +let addr32Full: UInt32 = 0xFFFFFFFF +let addr32Empty: UInt32 = 0x00000000 +let addr32Digit1: UInt32 = 0xFF000000 +let addr32Digit2: UInt32 = 0x00FF0000 +let addr32Digit3: UInt32 = 0x0000FF00 +let addr32Digit4: UInt32 = 0x000000FF +let netIdClassA: UInt32 = 0x01000000 +let maskClassA: UInt32 = 0xFF000000 +let netIdClassB: UInt32 = 0x80000000 +let maskClassB: UInt32 = 0xFFFF0000 +let netIdClassC: UInt32 = 0xc0000000 +let maskClassC: UInt32 = 0xFFFFFF00 + + +//IPv4 SECTION +func binarize(ipAddress: String) -> String +{ + var ipAddressBin = [String]() + var binStr = String() + var ipDigits = [String]() + + ipDigits = ipAddress.components(separatedBy: ".") + + for index in 0...3 { + ipAddressBin.append(String(Int(ipDigits[index])!, radix: 2)) + while (ipAddressBin[index].count < 8) + { + ipAddressBin[index].insert("0", at: ipAddressBin[index].startIndex) + } + + var digitBin = ipAddressBin[index] + digitBin.insert(" ", at: ipAddressBin[index].index(ipAddressBin[index].startIndex, offsetBy: 4)) + if (index < 3) + { + binStr += digitBin + "." + } + else + { + binStr += digitBin + } + } + return (binStr) +} + +func hexarize(ipAddress: String) -> String +{ + var ipDigits = [String]() + var hexIP = String() + var hex4: String + + ipDigits = ipAddress.components(separatedBy: ".") + for index in 0...3 { + hex4 = String(format: "%X", Int(ipDigits[index])!) + if (hex4.count == 1) + { + hex4 = "0" + hex4 + } + hexIP += hex4 + if (index < 3) + { + hexIP += "." + } + } + return (hexIP) +} + +func numerize(ipAddress: String) -> UInt32 +{ + var ipAddressNum: UInt32 = 0 + var ipDigits = [String]() + + ipDigits = ipAddress.components(separatedBy: ".") + + for index in 0...3 { + ipAddressNum += UInt32(ipDigits[index])! << (32 - 8 * (index + 1)) + } + return (ipAddressNum & addr32Full) +} + +func numerize(mask: String) -> UInt32 +{ + var maskNum: UInt32 = 0 + + maskNum = (addr32Full << (32 - Int(mask)!)) & addr32Full + return (maskNum) +} + +func splitAddrMask(address: String) -> (String, String) { + let ipInfo = address.split(separator: "/") + if ipInfo.count == 2 { + return (String(ipInfo[0]), String(ipInfo[1])) + } + else if ipInfo.count > 2 { + print("Bad IP format: \(ipInfo)") + return ("", "") + } + return (address, "") +} + +func isValidIP(ipAddress: String, mask: String?) -> Bool +{ + var ip4Digits = [String]() + + ip4Digits = ipAddress.components(separatedBy: ".") + if (ip4Digits.count == 4) { + for item in ip4Digits { + if let digit = Int(item, radix: 10) { + if (digit > 255) { + print("bad IP digit \(digit)") + return false + } + } + else { + print("not digit: \(item)") + return false + } + } + } + else { + print("bad IP format \(ip4Digits)") + return false + } + if mask != nil { + if let maskNum = Int(mask!) { + if (maskNum < 0 || maskNum > 32) { + print("mask \(maskNum) invalid") + return false + } + } + else { + print("mask \(mask!) is not digit") + return false + } + } + else { + print("null mask") + } + return true +} + +func subnetId(ipAddress: String, mask: String) -> UInt32 +{ + var subnetId: UInt32 = 0 + let ipBits = numerize(ipAddress: ipAddress) + let maskBits = numerize(mask: mask) + + subnetId = ipBits & maskBits + return (subnetId) +} + +func subnetBroadcast(ipAddress: String, mask: String) -> UInt32 +{ + var broadcast: UInt32 = 0 + let ipBits = numerize(ipAddress: ipAddress) + let maskBits = numerize(mask: mask) + + broadcast = ipBits & maskBits | (addr32Full >> Int(mask)!) + return (broadcast) +} + +func subnetMask(mask: String) -> UInt32 +{ + var subnetMask: UInt32 = 0 + + subnetMask = addr32Full << (32 - Int(mask)!) + return (subnetMask) +} + +func wildcardMask(mask: String) -> UInt32 +{ + var wildcardMask: UInt32 = 0 + + wildcardMask = ~(addr32Full << (32 - Int(mask)!)) + return (wildcardMask) +} + +func digitize(ipAddress: UInt32) -> String +{ + var ipDigits = String() + + ipDigits.append(String(((ipAddress & addr32Digit1) >> 24)) + ".") + ipDigits.append(String(((ipAddress & addr32Digit2) >> 16)) + ".") + ipDigits.append(String(((ipAddress & addr32Digit3) >> 8)) + ".") + ipDigits.append(String(((ipAddress & addr32Digit4)))) + return (ipDigits) +} + +func maxHosts(mask: String) -> String +{ + var maxHosts: UInt32 = 0 + + maxHosts = (addr32Full >> UInt32(mask)!) - 1 + return (String(maxHosts)) +} + +func maxCIDRSubnets(mask: String) -> String +{ + var max: Int = 0 + + max = Int(truncating: NSDecimalNumber(decimal: pow(2, (32 - Int(mask)!)))) + return (String(max)) +} + +func subnetRange(ipAddress: String, mask: String) -> String +{ + var range = String() + var firstIP: UInt32 = 0 + var lastIP: UInt32 = 0 + + firstIP = subnetId(ipAddress: ipAddress, mask: mask) + 1 + lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) - 1 + range = digitize(ipAddress: firstIP) + " - " + digitize(ipAddress: lastIP) + return (range) +} + +func subnetCIDRRange(ipAddress: String, mask: String) -> String +{ + var range = String() + var firstIP: UInt32 = 0 + var lastIP: UInt32 = 0 + + firstIP = subnetId(ipAddress: ipAddress, mask: mask) + lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) + range = digitize(ipAddress: firstIP) + " - " + digitize(ipAddress: lastIP) + return (range) +} + +func netClass(ipAddress: String) -> String +{ + let ipNum = numerize(ipAddress: ipAddress) + let addr1stByte = (ipNum & maskClassA) >> 24 + + if (addr1stByte < 127) { + return ("A") + } + if (addr1stByte >= 127 && addr1stByte < 192) { + return ("B") + } + if (addr1stByte >= 192 && addr1stByte < 224) { + return ("C") + } + return ("D") +} + +func subnetBits(ipAddress: String, mask: String) -> String +{ + let classType = netClass(ipAddress: ipAddress) + var bits: Int = 0 + + if (classType == "A") { + bits = Int(mask)! - 8 + } + else if (classType == "B") { + bits = Int(mask)! - 16 + } + else if (classType == "C") { + bits = Int(mask)! - 24 + } + if (bits < 0) { + bits = 0 + } + return (String(bits)) +} + +func maxSubnets(ipAddress: String, mask: String) -> String +{ + var maxSubnets: Int = 0 + + let bits = subnetBits(ipAddress: ipAddress, mask: mask) + maxSubnets = Int(truncating: NSDecimalNumber(decimal: pow(2, Int(bits)!))) + return (String(maxSubnets)) +} + +func bitMap(ipAddress: String, mask: String) -> String +{ + let mask_num = numerize(mask: mask) + let classAddr = netClass(ipAddress: ipAddress) + var maskClass: UInt32 = 0 + + if (classAddr == "A") + { + maskClass = maskClassA + } + else if (classAddr == "B") + { + maskClass = maskClassB + } + else if (classAddr == "C") + { + maskClass = maskClassC + } + + var bitMap = String() + + for index in 0...31 { + if (((mask_num >> index) & maskClass) > 0) + { + bitMap.append("n") + } + else if (((mask_num >> index) & mask_num) > 0) + { + bitMap.append("s") + } + else + { + bitMap.append("h") + } + if ((index < 31) && ((index + 1) % 8 == 0)) + { + bitMap.append(".") + } + } + return (bitMap) +} + +func displayIPInfo(ipAddress: String, mask: String) +{ + if (isValidIP(ipAddress: ipAddress, mask: mask)) + { + print("IP Host : " + ipAddress) + print("Mask bits : " + mask) + print("Mask : " + digitize(ipAddress: subnetMask(mask: mask))) + print("Subnet bits : " + subnetBits(ipAddress: ipAddress, mask: mask)) + print("Subnet ID : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) + print("Broadcast : " + digitize(ipAddress: subnetBroadcast(ipAddress: ipAddress, mask: mask))) + print("Max Host : " + maxHosts(mask: mask)) + print("Max Subnet : " + maxSubnets(ipAddress: ipAddress, mask: mask)) + print("Subnet Range : " + subnetRange(ipAddress: ipAddress, mask: mask)) + print("IP Class Type : " + netClass(ipAddress: ipAddress)) + print("Hexa IP : " + hexarize(ipAddress: ipAddress)) + print("Binary IP : " + binarize(ipAddress: ipAddress)) + print("BitMap : " + bitMap(ipAddress: ipAddress, mask: mask)) + print("CIDR Netmask : " + digitize(ipAddress: subnetMask(mask: mask))) + print("Wildcard Mask : " + digitize(ipAddress: wildcardMask(mask: mask))) + print("CIDR Max Subnet : " + maxCIDRSubnets(mask: mask)) + print("CIDR Max Hosts : " + maxHosts(mask: mask)) + print("CIDR Network (Route) : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) + print("CIDR Net Notation : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask)) + "/" + mask) + print("CIDR Address Range : " + subnetCIDRRange(ipAddress: ipAddress, mask: mask)) + print("IP number in binary : " + String(numerize(ipAddress: ipAddress), radix: 2)) + //print("IP number reverse : " + digitize(ipAddress: numerize(ipAddress: ipAddress))) + print("Mask bin : " + String(numerize(mask: mask), radix: 2)) + print("Subnet ID bin : " + String(subnetId(ipAddress: ipAddress, mask: mask), radix: 2)) + print("Broadcast bin : " + String(subnetBroadcast(ipAddress: ipAddress, mask: mask), radix: 2)) + } + else + { + print("IP \(ipAddress) is not valid") + } +} + +//IPv6 SECTION +func numerizeIPv6(ipAddress: String) -> [UInt16] +{ + var ipAddressNum: [UInt16] = Array(repeating: 0, count: 8) + var ip4Hex = [String]() + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...7 { + ipAddressNum[index] = UInt16(ip4Hex[index], radix: 16)! + //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Hexa : \(UInt16(ip4Hex[index], radix: 16)!)") + } + return (ipAddressNum) +} + +func binarizeIPv6(ipAddress: String, delimiter: Bool = false) -> String +{ + var ip4Hex: [String] + var binary: String + var binStr = String() + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...7 { + binary = String(UInt16(ip4Hex[index], radix: 16)!, radix: 2) + while (binary.count < 16) + { + binary.insert("0", at: binary.startIndex) + } + binStr.append(binary) + if (delimiter && index < 7) + { + binStr.append(":") + } + //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Bin : \(binary)") + } + return (binStr) +} + +func getHexID(ipAddress: String) -> String +{ + var hexID: String = ipAddress + let delimiter: Set = [":"] + hexID.removeAll(where: { delimiter.contains($0) }) + return("0x\(hexID)") +} + +func getBinID(ipAddress: String) -> String { + return (binarizeIPv6(ipAddress: ipAddress)) +} + +func getIPv6Digit(ipAddress: String) -> String { + var digitStr = String() + let numIP = numerizeIPv6(ipAddress: ipAddress) + + for index in 0...7 { + if (index != 7) { + digitStr.append("\(numIP[index]):") + } + else { + digitStr.append("\(numIP[index])") + } + } + return (digitStr) +} + +func fullIPv6Address(ipAddress: String) -> String +{ + var fullAddr = String() + var ip4Hex = [String]() + var prevIsZero = false + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...(ip4Hex.count - 1) { + //print("Index : \(index) Hex : \(ip4Hex[index])") + if (ip4Hex[index] == "" && !prevIsZero) + { + prevIsZero = true + //print("Index : \(index + 1) is empty, \(8 - ip4Hex.count + 1) hex quad are missing") + while (ip4Hex[index].count < (4 * (8 - ip4Hex.count + 1))) + { + ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) + } + } + else { + while (ip4Hex[index].count < 4) + { + ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) + } + } + fullAddr.append(ip4Hex[index]) + } + var offset = fullAddr.index(fullAddr.startIndex, offsetBy: 4) + for _ in 1...7 + { + fullAddr.insert(":", at: offset) + offset = fullAddr.index(offset, offsetBy: 5) + } + return (fullAddr) +} + +func compactIPv6Address(ipAddress: String) -> String +{ + var shortAddr = String() + var ip4Hex = [String]() + var prevIsZero = false + var prevAreZero = false + var prevCompactZero = false + + + //print("IP Address: \(ipAddress)") + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...(ip4Hex.count - 1) { + //print("Index : \(index) IPHex : \(ip4Hex[index]) Dec : \(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16))") + if (UInt16(ip4Hex[index], radix: 16)! == 0) + { + if (!prevIsZero || prevCompactZero) + { + if index == (ip4Hex.count - 1) + { + shortAddr.append("0") + } + else + { + shortAddr.append("0:") + } + } + else if (prevIsZero && !prevAreZero) + { + shortAddr.removeLast(2) + prevAreZero = true + } + if (prevIsZero && index == (ip4Hex.count - 1)) + { + if (shortAddr == "") + { + shortAddr.append("::") + } + else + { + shortAddr.append(":") + } + } + prevIsZero = true + } + else + { + if (prevAreZero && !prevCompactZero) + { + if index == (ip4Hex.count - 1) + { + shortAddr.append("::") + } + else + { + shortAddr.append(":") + } + prevCompactZero = true + } + shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) + if (index != (ip4Hex.count - 1)) + { + shortAddr.append(":") + } + prevIsZero = false + prevAreZero = false + } + + } + /* + var offset = shortAddr.index(shortAddr.startIndex, offsetBy: 4) + for _ in 1...7 + { + shortAddr.insert(":", at: offset) + offset = shortAddr.index(offset, offsetBy: 5) + } + */ + return (shortAddr) +} + +func numerizeMask(maskbits: Int) -> [UInt16] +{ + var maskNum: [UInt16] = Array(repeating: 0, count: 8) + + for i in 0...7 { + //print("Index : \(i), mask bits : \(maskbits - (16 * (i + 1)) >= 0 ? 16 : (maskbits % (16 * i)) < maskbits ? (maskbits % (16 * i)) : 0) Div : \(maskbits / (16 * (i + 1))) Mod : \(maskbits % (16 * (i + 1)))") + if ((maskbits - (16 * i)) < 16) + { + if ((maskbits - (16 * i)) > 0) + { + maskNum[i] = UInt16(addr16Full & (addr16Full << (16 - (maskbits - (16 * i))))) + } + else + { + //print("Index : \(i), ZERO mask : \(maskNum[i])") + } + } + else + { + maskNum[i] = addr16Full + } + } + return (maskNum) +} + +func hexarize(num: [UInt16], full: Bool = true, column: Bool = false) -> String +{ + var hex: String + var hexStr = String() + + for index in 0...(num.count - 1) { + hex = String(num[index], radix: 16) + while (hex.count < 4 && full) + { + hex.insert("0", at: hex.startIndex) + } + hexStr.append(hex) + if (column && index < (num.count - 1)) + { + hexStr.append(":") + } + } + return (hexStr) +} + +func networkID(ipAddress: String, maskbits: Int) -> String +{ + var netID = [UInt16]() + let numMask = numerizeMask(maskbits: maskbits) + let numIP = numerizeIPv6(ipAddress: fullIPv6Address(ipAddress: ipAddress)) + let nbIndex = maskbits / 16 + + for index in 0...nbIndex { + if (index < 8) + { + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID.append((numIP[index] & numMask[index])) + } + } + var netIDStr = hexarize(num: netID, full: false, column: true) + if (nbIndex < 7) + { + netIDStr.append("::") + } + return (netIDStr) +} + +func networkRange(ipAddress: String, maskbits: Int) -> String +{ + var netID = [UInt16]() + var netID2 = [UInt16]() + let numMask = numerizeMask(maskbits: maskbits) + let numIP = numerizeIPv6(ipAddress: ipAddress) + + for index in 0...7 { + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID.append((numIP[index] & numMask[index])) + } + for index in 0...7 { + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID2.append((numIP[index] | ~numMask[index])) + } + var netIDStr = hexarize(num: netID, full: true, column: true) + netIDStr.append(" - \(hexarize(num: netID2, full: true, column: true))") + return (netIDStr) +} + +func getTotalIPAddr(maskbits: Int) -> Decimal +{ + var total = Decimal() + var number: Decimal = 2 + + NSDecimalPower(&total, &number , (128 - maskbits), NSDecimalNumber.RoundingMode.plain) + //return (pow(2, Double(128 - maskbits))) + return (total) +} + +func ip6ARPA (ipAddress: String) -> String +{ + var ipARPA = fullIPv6Address(ipAddress: ipAddress) + let delimiter: Set = [":"] + + ipARPA.removeAll(where: { delimiter.contains($0) }) + ipARPA = String(ipARPA.reversed()) + + var offset = ipARPA.index(ipARPA.startIndex, offsetBy: 1) + for _ in 0...(ipARPA.count - 2) { + ipARPA.insert(".", at: offset) + offset = ipARPA.index(offset, offsetBy: 2) + } + ipARPA.append(".ip6.arpa") + return (ipARPA) +} + +func resIPv6Block(ipAddress: String, maskbits: Int) -> String? +{ + var netID = networkID(ipAddress: ipAddress, maskbits: maskbits) + + netID = fullIPv6Address(ipAddress: netID) + //print("NetID BEFORE compact : \(netID)") + netID = compactIPv6Address(ipAddress: netID) + //print("NetID AFTER compact : \(netID)") + netID.append("/\(maskbits)") + + for item in resIPv6Blocks { + if (item.key == netID) + { + return (item.value + " (\(item.key))") + } + } + return nil +} diff --git a/README.md b/README.md index faa2471..4b74e95 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # SubnetCalc -Subnet Calculator for MacOS X +Subnet Calculator for MacOS What's New in version 1.6: - Dark Mode support diff --git a/SubnetCalc-Bridging-Header.h b/SubnetCalc-Bridging-Header.h new file mode 100644 index 0000000..1b2cb5d --- /dev/null +++ b/SubnetCalc-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/SubnetCalc-Info.plist b/SubnetCalc-Info.plist index 93b4c6a..fe69fbd 100644 --- a/SubnetCalc-Info.plist +++ b/SubnetCalc-Info.plist @@ -15,11 +15,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.6 + 1.7 CFBundleSignature JMUL CFBundleVersion - 3 + 4 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/SubnetCalc.xcodeproj/project.pbxproj b/SubnetCalc.xcodeproj/project.pbxproj index 0a5376e..175991b 100644 --- a/SubnetCalc.xcodeproj/project.pbxproj +++ b/SubnetCalc.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 949420B812D3C62A00E2F57D /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 949420B712D3C62A00E2F57D /* License.txt */; }; 949420BD12D3C64500E2F57D /* IPSubnetCalc.m in Sources */ = {isa = PBXBuildFile; fileRef = 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */; }; 9494DD211F7BEAE80032DB19 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9494DD201F7BEAE80032DB19 /* Images.xcassets */; }; + 94B1C507256ABC1B00F992A3 /* IPSubnetcalc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */; }; 94B6031212F74DC7005AA5EB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94B6031112F74DC7005AA5EB /* CoreFoundation.framework */; }; /* End PBXBuildFile section */ @@ -49,6 +50,8 @@ 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = IPSubnetCalc.m; sourceTree = ""; }; 9494DD1F1F7BE7B40032DB19 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 9494DD201F7BEAE80032DB19 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SubnetCalc/Images.xcassets; sourceTree = ""; }; + 94B1C505256ABC1A00F992A3 /* SubnetCalc-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SubnetCalc-Bridging-Header.h"; sourceTree = ""; }; + 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPSubnetcalc.swift; sourceTree = ""; }; 94B6031112F74DC7005AA5EB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; 94CDB5F6255EE11D0010F1E4 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 94D8C5731520F99500B27A3A /* SubnetCalc.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = SubnetCalc.entitlements; sourceTree = ""; }; @@ -79,8 +82,10 @@ children = ( 949420B912D3C64500E2F57D /* IPSubnetCalc.h */, 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */, + 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */, 256AC3D80F4B6AC300CF3369 /* SubnetCalcAppDelegate.h */, 256AC3D90F4B6AC300CF3369 /* SubnetCalcAppDelegate.m */, + 94B1C505256ABC1A00F992A3 /* SubnetCalc-Bridging-Header.h */, ); name = Classes; sourceTree = ""; @@ -215,7 +220,7 @@ LastUpgradeCheck = 1220; TargetAttributes = { 8D1107260486CEB800E47090 = { - LastSwiftMigration = 0820; + LastSwiftMigration = 1220; ProvisioningStyle = Automatic; SystemCapabilities = { com.apple.Sandbox = { @@ -276,6 +281,7 @@ files = ( 8D11072D0486CEB800E47090 /* main.m in Sources */, 256AC3DA0F4B6AC300CF3369 /* SubnetCalcAppDelegate.m in Sources */, + 94B1C507256ABC1B00F992A3 /* IPSubnetcalc.swift in Sources */, 949420BD12D3C64500E2F57D /* IPSubnetCalc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -321,6 +327,7 @@ 945E62FD25658DBF00CDC9C7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -362,6 +369,7 @@ 945E62FE25658DBF00CDC9C7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; @@ -400,6 +408,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = SubnetCalc.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; @@ -413,10 +422,13 @@ GCC_PREFIX_HEADER = SubnetCalc_Prefix.pch; INFOPLIST_FILE = "SubnetCalc-Info.plist"; INSTALL_PATH = "$(HOME)/Applications"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.mulot.subnetcalc; PRODUCT_NAME = SubnetCalc; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; + SWIFT_OBJC_BRIDGING_HEADER = "SubnetCalc-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -425,6 +437,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = SubnetCalc.entitlements; CODE_SIGN_IDENTITY = "Mac Developer"; COMBINE_HIDPI_IMAGES = YES; @@ -436,10 +449,12 @@ GCC_PREFIX_HEADER = SubnetCalc_Prefix.pch; INFOPLIST_FILE = "SubnetCalc-Info.plist"; INSTALL_PATH = /Applications; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = net.mulot.subnetcalc; PRODUCT_NAME = SubnetCalc; PROVISIONING_PROFILE_SPECIFIER = ""; - SWIFT_VERSION = 3.0; + SWIFT_OBJC_BRIDGING_HEADER = "SubnetCalc-Bridging-Header.h"; + SWIFT_VERSION = 5.0; }; name = Release; }; From d62a51932bc168b9e8907abf326a1c5f07422888 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sun, 22 Nov 2020 21:46:33 +0100 Subject: [PATCH 02/66] Add swift files with SubnetCalc swift engine and swift AppDelegate App broken, need to remap all UI actions to swift AppDelegate class --- Base.lproj/MainMenu.xib | 43 ++++++++++++++++------------ IPSubnetcalc.swift | 3 +- SubnetCalc.xcodeproj/project.pbxproj | 6 +++- SubnetCalcAppDelegate.swift | 38 ++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 SubnetCalcAppDelegate.swift diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 348f392..381822d 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -8,7 +8,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -269,14 +269,14 @@ - + - + - + @@ -292,14 +292,14 @@ - + - + - + @@ -330,7 +330,7 @@ - + @@ -338,14 +338,14 @@ - + - + - + @@ -361,7 +361,7 @@ - + @@ -404,14 +404,14 @@ - + - + - + @@ -424,7 +424,7 @@ - + @@ -526,7 +526,7 @@ - + @@ -809,7 +809,7 @@ - + @@ -849,5 +849,10 @@ + + + + + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index ed897d1..a6c7766 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -35,7 +35,7 @@ let maskClassB: UInt32 = 0xFFFF0000 let netIdClassC: UInt32 = 0xc0000000 let maskClassC: UInt32 = 0xFFFFFF00 - +class IPSubnetCalc: NSObject { //IPv4 SECTION func binarize(ipAddress: String) -> String { @@ -683,3 +683,4 @@ func resIPv6Block(ipAddress: String, maskbits: Int) -> String? } return nil } +} diff --git a/SubnetCalc.xcodeproj/project.pbxproj b/SubnetCalc.xcodeproj/project.pbxproj index 175991b..db63fae 100644 --- a/SubnetCalc.xcodeproj/project.pbxproj +++ b/SubnetCalc.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 949420B812D3C62A00E2F57D /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 949420B712D3C62A00E2F57D /* License.txt */; }; 949420BD12D3C64500E2F57D /* IPSubnetCalc.m in Sources */ = {isa = PBXBuildFile; fileRef = 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */; }; 9494DD211F7BEAE80032DB19 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9494DD201F7BEAE80032DB19 /* Images.xcassets */; }; + 94AC2613256AF7C900811156 /* SubnetCalcAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94AC2612256AF7C900811156 /* SubnetCalcAppDelegate.swift */; }; 94B1C507256ABC1B00F992A3 /* IPSubnetcalc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */; }; 94B6031212F74DC7005AA5EB /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94B6031112F74DC7005AA5EB /* CoreFoundation.framework */; }; /* End PBXBuildFile section */ @@ -50,6 +51,7 @@ 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.objc; fileEncoding = 4; path = IPSubnetCalc.m; sourceTree = ""; }; 9494DD1F1F7BE7B40032DB19 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 9494DD201F7BEAE80032DB19 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SubnetCalc/Images.xcassets; sourceTree = ""; }; + 94AC2612256AF7C900811156 /* SubnetCalcAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubnetCalcAppDelegate.swift; sourceTree = ""; }; 94B1C505256ABC1A00F992A3 /* SubnetCalc-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SubnetCalc-Bridging-Header.h"; sourceTree = ""; }; 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPSubnetcalc.swift; sourceTree = ""; }; 94B6031112F74DC7005AA5EB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; @@ -83,8 +85,9 @@ 949420B912D3C64500E2F57D /* IPSubnetCalc.h */, 949420BA12D3C64500E2F57D /* IPSubnetCalc.m */, 94B1C506256ABC1B00F992A3 /* IPSubnetcalc.swift */, - 256AC3D80F4B6AC300CF3369 /* SubnetCalcAppDelegate.h */, 256AC3D90F4B6AC300CF3369 /* SubnetCalcAppDelegate.m */, + 256AC3D80F4B6AC300CF3369 /* SubnetCalcAppDelegate.h */, + 94AC2612256AF7C900811156 /* SubnetCalcAppDelegate.swift */, 94B1C505256ABC1A00F992A3 /* SubnetCalc-Bridging-Header.h */, ); name = Classes; @@ -283,6 +286,7 @@ 256AC3DA0F4B6AC300CF3369 /* SubnetCalcAppDelegate.m in Sources */, 94B1C507256ABC1B00F992A3 /* IPSubnetcalc.swift in Sources */, 949420BD12D3C64500E2F57D /* IPSubnetCalc.m in Sources */, + 94AC2613256AF7C900811156 /* SubnetCalcAppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift new file mode 100644 index 0000000..0e2ec1a --- /dev/null +++ b/SubnetCalcAppDelegate.swift @@ -0,0 +1,38 @@ +// +// SubnetCalcAppDelegate.swift +// SubnetCalc +// +// Created by Julien Mulot on 22/11/2020. +// + +import Foundation +import Cocoa + +struct Constants { + static let BUFFER_LINES:Int = 1000 + static let NETWORK_BITS_MIN_CLASSLESS:Int = 1 + static let NETWORK_BITS_MIN:Int = 8 + static let NETWORK_BITS_MAX:Int = 32 +} + +class AppDelegate: NSObject, NSApplicationDelegate { + + @IBOutlet var window: NSWindow! + + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } + + @IBAction func changeMaskBits(sender: Any) + { + + } + +} + + From ca2b1748205395e7cdf06d402cb07759421ee705 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Mon, 23 Nov 2020 10:53:16 +0100 Subject: [PATCH 03/66] convert Swift constants to an enum Constants Add IPSubnetcalc class properties and Init classes to init them Define all IBOutlet ref for Swift App Delegate Define all IBAction func for Swift App Delegate Define a working darkMode func for Swift App Delegate Declare properly setBitMap func in Header Modify setBitMap return type to void --- Base.lproj/MainMenu.xib | 6 +- IPSubnetCalc.h | 1 + IPSubnetCalc.m | 2 +- IPSubnetcalc.swift | 1199 +++++++++++++++++------------------ SubnetCalcAppDelegate.swift | 223 ++++++- 5 files changed, 800 insertions(+), 631 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 381822d..61b6a5b 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -129,7 +129,7 @@ - + @@ -817,14 +817,12 @@ - - @@ -851,6 +849,8 @@ + + diff --git a/IPSubnetCalc.h b/IPSubnetCalc.h index 2f8e620..330ff47 100644 --- a/IPSubnetCalc.h +++ b/IPSubnetCalc.h @@ -54,6 +54,7 @@ - (NSString *)hexMap; - (NSString *)binMap; - (NSString *)bitMap; +- (void)setBitMap; - (NSNumber *)hostAddr; - (unsigned int)hostAddrIntValue; - (NSNumber *)subnetBits; diff --git a/IPSubnetCalc.m b/IPSubnetCalc.m index 54ef8c5..0883514 100644 --- a/IPSubnetCalc.m +++ b/IPSubnetCalc.m @@ -72,7 +72,7 @@ + (int)countOnBits:(unsigned int)number } -- (IBAction)setBitMap +- (void)setBitMap { int i; int dots = 0; diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index a6c7766..bd5199c 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -9,678 +9,651 @@ import Foundation import Cocoa -//Const IPv6 -let addr16Full: UInt16 = 0xFFFF -let addr16Empty: UInt16 = 0x0000 -let addr128Full: [UInt16] = [addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full] -let addr128Empty: [UInt16] = [addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty] -let addr16Hex1: UInt16 = 0xF000 -let addr16Hex2: UInt16 = 0x0F00 -let addr16Hex3: UInt16 = 0x00F0 -let addr16Hex4: UInt16 = 0x000F - -let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", "::/128" : " Unspecified Address", "2001:db8::/32" : "Documentation"] - -//Const IPv4 -let addr32Full: UInt32 = 0xFFFFFFFF -let addr32Empty: UInt32 = 0x00000000 -let addr32Digit1: UInt32 = 0xFF000000 -let addr32Digit2: UInt32 = 0x00FF0000 -let addr32Digit3: UInt32 = 0x0000FF00 -let addr32Digit4: UInt32 = 0x000000FF -let netIdClassA: UInt32 = 0x01000000 -let maskClassA: UInt32 = 0xFF000000 -let netIdClassB: UInt32 = 0x80000000 -let maskClassB: UInt32 = 0xFFFF0000 -let netIdClassC: UInt32 = 0xc0000000 -let maskClassC: UInt32 = 0xFFFFFF00 - class IPSubnetCalc: NSObject { -//IPv4 SECTION -func binarize(ipAddress: String) -> String -{ - var ipAddressBin = [String]() - var binStr = String() - var ipDigits = [String]() - - ipDigits = ipAddress.components(separatedBy: ".") - - for index in 0...3 { - ipAddressBin.append(String(Int(ipDigits[index])!, radix: 2)) - while (ipAddressBin[index].count < 8) - { - ipAddressBin[index].insert("0", at: ipAddressBin[index].startIndex) - } - - var digitBin = ipAddressBin[index] - digitBin.insert(" ", at: ipAddressBin[index].index(ipAddressBin[index].startIndex, offsetBy: 4)) - if (index < 3) - { - binStr += digitBin + "." + //************* + //Constants + //************* + enum Constants { + //IPv6 constants + static let addr16Full: UInt16 = 0xFFFF + static let addr16Empty: UInt16 = 0x0000 + static let addr128Full: [UInt16] = [addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full] + static let addr128Empty: [UInt16] = [addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty] + static let addr16Hex1: UInt16 = 0xF000 + static let addr16Hex2: UInt16 = 0x0F00 + static let addr16Hex3: UInt16 = 0x00F0 + static let addr16Hex4: UInt16 = 0x000F + + static let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", "::/128" : " Unspecified Address", "2001:db8::/32" : "Documentation"] + + //IPv4 constants + static let addr32Full: UInt32 = 0xFFFFFFFF + static let addr32Empty: UInt32 = 0x00000000 + static let addr32Digit1: UInt32 = 0xFF000000 + static let addr32Digit2: UInt32 = 0x00FF0000 + static let addr32Digit3: UInt32 = 0x0000FF00 + static let addr32Digit4: UInt32 = 0x000000FF + static let netIdClassA: UInt32 = 0x01000000 + static let maskClassA: UInt32 = 0xFF000000 + static let netIdClassB: UInt32 = 0x80000000 + static let maskClassB: UInt32 = 0xFFFF0000 + static let netIdClassC: UInt32 = 0xc0000000 + static let maskClassC: UInt32 = 0xFFFFFF00 + } + + //************* + //Properties + //************* + var ipv4Address: String + var networkClass: String + var netId: UInt + var netBits: UInt + var mask: UInt + var subnetMax: UInt + var subnetBits: UInt + var maskBits: UInt + var subnetBitsMax: UInt + var subnetMask: UInt + var hostBits: UInt + var hostMax: UInt + var hostAddr: UInt + var hostId: UInt + var hostSubnetLbound: UInt + var hostSubnetUbound: UInt + var ciscoWildcard: UInt + var bitMap: String + + //************* + //IPv4 SECTION + //************* + static func binarize(ipAddress: String) -> String { + var ipAddressBin = [String]() + var binStr = String() + var ipDigits = [String]() + + ipDigits = ipAddress.components(separatedBy: ".") + + for index in 0...3 { + ipAddressBin.append(String(Int(ipDigits[index])!, radix: 2)) + while (ipAddressBin[index].count < 8) { + ipAddressBin[index].insert("0", at: ipAddressBin[index].startIndex) + } + + var digitBin = ipAddressBin[index] + digitBin.insert(" ", at: ipAddressBin[index].index(ipAddressBin[index].startIndex, offsetBy: 4)) + if (index < 3) { + binStr += digitBin + "." + } + else { + binStr += digitBin + } } - else - { - binStr += digitBin + return (binStr) + } + + static func hexarize(ipAddress: String) -> String { + var ipDigits = [String]() + var hexIP = String() + var hex4: String + + ipDigits = ipAddress.components(separatedBy: ".") + for index in 0...3 { + hex4 = String(format: "%X", Int(ipDigits[index])!) + if (hex4.count == 1) { + hex4 = "0" + hex4 + } + hexIP += hex4 + if (index < 3) { + hexIP += "." + } } + return (hexIP) } - return (binStr) -} - -func hexarize(ipAddress: String) -> String -{ - var ipDigits = [String]() - var hexIP = String() - var hex4: String - - ipDigits = ipAddress.components(separatedBy: ".") - for index in 0...3 { - hex4 = String(format: "%X", Int(ipDigits[index])!) - if (hex4.count == 1) - { - hex4 = "0" + hex4 - } - hexIP += hex4 - if (index < 3) - { - hexIP += "." - } - } - return (hexIP) -} - -func numerize(ipAddress: String) -> UInt32 -{ - var ipAddressNum: UInt32 = 0 - var ipDigits = [String]() - - ipDigits = ipAddress.components(separatedBy: ".") - for index in 0...3 { - ipAddressNum += UInt32(ipDigits[index])! << (32 - 8 * (index + 1)) + static func numerize(ipAddress: String) -> UInt32 { + var ipAddressNum: UInt32 = 0 + var ipDigits = [String]() + + ipDigits = ipAddress.components(separatedBy: ".") + + for index in 0...3 { + ipAddressNum += UInt32(ipDigits[index])! << (32 - 8 * (index + 1)) + } + return (ipAddressNum & Constants.addr32Full) } - return (ipAddressNum & addr32Full) -} - -func numerize(mask: String) -> UInt32 -{ - var maskNum: UInt32 = 0 - maskNum = (addr32Full << (32 - Int(mask)!)) & addr32Full - return (maskNum) -} - -func splitAddrMask(address: String) -> (String, String) { - let ipInfo = address.split(separator: "/") - if ipInfo.count == 2 { - return (String(ipInfo[0]), String(ipInfo[1])) + static func numerize(mask: String) -> UInt32 { + var maskNum: UInt32 = 0 + + maskNum = (Constants.addr32Full << (32 - Int(mask)!)) & Constants.addr32Full + return (maskNum) } - else if ipInfo.count > 2 { - print("Bad IP format: \(ipInfo)") - return ("", "") + + static func digitize(ipAddress: UInt32) -> String { + var ipDigits = String() + + ipDigits.append(String(((ipAddress & Constants.addr32Digit1) >> 24)) + ".") + ipDigits.append(String(((ipAddress & Constants.addr32Digit2) >> 16)) + ".") + ipDigits.append(String(((ipAddress & Constants.addr32Digit3) >> 8)) + ".") + ipDigits.append(String(((ipAddress & Constants.addr32Digit4)))) + return (ipDigits) } - return (address, "") -} - -func isValidIP(ipAddress: String, mask: String?) -> Bool -{ - var ip4Digits = [String]() - - ip4Digits = ipAddress.components(separatedBy: ".") - if (ip4Digits.count == 4) { - for item in ip4Digits { - if let digit = Int(item, radix: 10) { - if (digit > 255) { - print("bad IP digit \(digit)") + + func splitAddrMask(address: String) -> (String, String) { + let ipInfo = address.split(separator: "/") + if ipInfo.count == 2 { + return (String(ipInfo[0]), String(ipInfo[1])) + } + else if ipInfo.count > 2 { + print("Bad IP format: \(ipInfo)") + return ("", "") + } + return (address, "") + } + + func isValidIP(ipAddress: String, mask: String?) -> Bool { + var ip4Digits = [String]() + + ip4Digits = ipAddress.components(separatedBy: ".") + if (ip4Digits.count == 4) { + for item in ip4Digits { + if let digit = Int(item, radix: 10) { + if (digit > 255) { + print("bad IP digit \(digit)") + return false + } + } + else { + print("not digit: \(item)") return false } } - else { - print("not digit: \(item)") - return false - } } - } - else { - print("bad IP format \(ip4Digits)") - return false - } - if mask != nil { - if let maskNum = Int(mask!) { - if (maskNum < 0 || maskNum > 32) { - print("mask \(maskNum) invalid") + else { + print("bad IP format \(ip4Digits)") + return false + } + if mask != nil { + if let maskNum = Int(mask!) { + if (maskNum < 0 || maskNum > 32) { + print("mask \(maskNum) invalid") + return false + } + } + else { + print("mask \(mask!) is not digit") return false } } else { - print("mask \(mask!) is not digit") - return false + print("null mask") } + return true + } + + func subnetId(ipAddress: String, mask: String) -> UInt32 { + var subnetId: UInt32 = 0 + let ipBits = IPSubnetCalc.numerize(ipAddress: ipAddress) + let maskBits = IPSubnetCalc.numerize(mask: mask) + + subnetId = ipBits & maskBits + return (subnetId) + } + + func subnetBroadcast(ipAddress: String, mask: String) -> UInt32 { + var broadcast: UInt32 = 0 + let ipBits = IPSubnetCalc.numerize(ipAddress: ipAddress) + let maskBits = IPSubnetCalc.numerize(mask: mask) + + broadcast = ipBits & maskBits | (Constants.addr32Full >> Int(mask)!) + return (broadcast) + } + + func subnetMask(mask: String) -> UInt32 { + var subnetMask: UInt32 = 0 + + subnetMask = Constants.addr32Full << (32 - Int(mask)!) + return (subnetMask) + } + + func wildcardMask(mask: String) -> UInt32 { + var wildcardMask: UInt32 = 0 + + wildcardMask = ~(Constants.addr32Full << (32 - Int(mask)!)) + return (wildcardMask) + } + + func maxHosts(mask: String) -> String { + var maxHosts: UInt32 = 0 + + maxHosts = (Constants.addr32Full >> UInt32(mask)!) - 1 + return (String(maxHosts)) + } + + func maxCIDRSubnets(mask: String) -> String { + var max: Int = 0 + + max = Int(truncating: NSDecimalNumber(decimal: pow(2, (32 - Int(mask)!)))) + return (String(max)) + } + + func subnetRange(ipAddress: String, mask: String) -> String { + var range = String() + var firstIP: UInt32 = 0 + var lastIP: UInt32 = 0 + + firstIP = subnetId(ipAddress: ipAddress, mask: mask) + 1 + lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) - 1 + range = IPSubnetCalc.digitize(ipAddress: firstIP) + " - " + IPSubnetCalc.digitize(ipAddress: lastIP) + return (range) + } + + func subnetCIDRRange(ipAddress: String, mask: String) -> String { + var range = String() + var firstIP: UInt32 = 0 + var lastIP: UInt32 = 0 + + firstIP = subnetId(ipAddress: ipAddress, mask: mask) + lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) + range = IPSubnetCalc.digitize(ipAddress: firstIP) + " - " + IPSubnetCalc.digitize(ipAddress: lastIP) + return (range) + } + + func netClass(ipAddress: String) -> String { + let ipNum = IPSubnetCalc.numerize(ipAddress: ipAddress) + let addr1stByte = (ipNum & Constants.maskClassA) >> 24 + + if (addr1stByte < 127) { + return ("A") + } + if (addr1stByte >= 127 && addr1stByte < 192) { + return ("B") + } + if (addr1stByte >= 192 && addr1stByte < 224) { + return ("C") + } + return ("D") } - else { - print("null mask") - } - return true -} - -func subnetId(ipAddress: String, mask: String) -> UInt32 -{ - var subnetId: UInt32 = 0 - let ipBits = numerize(ipAddress: ipAddress) - let maskBits = numerize(mask: mask) - - subnetId = ipBits & maskBits - return (subnetId) -} - -func subnetBroadcast(ipAddress: String, mask: String) -> UInt32 -{ - var broadcast: UInt32 = 0 - let ipBits = numerize(ipAddress: ipAddress) - let maskBits = numerize(mask: mask) - - broadcast = ipBits & maskBits | (addr32Full >> Int(mask)!) - return (broadcast) -} - -func subnetMask(mask: String) -> UInt32 -{ - var subnetMask: UInt32 = 0 - - subnetMask = addr32Full << (32 - Int(mask)!) - return (subnetMask) -} - -func wildcardMask(mask: String) -> UInt32 -{ - var wildcardMask: UInt32 = 0 - - wildcardMask = ~(addr32Full << (32 - Int(mask)!)) - return (wildcardMask) -} - -func digitize(ipAddress: UInt32) -> String -{ - var ipDigits = String() - - ipDigits.append(String(((ipAddress & addr32Digit1) >> 24)) + ".") - ipDigits.append(String(((ipAddress & addr32Digit2) >> 16)) + ".") - ipDigits.append(String(((ipAddress & addr32Digit3) >> 8)) + ".") - ipDigits.append(String(((ipAddress & addr32Digit4)))) - return (ipDigits) -} - -func maxHosts(mask: String) -> String -{ - var maxHosts: UInt32 = 0 - - maxHosts = (addr32Full >> UInt32(mask)!) - 1 - return (String(maxHosts)) -} - -func maxCIDRSubnets(mask: String) -> String -{ - var max: Int = 0 - - max = Int(truncating: NSDecimalNumber(decimal: pow(2, (32 - Int(mask)!)))) - return (String(max)) -} - -func subnetRange(ipAddress: String, mask: String) -> String -{ - var range = String() - var firstIP: UInt32 = 0 - var lastIP: UInt32 = 0 - - firstIP = subnetId(ipAddress: ipAddress, mask: mask) + 1 - lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) - 1 - range = digitize(ipAddress: firstIP) + " - " + digitize(ipAddress: lastIP) - return (range) -} - -func subnetCIDRRange(ipAddress: String, mask: String) -> String -{ - var range = String() - var firstIP: UInt32 = 0 - var lastIP: UInt32 = 0 - - firstIP = subnetId(ipAddress: ipAddress, mask: mask) - lastIP = subnetBroadcast(ipAddress: ipAddress, mask: mask) - range = digitize(ipAddress: firstIP) + " - " + digitize(ipAddress: lastIP) - return (range) -} - -func netClass(ipAddress: String) -> String -{ - let ipNum = numerize(ipAddress: ipAddress) - let addr1stByte = (ipNum & maskClassA) >> 24 - - if (addr1stByte < 127) { - return ("A") - } - if (addr1stByte >= 127 && addr1stByte < 192) { - return ("B") - } - if (addr1stByte >= 192 && addr1stByte < 224) { - return ("C") - } - return ("D") -} - -func subnetBits(ipAddress: String, mask: String) -> String -{ - let classType = netClass(ipAddress: ipAddress) - var bits: Int = 0 - if (classType == "A") { - bits = Int(mask)! - 8 - } - else if (classType == "B") { - bits = Int(mask)! - 16 - } - else if (classType == "C") { - bits = Int(mask)! - 24 - } - if (bits < 0) { - bits = 0 + func subnetBits(ipAddress: String, mask: String) -> String { + let classType = netClass(ipAddress: ipAddress) + var bits: Int = 0 + + if (classType == "A") { + bits = Int(mask)! - 8 + } + else if (classType == "B") { + bits = Int(mask)! - 16 + } + else if (classType == "C") { + bits = Int(mask)! - 24 + } + if (bits < 0) { + bits = 0 + } + return (String(bits)) } - return (String(bits)) -} - -func maxSubnets(ipAddress: String, mask: String) -> String -{ - var maxSubnets: Int = 0 - - let bits = subnetBits(ipAddress: ipAddress, mask: mask) - maxSubnets = Int(truncating: NSDecimalNumber(decimal: pow(2, Int(bits)!))) - return (String(maxSubnets)) -} - -func bitMap(ipAddress: String, mask: String) -> String -{ - let mask_num = numerize(mask: mask) - let classAddr = netClass(ipAddress: ipAddress) - var maskClass: UInt32 = 0 - if (classAddr == "A") - { - maskClass = maskClassA + func maxSubnets(ipAddress: String, mask: String) -> String { + var maxSubnets: Int = 0 + + let bits = subnetBits(ipAddress: ipAddress, mask: mask) + maxSubnets = Int(truncating: NSDecimalNumber(decimal: pow(2, Int(bits)!))) + return (String(maxSubnets)) } - else if (classAddr == "B") - { - maskClass = maskClassB - } - else if (classAddr == "C") - { - maskClass = maskClassC - } - - var bitMap = String() - for index in 0...31 { - if (((mask_num >> index) & maskClass) > 0) - { - bitMap.append("n") + func bitMap(ipAddress: String, mask: String) -> String { + let mask_num = IPSubnetCalc.numerize(mask: mask) + let classAddr = netClass(ipAddress: ipAddress) + var maskClass: UInt32 = 0 + var bitMap = String() + + if (classAddr == "A") { + maskClass = Constants.maskClassA } - else if (((mask_num >> index) & mask_num) > 0) - { - bitMap.append("s") + else if (classAddr == "B") { + maskClass = Constants.maskClassB } - else - { - bitMap.append("h") + else if (classAddr == "C") { + maskClass = Constants.maskClassC + } + + for index in 0...31 { + if (((mask_num >> index) & maskClass) > 0) { + bitMap.append("n") + } + else if (((mask_num >> index) & mask_num) > 0) { + bitMap.append("s") + } + else { + bitMap.append("h") + } + if ((index < 31) && ((index + 1) % 8 == 0)) { + bitMap.append(".") + } } - if ((index < 31) && ((index + 1) % 8 == 0)) - { - bitMap.append(".") + return (bitMap) + } + + func displayIPInfo(ipAddress: String, mask: String) { + if (isValidIP(ipAddress: ipAddress, mask: mask)) { + print("IP Host : " + ipAddress) + print("Mask bits : " + mask) + print("Mask : " + IPSubnetCalc.digitize(ipAddress: subnetMask(mask: mask))) + print("Subnet bits : " + subnetBits(ipAddress: ipAddress, mask: mask)) + print("Subnet ID : " + IPSubnetCalc.digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) + print("Broadcast : " + IPSubnetCalc.digitize(ipAddress: subnetBroadcast(ipAddress: ipAddress, mask: mask))) + print("Max Host : " + maxHosts(mask: mask)) + print("Max Subnet : " + maxSubnets(ipAddress: ipAddress, mask: mask)) + print("Subnet Range : " + subnetRange(ipAddress: ipAddress, mask: mask)) + print("IP Class Type : " + netClass(ipAddress: ipAddress)) + print("Hexa IP : " + IPSubnetCalc.hexarize(ipAddress: ipAddress)) + print("Binary IP : " + IPSubnetCalc.binarize(ipAddress: ipAddress)) + print("BitMap : " + bitMap(ipAddress: ipAddress, mask: mask)) + print("CIDR Netmask : " + IPSubnetCalc.digitize(ipAddress: subnetMask(mask: mask))) + print("Wildcard Mask : " + IPSubnetCalc.digitize(ipAddress: wildcardMask(mask: mask))) + print("CIDR Max Subnet : " + maxCIDRSubnets(mask: mask)) + print("CIDR Max Hosts : " + maxHosts(mask: mask)) + print("CIDR Network (Route) : " + IPSubnetCalc.digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) + print("CIDR Net Notation : " + IPSubnetCalc.digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask)) + "/" + mask) + print("CIDR Address Range : " + subnetCIDRRange(ipAddress: ipAddress, mask: mask)) + print("IP number in binary : " + String(IPSubnetCalc.numerize(ipAddress: ipAddress), radix: 2)) + //print("IP number reverse : " + digitize(ipAddress: numerize(ipAddress: ipAddress))) + print("Mask bin : " + String(IPSubnetCalc.numerize(mask: mask), radix: 2)) + print("Subnet ID bin : " + String(subnetId(ipAddress: ipAddress, mask: mask), radix: 2)) + print("Broadcast bin : " + String(subnetBroadcast(ipAddress: ipAddress, mask: mask), radix: 2)) + } + else { + print("IP \(ipAddress) is not valid") } } - return (bitMap) -} - -func displayIPInfo(ipAddress: String, mask: String) -{ - if (isValidIP(ipAddress: ipAddress, mask: mask)) - { - print("IP Host : " + ipAddress) - print("Mask bits : " + mask) - print("Mask : " + digitize(ipAddress: subnetMask(mask: mask))) - print("Subnet bits : " + subnetBits(ipAddress: ipAddress, mask: mask)) - print("Subnet ID : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) - print("Broadcast : " + digitize(ipAddress: subnetBroadcast(ipAddress: ipAddress, mask: mask))) - print("Max Host : " + maxHosts(mask: mask)) - print("Max Subnet : " + maxSubnets(ipAddress: ipAddress, mask: mask)) - print("Subnet Range : " + subnetRange(ipAddress: ipAddress, mask: mask)) - print("IP Class Type : " + netClass(ipAddress: ipAddress)) - print("Hexa IP : " + hexarize(ipAddress: ipAddress)) - print("Binary IP : " + binarize(ipAddress: ipAddress)) - print("BitMap : " + bitMap(ipAddress: ipAddress, mask: mask)) - print("CIDR Netmask : " + digitize(ipAddress: subnetMask(mask: mask))) - print("Wildcard Mask : " + digitize(ipAddress: wildcardMask(mask: mask))) - print("CIDR Max Subnet : " + maxCIDRSubnets(mask: mask)) - print("CIDR Max Hosts : " + maxHosts(mask: mask)) - print("CIDR Network (Route) : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask))) - print("CIDR Net Notation : " + digitize(ipAddress: subnetId(ipAddress: ipAddress, mask: mask)) + "/" + mask) - print("CIDR Address Range : " + subnetCIDRRange(ipAddress: ipAddress, mask: mask)) - print("IP number in binary : " + String(numerize(ipAddress: ipAddress), radix: 2)) - //print("IP number reverse : " + digitize(ipAddress: numerize(ipAddress: ipAddress))) - print("Mask bin : " + String(numerize(mask: mask), radix: 2)) - print("Subnet ID bin : " + String(subnetId(ipAddress: ipAddress, mask: mask), radix: 2)) - print("Broadcast bin : " + String(subnetBroadcast(ipAddress: ipAddress, mask: mask), radix: 2)) - } - else - { - print("IP \(ipAddress) is not valid") - } -} - -//IPv6 SECTION -func numerizeIPv6(ipAddress: String) -> [UInt16] -{ - var ipAddressNum: [UInt16] = Array(repeating: 0, count: 8) - var ip4Hex = [String]() - - ip4Hex = ipAddress.components(separatedBy: ":") - for index in 0...7 { - ipAddressNum[index] = UInt16(ip4Hex[index], radix: 16)! - //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Hexa : \(UInt16(ip4Hex[index], radix: 16)!)") - } - return (ipAddressNum) -} - -func binarizeIPv6(ipAddress: String, delimiter: Bool = false) -> String -{ - var ip4Hex: [String] - var binary: String - var binStr = String() - - ip4Hex = ipAddress.components(separatedBy: ":") - for index in 0...7 { - binary = String(UInt16(ip4Hex[index], radix: 16)!, radix: 2) - while (binary.count < 16) - { - binary.insert("0", at: binary.startIndex) - } - binStr.append(binary) - if (delimiter && index < 7) - { - binStr.append(":") - } - //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Bin : \(binary)") - } - return (binStr) -} - -func getHexID(ipAddress: String) -> String -{ - var hexID: String = ipAddress - let delimiter: Set = [":"] - hexID.removeAll(where: { delimiter.contains($0) }) - return("0x\(hexID)") -} - -func getBinID(ipAddress: String) -> String { - return (binarizeIPv6(ipAddress: ipAddress)) -} - -func getIPv6Digit(ipAddress: String) -> String { - var digitStr = String() - let numIP = numerizeIPv6(ipAddress: ipAddress) - for index in 0...7 { - if (index != 7) { - digitStr.append("\(numIP[index]):") + //************* + //IPv6 SECTION + //************* + static func numerizeIPv6(ipAddress: String) -> [UInt16] { + var ipAddressNum: [UInt16] = Array(repeating: 0, count: 8) + var ip4Hex = [String]() + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...7 { + ipAddressNum[index] = UInt16(ip4Hex[index], radix: 16)! + //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Hexa : \(UInt16(ip4Hex[index], radix: 16)!)") } - else { - digitStr.append("\(numIP[index])") + return (ipAddressNum) + } + + static func binarizeIPv6(ipAddress: String, delimiter: Bool = false) -> String { + var ip4Hex: [String] + var binary: String + var binStr = String() + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...7 { + binary = String(UInt16(ip4Hex[index], radix: 16)!, radix: 2) + while (binary.count < 16) { + binary.insert("0", at: binary.startIndex) + } + binStr.append(binary) + if (delimiter && index < 7) { + binStr.append(":") + } + //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Bin : \(binary)") } + return (binStr) } - return (digitStr) -} - -func fullIPv6Address(ipAddress: String) -> String -{ - var fullAddr = String() - var ip4Hex = [String]() - var prevIsZero = false - - ip4Hex = ipAddress.components(separatedBy: ":") - for index in 0...(ip4Hex.count - 1) { - //print("Index : \(index) Hex : \(ip4Hex[index])") - if (ip4Hex[index] == "" && !prevIsZero) - { - prevIsZero = true - //print("Index : \(index + 1) is empty, \(8 - ip4Hex.count + 1) hex quad are missing") - while (ip4Hex[index].count < (4 * (8 - ip4Hex.count + 1))) - { - ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) + + static func numerizeMask(maskbits: Int) -> [UInt16] { + var maskNum: [UInt16] = Array(repeating: 0, count: 8) + + for i in 0...7 { + //print("Index : \(i), mask bits : \(maskbits - (16 * (i + 1)) >= 0 ? 16 : (maskbits % (16 * i)) < maskbits ? (maskbits % (16 * i)) : 0) Div : \(maskbits / (16 * (i + 1))) Mod : \(maskbits % (16 * (i + 1)))") + if ((maskbits - (16 * i)) < 16) { + if ((maskbits - (16 * i)) > 0) { + maskNum[i] = UInt16(Constants.addr16Full & (Constants.addr16Full << (16 - (maskbits - (16 * i))))) + } + else { + //print("Index : \(i), ZERO mask : \(maskNum[i])") + } + } + else { + maskNum[i] = Constants.addr16Full } } - else { - while (ip4Hex[index].count < 4) - { - ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) + return (maskNum) + } + + static func hexarize(num: [UInt16], full: Bool = true, column: Bool = false) -> String { + var hex: String + var hexStr = String() + + for index in 0...(num.count - 1) { + hex = String(num[index], radix: 16) + while (hex.count < 4 && full) { + hex.insert("0", at: hex.startIndex) + } + hexStr.append(hex) + if (column && index < (num.count - 1)) { + hexStr.append(":") } } - fullAddr.append(ip4Hex[index]) + return (hexStr) } - var offset = fullAddr.index(fullAddr.startIndex, offsetBy: 4) - for _ in 1...7 - { - fullAddr.insert(":", at: offset) - offset = fullAddr.index(offset, offsetBy: 5) + + func getHexID(ipAddress: String) -> String { + var hexID: String = ipAddress + let delimiter: Set = [":"] + hexID.removeAll(where: { delimiter.contains($0) }) + return("0x\(hexID)") } - return (fullAddr) -} - -func compactIPv6Address(ipAddress: String) -> String -{ - var shortAddr = String() - var ip4Hex = [String]() - var prevIsZero = false - var prevAreZero = false - var prevCompactZero = false - - //print("IP Address: \(ipAddress)") - ip4Hex = ipAddress.components(separatedBy: ":") - for index in 0...(ip4Hex.count - 1) { - //print("Index : \(index) IPHex : \(ip4Hex[index]) Dec : \(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16))") - if (UInt16(ip4Hex[index], radix: 16)! == 0) - { - if (!prevIsZero || prevCompactZero) - { - if index == (ip4Hex.count - 1) - { - shortAddr.append("0") - } - else - { - shortAddr.append("0:") + func getBinID(ipAddress: String) -> String { + return (IPSubnetCalc.binarizeIPv6(ipAddress: ipAddress)) + } + + func getIPv6Digit(ipAddress: String) -> String { + var digitStr = String() + let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: ipAddress) + + for index in 0...7 { + if (index != 7) { + digitStr.append("\(numIP[index]):") + } + else { + digitStr.append("\(numIP[index])") + } + } + return (digitStr) + } + + func fullIPv6Address(ipAddress: String) -> String { + var fullAddr = String() + var ip4Hex = [String]() + var prevIsZero = false + + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...(ip4Hex.count - 1) { + //print("Index : \(index) Hex : \(ip4Hex[index])") + if (ip4Hex[index] == "" && !prevIsZero) { + prevIsZero = true + //print("Index : \(index + 1) is empty, \(8 - ip4Hex.count + 1) hex quad are missing") + while (ip4Hex[index].count < (4 * (8 - ip4Hex.count + 1))) { + ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) } } - else if (prevIsZero && !prevAreZero) - { - shortAddr.removeLast(2) - prevAreZero = true + else { + while (ip4Hex[index].count < 4) { + ip4Hex[index].insert("0", at: ip4Hex[index].startIndex) + } } - if (prevIsZero && index == (ip4Hex.count - 1)) - { - if (shortAddr == "") - { - shortAddr.append("::") + fullAddr.append(ip4Hex[index]) + } + var offset = fullAddr.index(fullAddr.startIndex, offsetBy: 4) + for _ in 1...7 { + fullAddr.insert(":", at: offset) + offset = fullAddr.index(offset, offsetBy: 5) + } + return (fullAddr) + } + + func compactIPv6Address(ipAddress: String) -> String { + var shortAddr = String() + var ip4Hex = [String]() + var prevIsZero = false + var prevAreZero = false + var prevCompactZero = false + + //print("IP Address: \(ipAddress)") + ip4Hex = ipAddress.components(separatedBy: ":") + for index in 0...(ip4Hex.count - 1) { + //print("Index : \(index) IPHex : \(ip4Hex[index]) Dec : \(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16))") + if (UInt16(ip4Hex[index], radix: 16)! == 0) { + if (!prevIsZero || prevCompactZero) { + if index == (ip4Hex.count - 1) { + shortAddr.append("0") + } + else { + shortAddr.append("0:") + } } - else - { - shortAddr.append(":") + else if (prevIsZero && !prevAreZero) { + shortAddr.removeLast(2) + prevAreZero = true } + if (prevIsZero && index == (ip4Hex.count - 1)) { + if (shortAddr == "") { + shortAddr.append("::") + } + else { + shortAddr.append(":") + } + } + prevIsZero = true } - prevIsZero = true - } - else - { - if (prevAreZero && !prevCompactZero) - { - if index == (ip4Hex.count - 1) - { - shortAddr.append("::") + else { + if (prevAreZero && !prevCompactZero) { + if index == (ip4Hex.count - 1) { + shortAddr.append("::") + } + else { + shortAddr.append(":") + } + prevCompactZero = true } - else - { + shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) + if (index != (ip4Hex.count - 1)) { shortAddr.append(":") } - prevCompactZero = true + prevIsZero = false + prevAreZero = false } - shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) - if (index != (ip4Hex.count - 1)) - { - shortAddr.append(":") - } - prevIsZero = false - prevAreZero = false + } - - } - /* - var offset = shortAddr.index(shortAddr.startIndex, offsetBy: 4) - for _ in 1...7 - { - shortAddr.insert(":", at: offset) - offset = shortAddr.index(offset, offsetBy: 5) - } - */ - return (shortAddr) -} - -func numerizeMask(maskbits: Int) -> [UInt16] -{ - var maskNum: [UInt16] = Array(repeating: 0, count: 8) - - for i in 0...7 { - //print("Index : \(i), mask bits : \(maskbits - (16 * (i + 1)) >= 0 ? 16 : (maskbits % (16 * i)) < maskbits ? (maskbits % (16 * i)) : 0) Div : \(maskbits / (16 * (i + 1))) Mod : \(maskbits % (16 * (i + 1)))") - if ((maskbits - (16 * i)) < 16) - { - if ((maskbits - (16 * i)) > 0) - { - maskNum[i] = UInt16(addr16Full & (addr16Full << (16 - (maskbits - (16 * i))))) - } - else - { - //print("Index : \(i), ZERO mask : \(maskNum[i])") + return (shortAddr) + } + + func networkID(ipAddress: String, maskbits: Int) -> String { + var netID = [UInt16]() + let numMask = IPSubnetCalc.numerizeMask(maskbits: maskbits) + let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: fullIPv6Address(ipAddress: ipAddress)) + let nbIndex = maskbits / 16 + + for index in 0...nbIndex { + if (index < 8) { + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID.append((numIP[index] & numMask[index])) } } - else - { - maskNum[i] = addr16Full + var netIDStr = IPSubnetCalc.hexarize(num: netID, full: false, column: true) + if (nbIndex < 7) { + netIDStr.append("::") } + return (netIDStr) } - return (maskNum) -} - -func hexarize(num: [UInt16], full: Bool = true, column: Bool = false) -> String -{ - var hex: String - var hexStr = String() - for index in 0...(num.count - 1) { - hex = String(num[index], radix: 16) - while (hex.count < 4 && full) - { - hex.insert("0", at: hex.startIndex) - } - hexStr.append(hex) - if (column && index < (num.count - 1)) - { - hexStr.append(":") - } - } - return (hexStr) -} - -func networkID(ipAddress: String, maskbits: Int) -> String -{ - var netID = [UInt16]() - let numMask = numerizeMask(maskbits: maskbits) - let numIP = numerizeIPv6(ipAddress: fullIPv6Address(ipAddress: ipAddress)) - let nbIndex = maskbits / 16 - - for index in 0...nbIndex { - if (index < 8) - { + func networkRange(ipAddress: String, maskbits: Int) -> String { + var netID = [UInt16]() + var netID2 = [UInt16]() + let numMask = IPSubnetCalc.numerizeMask(maskbits: maskbits) + let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: ipAddress) + + for index in 0...7 { //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") netID.append((numIP[index] & numMask[index])) } - } - var netIDStr = hexarize(num: netID, full: false, column: true) - if (nbIndex < 7) - { - netIDStr.append("::") - } - return (netIDStr) -} - -func networkRange(ipAddress: String, maskbits: Int) -> String -{ - var netID = [UInt16]() - var netID2 = [UInt16]() - let numMask = numerizeMask(maskbits: maskbits) - let numIP = numerizeIPv6(ipAddress: ipAddress) - - for index in 0...7 { - //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") - netID.append((numIP[index] & numMask[index])) - } - for index in 0...7 { - //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") - netID2.append((numIP[index] | ~numMask[index])) - } - var netIDStr = hexarize(num: netID, full: true, column: true) - netIDStr.append(" - \(hexarize(num: netID2, full: true, column: true))") - return (netIDStr) -} - -func getTotalIPAddr(maskbits: Int) -> Decimal -{ - var total = Decimal() - var number: Decimal = 2 - - NSDecimalPower(&total, &number , (128 - maskbits), NSDecimalNumber.RoundingMode.plain) - //return (pow(2, Double(128 - maskbits))) - return (total) -} - -func ip6ARPA (ipAddress: String) -> String -{ - var ipARPA = fullIPv6Address(ipAddress: ipAddress) - let delimiter: Set = [":"] - - ipARPA.removeAll(where: { delimiter.contains($0) }) - ipARPA = String(ipARPA.reversed()) - - var offset = ipARPA.index(ipARPA.startIndex, offsetBy: 1) - for _ in 0...(ipARPA.count - 2) { - ipARPA.insert(".", at: offset) - offset = ipARPA.index(offset, offsetBy: 2) - } - ipARPA.append(".ip6.arpa") - return (ipARPA) -} - -func resIPv6Block(ipAddress: String, maskbits: Int) -> String? -{ - var netID = networkID(ipAddress: ipAddress, maskbits: maskbits) - - netID = fullIPv6Address(ipAddress: netID) - //print("NetID BEFORE compact : \(netID)") - netID = compactIPv6Address(ipAddress: netID) - //print("NetID AFTER compact : \(netID)") - netID.append("/\(maskbits)") - - for item in resIPv6Blocks { - if (item.key == netID) - { - return (item.value + " (\(item.key))") + for index in 0...7 { + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID2.append((numIP[index] | ~numMask[index])) + } + var netIDStr = IPSubnetCalc.hexarize(num: netID, full: true, column: true) + netIDStr.append(" - \(IPSubnetCalc.hexarize(num: netID2, full: true, column: true))") + return (netIDStr) + } + + func getTotalIPAddr(maskbits: Int) -> Decimal { + var total = Decimal() + var number: Decimal = 2 + + NSDecimalPower(&total, &number , (128 - maskbits), NSDecimalNumber.RoundingMode.plain) + //return (pow(2, Double(128 - maskbits))) + return (total) + } + + func ip6ARPA (ipAddress: String) -> String { + var ipARPA = fullIPv6Address(ipAddress: ipAddress) + let delimiter: Set = [":"] + + ipARPA.removeAll(where: { delimiter.contains($0) }) + ipARPA = String(ipARPA.reversed()) + + var offset = ipARPA.index(ipARPA.startIndex, offsetBy: 1) + for _ in 0...(ipARPA.count - 2) { + ipARPA.insert(".", at: offset) + offset = ipARPA.index(offset, offsetBy: 2) } + ipARPA.append(".ip6.arpa") + return (ipARPA) + } + + func resIPv6Block(ipAddress: String, maskbits: Int) -> String? { + var netID = networkID(ipAddress: ipAddress, maskbits: maskbits) + + netID = fullIPv6Address(ipAddress: netID) + //print("NetID BEFORE compact : \(netID)") + netID = compactIPv6Address(ipAddress: netID) + //print("NetID AFTER compact : \(netID)") + netID.append("/\(maskbits)") + + for item in Constants.resIPv6Blocks { + if (item.key == netID) { + return (item.value + " (\(item.key))") + } + } + return nil + } + + init(ipAddress: String, maskbits: UInt) { + self.ipv4Address = ipAddress + self.networkClass = "A" + self.netId = 0 + self.netBits = 0 + self.mask = 0 + self.subnetMax = 0 + self.subnetBits = 0 + self.maskBits = maskbits + self.subnetBitsMax = 0 + self.subnetMask = 0 + self.hostBits = 0 + self.hostMax = 0 + self.hostAddr = 0 + self.hostId = 0 + self.hostSubnetLbound = 0 + self.hostSubnetUbound = 0 + self.ciscoWildcard = 0 + self.bitMap = "" + } + + convenience init(_ ipAddress: String) { + self.init(ipAddress: ipAddress, maskbits: 8) } - return nil -} } diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 0e2ec1a..c4fa761 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -8,31 +8,226 @@ import Foundation import Cocoa -struct Constants { - static let BUFFER_LINES:Int = 1000 - static let NETWORK_BITS_MIN_CLASSLESS:Int = 1 - static let NETWORK_BITS_MIN:Int = 8 - static let NETWORK_BITS_MAX:Int = 32 -} class AppDelegate: NSObject, NSApplicationDelegate { - + enum Constants { + static let BUFFER_LINES:UInt = 1000 + static let NETWORK_BITS_MIN_CLASSLESS:UInt = 1 + static let NETWORK_BITS_MIN:UInt = 8 + static let NETWORK_BITS_MAX:UInt = 32 + } + @IBOutlet var window: NSWindow! - - + @IBOutlet var addrField: NSTextField! + @IBOutlet var classBinaryMap: NSTextField! + @IBOutlet var classBitMap: NSTextField! + @IBOutlet var classHexaMap: NSTextField! + @IBOutlet var exportButton: NSPopUpButton! + @IBOutlet var classType: NSPopUpButton! + @IBOutlet var maskBitsCombo: NSComboBox! + @IBOutlet var maxHostsBySubnetCombo: NSComboBox! + @IBOutlet var maxSubnetsCombo: NSComboBox! + @IBOutlet var subnetBitsCombo: NSComboBox! + @IBOutlet var subnetBroadcast: NSTextField! + @IBOutlet var subnetHostAddrRange: NSTextField! + @IBOutlet var subnetId: NSTextField! + @IBOutlet var subnetMaskCombo: NSComboBox! + @IBOutlet var subnetsHostsView: NSTableView! + @IBOutlet var supernetMaskBitsCombo: NSComboBox! + @IBOutlet var supernetMaskCombo: NSComboBox! + @IBOutlet var supernetMaxCombo: NSComboBox! + @IBOutlet var supernetMaxAddr: NSComboBox! + @IBOutlet var supernetMaxSubnetsCombo: NSComboBox! + @IBOutlet var supernetRoute: NSTextField! + @IBOutlet var supernetAddrRange: NSTextField! + @IBOutlet var tabView: NSTabView! + @IBOutlet var subnetBitsSlide: NSSlider! + @IBOutlet var bitsOnSlide: NSTextField! + @IBOutlet var tabViewClassLess: NSButton! + @IBOutlet var wildcard: NSButton! + @IBOutlet var darkModeMenu: NSMenuItem! + @IBOutlet var NSApp: NSApplication! + var classless: Bool = false + func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application } - + func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } - @IBAction func changeMaskBits(sender: Any) + func checkAddr(address: NSString) -> Bool + { + return false + } + + func initClassInfos(c: NSString) { } - + + func initCIDR() + { + + } + + func doIPSubnetCalc(mask: UInt) + { + + } + + + @IBAction func calc(_ sender: AnyObject) + { + + } + + @IBAction func ipAddrEdit(_ sender: AnyObject) + { + + } + + @IBAction func changeAddrClassType(_ sender: AnyObject) + { + + } + + @IBAction func changeMaxHosts(_ sender: AnyObject) + { + + } + + @IBAction func changeMaxSubnets(_ sender: AnyObject) + { + + } + + @IBAction func changeSubnetBits(_ sender: AnyObject) + { + + } + + @IBAction func changeSubnetMask(_ sender: AnyObject) + { + + } + + @IBAction func changeMaskBits(_ sender: AnyObject) + { + + } + + func doSupernetCalc(maskBits: UInt) + { + + } + + @IBAction func changeSupernetMaskBits(_ sender: AnyObject) + { + + } + + @IBAction func changeSupernetMask(_ sender: AnyObject) + { + + } + + @IBAction func changeSupernetMax(_ sender: AnyObject) + { + + } + + @IBAction func changeSupernetMaxAddr(_ sender: AnyObject) + { + + } + + @IBAction func changeSupernetMaxSubnets(_ sender: AnyObject) + { + + } + + func numberOfRowsInTableView(aTableView: NSTableView) -> Int + { + return 0 + } + + //Display all subnets info in the TableView Subnet/Hosts + func tableView(aTableView: NSTableView, aTableColumn: NSTableColumn, row: Int) -> Any + { + return (Any).self + } + + func printAllSubnets() + { + + } + + func tableView(aTableView: NSTableView, anObject: Any, aTableColumn: NSTableColumn, row: Int) + { + + } + + func bitsOnSlidePos() + { + + + } + + @IBAction func subnetBitsSlide(_ sender: AnyObject) + { + + } + + @IBAction func changeTableViewClass(_ sender: AnyObject) + { + + } + + @IBAction func changeWildcard(_ sender: AnyObject) + { + + } + + + @IBAction func exportCSV(_ sender: AnyObject) + { + + } + + @IBAction func exportClipboard(_ sender: AnyObject) + { + + } + + func URLEncode(url: NSString) -> NSString + { + return "@TEST" + } + + func windowDidResize(notif: NSNotification) + { + bitsOnSlidePos() + } + + func windowWillClose(notif: NSNotification) + { + NSApp.terminate(self) + } + + + @IBAction func darkMode(_ sender: AnyObject) + { + if #available(OSX 10.14, *) { + if (darkModeMenu!.state == NSControl.StateValue.off) { + NSApp!.appearance = NSAppearance(named: NSAppearance.Name.darkAqua) + darkModeMenu.state = NSControl.StateValue.on + } else if (darkModeMenu!.state == NSControl.StateValue.on) { + NSApp!.appearance = nil + darkModeMenu.state = NSControl.StateValue.off + } + } + } + } - - From f08c9adc141ef48f7ee8b66dfc577e79a4edb360 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Mon, 23 Nov 2020 12:02:53 +0100 Subject: [PATCH 04/66] Change some properties to Int type because they do not need to be Unsigned for compute Make init func as failable if IP address is not valid --- IPSubnetCalc.m | 2 +- IPSubnetcalc.swift | 69 +++++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/IPSubnetCalc.m b/IPSubnetCalc.m index 0883514..52c45d7 100644 --- a/IPSubnetCalc.m +++ b/IPSubnetCalc.m @@ -100,7 +100,7 @@ - (void)setBitMap - (IBAction)initNetwork { - netId= mask & hostAddr; + netId = mask & hostAddr; maskBits = netBits + subnetBits; hostBits = 32 - maskBits; hostMax = pow(2, hostBits) - 2; diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index bd5199c..edaad7e 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -23,8 +23,9 @@ class IPSubnetCalc: NSObject { static let addr16Hex2: UInt16 = 0x0F00 static let addr16Hex3: UInt16 = 0x00F0 static let addr16Hex4: UInt16 = 0x000F - - static let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", "::/128" : " Unspecified Address", "2001:db8::/32" : "Documentation"] + static let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", + "::/128" : " Unspecified Address", + "2001:db8::/32" : "Documentation"] //IPv4 constants static let addr32Full: UInt32 = 0xFFFFFFFF @@ -47,14 +48,14 @@ class IPSubnetCalc: NSObject { var ipv4Address: String var networkClass: String var netId: UInt - var netBits: UInt + var netBits: Int var mask: UInt var subnetMax: UInt - var subnetBits: UInt - var maskBits: UInt - var subnetBitsMax: UInt + var subnetBits: Int + var maskBits: Int + var subnetBitsMax: Int var subnetMask: UInt - var hostBits: UInt + var hostBits: Int var hostMax: UInt var hostAddr: UInt var hostId: UInt @@ -142,6 +143,7 @@ class IPSubnetCalc: NSObject { func splitAddrMask(address: String) -> (String, String) { let ipInfo = address.split(separator: "/") if ipInfo.count == 2 { + //CHECK if String convert is needed? return (String(ipInfo[0]), String(ipInfo[1])) } else if ipInfo.count > 2 { @@ -151,7 +153,7 @@ class IPSubnetCalc: NSObject { return (address, "") } - func isValidIP(ipAddress: String, mask: String?) -> Bool { + static func isValidIP(ipAddress: String, mask: String?) -> Bool { var ip4Digits = [String]() ip4Digits = ipAddress.components(separatedBy: ".") @@ -336,7 +338,7 @@ class IPSubnetCalc: NSObject { } func displayIPInfo(ipAddress: String, mask: String) { - if (isValidIP(ipAddress: ipAddress, mask: mask)) { + if (IPSubnetCalc.isValidIP(ipAddress: ipAddress, mask: mask)) { print("IP Host : " + ipAddress) print("Mask bits : " + mask) print("Mask : " + IPSubnetCalc.digitize(ipAddress: subnetMask(mask: mask))) @@ -632,28 +634,33 @@ class IPSubnetCalc: NSObject { return nil } - init(ipAddress: String, maskbits: UInt) { - self.ipv4Address = ipAddress - self.networkClass = "A" - self.netId = 0 - self.netBits = 0 - self.mask = 0 - self.subnetMax = 0 - self.subnetBits = 0 - self.maskBits = maskbits - self.subnetBitsMax = 0 - self.subnetMask = 0 - self.hostBits = 0 - self.hostMax = 0 - self.hostAddr = 0 - self.hostId = 0 - self.hostSubnetLbound = 0 - self.hostSubnetUbound = 0 - self.ciscoWildcard = 0 - self.bitMap = "" - } - - convenience init(_ ipAddress: String) { + init?(ipAddress: String, maskbits: Int) { + if (IPSubnetCalc.isValidIP(ipAddress: ipAddress, mask: String(maskbits))) { + self.ipv4Address = ipAddress + self.networkClass = "A" + self.netId = 0 + self.netBits = 0 + self.mask = 0 + self.subnetMax = 0 + self.subnetBits = 0 + self.maskBits = maskbits + self.subnetBitsMax = 0 + self.subnetMask = 0 + self.hostBits = 0 + self.hostMax = 0 + self.hostAddr = 0 + self.hostId = 0 + self.hostSubnetLbound = 0 + self.hostSubnetUbound = 0 + self.ciscoWildcard = 0 + self.bitMap = "" + } + else { + return nil + } + } + + convenience init?(_ ipAddress: String) { self.init(ipAddress: ipAddress, maskbits: 8) } } From fb7ac96b6bd85c1f79c4c70de207561600c6db04 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Mon, 23 Nov 2020 18:26:24 +0100 Subject: [PATCH 05/66] Rebind all IBAction and IBOutlets to new swift AppDelegate class Restrict IPSubnetcalc class properties to strict minimum Define properly init IPSubnetcalc class without mask parameter Make netclass as static method Make AppDelegate Constants as private Begin to define private functions to initialize Window values at launch --- Base.lproj/MainMenu.xib | 104 ++++++++++++++++++------------------ IPSubnetcalc.swift | 42 +++++++++++---- SubnetCalcAppDelegate.swift | 46 +++++++++++++++- 3 files changed, 129 insertions(+), 63 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 61b6a5b..d5578f3 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -69,12 +69,12 @@ - + - + @@ -129,7 +129,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -284,7 +284,7 @@ - + @@ -307,7 +307,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -451,7 +451,7 @@ - + @@ -565,7 +565,7 @@ - + @@ -580,7 +580,7 @@ - + @@ -592,14 +592,14 @@ - + - + - + @@ -607,7 +607,7 @@ - + @@ -630,7 +630,7 @@ - + @@ -653,7 +653,7 @@ - + @@ -696,7 +696,7 @@ - + @@ -739,7 +739,7 @@ - + @@ -760,7 +760,7 @@ - + @@ -780,7 +780,7 @@ - + @@ -794,12 +794,12 @@ @@ -1057,6 +1077,7 @@ + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 7bcb70c..329b7d7 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -615,7 +615,7 @@ class IPSubnetCalc: NSObject { } func hexaIDIPv6() -> String { - var hexID: String = self.ipv6Address + var hexID: String = fullAddressIPv6(ipAddress: self.ipv6Address) let delimiter: Set = [":"] hexID.removeAll(where: { delimiter.contains($0) }) return("0x\(hexID)") @@ -625,9 +625,9 @@ class IPSubnetCalc: NSObject { return (IPSubnetCalc.binarizeIPv6(ipAddress: self.ipv6Address)) } - func digitizeIPv6(ipAddress: String) -> String { + func digitizeIPv6() -> String { var digitStr = String() - let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: ipAddress) + let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: self.ipv6Address) for index in 0...7 { if (index != 7) { diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 86ea496..a15b5c3 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -12,6 +12,7 @@ import Cocoa class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, NSTableViewDataSource { private enum Constants { static let defaultIP: String = "10.0.0.0" + static let defaultIPv6Mask: String = "64" static let BUFFER_LINES:Int = 200000000 static let NETWORK_BITS_MIN_CLASSLESS:Int = 1 static let NETWORK_BITS_MIN:Int = 8 @@ -54,6 +55,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, //IPv6 UI elements @IBOutlet var ipv6Address: NSTextField! + @IBOutlet var ipv6to4Address: NSTextField! @IBOutlet var ipv6maskBitsCombo: NSComboBox! @IBOutlet var ipv6maxSubnetsCombo: NSComboBox! @IBOutlet var ipv6maxHostsCombo: NSComboBox! @@ -65,6 +67,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBOutlet var ipv6Arpa: NSTextField! @IBOutlet var ipv6Compact: NSButton! + //Private global vars private var savedTabView: [NSTabViewItem]? //ex tab_tabView private var ipsc: IPSubnetCalc? @@ -299,7 +302,20 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, private func doIPv6() { if (ipsc != nil) { - ipv6Address.stringValue = ipsc!.ipv6Address + if (ipv6Compact.state == NSControl.StateValue.on) { + ipv6Address.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.ipv6Address) + } + else { + ipv6Address.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.ipv6Address) + } + ipv6to4Address.stringValue = ipsc!.ipv4Address + ipv6Network.stringValue = ipsc!.networkIPv6() + ipv6Range.stringValue = ipsc!.networkRangeIPv6() + ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "" + ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() + ipv6Decimal.stringValue = ipsc!.digitizeIPv6() + ipv6Arpa.stringValue = ipsc!.ip6ARPA() + /* subnetBitsCombo.selectItem(withObjectValue: String(ipsc!.subnetBits())) maskBitsCombo.selectItem(withObjectValue: String(ipsc!.maskBits)) @@ -329,7 +345,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipmask = String(ipsc!.ipv6MaskBits) } else { - ipmask = "64" + ipmask = Constants.defaultIPv6Mask } } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { From 024f10f3dfda118060eafcc02a437ad44581c5b9 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 9 Dec 2020 16:55:21 +0100 Subject: [PATCH 38/66] Resize Window width for IPv6 address range Implement changeIPv6Format func --- Base.lproj/MainMenu.xib | 322 ++++++++++++++++++------------------ SubnetCalcAppDelegate.swift | 2 +- 2 files changed, 162 insertions(+), 162 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 4edb443..8fcc966 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -153,32 +153,32 @@ - + - + - + - + - + - + - + - + @@ -194,14 +194,14 @@ - + - + - + @@ -217,14 +217,14 @@ - + - + - + @@ -240,14 +240,14 @@ - + - + - + @@ -263,14 +263,14 @@ - + - + - + @@ -286,14 +286,14 @@ - + - + - + @@ -306,14 +306,14 @@ - + - + - + @@ -326,14 +326,14 @@ - + - + - + @@ -346,7 +346,7 @@ - + - + - + @@ -377,14 +377,14 @@ - + - + - + @@ -396,35 +396,15 @@ - - - - - - - - - - - - - - - - - - - - - + - + - + @@ -446,23 +426,43 @@ + + + + + + + + + + + + + + + + + + + + - + - + - + - + @@ -524,27 +524,27 @@ - + - + - + - + - + - + @@ -553,7 +553,7 @@ - + @@ -565,7 +565,7 @@ - + - + - + @@ -992,7 +992,7 @@ - + @@ -1003,17 +1003,8 @@ - - - - - - - - - - + @@ -1036,7 +1027,7 @@ + + + + + + + + + - + diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index a15b5c3..40c8de8 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -744,7 +744,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, //IPv6 UI actions @IBAction func changeIPv6Format(_ sender: AnyObject) { - + self.doIPv6() } @IBAction func changeIPv6MaskBits(_ sender: AnyObject) From 726102f99d60c78545c5d53759648091baf66568 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 9 Dec 2020 16:59:27 +0100 Subject: [PATCH 39/66] Populate ipv6maskBitsCombo int initIPv6Tab func --- SubnetCalcAppDelegate.swift | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 40c8de8..cce9c63 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -297,6 +297,10 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, //Private IPv6 functions private func initIPv6Tab() { + for index in (1...128) { + ipv6maskBitsCombo.addItem(withObjectValue: String(index)) + } + } private func doIPv6() @@ -321,15 +325,6 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, maskBitsCombo.selectItem(withObjectValue: String(ipsc!.maskBits)) maxSubnetsCombo.selectItem(withObjectValue: String(ipsc!.maxSubnets())) maxHostsBySubnetCombo.selectItem(withObjectValue: String(ipsc!.maxHosts())) - subnetId.stringValue = ipsc!.subnetId() - subnetBroadcast.stringValue = ipsc!.subnetBroadcast() - subnetHostAddrRange.stringValue = ipsc!.subnetRange() - if (wildcard.state == NSControl.StateValue.on) { - subnetMaskCombo.selectItem(withObjectValue: ipsc!.wildcardMask()) - } - else { - subnetMaskCombo.selectItem(withObjectValue: ipsc!.subnetMask()) - } */ } } From 387678d11711899c1a8d0146c212ac68c142f0db Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 9 Dec 2020 17:19:45 +0100 Subject: [PATCH 40/66] Change networkIPv6 to return full address --- IPSubnetcalc.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 329b7d7..7f3393b 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -742,7 +742,7 @@ class IPSubnetCalc: NSObject { if (nbIndex < 7) { netIDStr.append("::") } - return (netIDStr) + return (self.fullAddressIPv6(ipAddress: netIDStr)) } func networkRangeIPv6() -> String { From 14b4b582794486750da9687a699281a11ca56abd Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 9 Dec 2020 17:31:17 +0100 Subject: [PATCH 41/66] Improve networkIPv6 func Display IPv6 Network according to Short option --- IPSubnetcalc.swift | 11 ++--------- SubnetCalcAppDelegate.swift | 3 ++- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 7f3393b..384940e 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -730,19 +730,12 @@ class IPSubnetCalc: NSObject { var netID = [UInt16]() let numMask = IPSubnetCalc.numerizeMaskIPv6(maskbits: self.ipv6MaskBits) let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: fullAddressIPv6(ipAddress: self.ipv6Address)) - let nbIndex = self.ipv6MaskBits / 16 - for index in 0...nbIndex { - if (index < 8) { + for index in 0...7 { //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") netID.append((numIP[index] & numMask[index])) - } - } - var netIDStr = IPSubnetCalc.hexarizeIPv6(num: netID, full: false, column: true) - if (nbIndex < 7) { - netIDStr.append("::") } - return (self.fullAddressIPv6(ipAddress: netIDStr)) + return (IPSubnetCalc.hexarizeIPv6(num: netID, full: false, column: true)) } func networkRangeIPv6() -> String { diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index cce9c63..d55f200 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -308,12 +308,13 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, if (ipsc != nil) { if (ipv6Compact.state == NSControl.StateValue.on) { ipv6Address.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.ipv6Address) + ipv6Network.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.networkIPv6()) } else { ipv6Address.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.ipv6Address) + ipv6Network.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.networkIPv6()) } ipv6to4Address.stringValue = ipsc!.ipv4Address - ipv6Network.stringValue = ipsc!.networkIPv6() ipv6Range.stringValue = ipsc!.networkRangeIPv6() ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "" ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() From a2a20cb18625c7a22c2d82a0fa57d4ca094a7b3e Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 9 Dec 2020 18:00:50 +0100 Subject: [PATCH 42/66] Rename IPv6 Max Subnets to IPv6 Available Subnet Init IPv6 Tab for Maskbits and Max Hosts Select correct IPv6 maskbits and max host when doIPv6 --- Base.lproj/MainMenu.xib | 8 ++++---- SubnetCalcAppDelegate.swift | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 8fcc966..c8debd8 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -459,7 +459,7 @@ - + @@ -929,7 +929,7 @@ - + @@ -945,7 +945,7 @@ - + @@ -1073,10 +1073,10 @@ + - diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index d55f200..7edf46f 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -57,7 +57,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBOutlet var ipv6Address: NSTextField! @IBOutlet var ipv6to4Address: NSTextField! @IBOutlet var ipv6maskBitsCombo: NSComboBox! - @IBOutlet var ipv6maxSubnetsCombo: NSComboBox! + @IBOutlet var ipv6SubnetsCombo: NSComboBox! @IBOutlet var ipv6maxHostsCombo: NSComboBox! @IBOutlet var ipv6Network: NSTextField! @IBOutlet var ipv6Range: NSTextField! @@ -296,16 +296,25 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, //Private IPv6 functions private func initIPv6Tab() { + var total = Decimal() + var number: Decimal = 2 for index in (1...128) { ipv6maskBitsCombo.addItem(withObjectValue: String(index)) } - + for index in (0...127) { + NSDecimalPower(&total, &number , index, NSDecimalNumber.RoundingMode.plain) + ipv6maxHostsCombo.addItem(withObjectValue: total) + } } private func doIPv6() { if (ipsc != nil) { + var total = Decimal() + var number: Decimal = 2 + + NSDecimalPower(&total, &number , 128 - ipsc!.ipv6MaskBits, NSDecimalNumber.RoundingMode.plain) if (ipv6Compact.state == NSControl.StateValue.on) { ipv6Address.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.ipv6Address) ipv6Network.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.networkIPv6()) @@ -315,6 +324,8 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipv6Network.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.networkIPv6()) } ipv6to4Address.stringValue = ipsc!.ipv4Address + ipv6maskBitsCombo.selectItem(withObjectValue: String(ipsc!.ipv6MaskBits)) + ipv6maxHostsCombo.selectItem(withObjectValue: total) ipv6Range.stringValue = ipsc!.networkRangeIPv6() ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "" ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() @@ -748,7 +759,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } - @IBAction func changeIPv6MaxSubnets(_ sender: AnyObject) + @IBAction func changeIPv6Subnets(_ sender: AnyObject) { } From bd0744366349fb678d08915b151db5e8f99e37d4 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Thu, 10 Dec 2020 11:03:47 +0100 Subject: [PATCH 43/66] Init Subnet Combobox in doIPv6 func --- SubnetCalcAppDelegate.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 7edf46f..19b8e4e 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -331,6 +331,16 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() ipv6Decimal.stringValue = ipsc!.digitizeIPv6() ipv6Arpa.stringValue = ipsc!.ip6ARPA() + for index in (1...ipsc!.ipv6MaskBits).reversed() { + NSDecimalPower(&total, &number , ipsc!.ipv6MaskBits - index, NSDecimalNumber.RoundingMode.plain) + if (total == 1) { + ipv6SubnetsCombo.addItem(withObjectValue: "/\(index)\t\(total) network") + } + else { + ipv6SubnetsCombo.addItem(withObjectValue: "/\(index)\t\(total) networks") + } + } + ipv6SubnetsCombo.selectItem(at: 0) /* subnetBitsCombo.selectItem(withObjectValue: String(ipsc!.subnetBits())) From 4b6b6fadd263a1cd86c9152f9ae440eb1f1ff144 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Thu, 10 Dec 2020 11:35:20 +0100 Subject: [PATCH 44/66] Implement dottedDecimalIPv6 to return IPv6 address in Decimal with dots --- IPSubnetcalc.swift | 20 ++++++++++++++++++++ SubnetCalcAppDelegate.swift | 10 ++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 384940e..658ee65 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -765,6 +765,26 @@ class IPSubnetCalc: NSObject { return (total) } + func dottedDecimalIPv6() -> String { + var ipv4str = String() + + let ip4Hex = fullAddressIPv6(ipAddress: self.ipv6Address).components(separatedBy: ":") + for index in (0...(ip4Hex.count - 1)) { + if (index != 0) { + ipv4str.append(".") + + } + if (ip4Hex[index] == "") { + ipv4str.append("0.0") + } + else { + ipv4str.append(String((UInt32(ip4Hex[index], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[index], radix: 16)! & Constants.addr32Digit4))) + } + } + return ipv4str + } + func ip6ARPA () -> String { var ipARPA = fullAddressIPv6(ipAddress: self.ipv6Address) let delimiter: Set = [":"] diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 19b8e4e..b234b05 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -329,8 +329,9 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipv6Range.stringValue = ipsc!.networkRangeIPv6() ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "" ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() - ipv6Decimal.stringValue = ipsc!.digitizeIPv6() + ipv6Decimal.stringValue = ipsc!.dottedDecimalIPv6() ipv6Arpa.stringValue = ipsc!.ip6ARPA() + ipv6SubnetsCombo.removeAllItems() for index in (1...ipsc!.ipv6MaskBits).reversed() { NSDecimalPower(&total, &number , ipsc!.ipv6MaskBits - index, NSDecimalNumber.RoundingMode.plain) if (total == 1) { @@ -341,13 +342,6 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } ipv6SubnetsCombo.selectItem(at: 0) - - /* - subnetBitsCombo.selectItem(withObjectValue: String(ipsc!.subnetBits())) - maskBitsCombo.selectItem(withObjectValue: String(ipsc!.maskBits)) - maxSubnetsCombo.selectItem(withObjectValue: String(ipsc!.maxSubnets())) - maxHostsBySubnetCombo.selectItem(withObjectValue: String(ipsc!.maxHosts())) - */ } } From 75ce97fceee20d33b5fe022a6c231b540d55d819 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Fri, 11 Dec 2020 11:36:27 +0100 Subject: [PATCH 45/66] Precise bad IP format between IPv4 and IPv6 Change default conversion of IPv4toIPv6 as the same format for IPv6toIPv4 Do not change IP address field value if there is already a value ipv6to4Address is display according to convertIPv6toIPv4 func Implement changeIPv6MaskBits func --- Base.lproj/MainMenu.xib | 5 +++-- IPSubnetcalc.swift | 14 ++++++------ SubnetCalcAppDelegate.swift | 45 ++++++++++++++++++++++++++++++------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index c8debd8..b998c18 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -459,7 +459,7 @@ - + @@ -766,7 +766,7 @@ - + @@ -1078,6 +1078,7 @@ + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 658ee65..6bd5f59 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -163,7 +163,7 @@ class IPSubnetCalc: NSObject { for item in ip4Digits { if let digit = Int(item, radix: 10) { if (digit > 255) { - print("bad IP digit \(digit)") + print("bad IPv4 digit \(digit)") return false } } @@ -174,24 +174,24 @@ class IPSubnetCalc: NSObject { } } else { - print("bad IP format \(ip4Digits)") + print("bad IPv4 format \(ip4Digits)") return false } if mask != nil { if let maskNum = Int(mask!) { if (classless == true) { if (maskNum < Constants.NETWORK_BITS_MIN_CLASSLESS || maskNum > Constants.NETWORK_BITS_MAX) { - print("classless mask \(maskNum) invalid") + print("IPv4 classless mask \(maskNum) invalid") return false } } else if (maskNum < Constants.NETWORK_BITS_MIN || maskNum > Constants.NETWORK_BITS_MAX) { - print("mask \(maskNum) invalid") + print("IPv4 mask \(maskNum) invalid") return false } } else { - print("mask \(mask!) is not digit") + print("IPv4 mask \(mask!) is not digit") return false } } @@ -522,7 +522,7 @@ class IPSubnetCalc: NSObject { return ("0:0:0:0:0:ffff:" + ipv6str) } - static func convertIPv6toIPv4(ipAddress: String) -> String { + static func convertIPv6toIPv4(ipAddress: String, _6to4: Bool = false) -> String { var ipv4str = String() //let ip4Hex = fullAddressIPv6(ipAddress: ipAddress).components(separatedBy: ":") @@ -822,7 +822,7 @@ class IPSubnetCalc: NSObject { if (IPSubnetCalc.isValidIP(ipAddress: ipAddress, mask: String(maskbits), classless: true)) { self.ipv4Address = ipAddress self.maskBits = maskbits - self.ipv6Address = IPSubnetCalc.convertIPv4toIPv6(ipAddress: ipAddress, _6to4: true) + self.ipv6Address = IPSubnetCalc.convertIPv4toIPv6(ipAddress: ipAddress) self.ipv6MaskBits = maskbits + 96 } else { diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index b234b05..afa7955 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -66,6 +66,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBOutlet var ipv6Decimal: NSTextField! @IBOutlet var ipv6Arpa: NSTextField! @IBOutlet var ipv6Compact: NSButton! + @IBOutlet var ipv6to4Box: NSBox! //Private global vars @@ -244,7 +245,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, private func doIPSubnetCalc() { - let ipaddr: String + var ipaddr: String var ipmask: String? if (addrField.stringValue.isEmpty) { @@ -262,13 +263,20 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } else { (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) + if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask ?? Constants.defaultIPv6Mask)) == true) { + if (ipsc != nil) { + ipaddr = ipsc!.ipv4Address + } + } if (ipmask == nil && ipsc != nil) { ipmask = String(ipsc!.maskBits) } } if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - addrField.stringValue = ipaddr + if (addrField.stringValue.isEmpty) { + addrField.stringValue = ipaddr + } if (ipmask == nil) { ipsc = IPSubnetCalc(ipaddr) } @@ -323,7 +331,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipv6Address.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.ipv6Address) ipv6Network.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.networkIPv6()) } - ipv6to4Address.stringValue = ipsc!.ipv4Address + ipv6to4Address.stringValue = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipsc!.ipv6Address) ipv6maskBitsCombo.selectItem(withObjectValue: String(ipsc!.ipv6MaskBits)) ipv6maxHostsCombo.selectItem(withObjectValue: total) ipv6Range.stringValue = ipsc!.networkRangeIPv6() @@ -347,13 +355,20 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, private func doIPv6SubnetCalc() { - let ipaddr: String + var ipaddr: String var ipmask: String? (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) + if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { + if (ipsc != nil) { + ipaddr = ipsc!.ipv6Address + //print("doIPv6SubnetCalc ipaddr to ipv6 : \(ipsc!.ipv6Address)") + } + } if (ipmask == nil) { if (ipsc != nil) { ipmask = String(ipsc!.ipv6MaskBits) + //print("doIPv6SubnetCalc ipmask ipv6 : \(ipsc!.ipv6MaskBits)") } else { ipmask = Constants.defaultIPv6Mask @@ -361,7 +376,9 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - addrField.stringValue = ipaddr + if (addrField.stringValue.isEmpty) { + addrField.stringValue = ipaddr + } ipsc = IPSubnetCalc(ipv6: ipaddr, maskbits: Int(ipmask!)!) if (ipsc != nil) { if (tabView.numberOfTabViewItems != 4 && savedTabView != nil) { @@ -760,17 +777,29 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBAction func changeIPv6MaskBits(_ sender: AnyObject) { - + //print("changeIPv6MaskBits") + if (ipsc == nil) + { + ipsc = IPSubnetCalc(Constants.defaultIP) + } + if (sender.objectValueOfSelectedItem as? String) != nil { + ipsc!.ipv6MaskBits = sender.intValue + self.doIPv6SubnetCalc() + } + else { + myAlert(message: "Bad IPv6 Mask Bits", info: "Bad format") + return + } } @IBAction func changeIPv6Subnets(_ sender: AnyObject) { - + self.doIPv6() } @IBAction func changeIPv6MaxHosts(_ sender: AnyObject) { - + self.doIPv6() } //General UI actions From 109f544dcde1665dd7037b533e3eceedbeae15c8 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Fri, 11 Dec 2020 15:36:20 +0100 Subject: [PATCH 46/66] convertIPv6toIPv4 func detect IPv6 to IPv4 format and return correct IPv4 translation and conversion type --- Base.lproj/MainMenu.xib | 2 +- IPSubnetcalc.swift | 30 +++++++++++++++++++++++++----- SubnetCalcAppDelegate.swift | 4 +++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index b998c18..39f9f52 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -459,7 +459,7 @@ - + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 6bd5f59..74517ed 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -481,7 +481,7 @@ class IPSubnetCalc: NSObject { } } else { - print("IP \(ipAddress) bad format") + print("IPv6 \(ipAddress) bad format") return false } } @@ -522,12 +522,31 @@ class IPSubnetCalc: NSObject { return ("0:0:0:0:0:ffff:" + ipv6str) } - static func convertIPv6toIPv4(ipAddress: String, _6to4: Bool = false) -> String { + static func convertIPv6toIPv4(ipAddress: String) -> (String, String) { var ipv4str = String() - //let ip4Hex = fullAddressIPv6(ipAddress: ipAddress).components(separatedBy: ":") let ip4Hex = ipAddress.components(separatedBy: ":") let index = ip4Hex.count + if (ip4Hex[0] == "2002") { + if (index > 2) { + if (ip4Hex[1] == "") { + ipv4str.append("0.0") + } + else { + ipv4str.append(String((UInt32(ip4Hex[1], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[1], radix: 16)! & Constants.addr32Digit4))) + } + if (ip4Hex[2] == "") { + ipv4str.append("0.0") + } + else { + ipv4str.append("." + String((UInt32(ip4Hex[2], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[2], radix: 16)! & Constants.addr32Digit4))) + } + } + return (ipv4str, "6to4") + } + else { if (index < 2) { ipv4str.append("0.0") } @@ -542,7 +561,8 @@ class IPSubnetCalc: NSObject { } ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) - return ipv4str + return (ipv4str, "6PE") + } } static func numerizeIPv6(ipAddress: String) -> [UInt16] { @@ -853,7 +873,7 @@ class IPSubnetCalc: NSObject { init?(ipv6: String, maskbits: Int) { if (IPSubnetCalc.isValidIPv6(ipAddress: ipv6, mask: maskbits)) { - self.ipv4Address = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipv6) + (self.ipv4Address, _) = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipv6) if (maskbits > 96) { self.maskBits = maskbits - 96 } diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index afa7955..1f90ac0 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -321,6 +321,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, if (ipsc != nil) { var total = Decimal() var number: Decimal = 2 + var typeConv: String NSDecimalPower(&total, &number , 128 - ipsc!.ipv6MaskBits, NSDecimalNumber.RoundingMode.plain) if (ipv6Compact.state == NSControl.StateValue.on) { @@ -331,7 +332,8 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipv6Address.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.ipv6Address) ipv6Network.stringValue = ipsc!.fullAddressIPv6(ipAddress: ipsc!.networkIPv6()) } - ipv6to4Address.stringValue = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipsc!.ipv6Address) + (ipv6to4Address.stringValue, typeConv) = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipsc!.ipv6Address) + ipv6to4Box.title = "IPv4 conversion" + " (\(typeConv))" ipv6maskBitsCombo.selectItem(withObjectValue: String(ipsc!.ipv6MaskBits)) ipv6maxHostsCombo.selectItem(withObjectValue: total) ipv6Range.stringValue = ipsc!.networkRangeIPv6() From 9b9c4f5647c9523e564f2c5342a0b624594975a7 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Fri, 11 Dec 2020 17:13:43 +0100 Subject: [PATCH 47/66] Fix crash with IPv4 maxHosts func when a /128 mask is selected in IPv6 --- IPSubnetcalc.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 74517ed..96e1dfb 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -236,6 +236,9 @@ class IPSubnetCalc: NSObject { func maxHosts() -> Int { var maxHosts: UInt32 = 0 + if (self.maskBits == 32) { + return (1) + } maxHosts = (Constants.addr32Full >> self.maskBits) - 1 return (Int(maxHosts)) } From a297a15536cc7b1a77beef5811addefef0707998 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Fri, 11 Dec 2020 21:31:41 +0100 Subject: [PATCH 48/66] complete all resIPv6Blocks fix convertIPv6toIPv4 func when last hex is empty fix numerizeIPv6 when hex is empty fix compactAddressIPv6, starting by convert ip to fullAddressIPv6 before doing anything --- IPSubnetcalc.swift | 48 +++++++++++++++++++++++++++---------- SubnetCalcAppDelegate.swift | 4 ++++ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 96e1dfb..43ace22 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -30,7 +30,25 @@ class IPSubnetCalc: NSObject { //static let addr16Hex4: UInt16 = 0x000F static let resIPv6Blocks: [String : String] = ["::1/128" : "Loopback Address", "::/128" : " Unspecified Address", - "2001:db8::/32" : "Documentation"] + "::ffff:0:0/96" : "IPv4-mapped Address", + "64:ff9b::/96" : "IPv4-IPv6 Translation", + "64:ff9b:1::/48" : "IPv4-IPv6 Translation", + "100::/64" : "Discard-Only Address Block", + "2001::/23" : "IETF Protocol Assignments", + "2001::/32" : "TEREDO", + "2001:1::1/128" : "Port Control Protocol Anycast", + "2001:1::2/128" : "Traversal Using Relays around NAT Anycast", + "2001:2::/48" : "Benchmarking", + "2001:3::/32" : "AMT", + "2001:4:112::/48" : "AS112-v6", + "2001:10::/28" : "Deprecated (previously ORCHID)", + "2001:20::/28" : "ORCHIDv2", + "2001:db8::/32" : "Documentation", + "2002::/16" : "6to4", + "2620:4f:8000::/48" : "Direct Delegation AS112 Service", + "fc00::/7" : "Unique-Local", + "fe80::/10" : "Link-Local Unicast" + ] //IPv4 constants static let classAbits: Int = 8 @@ -540,7 +558,7 @@ class IPSubnetCalc: NSObject { ipv4str.append("." + String((UInt32(ip4Hex[1], radix: 16)! & Constants.addr32Digit4))) } if (ip4Hex[2] == "") { - ipv4str.append("0.0") + ipv4str.append(".0.0") } else { ipv4str.append("." + String((UInt32(ip4Hex[2], radix: 16)! & Constants.addr32Digit3) >> 8)) @@ -562,8 +580,13 @@ class IPSubnetCalc: NSObject { ipv4str.append("." + String((UInt32(ip4Hex[index - 2], radix: 16)! & Constants.addr32Digit4))) } } - ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) - ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) + if (ip4Hex[index - 1] == "") { + ipv4str.append(".0.0") + } + else { + ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) + } return (ipv4str, "6PE") } } @@ -573,7 +596,10 @@ class IPSubnetCalc: NSObject { var ip4Hex = [String]() ip4Hex = ipAddress.components(separatedBy: ":") - for index in 0...7 { + for index in 0...(ip4Hex.count - 1) { + if (ip4Hex[index] == "") { + ip4Hex[index] = "0" + } ipAddressNum[index] = UInt16(ip4Hex[index], radix: 16)! //print("Index: \(index) Ip4Hex: \(ip4Hex[index]) Hexa : \(UInt16(ip4Hex[index], radix: 16)!)") } @@ -701,9 +727,8 @@ class IPSubnetCalc: NSObject { var prevCompactZero = false //print("IP Address: \(ipAddress)") - ip4Hex = ipAddress.components(separatedBy: ":") + ip4Hex = self.fullAddressIPv6(ipAddress: ipAddress).components(separatedBy: ":") for index in 0...(ip4Hex.count - 1) { - //print("Index : \(index) IPHex : \(ip4Hex[index]) Dec : \(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16))") if (UInt16(ip4Hex[index], radix: 16)! == 0) { if (!prevIsZero || prevCompactZero) { if index == (ip4Hex.count - 1) { @@ -729,12 +754,7 @@ class IPSubnetCalc: NSObject { } else { if (prevAreZero && !prevCompactZero) { - if index == (ip4Hex.count - 1) { - shortAddr.append("::") - } - else { shortAddr.append(":") - } prevCompactZero = true } shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) @@ -744,8 +764,9 @@ class IPSubnetCalc: NSObject { prevIsZero = false prevAreZero = false } - + //print("Index : \(index) IPHex : \(ip4Hex[index]) shortAddr: \(shortAddr)") } + //print("compactAddressIPv6 short ip: \(shortAddr)") return (shortAddr) } @@ -887,6 +908,7 @@ class IPSubnetCalc: NSObject { // full ? compact ? validated ? self.ipv6Address = ipv6 self.ipv6MaskBits = maskbits + //print("init IPv6 ipv6 addr: \(self.ipv6Address) ipv4 addr: \(self.ipv4Address)") } else { return nil diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 1f90ac0..738851b 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -376,6 +376,10 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipmask = Constants.defaultIPv6Mask } } + else if (Int(ipmask!) == nil) { + myAlert(message: "Bad IPv6 mask", info: "Bad format") + return + } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") if (addrField.stringValue.isEmpty) { From e26199233e29f4e33b1f9249eaf8a2ccebefbaa5 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Fri, 11 Dec 2020 21:33:15 +0100 Subject: [PATCH 49/66] re-ident files --- IPSubnetcalc.swift | 58 ++++++++++++++++++------------------- SubnetCalcAppDelegate.swift | 36 +++++++++++------------ 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 43ace22..7e97827 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -48,7 +48,7 @@ class IPSubnetCalc: NSObject { "2620:4f:8000::/48" : "Direct Delegation AS112 Service", "fc00::/7" : "Unique-Local", "fe80::/10" : "Link-Local Unicast" - ] + ] //IPv4 constants static let classAbits: Int = 8 @@ -148,15 +148,15 @@ class IPSubnetCalc: NSObject { //OLD numerize a String as a Mask bits value to UInt32 /* - static func numerize(maskDigit: String) -> UInt32 { - var maskNum: UInt32 = 0 - - if (Int(maskDigit) != nil) { - maskNum = (Constants.addr32Full << (32 - Int(maskDigit)!)) & Constants.addr32Full - } - return (maskNum) - } - */ + static func numerize(maskDigit: String) -> UInt32 { + var maskNum: UInt32 = 0 + + if (Int(maskDigit) != nil) { + maskNum = (Constants.addr32Full << (32 - Int(maskDigit)!)) & Constants.addr32Full + } + return (maskNum) + } + */ //numerize a Mask bits value to UInt32 static func numerize(maskbits: Int) -> UInt32 { @@ -568,26 +568,26 @@ class IPSubnetCalc: NSObject { return (ipv4str, "6to4") } else { - if (index < 2) { - ipv4str.append("0.0") - } - else { - if (ip4Hex[index - 2] == "") { + if (index < 2) { ipv4str.append("0.0") } else { - ipv4str.append(String((UInt32(ip4Hex[index - 2], radix: 16)! & Constants.addr32Digit3) >> 8)) - ipv4str.append("." + String((UInt32(ip4Hex[index - 2], radix: 16)! & Constants.addr32Digit4))) + if (ip4Hex[index - 2] == "") { + ipv4str.append("0.0") + } + else { + ipv4str.append(String((UInt32(ip4Hex[index - 2], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[index - 2], radix: 16)! & Constants.addr32Digit4))) + } } - } if (ip4Hex[index - 1] == "") { ipv4str.append(".0.0") } - else { - ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) - ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) - } - return (ipv4str, "6PE") + else { + ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) + ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) + } + return (ipv4str, "6PE") } } @@ -754,7 +754,7 @@ class IPSubnetCalc: NSObject { } else { if (prevAreZero && !prevCompactZero) { - shortAddr.append(":") + shortAddr.append(":") prevCompactZero = true } shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) @@ -776,8 +776,8 @@ class IPSubnetCalc: NSObject { let numIP = IPSubnetCalc.numerizeIPv6(ipAddress: fullAddressIPv6(ipAddress: self.ipv6Address)) for index in 0...7 { - //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") - netID.append((numIP[index] & numMask[index])) + //print("Index: \(index) IP: \(numIP[index]) Mask : \(numMask[index]) Result : \(numIP[index] & (numMask[index])) ") + netID.append((numIP[index] & numMask[index])) } return (IPSubnetCalc.hexarizeIPv6(num: netID, full: false, column: true)) } @@ -905,9 +905,9 @@ class IPSubnetCalc: NSObject { self.maskBits = Constants.classAbits } - // full ? compact ? validated ? - self.ipv6Address = ipv6 - self.ipv6MaskBits = maskbits + // full ? compact ? validated ? + self.ipv6Address = ipv6 + self.ipv6MaskBits = maskbits //print("init IPv6 ipv6 addr: \(self.ipv6Address) ipv4 addr: \(self.ipv4Address)") } else { diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 738851b..e7f8dff 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -360,32 +360,32 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, var ipaddr: String var ipmask: String? - (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) + (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { if (ipsc != nil) { ipaddr = ipsc!.ipv6Address //print("doIPv6SubnetCalc ipaddr to ipv6 : \(ipsc!.ipv6Address)") } } - if (ipmask == nil) { - if (ipsc != nil) { - ipmask = String(ipsc!.ipv6MaskBits) - //print("doIPv6SubnetCalc ipmask ipv6 : \(ipsc!.ipv6MaskBits)") - } - else { - ipmask = Constants.defaultIPv6Mask - } + if (ipmask == nil) { + if (ipsc != nil) { + ipmask = String(ipsc!.ipv6MaskBits) + //print("doIPv6SubnetCalc ipmask ipv6 : \(ipsc!.ipv6MaskBits)") } - else if (Int(ipmask!) == nil) { - myAlert(message: "Bad IPv6 mask", info: "Bad format") - return + else { + ipmask = Constants.defaultIPv6Mask } + } + else if (Int(ipmask!) == nil) { + myAlert(message: "Bad IPv6 mask", info: "Bad format") + return + } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") if (addrField.stringValue.isEmpty) { addrField.stringValue = ipaddr } - ipsc = IPSubnetCalc(ipv6: ipaddr, maskbits: Int(ipmask!)!) + ipsc = IPSubnetCalc(ipv6: ipaddr, maskbits: Int(ipmask!)!) if (ipsc != nil) { if (tabView.numberOfTabViewItems != 4 && savedTabView != nil) { tabView.addTabViewItem(savedTabView![1]) @@ -579,7 +579,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, let maskbits:Int = IPSubnetCalc.maskBits(mask: mask) let classType = ipsc!.netClass() var result: Int = -1 - + if (classType == "A") { result = maskbits - 8 } @@ -677,7 +677,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, return } } - + func numberOfRows(in tableView: NSTableView) -> Int { if (ipsc != nil) { @@ -857,11 +857,11 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } else { // Fallback on earlier versions } - - } + } - ) } + ) + } } @IBAction func exportClipboard(_ sender: AnyObject) From 5006f2ece160a8113475d3c8565914a805b3275e Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 10:55:25 +0100 Subject: [PATCH 50/66] Change README.md to list new stuffs in this alpha 2.0 version Add IPv6 info in Export to Clipboard --- IPSubnetcalc.swift | 2 +- README.md | 12 +++++++----- SubnetCalcAppDelegate.swift | 10 +++++----- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 7e97827..6bddbed 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -587,7 +587,7 @@ class IPSubnetCalc: NSObject { ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit3) >> 8)) ipv4str.append("." + String((UInt32(ip4Hex[index - 1], radix: 16)! & Constants.addr32Digit4))) } - return (ipv4str, "6PE") + return (ipv4str, "IPv4-Mapped") } } diff --git a/README.md b/README.md index 4b74e95..2c36c9c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ # SubnetCalc Subnet Calculator for MacOS -What's New in version 1.6: -- Dark Mode support -- Selectable cells for copy -- New App icon -- Universal binary (Apple Silicon support) +What's New in version 2.0: +- IPv6 support! +- New Tab presentation +- Recoded in Swift +- Add alerts for bad IP or mask format +- Fix bugs + For more information: http://subnetcalc.mulot.org diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index e7f8dff..bd637d6 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -323,7 +323,6 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, var number: Decimal = 2 var typeConv: String - NSDecimalPower(&total, &number , 128 - ipsc!.ipv6MaskBits, NSDecimalNumber.RoundingMode.plain) if (ipv6Compact.state == NSControl.StateValue.on) { ipv6Address.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.ipv6Address) ipv6Network.stringValue = ipsc!.compactAddressIPv6(ipAddress: ipsc!.networkIPv6()) @@ -335,9 +334,9 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, (ipv6to4Address.stringValue, typeConv) = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipsc!.ipv6Address) ipv6to4Box.title = "IPv4 conversion" + " (\(typeConv))" ipv6maskBitsCombo.selectItem(withObjectValue: String(ipsc!.ipv6MaskBits)) - ipv6maxHostsCombo.selectItem(withObjectValue: total) + ipv6maxHostsCombo.selectItem(withObjectValue: ipsc!.totalIPAddrIPv6()) ipv6Range.stringValue = ipsc!.networkRangeIPv6() - ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "" + ipv6Type.stringValue = ipsc!.resBlockIPv6() ?? "None" ipv6HexaID.stringValue = ipsc!.hexaIDIPv6() ipv6Decimal.stringValue = ipsc!.dottedDecimalIPv6() ipv6Arpa.stringValue = ipsc!.ip6ARPA() @@ -869,8 +868,9 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, if (ipsc != nil) { let pb: NSPasteboard = NSPasteboard.general pb.clearContents() - let str = "Address Class Type: \(ipsc!.netClass())\nIP Address: \(ipsc!.ipv4Address)\nSubnet ID: \(ipsc!.subnetId())\nSubnet Mask: \(ipsc!.subnetMask())\nBroadcast: \(ipsc!.subnetBroadcast())\nIP Range: \(ipsc!.subnetRange())\nMask Bits: \(ipsc!.maskBits)\nSubnet Bits: \(ipsc!.subnetBits())\nMax Subnets: \(ipsc!.maxSubnets())\nMax Hosts / Subnet: \(ipsc!.maxHosts())\nAddress Hexa: \(ipsc!.hexaMap())\nBit Map: \(ipsc!.bitMap())\nBinary Map: \(ipsc!.binaryMap())\n" - pb.setString(str, forType: NSPasteboard.PasteboardType.string) + let ipv4Info = "IPv4 Address Class Type: \(ipsc!.netClass())\nIPv4 Address: \(ipsc!.ipv4Address)\nIPv4 Subnet ID: \(ipsc!.subnetId())\nIPv4 Subnet Mask: \(ipsc!.subnetMask())\nIPv4 Broadcast: \(ipsc!.subnetBroadcast())\nIPv4 Address Range: \(ipsc!.subnetRange())\nIPv4 Mask Bits: \(ipsc!.maskBits)\nIPv4 Subnet Bits: \(ipsc!.subnetBits())\nMax IPv4 Subnets: \(ipsc!.maxSubnets())\nIPv4 Max Hosts / Subnet: \(ipsc!.maxHosts())\nIPv4 Address Hexa: \(ipsc!.hexaMap())\nIPv4 Bit Map: \(ipsc!.bitMap())\nIPv4 Binary Map: \(ipsc!.binaryMap())\n" + let ipv6Info = "\nIPv6 Address: \(ipsc!.ipv6Address)\nLong IPv6 Address: \(ipsc!.fullAddressIPv6(ipAddress: ipsc!.ipv6Address))\nShort IPv6 Address: \(ipsc!.compactAddressIPv6(ipAddress: ipsc!.ipv6Address))\nIPv6-to-IPv4: \(IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipsc!.ipv6Address))\nIPv6 Mask Bits: \(ipsc!.ipv6MaskBits)\nIPv6 Max Hosts / Subnet: \(ipsc!.totalIPAddrIPv6())\nNetwork: \(ipsc!.compactAddressIPv6(ipAddress: ipsc!.networkIPv6()))\nIPv6 Address Range: \(ipsc!.networkRangeIPv6())\nIPv6 Address Type: \(ipsc!.resBlockIPv6() ?? "None")\nIPv6 Address Hexa: \(ipsc!.hexaIDIPv6())\nIPv6 Address Dotted Decimal: \(ipsc!.dottedDecimalIPv6())\nIP6.ARPA: \(ipsc!.ip6ARPA())\n" + pb.setString(ipv4Info + ipv6Info, forType: NSPasteboard.PasteboardType.string) } } From 2e3a31efe04fc6ffad394b0446614e36bd1cdea6 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 11:21:42 +0100 Subject: [PATCH 51/66] Fix compactAddressIPv6 when IPv6 address begins with 000:000:... Refine ipv6 mask bits conversion to ipv4 mask bits (no less than 8 bits) --- IPSubnetcalc.swift | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 6bddbed..f1839da 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -725,6 +725,7 @@ class IPSubnetCalc: NSObject { var prevIsZero = false var prevAreZero = false var prevCompactZero = false + var prevNonZero = false //print("IP Address: \(ipAddress)") ip4Hex = self.fullAddressIPv6(ipAddress: ipAddress).components(separatedBy: ":") @@ -754,7 +755,12 @@ class IPSubnetCalc: NSObject { } else { if (prevAreZero && !prevCompactZero) { - shortAddr.append(":") + if (!prevNonZero) { + shortAddr.append("::") + } + else { + shortAddr.append(":") + } prevCompactZero = true } shortAddr.append(String(UInt16(ip4Hex[index], radix: 16)!, radix: 16)) @@ -763,10 +769,10 @@ class IPSubnetCalc: NSObject { } prevIsZero = false prevAreZero = false + prevNonZero = true } //print("Index : \(index) IPHex : \(ip4Hex[index]) shortAddr: \(shortAddr)") } - //print("compactAddressIPv6 short ip: \(shortAddr)") return (shortAddr) } @@ -898,7 +904,7 @@ class IPSubnetCalc: NSObject { init?(ipv6: String, maskbits: Int) { if (IPSubnetCalc.isValidIPv6(ipAddress: ipv6, mask: maskbits)) { (self.ipv4Address, _) = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipv6) - if (maskbits > 96) { + if (maskbits >= (96 + Constants.classAbits)) { self.maskBits = maskbits - 96 } else { From 475da39e7d6ef3c8df1fe389046942116cbc0be4 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 11:42:08 +0100 Subject: [PATCH 52/66] Add dotted option on IPv4 address conversion functions Add dotted option in IPv4 Tab --- Base.lproj/MainMenu.xib | 16 ++++++++++++++-- IPSubnetcalc.swift | 29 +++++++++++++++++++---------- SubnetCalcAppDelegate.swift | 19 ++++++++++++++++--- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 39f9f52..c92cf2e 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -346,9 +346,9 @@ @@ -1065,6 +1076,7 @@ + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index f1839da..d1fcfa0 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -80,7 +80,7 @@ class IPSubnetCalc: NSObject { //************* //IPv4 SECTION //************* - static func binarize(ipAddress: String, space: Bool) -> String { + static func binarize(ipAddress: String, space: Bool = false, dotted: Bool = true) -> String { var ipAddressBin = [String]() var binStr = String() var ipDigits = [String]() @@ -98,7 +98,12 @@ class IPSubnetCalc: NSObject { digitBin.insert(" ", at: ipAddressBin[index].index(ipAddressBin[index].startIndex, offsetBy: 4)) } if (index < 3) { - binStr += digitBin + "." + if (dotted == true) { + binStr += digitBin + "." + } + else { + binStr += digitBin + } } else { binStr += digitBin @@ -107,11 +112,11 @@ class IPSubnetCalc: NSObject { return (binStr) } - func binaryMap() -> String { - return (IPSubnetCalc.binarize(ipAddress: ipv4Address, space: false)) + func binaryMap(dotted: Bool = true) -> String { + return (IPSubnetCalc.binarize(ipAddress: ipv4Address, space: false, dotted: dotted)) } - static func hexarize(ipAddress: String) -> String { + static func hexarize(ipAddress: String, dotted: Bool = true) -> String { var ipDigits = [String]() var hexIP = String() var hex4: String @@ -124,14 +129,16 @@ class IPSubnetCalc: NSObject { } hexIP += hex4 if (index < 3) { - hexIP += "." + if (dotted == true) { + hexIP += "." + } } } return (hexIP) } - func hexaMap() -> String { - return (IPSubnetCalc.hexarize(ipAddress: ipv4Address)) + func hexaMap(dotted: Bool = true) -> String { + return (IPSubnetCalc.hexarize(ipAddress: ipv4Address, dotted: dotted)) } static func numerize(ipAddress: String) -> UInt32 { @@ -421,7 +428,7 @@ class IPSubnetCalc: NSObject { return (maxSubnets) } - func bitMap() -> String { + func bitMap(dotted: Bool = true) -> String { let netBits = self.netBits() let subnetBits = self.subnetBits() var bitMap = String() @@ -437,7 +444,9 @@ class IPSubnetCalc: NSObject { bitMap.append("h") } if ((index < 31) && ((index + 1) % 8 == 0)) { - bitMap.append(".") + if (dotted == true) { + bitMap.append(".") + } } } return (bitMap) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index bd637d6..1bb9a96 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -52,6 +52,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBOutlet var bitsOnSlide: NSTextField! @IBOutlet var tabViewClassLess: NSButton! @IBOutlet var wildcard: NSButton! + @IBOutlet var dotted: NSButton! //IPv6 UI elements @IBOutlet var ipv6Address: NSTextField! @@ -171,9 +172,16 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, private func doAddressMap() { if (ipsc != nil) { self.initClassInfos(ipsc!.netClass()) - classBitMap.stringValue = ipsc!.bitMap() - classBinaryMap.stringValue = ipsc!.binaryMap() - classHexaMap.stringValue = ipsc!.hexaMap() + if (dotted.state == NSControl.StateValue.on) { + classBitMap.stringValue = ipsc!.bitMap(dotted: true) + classBinaryMap.stringValue = ipsc!.binaryMap(dotted: true) + classHexaMap.stringValue = ipsc!.hexaMap(dotted: true) + } + else { + classBitMap.stringValue = ipsc!.bitMap(dotted: false) + classBinaryMap.stringValue = ipsc!.binaryMap(dotted: false) + classHexaMap.stringValue = ipsc!.hexaMap(dotted: false) + } } } @@ -774,6 +782,11 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } + @IBAction func changeDotted(_ sender: AnyObject) + { + self.doAddressMap() + } + //IPv6 UI actions @IBAction func changeIPv6Format(_ sender: AnyObject) { From afcc8d1417b742a348ccfb77d166a8a268e0895b Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 14:59:23 +0100 Subject: [PATCH 53/66] Fix Subnet/Host Tab error on listed subnets calculation Update CIDR Tab maskbits according to Subnets/host bits slide --- SubnetCalcAppDelegate.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 1bb9a96..27a2f60 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -703,10 +703,9 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, row: Int) -> Any? { if (ipsc != nil) { - let mask: UInt32 = UInt32(row) << (32 - ipsc!.maskBits) - //print("tableView mask : \(mask) row : \(UInt32(row)) lshift : \(32 - ipsc!.maskBits)") - let ipaddr = (IPSubnetCalc.numerize(ipAddress: ipsc!.subnetId())) | mask + let ipaddr: UInt32 = (((IPSubnetCalc.numerize(ipAddress: ipsc!.subnetId())) >> (32 - ipsc!.maskBits)) + UInt32(row)) << (32 - ipsc!.maskBits) let ipsc_tmp = IPSubnetCalc(ipAddress: IPSubnetCalc.digitize(ipAddress: ipaddr), maskbits: ipsc!.maskBits) + //print("tableView Row: \(row) IP num : \(ipaddr) IP: \(IPSubnetCalc.digitize(ipAddress: ipaddr)) IP Subnet: \(ipsc_tmp!.subnetId())") if (tableColumn != nil && ipsc_tmp != nil) { if (tableColumn!.identifier.rawValue == "numCol") { return (row + 1) @@ -744,6 +743,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, if (tabViewClassLess.state == NSControl.StateValue.on) { ipsc!.maskBits = maskbits self.doSubnetHost() + self.doCIDR(maskbits: maskbits) } } } From 9e61c2ed456e3b0fe914bc3f082d6aabd4e0d0b0 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 16:00:39 +0100 Subject: [PATCH 54/66] Implement changeIPv6Subnets and changeIPv6MaxHosts functions --- SubnetCalcAppDelegate.swift | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 27a2f60..849529b 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -812,12 +812,27 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, @IBAction func changeIPv6Subnets(_ sender: AnyObject) { - self.doIPv6() + if (ipsc == nil ) { + ipsc = IPSubnetCalc(Constants.defaultIP) + } + ipsc!.ipv6MaskBits -= sender.indexOfSelectedItem() + self.doIPv6SubnetCalc() } @IBAction func changeIPv6MaxHosts(_ sender: AnyObject) { - self.doIPv6() + if (ipsc == nil) + { + ipsc = IPSubnetCalc(Constants.defaultIP) + } + if (sender.indexOfSelectedItem != -1) { + ipsc!.ipv6MaskBits = 128 - sender.indexOfSelectedItem() + self.doIPv6SubnetCalc() + } + else { + myAlert(message: "Bad Max Hosts", info: "Bad format") + return + } } //General UI actions From 6466afb6902309130f7f70f0034a7803946852ae Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 16:59:03 +0100 Subject: [PATCH 55/66] Change Address field behaviour when there is already an IP Fix UI Unit tests --- SubnetCalcAppDelegate.swift | 16 ++++++++++------ SubnetCalcUITests/SubnetCalcUITest.swift | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 849529b..6c03e35 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -275,6 +275,14 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, if (ipsc != nil) { ipaddr = ipsc!.ipv4Address } + if (ipmask != nil) { + if (Int(ipmask!)! >= (96 + 8)) { + ipmask = String(Int(ipmask!)! - 96) + } + else { + ipmask = "8" + } + } } if (ipmask == nil && ipsc != nil) { ipmask = String(ipsc!.maskBits) @@ -282,9 +290,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - if (addrField.stringValue.isEmpty) { - addrField.stringValue = ipaddr - } + addrField.stringValue = ipaddr if (ipmask == nil) { ipsc = IPSubnetCalc(ipaddr) } @@ -389,9 +395,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - if (addrField.stringValue.isEmpty) { - addrField.stringValue = ipaddr - } + addrField.stringValue = ipaddr ipsc = IPSubnetCalc(ipv6: ipaddr, maskbits: Int(ipmask!)!) if (ipsc != nil) { if (tabView.numberOfTabViewItems != 4 && savedTabView != nil) { diff --git a/SubnetCalcUITests/SubnetCalcUITest.swift b/SubnetCalcUITests/SubnetCalcUITest.swift index 1f5ca9d..ecd3e83 100644 --- a/SubnetCalcUITests/SubnetCalcUITest.swift +++ b/SubnetCalcUITests/SubnetCalcUITest.swift @@ -111,7 +111,7 @@ class SubnetCalcUITest: XCTestCase { subnetcalcWindow.menuItems["exportClipboard:"].click() let pb: NSPasteboard = NSPasteboard.general let pbContent = pb.string(forType: NSPasteboard.PasteboardType.string) - let validContent = "Address Class Type: B\nIP Address: 172.16.242.132\nSubnet ID: 172.0.0.0\nSubnet Mask: 255.0.0.0\nBroadcast: 172.255.255.255\nIP Range: 172.0.0.1 - 172.255.255.254\nMask Bits: 8\nSubnet Bits: 0\nMax Subnets: 1\nMax Hosts / Subnet: 16777214\nAddress Hexa: AC.10.F2.84\nBit Map: nnnnnnnn.hhhhhhhh.hhhhhhhh.hhhhhhhh\nBinary Map: 10101100.00010000.11110010.10000100\n" + let validContent = "IPv4 Address Class Type: B\nIPv4 Address: 172.16.242.132\nIPv4 Subnet ID: 172.0.0.0\nIPv4 Subnet Mask: 255.0.0.0\nIPv4 Broadcast: 172.255.255.255\nIPv4 Address Range: 172.0.0.1 - 172.255.255.254\nIPv4 Mask Bits: 8\nIPv4 Subnet Bits: 0\nMax IPv4 Subnets: 1\nIPv4 Max Hosts / Subnet: 16777214\nIPv4 Address Hexa: AC.10.F2.84\nIPv4 Bit Map: nnnnnnnn.hhhhhhhh.hhhhhhhh.hhhhhhhh\nIPv4 Binary Map: 10101100.00010000.11110010.10000100\n\nIPv6 Address: 0:0:0:0:0:ffff:ac10:f284\nLong IPv6 Address: 0000:0000:0000:0000:0000:ffff:ac10:f284\nShort IPv6 Address: ::ffff:ac10:f284\nIPv6-to-IPv4: (\"172.16.242.132\", \"IPv4-Mapped\")\nIPv6 Mask Bits: 104\nIPv6 Max Hosts / Subnet: 16777216\nNetwork: ::ffff:ac00:0\nIPv6 Address Range: 0000:0000:0000:0000:0000:ffff:ac00:0000 - 0000:0000:0000:0000:0000:ffff:acff:ffff\nIPv6 Address Type: None\nIPv6 Address Hexa: 0x00000000000000000000ffffac10f284\nIPv6 Address Dotted Decimal: 0.0.0.0.0.0.0.0.0.0.255.255.172.16.242.132\nIP6.ARPA: 4.8.2.f.0.1.c.a.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\n" XCTAssertEqual(pbContent,validContent) //subnetcalcWindow.buttons["Calc"].click() From b4abf3b59adc84b539e1930cdf08b4adbd54f54c Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 17:33:38 +0100 Subject: [PATCH 56/66] Begin UI Unit tests for IPv6 compact address --- SubnetCalcUITests/SubnetCalcUITest.swift | 64 +++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/SubnetCalcUITests/SubnetCalcUITest.swift b/SubnetCalcUITests/SubnetCalcUITest.swift index ecd3e83..79e5be1 100644 --- a/SubnetCalcUITests/SubnetCalcUITest.swift +++ b/SubnetCalcUITests/SubnetCalcUITest.swift @@ -58,7 +58,8 @@ class SubnetCalcUITest: XCTestCase { subnetcalcWindow.tabs["IPv4"].click() ipaddrfieldTextField.click() - ipaddrfieldTextField.doubleClick() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) ipaddrfieldTextField.typeText("192.168.254.129/12\r") XCTAssertEqual(subnetcalcWindow.comboBoxes["subnetbitscombo"].value as! String, "0") XCTAssertEqual(subnetcalcWindow.comboBoxes["maskbitscombo"].value as! String, "12") @@ -84,7 +85,8 @@ class SubnetCalcUITest: XCTestCase { subnetcalcWindow.tabs["IPv4"].click() ipaddrfieldTextField.click() - ipaddrfieldTextField.doubleClick() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) ipaddrfieldTextField.typeText("172.16.242.132/8\r") XCTAssertEqual(subnetcalcWindow.comboBoxes["subnetbitscombo"].value as! String, "0") XCTAssertEqual(subnetcalcWindow.comboBoxes["maskbitscombo"].value as! String, "8") @@ -114,6 +116,64 @@ class SubnetCalcUITest: XCTestCase { let validContent = "IPv4 Address Class Type: B\nIPv4 Address: 172.16.242.132\nIPv4 Subnet ID: 172.0.0.0\nIPv4 Subnet Mask: 255.0.0.0\nIPv4 Broadcast: 172.255.255.255\nIPv4 Address Range: 172.0.0.1 - 172.255.255.254\nIPv4 Mask Bits: 8\nIPv4 Subnet Bits: 0\nMax IPv4 Subnets: 1\nIPv4 Max Hosts / Subnet: 16777214\nIPv4 Address Hexa: AC.10.F2.84\nIPv4 Bit Map: nnnnnnnn.hhhhhhhh.hhhhhhhh.hhhhhhhh\nIPv4 Binary Map: 10101100.00010000.11110010.10000100\n\nIPv6 Address: 0:0:0:0:0:ffff:ac10:f284\nLong IPv6 Address: 0000:0000:0000:0000:0000:ffff:ac10:f284\nShort IPv6 Address: ::ffff:ac10:f284\nIPv6-to-IPv4: (\"172.16.242.132\", \"IPv4-Mapped\")\nIPv6 Mask Bits: 104\nIPv6 Max Hosts / Subnet: 16777216\nNetwork: ::ffff:ac00:0\nIPv6 Address Range: 0000:0000:0000:0000:0000:ffff:ac00:0000 - 0000:0000:0000:0000:0000:ffff:acff:ffff\nIPv6 Address Type: None\nIPv6 Address Hexa: 0x00000000000000000000ffffac10f284\nIPv6 Address Dotted Decimal: 0.0.0.0.0.0.0.0.0.0.255.255.172.16.242.132\nIP6.ARPA: 4.8.2.f.0.1.c.a.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa\n" XCTAssertEqual(pbContent,validContent) + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("2001:0db8:0000:85a3:0000:0000:ac1f:8001\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001:db8:0:85a3::ac1f:8001") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("2001:0000:0000:85a3:0000:0000:ac1f:0801\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001::85a3:0:0:ac1f:801") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("2001:0000:0000:85a3:0000:0000:ac1f:0000\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001::85a3:0:0:ac1f:0") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("2001:0db8:0000:85a3:0200:0000:ac1f:0000\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001:db8:0:85a3:200:0:ac1f:0") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("2001:0db8:0000:85a3:0200:0020:0000:0000\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001:db8:0:85a3:200:20::") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("0000:0000:0000:0000:0000:0000:0000:0001\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "::1") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("0000:0000:0000:0000:0000:0000:0000:0000\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "::") + + subnetcalcWindow.tabs["IPv6"].click() + ipaddrfieldTextField.click() + ipaddrfieldTextField.typeKey("a", modifierFlags:.command) + ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + ipaddrfieldTextField.typeText("0:0:0::\r") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "::") + + //ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) + //subnetcalcWindow.buttons["Calc"].click() ipaddrfieldTextField.typeKey("q", modifierFlags:.command) } From 8e7e273b958154807f585bc384c8aa488159a890 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sat, 12 Dec 2020 17:48:32 +0100 Subject: [PATCH 57/66] UI Unit tests for all IPv6 field for one test --- SubnetCalcUITests/SubnetCalcUITest.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/SubnetCalcUITests/SubnetCalcUITest.swift b/SubnetCalcUITests/SubnetCalcUITest.swift index 79e5be1..898fad5 100644 --- a/SubnetCalcUITests/SubnetCalcUITest.swift +++ b/SubnetCalcUITests/SubnetCalcUITest.swift @@ -120,8 +120,18 @@ class SubnetCalcUITest: XCTestCase { ipaddrfieldTextField.click() ipaddrfieldTextField.typeKey("a", modifierFlags:.command) ipaddrfieldTextField.typeKey(.delete, modifierFlags:[]) - ipaddrfieldTextField.typeText("2001:0db8:0000:85a3:0000:0000:ac1f:8001\r") + ipaddrfieldTextField.typeText("2001:0db8:0000:85a3:0000:0000:ac1f:8001/127\r") XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6addrtext"].value as! String, "2001:db8:0:85a3::ac1f:8001") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv4addrconvtext"].value as! String, "172.31.128.1") + XCTAssertEqual(subnetcalcWindow.comboBoxes["ipv6maskbitscombo"].value as! String, "127") + XCTAssertEqual(subnetcalcWindow.comboBoxes["ipv6maxsubnetscombo"].value as! String, "/127\t1 network") + XCTAssertEqual(subnetcalcWindow.comboBoxes["ipv6maxhostscombo"].value as! String, "2") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6networktext"].value as! String, "2001:db8:0:85a3::ac1f:8000") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6rangetext"].value as! String, "2001:0db8:0000:85a3:0000:0000:ac1f:8000 - 2001:0db8:0000:85a3:0000:0000:ac1f:8001") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6typetext"].value as! String, "None") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6hexatext"].value as! String, "0x20010db8000085a300000000ac1f8001") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6decimaltext"].value as! String, "32.1.13.184.0.0.133.163.0.0.0.0.172.31.128.1") + XCTAssertEqual(subnetcalcWindow.staticTexts["ipv6arpatext"].value as! String, "1.0.0.8.f.1.c.a.0.0.0.0.0.0.0.0.3.a.5.8.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa") subnetcalcWindow.tabs["IPv6"].click() ipaddrfieldTextField.click() From 5b94853f9fd567af46f52a7833c1bfe2563648bc Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Sun, 13 Dec 2020 11:45:30 +0100 Subject: [PATCH 58/66] Change address field behaviour: mask is always remove after calc and the address field is preserved if there is already an address Support for Class E Allow calculation on Class D and E address --- Base.lproj/MainMenu.xib | 13 +++++---- IPSubnetcalc.swift | 11 +++++-- SubnetCalcAppDelegate.swift | 57 ++++++++++++++++++++++++++----------- 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index c92cf2e..93df1e1 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -406,15 +406,16 @@ - + - - - - + + + + + @@ -470,7 +471,7 @@ - + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index d1fcfa0..9e1049f 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -64,8 +64,12 @@ class IPSubnetCalc: NSObject { static let maskClassA: UInt32 = 0xFF000000 static let netIdClassB: UInt32 = 0x80000000 static let maskClassB: UInt32 = 0xFFFF0000 - static let netIdClassC: UInt32 = 0xc0000000 + static let netIdClassC: UInt32 = 0xC0000000 static let maskClassC: UInt32 = 0xFFFFFF00 + static let netIdClassD: UInt32 = 0xE0000000 + static let maskClassD: UInt32 = 0xF0000000 + static let netIdClassE: UInt32 = 0xF0000000 + static let maskClassE: UInt32 = 0xF0000000 } //**************** @@ -336,7 +340,10 @@ class IPSubnetCalc: NSObject { if (addr1stByte >= 192 && addr1stByte < 224) { return ("C") } - return ("D") + if (addr1stByte >= 224 && addr1stByte < 240) { + return ("D") + } + return ("E") } func netClass() -> String { diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 6c03e35..1875379 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -147,6 +147,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, else if (c == "D") { classType.selectItem(at: 3) + /* savedTabView = tabView.tabViewItems if (savedTabView != nil) { @@ -154,6 +155,11 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, tabView.removeTabViewItem(savedTabView![2]) tabView.removeTabViewItem(savedTabView![3]) } + */ + } + else if (c == "E") + { + classType.selectItem(at: 4) } } @@ -271,6 +277,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } else { (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) + addrField.stringValue = ipaddr if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask ?? Constants.defaultIPv6Mask)) == true) { if (ipsc != nil) { ipaddr = ipsc!.ipv4Address @@ -290,7 +297,6 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - addrField.stringValue = ipaddr if (ipmask == nil) { ipsc = IPSubnetCalc(ipaddr) } @@ -311,7 +317,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad IPv4 Address", info: "Bad format") + myAlert(message: "Bad IPv4 Address", info: "Bad format: \(ipaddr)/\(ipmask ?? "")") return } } @@ -374,6 +380,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, var ipmask: String? (ipaddr, ipmask) = splitAddrMask(address: addrField.stringValue) + addrField.stringValue = ipaddr if (IPSubnetCalc.isValidIP(ipAddress: ipaddr, mask: ipmask) == true) { if (ipsc != nil) { ipaddr = ipsc!.ipv6Address @@ -390,12 +397,11 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else if (Int(ipmask!) == nil) { - myAlert(message: "Bad IPv6 mask", info: "Bad format") + myAlert(message: "Bad IPv6 mask", info: "Bad format: \(ipmask!)") return } if (IPSubnetCalc.isValidIPv6(ipAddress: ipaddr, mask: Int(ipmask!)) == true) { //print("IP Address: \(ipaddr) mask: \(ipmask)") - addrField.stringValue = ipaddr ipsc = IPSubnetCalc(ipv6: ipaddr, maskbits: Int(ipmask!)!) if (ipsc != nil) { if (tabView.numberOfTabViewItems != 4 && savedTabView != nil) { @@ -411,7 +417,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad IPv6 Address", info: "Bad format") + myAlert(message: "Bad IPv6 Address", info: "Bad format: \(ipaddr)/\(ipmask ?? "")") return } } @@ -445,6 +451,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } else if (sender.indexOfSelectedItem() == 3) { + /* savedTabView = tabView.tabViewItems if (savedTabView != nil) { @@ -452,10 +459,26 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, tabView.removeTabViewItem(savedTabView![2]) tabView.removeTabViewItem(savedTabView![3]) } + */ classBitMap.stringValue = "hhhhhhhh.hhhhhhhh.hhhhhhhh.hhhhhhhh" classBinaryMap.stringValue = "11100000.00000000.00000000.00000000" classHexaMap.stringValue = "E0.00.00.00" } + else if (sender.indexOfSelectedItem() == 4) + { + /* + savedTabView = tabView.tabViewItems + if (savedTabView != nil) + { + tabView.removeTabViewItem(savedTabView![1]) + tabView.removeTabViewItem(savedTabView![2]) + tabView.removeTabViewItem(savedTabView![3]) + } + */ + classBitMap.stringValue = "hhhhhhhh.hhhhhhhh.hhhhhhhh.hhhhhhhh" + classBinaryMap.stringValue = "11110000.00000000.00000000.00000000" + classHexaMap.stringValue = "F0.00.00.00" + } } @IBAction func changeMaxHosts(_ sender: AnyObject) @@ -469,7 +492,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPSubnetCalc() } else { - myAlert(message: "Bad Max Hosts", info: "Bad value") + myAlert(message: "Bad Max Hosts", info: "Bad selection") return } } @@ -485,7 +508,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPSubnetCalc() } else { - myAlert(message: "Bad Max Subnets", info: "Bad value") + myAlert(message: "Bad Max Subnets", info: "Bad selection") return } } @@ -501,7 +524,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPSubnetCalc() } else { - myAlert(message: "Bad Subnet Bits", info: "Bad format") + myAlert(message: "Bad Subnet Bits", info: "Bad selection") return } } @@ -525,7 +548,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPSubnetCalc() } else { - myAlert(message: "Bad Subnet Mask", info: "Bad format") + myAlert(message: "Bad Subnet Mask", info: "Bad selection") return } } @@ -541,7 +564,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPSubnetCalc() } else { - myAlert(message: "Bad Mask Bits", info: "Bad format") + myAlert(message: "Bad Mask Bits", info: "Bad selection") return } } @@ -574,7 +597,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad CIDR Mask Bits", info: "Bad format") + myAlert(message: "Bad CIDR Mask Bits", info: "Bad selection") return } } @@ -609,7 +632,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad CIDR Mask", info: "Bad format") + myAlert(message: "Bad CIDR Mask", info: "Bad selection") return } } @@ -642,7 +665,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad Max Supernets", info: "Bad value") + myAlert(message: "Bad Max Supernets", info: "Bad selection") return } } @@ -663,7 +686,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad Max Adresses", info: "Bad value") + myAlert(message: "Bad Max Adresses", info: "Bad selection") return } } @@ -684,7 +707,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, } } else { - myAlert(message: "Bad Max Subnets", info: "Bad value") + myAlert(message: "Bad Max Subnets", info: "Bad selection") return } } @@ -809,7 +832,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPv6SubnetCalc() } else { - myAlert(message: "Bad IPv6 Mask Bits", info: "Bad format") + myAlert(message: "Bad IPv6 Mask Bits", info: "Bad selection") return } } @@ -834,7 +857,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, self.doIPv6SubnetCalc() } else { - myAlert(message: "Bad Max Hosts", info: "Bad format") + myAlert(message: "Bad Max Hosts", info: "Bad selection") return } } From 18d2380e2bcbf68b8447eb155a9608974196e003 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 16 Dec 2020 11:33:16 +0100 Subject: [PATCH 59/66] Add Constants.defaultIPv6to4Mask for 96 bits mask UI tests are working again --- Base.lproj/MainMenu.xib | 2 +- IPSubnetcalc.swift | 7 ++++--- SubnetCalcAppDelegate.swift | 5 +++-- SubnetCalcUITests/SubnetCalcUITest.swift | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 93df1e1..6e3bbf7 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -471,7 +471,7 @@ - + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 9e1049f..2e94646 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -22,6 +22,7 @@ class IPSubnetCalc: NSObject { //IPv6 constants static let addr16Full: UInt16 = 0xFFFF static let addr16Empty: UInt16 = 0x0000 + static let defaultIPv6to4Mask: Int = 96 //static let addr128Full: [UInt16] = [addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full, addr16Full] //static let addr128Empty: [UInt16] = [addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty, addr16Empty] //static let addr16Hex1: UInt16 = 0xF000 @@ -889,7 +890,7 @@ class IPSubnetCalc: NSObject { self.ipv4Address = ipAddress self.maskBits = maskbits self.ipv6Address = IPSubnetCalc.convertIPv4toIPv6(ipAddress: ipAddress) - self.ipv6MaskBits = maskbits + 96 + self.ipv6MaskBits = maskbits + Constants.defaultIPv6to4Mask } else { return nil @@ -920,8 +921,8 @@ class IPSubnetCalc: NSObject { init?(ipv6: String, maskbits: Int) { if (IPSubnetCalc.isValidIPv6(ipAddress: ipv6, mask: maskbits)) { (self.ipv4Address, _) = IPSubnetCalc.convertIPv6toIPv4(ipAddress: ipv6) - if (maskbits >= (96 + Constants.classAbits)) { - self.maskBits = maskbits - 96 + if (maskbits >= (Constants.defaultIPv6to4Mask + Constants.classAbits)) { + self.maskBits = maskbits - Constants.defaultIPv6to4Mask } else { self.maskBits = Constants.classAbits diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 1875379..0ce87be 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -13,6 +13,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, private enum Constants { static let defaultIP: String = "10.0.0.0" static let defaultIPv6Mask: String = "64" + static let defaultIPv6to4Mask: Int = 96 static let BUFFER_LINES:Int = 200000000 static let NETWORK_BITS_MIN_CLASSLESS:Int = 1 static let NETWORK_BITS_MIN:Int = 8 @@ -283,8 +284,8 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipaddr = ipsc!.ipv4Address } if (ipmask != nil) { - if (Int(ipmask!)! >= (96 + 8)) { - ipmask = String(Int(ipmask!)! - 96) + if (Int(ipmask!)! >= (Constants.defaultIPv6to4Mask + 8)) { + ipmask = String(Int(ipmask!)! - Constants.defaultIPv6to4Mask) } else { ipmask = "8" diff --git a/SubnetCalcUITests/SubnetCalcUITest.swift b/SubnetCalcUITests/SubnetCalcUITest.swift index 898fad5..7e8b877 100644 --- a/SubnetCalcUITests/SubnetCalcUITest.swift +++ b/SubnetCalcUITests/SubnetCalcUITest.swift @@ -43,7 +43,7 @@ class SubnetCalcUITest: XCTestCase { XCTAssertEqual(subnetcalcWindow.staticTexts["subnetrangetext"].value as! String, "10.32.2.53 - 10.32.2.54") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetidtext"].value as! String, "10.32.2.52") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetbroadcasttext"].value as! String, "10.32.2.55") - XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class A : 1.0.0.0 - 126.255.255.255") + XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class A: 1.0.0.0 - 126.255.255.255") XCTAssertEqual(subnetcalcWindow.staticTexts["classbitmap"].value as! String, "nnnnnnnn.ssssssss.ssssssss.sssssshh") XCTAssertEqual(subnetcalcWindow.staticTexts["binarymap"].value as! String, "00001010.00100000.00000010.00110100") XCTAssertEqual(subnetcalcWindow.staticTexts["hexamap"].value as! String, "0A.20.02.34") @@ -69,7 +69,7 @@ class SubnetCalcUITest: XCTestCase { XCTAssertEqual(subnetcalcWindow.staticTexts["subnetrangetext"].value as! String, "192.160.0.1 - 192.175.255.254") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetidtext"].value as! String, "192.160.0.0") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetbroadcasttext"].value as! String, "192.175.255.255") - XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class C : 192.0.0.0 - 223.255.255.255") + XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class C: 192.0.0.0 - 223.255.255.255") XCTAssertEqual(subnetcalcWindow.staticTexts["classbitmap"].value as! String, "nnnnnnnn.nnnnhhhh.hhhhhhhh.hhhhhhhh") XCTAssertEqual(subnetcalcWindow.staticTexts["binarymap"].value as! String, "11000000.10101000.11111110.10000001") XCTAssertEqual(subnetcalcWindow.staticTexts["hexamap"].value as! String, "C0.A8.FE.81") @@ -96,7 +96,7 @@ class SubnetCalcUITest: XCTestCase { XCTAssertEqual(subnetcalcWindow.staticTexts["subnetrangetext"].value as! String, "172.0.0.1 - 172.255.255.254") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetidtext"].value as! String, "172.0.0.0") XCTAssertEqual(subnetcalcWindow.staticTexts["subnetbroadcasttext"].value as! String, "172.255.255.255") - XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class B : 128.0.0.0 - 191.255.255.255") + XCTAssertEqual(subnetcalcWindow.popUpButtons["addrclasstypecell"].value as! String, "Class B: 128.0.0.0 - 191.255.255.255") XCTAssertEqual(subnetcalcWindow.staticTexts["classbitmap"].value as! String, "nnnnnnnn.hhhhhhhh.hhhhhhhh.hhhhhhhh") XCTAssertEqual(subnetcalcWindow.staticTexts["binarymap"].value as! String, "10101100.00010000.11110010.10000100") XCTAssertEqual(subnetcalcWindow.staticTexts["hexamap"].value as! String, "AC.10.F2.84") From 85f45ae2f5cc70c9aaf745d0379ff561595179c1 Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Tue, 22 Dec 2020 15:10:39 +0100 Subject: [PATCH 60/66] Add classBits func Increase version to 2.0 --- Base.lproj/MainMenu.xib | 6 +++--- IPSubnetcalc.swift | 15 +++++++++++++++ SubnetCalc-Info.plist | 2 +- 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 6e3bbf7..5274ec7 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -471,7 +471,7 @@ - + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 2e94646..1112aa9 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -373,6 +373,21 @@ class IPSubnetCalc: NSObject { return (bits) } + func classBits() -> Int { + let classType = self.netClass() + + if (classType == "A") { + return (Constants.classAbits) + } + else if (classType == "B") { + return (Constants.classBbits) + } + else if (classType == "C") { + return (Constants.classCbits) + } + return (32) + } + static func maskBits(maskAddr: String) -> Int { var bits: Int = 0 diff --git a/SubnetCalc-Info.plist b/SubnetCalc-Info.plist index fe69fbd..27f8f5a 100644 --- a/SubnetCalc-Info.plist +++ b/SubnetCalc-Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.7 + 2.0 CFBundleSignature JMUL CFBundleVersion From 96c25b093b909f1e9642bfb4d9721b71b5ea93ca Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 23 Dec 2020 11:19:24 +0100 Subject: [PATCH 61/66] 30 and 31 Mask bits support change MaxHosts return value to 0 for 32 mask bits Change SubnetRange return value for 32 and 31 mask bits Enable SWIFT_COMPILATION_MODE = wholemodule --- Base.lproj/MainMenu.xib | 6 ++--- IPSubnetcalc.swift | 12 ++++++--- README.md | 2 ++ SubnetCalc.xcodeproj/project.pbxproj | 3 ++- .../xcschemes/SubnetCalc.xcscheme | 2 +- SubnetCalcAppDelegate.swift | 26 +++++++++---------- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index 5274ec7..d9c50b6 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -154,7 +154,7 @@ - + @@ -565,9 +565,9 @@ - + - + diff --git a/IPSubnetcalc.swift b/IPSubnetcalc.swift index 1112aa9..57bcb20 100644 --- a/IPSubnetcalc.swift +++ b/IPSubnetcalc.swift @@ -267,7 +267,7 @@ class IPSubnetCalc: NSObject { var maxHosts: UInt32 = 0 if (self.maskBits == 32) { - return (1) + return (0) } maxHosts = (Constants.addr32Full >> self.maskBits) - 1 return (Int(maxHosts)) @@ -311,8 +311,14 @@ class IPSubnetCalc: NSObject { var firstIP: UInt32 = 0 var lastIP: UInt32 = 0 - firstIP = IPSubnetCalc.numerize(ipAddress: subnetId()) + 1 - lastIP = IPSubnetCalc.numerize(ipAddress: subnetBroadcast()) - 1 + if (maskBits == 31 || maskBits == 32) { + firstIP = IPSubnetCalc.numerize(ipAddress: subnetId()) + lastIP = IPSubnetCalc.numerize(ipAddress: subnetBroadcast()) + } + else { + firstIP = IPSubnetCalc.numerize(ipAddress: subnetId()) + 1 + lastIP = IPSubnetCalc.numerize(ipAddress: subnetBroadcast()) - 1 + } range = IPSubnetCalc.digitize(ipAddress: firstIP) + " - " + IPSubnetCalc.digitize(ipAddress: lastIP) return (range) } diff --git a/README.md b/README.md index 2c36c9c..afa0f02 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Subnet Calculator for MacOS What's New in version 2.0: - IPv6 support! +- Address Class D (Multicast) and Class E (Reserved) support +- 31 and 32 mask bits support - New Tab presentation - Recoded in Swift - Add alerts for bad IP or mask format diff --git a/SubnetCalc.xcodeproj/project.pbxproj b/SubnetCalc.xcodeproj/project.pbxproj index 402cffa..db52543 100644 --- a/SubnetCalc.xcodeproj/project.pbxproj +++ b/SubnetCalc.xcodeproj/project.pbxproj @@ -203,7 +203,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1220; + LastUpgradeCheck = 1230; TargetAttributes = { 8D1107260486CEB800E47090 = { LastSwiftMigration = 1220; @@ -534,6 +534,7 @@ PROVISIONING_PROFILE = ""; SDKROOT = macosx; STRIP_INSTALLED_PRODUCT = YES; + SWIFT_COMPILATION_MODE = wholemodule; }; name = Release; }; diff --git a/SubnetCalc.xcodeproj/xcshareddata/xcschemes/SubnetCalc.xcscheme b/SubnetCalc.xcodeproj/xcshareddata/xcschemes/SubnetCalc.xcscheme index 31eb15b..978c4c8 100644 --- a/SubnetCalc.xcodeproj/xcshareddata/xcschemes/SubnetCalc.xcscheme +++ b/SubnetCalc.xcodeproj/xcshareddata/xcschemes/SubnetCalc.xcscheme @@ -1,6 +1,6 @@ Date: Wed, 23 Dec 2020 11:55:10 +0100 Subject: [PATCH 62/66] Handle FileManager for macOS versions bellow 10.14 --- Base.lproj/MainMenu.xib | 5 ++--- SubnetCalcAppDelegate.swift | 43 +++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index d9c50b6..e0b9d0c 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -152,8 +152,7 @@ - - + @@ -471,7 +470,7 @@ - + diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 020c172..9164a2d 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -888,31 +888,32 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, panel.allowedFileTypes = ["csv"] panel.begin(completionHandler: { (result) in if (result == NSApplication.ModalResponse.OK && panel.url != nil) { + var fileMgt: FileManager if #available(OSX 10.14, *) { - let fileMgt = FileManager(authorization: NSWorkspace.Authorization()) - fileMgt.createFile(atPath: panel.url!.path, contents: nil, attributes: nil) - //var cvsData = NSMutableData.init(capacity: Constants.BUFFER_LINES) - var cvsData = Data(capacity: Constants.BUFFER_LINES) - let cvsFile = FileHandle(forWritingAtPath: panel.url!.path) - if (cvsFile != nil) { - var cvsStr = "#;Subnet ID;Range;Broadcast\n" - for index in (0...(self.ipsc!.maxSubnets() - 1)) { - let mask: UInt32 = UInt32(index) << (32 - self.ipsc!.maskBits) - let ipaddr = (IPSubnetCalc.numerize(ipAddress: self.ipsc!.subnetId())) | mask - let ipsc_tmp = IPSubnetCalc(ipAddress: IPSubnetCalc.digitize(ipAddress: ipaddr), maskbits: self.ipsc!.maskBits) - if (ipsc_tmp != nil) { - cvsStr.append("\(index + 1);\(ipsc_tmp!.subnetId());\(ipsc_tmp!.subnetRange());\(ipsc_tmp!.subnetBroadcast())\n") - } - } - cvsData.append(cvsStr.data(using: String.Encoding.ascii)!) - cvsFile!.write(cvsData) - cvsFile!.synchronizeFile() - cvsFile!.closeFile() - } + fileMgt = FileManager(authorization: NSWorkspace.Authorization()) } else { // Fallback on earlier versions + fileMgt = FileManager.default + } + fileMgt.createFile(atPath: panel.url!.path, contents: nil, attributes: nil) + //var cvsData = NSMutableData.init(capacity: Constants.BUFFER_LINES) + var cvsData = Data(capacity: Constants.BUFFER_LINES) + let cvsFile = FileHandle(forWritingAtPath: panel.url!.path) + if (cvsFile != nil) { + var cvsStr = "#;Subnet ID;Range;Broadcast\n" + for index in (0...(self.ipsc!.maxSubnets() - 1)) { + let mask: UInt32 = UInt32(index) << (32 - self.ipsc!.maskBits) + let ipaddr = (IPSubnetCalc.numerize(ipAddress: self.ipsc!.subnetId())) | mask + let ipsc_tmp = IPSubnetCalc(ipAddress: IPSubnetCalc.digitize(ipAddress: ipaddr), maskbits: self.ipsc!.maskBits) + if (ipsc_tmp != nil) { + cvsStr.append("\(index + 1);\(ipsc_tmp!.subnetId());\(ipsc_tmp!.subnetRange());\(ipsc_tmp!.subnetBroadcast())\n") + } + } + cvsData.append(cvsStr.data(using: String.Encoding.ascii)!) + cvsFile!.write(cvsData) + cvsFile!.synchronizeFile() + cvsFile!.closeFile() } - } } ) From a0aea838efd8e472451608732d92ff33d558a63a Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Wed, 23 Dec 2020 14:29:22 +0100 Subject: [PATCH 63/66] Reinit maskbits to NETWORK_BITS_MIN const when CIDR is enabled and SubnetHosts bits slide is under 8 --- SubnetCalcAppDelegate.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/SubnetCalcAppDelegate.swift b/SubnetCalcAppDelegate.swift index 9164a2d..762f784 100644 --- a/SubnetCalcAppDelegate.swift +++ b/SubnetCalcAppDelegate.swift @@ -772,6 +772,7 @@ class SubnetCalcAppDelegate: NSObject, NSApplicationDelegate, NSWindowDelegate, ipsc!.maskBits = maskbits self.doSubnetHost() self.doCIDR(maskbits: maskbits) + ipsc!.maskBits = Constants.NETWORK_BITS_MIN } } } From 0cd9f0d299bf284ac9a2de728c21a6f0841a6eed Mon Sep 17 00:00:00 2001 From: Julien Mulot Date: Thu, 24 Dec 2020 10:18:36 +0100 Subject: [PATCH 64/66] Add UI tests for class E and 32 bits mask --- Base.lproj/MainMenu.xib | 4 +- SubnetCalcUITests/SubnetCalcUITest.swift | 60 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index e0b9d0c..15abda1 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -344,7 +344,7 @@ -