88import Foundation
99import Cocoa
1010
11+ //*********************
12+ //Errors for IP format
13+ //*********************
14+ enum SubnetCalcError : Error {
15+ case invalidIPv4( _ info: String )
16+ case invalidIPv4Mask( _ info: String )
17+ case invalidIPv6( _ info: String )
18+ case invalidIPv6Mask( _ info: String )
19+ }
1120
1221class IPSubnetCalc : NSObject {
1322 //*********
@@ -97,15 +106,23 @@ class IPSubnetCalc: NSObject {
97106 the binary representation of the given IP address
98107
99108 */
100- static func binarize( ipAddress: String , space: Bool = false , dotted: Bool = true ) -> String {
109+ static func binarize( ipAddress: String , space: Bool = false , dotted: Bool = true ) -> String ? {
101110 var ipAddressBin = [ String] ( )
102111 var binStr = String ( )
103112 var ipDigits = [ String] ( )
104113
105114 ipDigits = ipAddress. components ( separatedBy: " . " )
106115
116+ if ipDigits. count != 4 {
117+ return nil
118+ }
107119 for index in 0 ... 3 {
108- ipAddressBin. append ( String ( Int ( ipDigits [ index] ) !, radix: 2 ) )
120+ if let ipDigit = Int ( ipDigits [ index] ) {
121+ ipAddressBin. append ( String ( ipDigit, radix: 2 ) )
122+ }
123+ else {
124+ return nil
125+ }
109126 while ( ipAddressBin [ index] . count < 8 ) {
110127 ipAddressBin [ index] . insert ( " 0 " , at: ipAddressBin [ index] . startIndex)
111128 }
@@ -139,7 +156,7 @@ class IPSubnetCalc: NSObject {
139156
140157 */
141158 func binaryMap( dotted: Bool = true ) -> String {
142- return ( IPSubnetCalc . binarize ( ipAddress: ipv4Address, space: false , dotted: dotted) )
159+ return ( IPSubnetCalc . binarize ( ipAddress: ipv4Address, space: false , dotted: dotted) ! )
143160 }
144161
145162 /**
@@ -153,14 +170,22 @@ class IPSubnetCalc: NSObject {
153170 the hexadecimal representation of the given IP address
154171
155172 */
156- static func hexarize( ipAddress: String , dotted: Bool = true ) -> String {
173+ static func hexarize( ipAddress: String , dotted: Bool = true ) -> String ? {
157174 var ipDigits = [ String] ( )
158175 var hexIP = String ( )
159176 var hex4 : String
160177
161178 ipDigits = ipAddress. components ( separatedBy: " . " )
179+ if ipDigits. count != 4 {
180+ return nil
181+ }
162182 for index in 0 ... 3 {
163- hex4 = String ( format: " %X " , Int ( ipDigits [ index] ) !)
183+ if let ipDigit = Int ( ipDigits [ index] ) {
184+ hex4 = String ( format: " %X " , ipDigit)
185+ }
186+ else {
187+ return nil
188+ }
164189 if ( hex4. count == 1 ) {
165190 hex4 = " 0 " + hex4
166191 }
@@ -184,7 +209,7 @@ class IPSubnetCalc: NSObject {
184209
185210 */
186211 func hexaMap( dotted: Bool = true ) -> String {
187- return ( IPSubnetCalc . hexarize ( ipAddress: ipv4Address, dotted: dotted) )
212+ return ( IPSubnetCalc . hexarize ( ipAddress: ipv4Address, dotted: dotted) ! )
188213 }
189214
190215 /**
@@ -196,14 +221,22 @@ class IPSubnetCalc: NSObject {
196221 a digital IP address in UInt32 format
197222
198223 */
199- static func digitize( ipAddress: String ) -> UInt32 {
224+ static func digitize( ipAddress: String ) -> UInt32 ? {
200225 var ipAddressNum : UInt32 = 0
201226 var ipDigits = [ String] ( )
227+ //var ipDigit: Unit32
202228
203229 ipDigits = ipAddress. components ( separatedBy: " . " )
204-
230+ if ipDigits. count != 4 {
231+ return nil
232+ }
205233 for index in 0 ... 3 {
206- ipAddressNum += UInt32 ( ipDigits [ index] ) ! << ( 32 - 8 * ( index + 1 ) )
234+ if let ipDigit = UInt32 ( ipDigits [ index] ) {
235+ ipAddressNum += ipDigit << ( 32 - 8 * ( index + 1 ) )
236+ }
237+ else {
238+ return nil
239+ }
207240 }
208241 return ( ipAddressNum & Constants . addr32Full)
209242 }
@@ -229,8 +262,11 @@ class IPSubnetCalc: NSObject {
229262 a digital subnet mask in UInt32 format
230263
231264 */
232- static func digitize( maskbits: Int ) -> UInt32 {
233- return ( ( Constants . addr32Full << ( 32 - maskbits) ) & Constants . addr32Full)
265+ static func digitize( maskbits: Int ) -> UInt32 ? {
266+ if ( maskbits <= Constants . NETWORK_BITS_MAX && maskbits >= Constants . NETWORK_BITS_MIN_CLASSLESS) {
267+ return ( ( Constants . addr32Full << ( 32 - maskbits) ) & Constants . addr32Full)
268+ }
269+ return nil
234270 }
235271
236272 /**
@@ -260,11 +296,10 @@ class IPSubnetCalc: NSObject {
260296 - mask: Optionnal subnet mask
261297 - classless: enable class less checks of the given IP address/mask
262298
263- - Returns:
264- Boolean if the given IP address is valid or not
299+ - Throws: an invalid IP or invalid mask error with a message explaining the reason
265300
266301 */
267- static func isValidIP ( ipAddress: String , mask: String ? , classless: Bool = false ) -> Bool {
302+ static func validateIPv4 ( ipAddress: String , mask: String ? , classless: Bool = false ) throws {
268303 var ip4Digits = [ String] ( )
269304
270305 ip4Digits = ipAddress. components ( separatedBy: " . " )
@@ -273,41 +308,47 @@ class IPSubnetCalc: NSObject {
273308 if let digit = Int ( item, radix: 10 ) {
274309 if ( digit > 255 ) {
275310 print ( " bad IPv4 digit \( digit) " )
276- return false
311+ throw SubnetCalcError . invalidIPv4 ( " IPv4 digit \( digit) is greater than 255 " )
312+ //return false
277313 }
278314 }
279315 else {
280316 print ( " not digit: \( item) " )
281- return false
317+ throw SubnetCalcError . invalidIPv4 ( " not digit: \( item) " )
318+ //return false
282319 }
283320 }
284321 }
285322 else {
286323 print ( " bad IPv4 format \( ip4Digits) " )
287- return false
324+ throw SubnetCalcError . invalidIPv4 ( " \( ipAddress) too short or too long " )
325+ //return false
288326 }
289327 if mask != nil {
290328 if let maskNum = Int ( mask!) {
291329 if ( classless == true ) {
292330 if ( maskNum < Constants . NETWORK_BITS_MIN_CLASSLESS || maskNum > Constants . NETWORK_BITS_MAX) {
293331 print ( " IPv4 classless mask \( maskNum) invalid " )
294- return false
332+ throw SubnetCalcError . invalidIPv4Mask ( " IPv4 classless mask \( maskNum) should be between \( Constants . NETWORK_BITS_MIN_CLASSLESS) and \( Constants . NETWORK_BITS_MAX) " )
333+ //return false
295334 }
296335 }
297336 else if ( maskNum < Constants . NETWORK_BITS_MIN || maskNum > Constants . NETWORK_BITS_MAX) {
298337 print ( " IPv4 mask \( maskNum) invalid " )
299- return false
338+ throw SubnetCalcError . invalidIPv4Mask ( " IPv4 mask \( maskNum) should be between \( Constants . NETWORK_BITS_MIN) and \( Constants . NETWORK_BITS_MAX) " )
339+ //return false
300340 }
301341 }
302342 else {
303343 print ( " IPv4 mask \( mask!) is not digit " )
304- return false
344+ throw SubnetCalcError . invalidIPv4Mask ( " IPv4 mask \( mask!) is not a digit " )
345+ //return false
305346 }
306347 }
307348 else {
308349 //print("null mask")
309350 }
310- return true
351+ // return true
311352 }
312353
313354 /**
@@ -319,8 +360,8 @@ class IPSubnetCalc: NSObject {
319360 */
320361 func subnetId( ) -> String {
321362 var subnetId : UInt32 = 0
322- let ipBits = IPSubnetCalc . digitize ( ipAddress: self . ipv4Address)
323- let maskBits = IPSubnetCalc . digitize ( maskbits: self . maskBits)
363+ let ipBits = IPSubnetCalc . digitize ( ipAddress: self . ipv4Address) !
364+ let maskBits = IPSubnetCalc . digitize ( maskbits: self . maskBits) !
324365
325366 subnetId = ipBits & maskBits
326367 return ( IPSubnetCalc . dottedDecimal ( ipAddress: subnetId) )
@@ -335,8 +376,8 @@ class IPSubnetCalc: NSObject {
335376 */
336377 func subnetBroadcast( ) -> String {
337378 var broadcast : UInt32 = 0
338- let ipBits = IPSubnetCalc . digitize ( ipAddress: self . ipv4Address)
339- let maskBits = IPSubnetCalc . digitize ( maskbits: self . maskBits)
379+ let ipBits = IPSubnetCalc . digitize ( ipAddress: self . ipv4Address) !
380+ let maskBits = IPSubnetCalc . digitize ( maskbits: self . maskBits) !
340381
341382 broadcast = ipBits & maskBits | ( Constants . addr32Full >> self . maskBits)
342383 return ( IPSubnetCalc . dottedDecimal ( ipAddress: broadcast) )
@@ -447,12 +488,12 @@ class IPSubnetCalc: NSObject {
447488 var lastIP : UInt32 = 0
448489
449490 if ( maskBits == 31 || maskBits == 32 ) {
450- firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) )
451- lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) )
491+ firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) ) !
492+ lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) ) !
452493 }
453494 else {
454- firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) ) + 1
455- lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) ) - 1
495+ firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) ) ! + 1
496+ lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) ) ! - 1
456497 }
457498 range = IPSubnetCalc . dottedDecimal ( ipAddress: firstIP) + " - " + IPSubnetCalc. dottedDecimal ( ipAddress: lastIP)
458499 return ( range)
@@ -470,8 +511,8 @@ class IPSubnetCalc: NSObject {
470511 var firstIP : UInt32 = 0
471512 var lastIP : UInt32 = 0
472513
473- firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) )
474- lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) )
514+ firstIP = IPSubnetCalc . digitize ( ipAddress: subnetId ( ) ) !
515+ lastIP = IPSubnetCalc . digitize ( ipAddress: subnetBroadcast ( ) ) !
475516 range = IPSubnetCalc . dottedDecimal ( ipAddress: firstIP) + " - " + IPSubnetCalc. dottedDecimal ( ipAddress: lastIP)
476517 return ( range)
477518 }
@@ -485,8 +526,8 @@ class IPSubnetCalc: NSObject {
485526 Network Class conforming to RFC 790
486527
487528 */
488- static func netClass( ipAddress: String ) -> String {
489- let ipNum = IPSubnetCalc . digitize ( ipAddress: ipAddress)
529+ static func netClass( ipAddress: String ) -> String ? {
530+ if let ipNum = IPSubnetCalc . digitize ( ipAddress: ipAddress) {
490531 let addr1stByte = ( ipNum & Constants . maskClassA) >> 24
491532
492533 if ( addr1stByte < 127 ) {
@@ -502,6 +543,8 @@ class IPSubnetCalc: NSObject {
502543 return ( " D " )
503544 }
504545 return ( " E " )
546+ }
547+ return nil
505548 }
506549
507550 /**
@@ -512,7 +555,7 @@ class IPSubnetCalc: NSObject {
512555
513556 */
514557 func netClass( ) -> String {
515- return ( IPSubnetCalc . netClass ( ipAddress: ipv4Address) )
558+ return ( IPSubnetCalc . netClass ( ipAddress: ipv4Address) ! )
516559 }
517560
518561 /**
@@ -603,16 +646,18 @@ class IPSubnetCalc: NSObject {
603646 the number of bits for the given mask
604647
605648 */
606- static func maskBits( maskAddr: String ) -> Int {
649+ static func maskBits( maskAddr: String ) -> Int ? {
607650 var bits : Int = 0
608651
609- var mask : UInt32 = IPSubnetCalc . digitize ( ipAddress: maskAddr)
652+ if var mask: UInt32 = IPSubnetCalc . digitize ( ipAddress: maskAddr) {
610653 while ( mask != 0 ) {
611654 bits += 1
612655 mask <<= 1
613656 }
614657 //print("maskBits \(maskAddr) bits: \(bits)")
615658 return ( bits)
659+ }
660+ return nil
616661 }
617662
618663 /**
@@ -766,8 +811,8 @@ class IPSubnetCalc: NSObject {
766811 print ( " CIDR Network (Route) : " + self . subnetId ( ) )
767812 print ( " CIDR Net Notation : " + self . subnetId ( ) + " / " + String( self . maskBits) )
768813 print ( " CIDR Address Range : " + self . subnetCIDRRange ( ) )
769- print ( " IP number in binary : " + String( IPSubnetCalc . digitize ( ipAddress: self . ipv4Address) , radix: 2 ) )
770- print ( " Mask bin : " + String( IPSubnetCalc . digitize ( maskbits: self . maskBits) , radix: 2 ) )
814+ print ( " IP number in binary : " + String( IPSubnetCalc . digitize ( ipAddress: self . ipv4Address) ! , radix: 2 ) )
815+ print ( " Mask bin : " + String( IPSubnetCalc . digitize ( maskbits: self . maskBits) ! , radix: 2 ) )
771816 //print("Subnet ID bin : " + String(self.subnetId(), radix: 2))
772817 //print("Broadcast bin : " + String(self.subnetBroadcast(), radix: 2))
773818 }
@@ -856,7 +901,7 @@ class IPSubnetCalc: NSObject {
856901 static func convertIPv4toIPv6( ipAddress: String , _6to4: Bool = false ) -> String {
857902 var ipv6str = String ( )
858903
859- let addr = digitize ( ipAddress: ipAddress)
904+ if let addr = digitize ( ipAddress: ipAddress) {
860905 ipv6str. append ( String ( ( ( ( Constants . addr32Digit1 | Constants . addr32Digit2) & addr) >> 16 ) , radix: 16 ) )
861906 ipv6str. append ( " : " )
862907 ipv6str. append ( String ( ( ( Constants . addr32Digit3 | Constants . addr32Digit4) & addr) , radix: 16 ) )
@@ -865,6 +910,10 @@ class IPSubnetCalc: NSObject {
865910 return ( " 2002: " + ipv6str + " :0:0:0:0:0 " )
866911 }
867912 return ( " 0:0:0:0:0:ffff: " + ipv6str)
913+ }
914+ else {
915+ return " "
916+ }
868917 }
869918
870919 /**
@@ -1312,13 +1361,15 @@ class IPSubnetCalc: NSObject {
13121361
13131362 */
13141363 init ? ( ipAddress: String , maskbits: Int ) {
1315- if ( IPSubnetCalc . isValidIP ( ipAddress: ipAddress, mask: String ( maskbits) , classless: true ) ) {
1364+ do {
1365+ try IPSubnetCalc . validateIPv4 ( ipAddress: ipAddress, mask: String ( maskbits) , classless: true )
13161366 self . ipv4Address = ipAddress
13171367 self . maskBits = maskbits
13181368 self . ipv6Address = IPSubnetCalc . convertIPv4toIPv6 ( ipAddress: ipAddress)
13191369 self . ipv6MaskBits = maskbits + Constants. defaultIPv6to4Mask
13201370 }
1321- else {
1371+ catch {
1372+ print ( " Init error: \( error) " )
13221373 return nil
13231374 }
13241375 }
@@ -1336,7 +1387,8 @@ class IPSubnetCalc: NSObject {
13361387 convenience init ? ( _ ipAddress: String ) {
13371388 var classbit : Int
13381389
1339- if ( IPSubnetCalc . isValidIP ( ipAddress: ipAddress, mask: nil ) ) {
1390+ do {
1391+ try IPSubnetCalc . validateIPv4 ( ipAddress: ipAddress, mask: nil )
13401392 switch ( IPSubnetCalc . netClass ( ipAddress: ipAddress) ) {
13411393 case " A " :
13421394 classbit = Constants . classAbits
@@ -1349,7 +1401,8 @@ class IPSubnetCalc: NSObject {
13491401 }
13501402 self . init ( ipAddress: ipAddress, maskbits: classbit)
13511403 }
1352- else {
1404+ catch {
1405+ print ( " Init error: \( error) " )
13531406 return nil
13541407 }
13551408 }
0 commit comments