IP Calculator Final Version

Bob Sneidar bobsneidar at iotecdigital.com
Mon Jan 26 10:47:26 EST 2015


Hi all. 

Mike Doub has offered to include this in the MasterLibrary, so I went through and added what I think is fairly comprehensive error checking to make sure that bogus input values return a descriptive error message. If any of you feel so inclined, please try to make it fail using incorrect input values. Also make sure that it returns the correct values for correct input values. 

I have already done this but as you are well aware, developers can easily miss things others can see. 

Bob S



> Begin forwarded message:
> 
> function IPCalc theIPAddress, theSubnetMask
>    /* IPCalc yyy
>       Syntax:
>       IPCalc theIPAddress, [theSubnetMask]
>       Examples:
>       
>       Description:
>       Derive Internet values from either CIDR notation in the IPAddress
>       or a standard IP and subnet mask
>    
>       Input: 
>       .    theIPAddress -  the IP address in CIDR notation
>        or
>       .    theIPAddress - a standard IP address and
>      .     theSubNetMask - a standard subNetMask
>    
>       Returns an array of the following values:
>       .   bcastaddr
>       .   cidraddr
>       .   cidrdepth
>       .   firstaddr
>       .   ipaddress
>       .   lastaddr
>       .   subnetaddr
>       .   subnetmask
>       .   usablecount
>       Returns a string beginning with ERROR: if the parameters are out of range
>       Check that the returned value is an array to see if there was an error
>    
>    Source:
>        Bob Sneidar,  slylabs13 at icloud.com
>    IPCalc */
>    
>    set the itemdelimiter to "."
>    
>    -- check parameters
>    -- the IP address must be 4 octets of numbers
>    if the last char of theIPAddress is "." then
>       delete the last char of theIPAddress
>    end if 
>    
>    if the number of items of theIPAddress <>4 then
>       return "ERROR: The IP Address must contain 4 octets. (ipaddress = " & theIPAddress & ")"
>    end if
>    
>    -- initial setup
>    set the numberFormat to "00000000"
>    
>    -- detemine format
>    if theIPAddress contains "/" then
>       put offset("/", theIPAddress) into theCIDRDelim
>       put char theCIDRDelim +1 to -1 of theIPAddress into theCIDRDepth
>       
>       -- CIDR depth must be a number
>       if theCIDRDepth is not a number then
>          return "ERROR: The CIDR Depth must be a number between 1 and 30. " & \
>                "(CIDRDepth = " & theCIDRDepth & ")"
>       end if
>       
>       put charx("1", theCIDRDepth) & charx("0", 32-theCIDRDepth) into theBinSubnetMask
>       put baseconvert(char 1 to 8 of theBinSubnetMask, 2, 10) into item 1 of theSubnetMask
>       put baseconvert(char 9 to 16 of theBinSubnetMask, 2, 10) into item 2 of theSubnetMask
>       put baseconvert(char 17 to 24 of theBinSubnetMask, 2, 10) into item 3 of theSubnetMask
>       put baseconvert(char 25 to 32 of theBinSubnetMask, 2, 10) into item 4 of theSubnetMask
>       put char 1 to theCIDRDelim -1 of theIPAddress into theIPAddress
>    else
>       -- subnet mask octets must be 4 numbers between 0 and 255
>       -- and all octets after the first octet less than 255 must be 0
>       
>       if the last char of theSubnetMask is "." then
>          delete the last char of theSubnetMask
>       end if
>       
>       if the number of items of theSubnetMask <>4 then
>          return "ERROR: The Subnet Mask must contain 4 numbers between 0 and 255 " & \
>                "separated by periods. (subnetmask = " & theSubnetMask & ")"
>       end if
>       
>       put false into mustBeZero
>       repeat for each item theOctet in theSubnetMask
>          
>          if theOctet <0 or theOctet >255 then
>             return "Each octet in the subnet mask must be a number between 0 and 255. " & \
>                   "(subnetmask = " & theSubnetMask & ")"
>          end if
>          
>          if mustBeZero and theOctet >0 then
>             return "ERROR: All octets after an octet less than 255 must be 0. " & \
>                   "(subnetmask = " & theSubnetMask & ")"
>          end if
>          
>          if theOctet <255 then
>             put true into mustBeZero
>          end if
>       end repeat
>       
>       -- convert the subnet mask to binary
>       put 0 into whichOctet
>       repeat for each item theOctet in theSubnetMask
>          add 1 to whichOctet
>          
>          -- subnet mask must contain only 4 octets
>          if whichOctet >4 then
>             return "ERROR: The Subnet Mask must contain 4 numbers between 0 and 255 " & \
>                   "separated by periods. (subnetmask = " & theSubnetMask & ")"
>          end if
>          
>          put value(baseConvert(theOctet, 10, 2)) after theBinSubnetMask
>       end repeat
>       put offset("0", theBinSubnetMask) -1 into theCIDRDepth
>    end if
>    
>    -- CIDR depth must be between 1 and 30
>    if theCIDRDepth <1 or theCIDRDepth >30 then
>       return "ERROR: The CIDR Depth must be between 1 and 30. " & \
>             "(CIDRDepth = " & theCIDRDepth & ")"
>    end if
>    
>    -- All octets of the IP address must be between 0 and 255
>    repeat for each item theOctet in theIPAddress
>       if theOctet <0 or theOctet >255 then
>          return "ERROR: Each IP Address octet must be a number between 0 and 255. " & \
>                "(ipaddress = " & theIPAddress & ")"
>       end if
>    end repeat
>    
>    -- convert the ip address to binary
>    put 0 into whichOctet
>    repeat for each item theOctet in theIPAddress
>       add 1 to whichOctet
>       put baseConvert(theOctet, 10, 2) into theBinValue
>       add 0 to theBinValue
>       put theBinValue after theBinIPAddress
>    end repeat
>    
>    -- calculate the binary subnet address
>    put char 1 to theCIDRDepth of theBinIPAddress into theBinNetworkAddr
>    put char theCIDRDepth +1 to -1 of theBinIPAddress into theBinNodeAddr
>    put theBinNodeAddr into theBinSubnetNodeAddr
>    set the numberFormat to "0"
>    replace "1" with "0" in theBinSubnetNodeAddr
>    put theBinNetworkAddr & theBinSubnetNodeAddr into theBinSubnetAddr
>    
>    -- convert the binary subnet address to decimal
>    put baseconvert(char 1 to 8 of theBinSubnetAddr, 2, 10)  into item 1 of theSubnetAddr
>    put baseconvert(char 9 to 16 of theBinSubnetAddr, 2, 10)  into item 2 of theSubnetAddr
>    put baseconvert(char 17 to 24 of theBinSubnetAddr, 2, 10)  into item 3 of theSubnetAddr
>    put baseconvert(char 25 to 32 of theBinSubnetAddr, 2, 10)  into item 4 of theSubnetAddr
>    
>    -- calculate the first usable IP address
>    put theSubnetAddr into theFirstAddr
>    add 1 to item 4 of theFirstAddr
>    
>    -- calculate the binary broadcast address
>    put theBinNodeAddr into theBinBcastNodeAddr
>    replace "0" with "1" in theBinBcastNodeAddr
>    put theBinNetworkAddr & theBinBcastNodeAddr into theBinBcastAddr
>    
>    -- convert the binary broadcast address to decimal
>    put baseconvert(char 1 to 8 of theBinBcastAddr, 2, 10) into item 1 of theBcastAddr
>    put baseconvert(char 9 to 16 of theBinBcastAddr, 2, 10) into item 2 of theBcastAddr
>    put baseconvert(char 17 to 24 of theBinBcastAddr, 2, 10) into item 3 of theBcastAddr
>    put baseconvert(char 25 to 32 of theBinBcastAddr, 2, 10) into item 4 of theBcastAddr
>    
>    -- calculate the last usable IP address
>    put theBcastAddr into theLastAddr
>    subtract 1 from item 4 of theLastAddr
>    
>    -- calculate the number of usable addresses
>    -- put item 4 of theLastAddr - item 4 of theFirstAddr +1 into theAddrCount
>    put baseconvert(theBinBcastNodeAddr, 2, 10) -1 into theAddrCount
>    
>    -- calculate the CIDR notation
>    put theIPAddress & "/" & theCIDRDepth into theCIDRAddr
>    
>    -- create array
>    put theIPAddress into ipdata ["ipaddress"]
>    put theSubnetMask into ipdata ["subnetmask"]
>    put theSubnetAddr into ipdata ["subnetaddr"]
>    put theFirstAddr into ipdata ["firstaddr"]
>    put theBcastAddr into ipdata["bcastaddr"]
>    put theLastAddr into ipdata ["lastaddr"]
>    put theCIDRDepth into ipdata ["cidrdepth"]
>    put theAddrCount into ipdata ["usablecount"]
>    put theCIDRAddr into ipdata ["cidraddr"]
>    return ipdata
> end IPCalc





More information about the use-livecode mailing list