diff --git a/CS/IP.cs b/CS/IP.cs new file mode 100644 index 0000000..cc3cf56 --- /dev/null +++ b/CS/IP.cs @@ -0,0 +1,743 @@ +using System; +using System.Collections.Generic; +using System.Collections; +using System.Linq; +using System.Text; +using System.Runtime.Serialization; + +namespace Network +{ + + public static class Int32Extensions + { + public static Boolean[] ToBooleanArray(this Int32 i) + { + return Convert.ToString(i, 2 /*for binary*/).Select(s => s.Equals('1')).ToArray(); + } + } + + public static class BitArrayMath + { + /* + * Seriously? You can't use operators in extensions? + * http://stackoverflow.com/questions/172658/operator-overloading-with-c-sharp-extension-methods + * + * + * + */ + public static BitArray Add(this BitArray bi, int val) + { + return BitArrayMathControl(bi, val, Operation.Add); + } + + public static BitArray Subtract(this BitArray bi, int val) + { + return BitArrayMathControl(bi, val, Operation.Subtract); + } + private enum Operation { + Add, + Subtract + } + private static bool[] fullAdder(bool abit, bool bbit, bool cbit) + { + // bit 0 = sum bit + // bit 1 = carry bit + bool[] ret = new bool[2] { false, false }; + ret[0] = (abit ^ bbit) ^ cbit; + ret[1] = (abit & bbit) | (bbit & cbit) | (abit & cbit); + return ret; + } + + private static bool[] fullSubtractor(bool xbit, bool ybit, bool zbit) + { + bool[] ret = new bool[2] { false, false }; + ret[0] = xbit ^ ybit ^ zbit; + ret[1] = zbit & (xbit ^ ybit) | !xbit & ybit; + return ret; + } + private static BitArray BitArrayMathControl(BitArray bi, int val, BitArrayMath.Operation op) + { + bool[] bits = new bool[bi.Count]; + bool[] result = new bool[2] { false, false }; + bool[] valboolarr = new bool[bi.Count]; + bool[] tmpboolarr = val.ToBooleanArray(); + + for (int i = 0; i < tmpboolarr.Length; i++) + { + valboolarr[bi.Count - 1 - i] = tmpboolarr[tmpboolarr.Length - i - 1]; + } + + List valbits = new List(); + BitArray baval; + baval = new BitArray(valboolarr); + for (int i = bi.Count - 1; i >= 0; i--) + { + if (op == Operation.Add) + result = fullAdder(bi[i], baval[i], result[1]); + else if (op == Operation.Subtract) + result = fullSubtractor(bi[i], baval[i], result[1]); + bits[i] = result[0]; + } + return new BitArray(bits); + } + public static bool bitsEqual(this BitArray bi1, BitArray bi2) + { + bool[] b1arr = new bool[bi1.Count]; + bool[] b2arr = new bool[bi2.Count]; + bi1.CopyTo(b1arr, 0); + bi2.CopyTo(b2arr, 0); + return (b1arr.SequenceEqual(b2arr)) ? true : false; + } + + public static bool lessThan(this BitArray input, BitArray compare) + { + bool isequal; + isequal = input.bitsEqual(compare); + if (isequal) + return false; + if (BitArrayMath.BitArrayCompare(input, compare)) + return true; + else + return false; + + } + + public static bool greaterThan(this BitArray input, BitArray compare) + { + bool isequal; + isequal = input.bitsEqual(compare); + if (isequal) + return false; + if (BitArrayMath.BitArrayCompare(input, compare)) + return false; + else + return true; + } + + public static bool lessThanOrEqual(this BitArray input, BitArray compare) + { + bool isequal; + isequal = input.bitsEqual(compare); + if (isequal) + return true; + if (BitArrayMath.BitArrayCompare(input, compare)) + return true; + else + return false; + } + + public static bool greaterThanOrEqual(this BitArray input, BitArray compare) + { + bool isequal; + isequal = input.bitsEqual(compare); + if (isequal) + return true; + if (BitArrayMath.BitArrayCompare(input, compare)) + return false; + else + return true; + } + + private static bool BitArrayCompare(BitArray bi1, BitArray bi2) + { + //Idea from -> http://mailman.linuxchix.org/pipermail/courses/2002-November/001043.html + /* + * true if bi1 < bi2 + * false if bi1 > bi2 + */ + for (int i = 0; i < bi1.Count; i++) + { + if (bi1[i] == true && bi2[i] != true) + return false; + else if (bi1[i] != true && bi2[i] == true) + return true; + } + return false; + } + } + +} + +namespace Network +{ + + public class InvalidIPFormat : System.Exception + { + public InvalidIPFormat(string msg) : base(msg) + { + + } + protected InvalidIPFormat(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { } + } + + public class InvalidIP : System.Exception + { + public InvalidIP(string msg) + : base(msg) + { + + } + protected InvalidIP(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { } + } + + public class InvalidIPInput : System.Exception + { + public InvalidIPInput(string msg) + : base(msg) + { + + } + protected InvalidIPInput(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { } + } + + public class InvalidMask : System.Exception + { + public InvalidMask(string msg) + : base(msg) + { + + } + protected InvalidMask(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { } + } + + public class IPNotSet : System.Exception + { + public IPNotSet(string msg) + : base(msg) + { + + } + protected IPNotSet(SerializationInfo info, StreamingContext ctxt) + : base(info, ctxt) + { } + } + +} + +namespace Network +{ + /* + * http://en.wikipedia.org/wiki/Logic_gate + * http://en.wikibooks.org/wiki/Practical_Electronics/Adders + * Algorithm: + * + * + * full adder(abit, bbit, carrybit) returns sumbit and carrybit: + * sumbit = ( abit XOR bbit ) XOR carrybit + * carrybit = ( abit & bbit ) | ( bbit & carrybit ) | ( abit & carrybit) + * + * create bit array consisting of cidrbits - 32 set to zero + * onarray = (numberofbits in rightarray - 1 set to zero) + one bit set to 1 + * carrybit = 0 + * sumarray = rightbitarray + * + * + * while( rightbitarray =! finalip ) + * if carrybit = 1 + * break + * else + * ipaddr = cidrbitarry + sumarray + * convert each 8 bits of ipaddr to oct1, oct2, oct3, oct4 + * print oct1 . oct2 . oct3 . oct4 + * + * for i = 0 to rightbitarray.length + * abit = rightbitarray[0] + * bbit = onearray[0] + * sumbit, carrybit = full_adder(abit, bbit, carrybit) + * shift onrarray to the right by one - http://stackoverflow.com/questions/3684002/bitarray-shift-bits/7696793#7696793 + * shift rightbitarray to the right by one + * sumarray += sumbit + * + * + * + */ + public class IP + { + private BitArray cidr; + private BitArray ipaddr; + private int iptype; + + public IP(string ipaddr) + { + if (this.setIPv4(ipaddr)) + return; + else if (this.setIPv6(ipaddr)) + return; + else + throw new Network.InvalidIPFormat("The input " + ipaddr + " was not a valid IP address in the proper format"); + } + + private bool setIPv4(string ipaddr) + { + List iparr; + List ipcidrarr; + + //int cidr; + if (ipaddr.Contains(":")) + return false; + if (ipaddr.Contains("/")) + { + ipcidrarr = ipaddr.Split('/').ToList(); + if (!this.isValidIPv4(ipcidrarr[0])) + throw new InvalidIP("The input " + ipaddr + " was not a valid IPv4" + " address in the proper format"); + iparr = ipcidrarr[0].Split('.').ToList(); + + this.cidr = this.getCIDR(Int32.Parse(ipcidrarr[1]), 32); + } + else + { + if (!this.isValidIPv4(ipaddr)) + throw new InvalidIP("The input " + ipaddr + " was not a valid IPv4" + " address in the proper format"); + iparr = ipaddr.Split('.').ToList(); + } + if (iparr.Count != 4) + { + throw new Exception("Not enough octects"); + } + else + { + this.ipaddr = this.IPv4ToBin(iparr); + } + this.iptype = 4; + return true; + } + + private BitArray IPv4ToBin(List iparr) + { + List octarr; + octarr = this.toBinary(Convert.ToInt32(iparr[0]), 8); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[1]), 8)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[2]), 8)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[3]), 8)); + //octarr.Reverse(); + return new BitArray(octarr.ToArray()); + } + + private BitArray IPv6ToBin(List iparr) + { + List octarr; + octarr = this.toBinary(Convert.ToInt32(iparr[0], 16), 16); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[1], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[2], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[3], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[4], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[5], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[6], 16), 16)); + octarr.AddRange(this.toBinary(Convert.ToInt32(iparr[8], 16), 16)); + //octarr.Reverse(); + return new BitArray(octarr.ToArray()); + } + + private List toBinary(int oct, int pad) + { + string binary = ""; + List biarr = new List(); + binary = Convert.ToString(oct, 2); + binary = binary.PadLeft(pad, '0'); + foreach (char digit in binary) + { + switch (digit) + { + case '0': + biarr.Add(false); + break; + case '1': + biarr.Add(true); + break; + } + } + return biarr; + } + + private BitArray getCIDR(int cidr, int numofbits) + { + List cidrbits = new List(); + for (int i = 0; i < cidr; i++) + { + cidrbits.Add(true); + } + if (cidrbits.Count < numofbits) + { + for (int i = 0; i < numofbits - cidr; i++) + { + cidrbits.Add(false); + } + } + return new BitArray(cidrbits.ToArray()); + } + + private bool setIPv6(string ipaddr) + { + List ipv6 = new List(); + List ipv6arr = new List(); + List newipaddr = new List(); + if (ipaddr.Contains("/")) + { + ipv6 = ipaddr.Split('/').ToList(); + this.cidr = this.getCIDR(Int32.Parse(ipv6[1]), 128); + ipv6arr = ipv6[0].Split(':').ToList() ; + } + else + { + ipv6arr = ipaddr.Split(':').ToList(); + } + newipaddr = this.fillIPv6Address(String.Join(":", ipv6arr.ToArray())); + if (!this.isValidIPv6(String.Join(":", newipaddr.ToArray()))) + throw new InvalidIP("The input " + ipaddr + " was not a valid IPv" + 6 + " address in the proper format"); + this.ipaddr = this.IPv6ToBin(newipaddr); + this.iptype = 6; + return true; + } + + private List IPv6ToDec(List ipaddr) + { + List octs = new List(); + foreach(string oct in ipaddr) + { + octs.Add(Convert.ToInt32(oct, 16)); + } + return octs; + } + + private bool isValidIPv4(string ipaddr) + { + List iparr; + int oct1, oct2, oct3, oct4; + try + { + iparr = ipaddr.Split('.').ToList(); + oct1 = int.Parse(iparr[0]); + oct2 = int.Parse(iparr[1]); + oct3 = int.Parse(iparr[2]); + oct4 = int.Parse(iparr[3]); + } + catch (Exception e) + { + throw new Exception("There was a problem converting the octects to ints", e); + } + if (oct1 <= 0 && oct1 >= 255) + return false; + if (oct2 <= 0 && oct2 >= 255) + return false; + if (oct3 <= 0 && oct3 >= 255) + return false; + if (oct4 <= 0 && oct4 >= 255) + return false; + return true; + } + + private bool isValidIPv6(string ipaddr) + { + List iparr; + int oct1, oct2, oct3, oct4, oct5, oct6, oct7, oct8; + try + { + iparr = ipaddr.Split(':').ToList(); + oct1 = Convert.ToInt32(iparr[0], 16); + oct2 = Convert.ToInt32(iparr[1], 16); + oct3 = Convert.ToInt32(iparr[2], 16); + oct4 = Convert.ToInt32(iparr[3], 16); + oct5 = Convert.ToInt32(iparr[4], 16); + oct6 = Convert.ToInt32(iparr[5], 16); + oct7 = Convert.ToInt32(iparr[6], 16); + oct8 = Convert.ToInt32(iparr[7], 16); + } + catch (Exception e) + { + throw new Exception("There was a problem converting the octects to ints", e); + } + if (oct1 <= 0 && oct1 >= 0xFFFF) + return false; + if (oct2 <= 0 && oct2 >= 0xFFFF) + return false; + if (oct3 <= 0 && oct3 >= 0xFFFF) + return false; + if (oct4 <= 0 && oct4 >= 0xFFFF) + return false; + if (oct5 <= 0 && oct5 >= 0xFFFF) + return false; + if (oct6 <= 0 && oct6 >= 0xFFFF) + return false; + if (oct7 <= 0 && oct7 >= 0xFFFF) + return false; + if (oct8 <= 0 && oct8 >= 0xFFFF) + return false; + return true; + } + + private List fillIPv6Address(string ipstr) + { + List sections = new List(); + List ipv6arr; + string tmpip; + int numofsections; + if (ipstr.Contains("::")) + { + ipv6arr = ipstr.Split(':').ToList(); + numofsections = 8 - (from x in ipv6arr where x != "" select x).ToList().Count(); + for (int i = 0; i <= numofsections; i++) + { + sections.Add("0000"); + } + tmpip = ipstr.Replace("::", ":" + String.Join(":", sections.ToArray()) + ":"); + return tmpip.Trim(':').Split(':').ToList(); + } + else + { + return ipstr.Split(':').ToList(); + } + } + + private ArrayList getIPv6SubnetMask(int cidr) + { + if (this.iptype == 6) + { + List bits = new List(); + for (int i = 0; i <= cidr; i++) + { + bits.Add(true); + } + for (int i = 0; i <= 128 - cidr; i++) + { + bits.Add(false); + } + return new ArrayList(bits.ToArray()); + } + else + { + return new ArrayList(); + } + } + + public string getIPv4SubnetMask() + { + if (this.iptype == 4) + return this.calcIPv4Address(this.cidr); + else + return ""; + } + + public string getIPv4Address() + { + + return this.calcIPv4Address(this.ipaddr); + + } + + private string calcIPv4Address(BitArray ip) + { + bool[] bits = new bool[32]; + ip.CopyTo(bits, 0); + List oct = new List(bits); + int oct1, oct2, oct3, oct4; + oct1 = this.bitsToDec(oct.GetRange(0, 8)); + oct2 = this.bitsToDec(oct.GetRange(8, 8)); + oct3 = this.bitsToDec(oct.GetRange(16, 8)); + oct4 = this.bitsToDec(oct.GetRange(24, 8)); + return String.Format("{0}.{1}.{2}.{3}", + oct1, + oct2, + oct3, + oct4); + } + + private string calcIPv6Address(BitArray ip) + { + bool[] bits = new bool[128]; + ip.CopyTo(bits, 0); + List oct = new List(bits); + string oct1, oct2, oct3, oct4, oct5, oct6, oct7, oct8; + oct1 = this.bitsToHex(oct.GetRange(0, 16)); + oct2 = this.bitsToHex(oct.GetRange(16, 16)); + oct3 = this.bitsToHex(oct.GetRange(32, 16)); + oct4 = this.bitsToHex(oct.GetRange(48, 16)); + oct5 = this.bitsToHex(oct.GetRange(64, 16)); + oct6 = this.bitsToHex(oct.GetRange(80, 16)); + oct7 = this.bitsToHex(oct.GetRange(96, 16)); + oct8 = this.bitsToHex(oct.GetRange(112, 16)); + return String.Format("{0}:{1}:{2}:{3}:{4}:{5}:{6}:{7}", + oct1, + oct2, + oct3, + oct4, + oct5, + oct6, + oct7, + oct8); + } + + private int bitsToDec(List bits) + { + string bitstr = String.Join("", bits.ToArray()); + bitstr = bitstr.Replace("False", "0"); + bitstr = bitstr.Replace("True", "1"); + return Convert.ToInt32(bitstr, 2); + } + + private string bitsToHex(List bits) + { + string bitstr = String.Join("", bits.ToArray()); + bitstr = bitstr.Replace("False", "0"); + bitstr = bitstr.Replace("True", "1"); + return Convert.ToInt32(bitstr, 2).ToString("X"); + } + + private BitArray calcIPv4FirstAddress() + { + // formula => ( ip & cidr ) + 1 + return (this.ipaddr.And(this.cidr).Add(1)); + } + + public string getIPv4FirstAddress() + { + return this.calcIPv4Address(this.calcIPv4FirstAddress()); + } + + public string getIPv4LastAddress() + { + return this.calcIPv4Address(this.calcIPv4LastAddress()); + } + + private BitArray calcIPv4LastAddress() + { + //formula => ( ip | ~cidr ) - 1 + BitArray tmp; + // Not alters the variable itself so we have to NOT it here, + // perform calculations, then NOT it later to reset the bits + this.cidr.Not(); + tmp = this.ipaddr.Or(this.cidr); + tmp = tmp.Subtract(1); + this.cidr.Not(); + return tmp; + } + + public string getIPv4NetworkAddress() + { + return this.calcIPv4Address(this.calcIPv4NetworkAddress()); + } + + private BitArray calcIPv4NetworkAddress() + { + //formula => ip & cidr + return this.ipaddr.And(this.cidr); + } + + private BitArray calcIPv4BroadcastAddress() + { + BitArray tmp; + this.cidr.Not(); + tmp = this.ipaddr.Or(this.cidr); + this.cidr.Not(); + return tmp; + } + + public string getIPv4BroadcastAddress() + { + return this.calcIPv4Address(this.calcIPv4BroadcastAddress()); + } + + public List getIPv4Range() + { + List ipaddrs = new List(); + BitArray currip = this.calcIPv4FirstAddress(); + BitArray lastip = this.calcIPv4LastAddress(); + while (!currip.bitsEqual(lastip)) + { + ipaddrs.Add(this.calcIPv4Address(currip)); + currip = currip.Add(1); + } + ipaddrs.Add(this.calcIPv4Address(currip) ); + return ipaddrs; + } + + public string getIPv6Address() + { + return this.calcIPv6Address(this.ipaddr); + } + + private BitArray calcIPv6FirstAddress() + { + return this.ipaddr.And(this.cidr).Add(1); + } + + public string getIPv6FirstAddress() + { + return this.calcIPv6Address(this.calcIPv6FirstAddress()); + } + + private BitArray cacIPv6LastAddress() + { + BitArray tmp; + this.cidr.Not(); + tmp = this.ipaddr.Or(this.cidr); + tmp = tmp.Subtract(1); + this.cidr.Not(); + return tmp; + } + + public string getIPv6LastAddress() + { + return this.calcIPv6Address(this.cacIPv6LastAddress()); + } + + public bool isIPv4AddressinRange(string ip) + { + if (ip.Contains(".") && this.isValidIPv4(ip)) + { + BitArray inputip = this.IPv4ToBin(ip.Split('.').ToList()); + BitArray firstip = this.calcIPv4FirstAddress(); + BitArray lastip = this.calcIPv4LastAddress(); + if (inputip.greaterThanOrEqual(firstip) && inputip.lessThanOrEqual(lastip)) + return true; + else + return false; + } + else + { + return false; + } + } + + public List getIPv6Range() + { + List ipaddrs = new List(); + BitArray currip = this.calcIPv6FirstAddress(); + BitArray lastip = this.cacIPv6LastAddress(); + + while (!currip.bitsEqual(lastip)) + { + ipaddrs.Add(this.calcIPv6Address(currip)); + currip = currip.Add(1); + } + ipaddrs.Add(this.calcIPv6Address(currip)); + return ipaddrs; + + } + + public bool isIPv6AddressinRange(string ip) + { + if (ip.Contains(":") && this.isValidIPv6(ip)) + { + BitArray inputip = this.IPv6ToBin(ip.Split(':').ToList(); + BitArray firstip = this.calcIPv6FirstAddress(); + BitArray lastip = this.cacIPv6LastAddress(); + if (inputip.greaterThanOrEqual(firstip) && inputip.lessThanOrEqual(lastip)) + return true; + else + return false; + } + else + { + return false; + } + } + } +} diff --git a/CS/documentation.txt b/CS/documentation.txt new file mode 100644 index 0000000..fc2a7ca --- /dev/null +++ b/CS/documentation.txt @@ -0,0 +1,137 @@ +Documentation for oneIP +================================= + +********************* +By Nathan Adams +License: Apache License 2.0 + +Languages: Python (others soon) +********************* + +Description: +oneIP was created to be a general purpose IP library. I felt that the libraries out there today lacked certain features or didn't work at all! +Especially since that most IP libraries are written in a single language and you have to hunt around if you are using a different language. +This project was created to address the need for one library in different languages. +It's goal was to create a very simple library while being verstiatle. + +Examples: +********************* + +Python: + +=================== +ipobj = IP("192.168.128.0/25") +print ipobj.getIPv4Range() +=================== + +=================== +ipobj = IP("2620:0:860:2::/64") +print ipobj.isIPv6AddressinRange("2621:0:860:2::1") +=================== + +C#: + +=================== +IP range = new IP("192.168.128.0/25"); +foreach (string ip in range.getIPv4Range()) +{ + Console.WriteLine(ip); +} +=================== + +Public Methods: +********************* + +getIPv4SubnetMask: +Return value: string +----------------------- +This function returns a string represtation of the subnet mask (ie "255.255.255.0") + +getIPv4NetworkAddress: +Return value: string +----------------------- +This function returns a string represtation of the network address (ie "192.168.128.1") + +getIPv4BroadcastAddress: +Return value: string +----------------------- +This function returns a string represtation of the network address (ie "192.168.128.255") + +getIPv4FirstAddress: +Return value: string +----------------------- +Given a CIDR and IP address this function will return the string represtation of the first address in that network (ie "192.168.128.1") + +getIPv4LastAddress: +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie "192.168.128.254") + +getIPv4Range: +Return value: array/list +----------------------- +Returns an array/list of all possible addresses from a given ip address in cidr notation + +@static method +toIPv4Notation +Input value: number +Return value: string +----------------------- +Given a decimal repesentation of an IP address, returns the string repesentation of it + +@static method +toIPv4Notation +Input value: number +Return value: array/list +geIPv4Octects +----------------------- +Given a decimal repesentation of an IP address, returns an array/list of octects + +getOct +Input value: number +Return value: number +----------------------- +This function allows you to input a numeric value to get the specific octect of the IP address you have set (ie octect 1 of 192.168.128.10 is 10) + +getIPv6FirstAddress +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie give "2620:0:860:2::/64" + it will return this "2620:0:860:2:0:0:0") + +getIPv6LastAddress +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie give "2620:0:860:2::/64" + it will return this "2620:0:860:2:FFFF:FFFF:FFFF") + +* DANGER DANGER DANGER * +getIPv6Range +Return value: array/list +* DANGER DANGER DANGER * +----------------------- +Returns an array/list of all possible addresses from a given IP address in cidr notation +Here's the deal: IPv6 networks can be HUGE and if you call this function it will NOT page the results. If you are willing to wait and have the memory to store +over 1000 strings, then by all means use it. Though, you may just want to call isIPv6AddressinRange because that will NOT create a list, it just compares the +first/last address in numeric format. + +isIPv6AddressinRange +Input value: string +Return value: True/False (language independent) +----------------------- +It will return True/False depending on if the given IP is in that range + +isIPv4AddressinRange +Input value: string +Return value: True/False (language independent) +----------------------- +It will return True/False depending on if the given IP is in that range + + +Excpetions: + +InvalidIPFormat +InvalidIP +InvalidIPInput +InvalidMask +IPNotSet \ No newline at end of file diff --git a/Python/BitArray.py b/Python/BitArray.py new file mode 100644 index 0000000..be45ba7 --- /dev/null +++ b/Python/BitArray.py @@ -0,0 +1,248 @@ +# BitArray by Nathan Adams + +import operator + +class BitArray: + #I couldn't get BitArray from the Python site to compile + #so I don't want other people tearing their hair out trying to do the same + #let us create our own + class BitArrayBooleanOperations: + AND = 0 + OR = 1 + XOR = 2 + class BitArrayMathOperations: + ADD = 0 + SUBTRACT = 1 + __barray = [] + LITTLE_ENDIAN = 0 + BIG_ENDIAN = 1 + __endian = None + def __init__(self, size=0, bitarray=None, endian=LITTLE_ENDIAN): + self.__endian = endian + if bitarray == None: + self.__barray = [False for i in self._lrange(0, size)] + elif type(bitarray) == type([]): + self.__barray = bitarray[:] + elif type(bitarray) == type(BitArray()): + if bitarray.size() < size: + self.__barray = [False for i in self._lrange(0, size - bitarray.size())] + bitarray.getRawArray()[:] + else: + self.__barray = bitarray.getRawArray()[:] + + def __strEndian(self, end): + if end == 0: + print "Little Endian" + elif end == 1: + print "Big Endian" + + def _lrange(self, num1, num2 = None, step = 1): + op = operator.__lt__ + + if num2 is None: + num1, num2 = 0, num1 + if num2 < num1: + if step > 0: + num1 = num2 + op = operator.__gt__ + elif step < 0: + num1 = num2 + + while op(num1, num2): + yield num1 + num1 += step + + def __str__(self): + if self.__endian == 1: + return "".join([str(int(i)) for i in self.__barray]) + else: + return "".join([str(int(i)) for i in reversed(self.__barray)]) + + def __invert__(self): + retarr = [(not i) for i in self.__barray] + #print retarr + #retarr.reverse() + #print retarr + return BitArray(bitarray=retarr) + + def __len__(self): + return len(self.__barray) + + def size(self): + return self.__len__() + + def __and__(self, b2): + return self.__booloperation(b2, self.BitArrayBooleanOperations.AND) + + def __booloperation(self, b2, operation): + if type(b2) == type(BitArray()): + if self.__endian != b2.getEndian(): + print "WARNING: Endians do not match - are you sure this is what you want?" + if self.size() == b2.size(): + if operation == self.BitArrayBooleanOperations.AND: + return self._and(self, b2) + elif operation == self.BitArrayBooleanOperations.OR: + return self._or(self, b2) + elif operation == self.BitArrayBooleanOperations.XOR: + return self._xor(self, b2) + elif self.size() > b2.size(): + if operation == self.BitArrayBooleanOperations.AND: + return self._and(self, BitArray(size=self.size(),bitarray=b2,endian=b2.getEndian())) + elif operation == self.BitArrayBooleanOperations.OR: + return self._or(self, BitArray(size=self.size(),bitarray=b2,endian=b2.getEndian())) + elif operation == self.BitArrayBooleanOperations.XOR: + return self._xor(self, BitArray(size=self.size(),bitarray=b2,endian=b2.getEndian())) + else: + if operation == self.BitArrayBooleanOperations.AND: + return self._and(BitArray(size=b2.size(),bitarray=self,endian=self.getEndian()),b2) + elif operation == self.BitArrayBooleanOperations.OR: + return self._or(BitArray(size=b2.size(),bitarray=self,endian=self.getEndian()),b2) + elif operation == self.BitArrayBooleanOperations.XOR: + return self._xor(BitArray(size=b2.size(),bitarray=self,endian=self.getEndian()),b2) + else: + return None + + def __xor__(self, b2): + return self.__booloperation(b2, self.BitArrayBooleanOperations.XOR) + + def _xor(self, ba1, ba2): + return BitArray(bitarray=[ba1[i] ^ ba2[i] for i in self._lrange(0, len(ba1))]) + + def __or__(self, b2): + return self.__booloperation(b2, self.BitArrayBooleanOperations.OR) + + def _or(self, ba1, ba2): + return BitArray(bitarray=[ba1[i] | ba2[i] for i in self._lrange(0, len(ba1))]) + + def _and(self, ba1, ba2): + return BitArray(bitarray=[ba1[i] & ba2[i] for i in self._lrange(0, len(ba1))]) + + def getRawArray(self): + return self.__barray + + def __getitem__(self, index): + return self.__barray[index] + + def __getslice__(self, low, high): + return self.__barray[low:high] + + def __setitem__(self, index, value): + if type(value) == type(True): + if self.__endian == BitArray.LITTLE_ENDIAN: + self.__barray[(len(self)-index)-1] = value + elif self.__endian == BitArray.BIG_ENDIAN: + self.__barray[index] = value + + def getEndian(self): + return self.__endian + + def __eq__(self, b2): + if b2: + return self.__barray == b2.getRawArray() + else: + return False + + def __ne__(self, b2): + return not self.__eq__(b2) + + def __lt__(self, b2): + #Idea from -> http://mailman.linuxchix.org/pipermail/courses/2002-November/001043.html + # + # true if bi1 < bi2 + # false if bi1 > bi2 + # need to create resizing function + #if self != b2 + if self == b2: + return False + if self.__BitArrayCompare(b2): + return False + else: + return True + + def __gt__(self, b2): + if self == b2: + return False + return not self.__lt__(b2) + + def __ge__(self, b2): + if self == b2: + return True + return self.__gt__(b2) + + def __le__(self, b2): + if self == b2: + return True + return self.__le__(b2) + + def __BitArrayMathControl(self, val, operation): + bits = [False for i in range(0, len(self))] + result = [False, False] + valboolarr = [False for i in range(0, len(self))] + + if self.__endian == 0: + tmpboolarr = [bool(int(i)) for i in bin(val)[2:].rjust(len(self), '0')] + elif self.__endian == 1: + tmpboolarr = [bool(int(i)) for i in bin(val)[2:].ljust(len(self), '0')] + + valbits = [] + bval = BitArray(bitarray=valboolarr) + + if self.__endian == 0: + for i in range(0, len(tmpboolarr)-1): + valboolarr[len(self) - 1 - i] = tmpboolarr[len(tmpboolarr) - i - 1] + elif self.__endian == 1: + for i in range(len(self)-1, 0, -1): + valboolarr[i] = tmpboolarr[i] + + for i in range(0, len(self)): + if operation == self.BitArrayMathOperations.ADD: + result = self.__fullAdder(self[i], valboolarr[i], result[1]) + elif operation == self.BitArrayMathOperations.SUBTRACT: + result = self.__fullSubtractor(self[i], valboolarr[i], result[1]) + bits[i] = result[0] + + if result[1]: # was there a carry over? return a resized array + bits.append(True) + if self.__endian == self.BIG_ENDIAN: + bits.reverse() + return BitArray(bitarray=bits) + + def __fullAdder(self, abit, bbit, cbit): + ret = [False, False] + ret[0] = (abit ^ bbit) ^ cbit + ret[1] = (abit & bbit) | (bbit & cbit) | (abit & cbit) + return ret + + def __fullSubtractor(self, abit, bbit, cbit): + ret = [False, False] + ret[0] = abit ^ bbit ^ cbit + ret[1] = cbit & (abit ^ bbit) | (not abit) & bbit + return ret + + def __add__(self, val): + return self.__BitArrayMathControl(val, BitArray.BitArrayMathOperations.ADD) + + def __sub__(self, val): + return self.__BitArrayMathControl(val, BitArray.BitArrayMathOperations.SUBTRACT) + + def __BitArrayCompare(self, b2): + # true if bi1 < bi2 + # false if bi1 > bi2 + if len(self) == len(b2): + if self.__endian != b2.getEndian(): + print "Endians do NOT match - is this what you want? Assuming Endian " + self.__strEndian(self.__endian) + if self.__endian == 0: + for i in range(len(self)-1, 0, -1): + if self[i] == True and b2[i] != True: + return False + if self[i] != True and b2[i] == False: + return True + return False + elif self.__endian == 1: + for i in range(0, len(self)): + if self[i] == True and b2[i] != True: + return False + if self[i] != True and b2[i] == False: + return True + return False + else: + raise Exception("Bitsize is not the same") diff --git a/Python/IP.py b/Python/IP.py new file mode 100644 index 0000000..c511f1d --- /dev/null +++ b/Python/IP.py @@ -0,0 +1,314 @@ +from BitArray import BitArray + +class InvalidIPFormat(Exception): + def __init__(self, value): + self.val = value + def __str__(self): + return "The input " + str(self.val) + " was not a valid IP address in the proper format" + +class InvalidIP(Exception): + def __init__(self, value, type): + self.val = value + self.type = type + def __str__(self): + return "The input " + str(self.val) + " was not a valid IPv" + str(self.type) + " address in the proper format" + +class InvalidIPInput(Exception): + def __init__(self, value, einput): + self.val = value + self.einput = einput + def __str__(self): + return "The input " + str(self.val) + " was not an expected object - expected " + str(einput) + +class InvalidMask(Exception): + def __init__(self): + pass + def __str__(self): + return "The subnet mask has not been set" + +class IPNotSet(Exception): + def __init__(self): + pass + def __str__(self): + return "The IP address has not been set" + +class IP: + __cidr = None + __ipaddr = None + __type = None + def __init__(self, ipaddr): + if self.setIPv4(ipaddr): + return + elif self.setIPv6(ipaddr): + return + else: + raise InvalidIPFormat(ipaddr) + #print " + + def setIPv4(self, ip): + # IP format is in CIDR notiation - 192.168.128.0/16 + + iparr = [] + ipcidrarr = [] + cidr = None + if ":" in ip: + return False + if type(ip) != type(str()): + raise InvalidIPInput(ip, "string") + if "/" in ip: + ipcidrarr = ip.split("/") + if not self.__isValidIPv4(ipcidrarr[0]): + raise InvalidIP(ip, 4) + iparr = ipcidrarr[0].split(".") + self.__cidr = self.__getCIDR(int(ipcidrarr[1]), 32) + else: + if not self.isValidIPv4(ip): + raise InvalidIP(ip, 4) + iparr = ip.split(".") + if len(iparr) != 4: + raise Exception("Not enough octects") + + else: + self.__ipaddr = self.__IPv4ToBin(iparr) + self.__type = 4 + return True + + def setIPv6(self, ip): + if "/" in ip: + ipv6 = ip.split("/") + self.__cidr = self.__getCIDR(int(ipv6[1]), 128) + ipv6arr = ipv6[0].split(":") + else: + ipv6arr = ip.split(":") + newipaddr = self.__fillIPv6Address(":".join(ipv6arr)) + if not self.__isValidIPv6(":".join(newipaddr)): + raise InvalidIP(ip, 6) + self.__ipaddr = self.__IPv6ToBin(newipaddr) + self.__type = 6 + return True + + + def __IPv4ToBin(self, iparr): + octarr = [] + octarr = self.__toBinary(int(iparr[0]), 8) + octarr.extend(self.__toBinary(int(iparr[1]), 8)) + octarr.extend(self.__toBinary(int(iparr[2]), 8)) + octarr.extend(self.__toBinary(int(iparr[3]), 8)) + return BitArray(bitarray=octarr) + + def __IPv6ToBin(self, iparr): + octarr = [] + octarr = self.__toBinary(int(iparr[0], 16), 16) + octarr.extend(self.__toBinary(int(iparr[1], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[2], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[3], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[4], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[5], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[6], 16), 16)) + octarr.extend(self.__toBinary(int(iparr[7], 16), 16)) + return BitArray(bitarray=octarr) + + def __isValidIPv4(self, ipaddr): + try: + iparr = ipaddr.split(".") + oct1 = int(iparr[0]) + oct2 = int(iparr[1]) + oct3 = int(iparr[2]) + oct4 = int(iparr[3]) + except Exception, e: + raise Exception("There was a problem converting the octects to ints", e) + + if oct1 <= 0 and oct1 >= 255: + return False + if oct2 <= 0 and oct2 >= 255: + return False + if oct3 <= 0 and oct3 >= 255: + return False + if oct4 <= 0 and oct4 >= 255: + return False + return True + + def __isValidIPv6(self, ipaddr): + try: + iparr = ipaddr.split(":") + oct1 = int(iparr[0]) + oct2 = int(iparr[1]) + oct3 = int(iparr[2]) + oct4 = int(iparr[3]) + oct5 = int(iparr[4]) + oct6 = int(iparr[5]) + oct7 = int(iparr[6]) + oct8 = int(iparr[7]) + except Exception, e: + raise Exception("There was a problem converting the octects to ints", e) + + if oct1 <= 0 and oct1 >= 0xFFFF: + return False + if oct2 <= 0 and oct2 >= 0xFFFF: + return False + if oct3 <= 0 and oct3 >= 0xFFFF: + return False + if oct4 <= 0 and oct4 >= 0xFFFF: + return False + if oct5 <= 0 and oct5 >= 0xFFFF: + return False + if oct6 <= 0 and oct6 >= 0xFFFF: + return False + if oct7 <= 0 and oct7 >= 0xFFFF: + return False + if oct8 <= 0 and oct8 >= 0xFFFF: + return False + return True + + def __toBinary(self, oct, pad): + biarr = [] + binary = bin(oct)[2:] + binary = binary.rjust(pad, '0') + for c in binary: + if c == '0': + biarr.append(False) + elif c == '1': + biarr.append(True) + return biarr + + def __getCIDR(self, cidr, numofbits): + cidrbits = [] + for i in range(0, cidr): + cidrbits.append(True) + if len(cidrbits) < numofbits: + for i in range(0, numofbits - cidr): + cidrbits.append(False) + return BitArray(bitarray=cidrbits) + + def __fillIPv6Address(self, ipstr): + sections = [] + ipv6arr = [] + if "::" in ipstr: + ipv6arr = ipstr.split(":") + numofsections = 8 - len([x for x in ipv6arr if x != ""]) + for i in range(0, numofsections): + sections.append("0000") + tmpip = ipstr.replace("::", ":" + ":".join(sections) + ":") + return tmpip.strip(":").split(":") + else: + return ipstr.split(":") + + def __calcIPv4Address(self, bitarr): + oct1 = self.__bitsToDec(bitarr[0:8]) + oct2 = self.__bitsToDec(bitarr[8:16]) + oct3 = self.__bitsToDec(bitarr[16:24]) + oct4 = self.__bitsToDec(bitarr[24:32]) + return "%s.%s.%s.%s" % (oct1, oct2, oct3, oct4) + + def __calcIPv6Address(self, bitarr): + oct1 = self.__bitsToHex(bitarr[0:16]) + oct2 = self.__bitsToHex(bitarr[16:32]) + oct3 = self.__bitsToHex(bitarr[32:48]) + oct4 = self.__bitsToHex(bitarr[48:64]) + oct5 = self.__bitsToHex(bitarr[64:80]) + oct6 = self.__bitsToHex(bitarr[80:96]) + oct7 = self.__bitsToHex(bitarr[96:112]) + oct8 = self.__bitsToHex(bitarr[112:128]) + return "%s:%s:%s:%s:%s:%s:%s:%s" % (oct1, oct2, oct3, oct4, oct5, oct6, oct7, oct8) + + def __bitsToDec(self, bitarr): + bitstr = "".join([str(x) for x in bitarr]) + bitstr = bitstr.replace("True", "1") + bitstr = bitstr.replace("False", "0") + return int(bitstr, 2) + + def __bitsToHex(self, bitarr): + return hex(self.__bitsToDec(bitarr))[2:].upper() + + def getIPv4SubnetMask(self): + if self.__type == 4: + return self.__calcIPv4Address(self.__cidr) + else: + return "" + + def getIPv4Address(self): + return self.__calcIPv4Address(self.__ipaddr) + + def __calcIPv4FirstAddress(self): + # print str(self.__ipaddr) + return (self.__ipaddr & self.__cidr) + 1 + + def __calcIPv4LastAddress(self): + return (self.__ipaddr | ~self.__cidr) - 1 + + def __calcIPv4NetworkAddress(self): + return (self.__ipaddr & self.__cidr) + + def __calcIPv4BroadcastAddress(self): + return (self.__ipaddr | ~self.__cidr) + + def getIPv4FirstAddress(self): + return self.__calcIPv4Address(self.__calcIPv4FirstAddress()) + + def getIPv4LastAddress(self): + return self.__calcIPv4Address(self.__calcIPv4LastAddress()) + + def getIPv4NetworkAddress(self): + return self.__calcIPv4Address(self.__calcIPv4NetworkAddress()) + + def getIPv4BroadcastAddress(self): + return self.__calcIPv4Address(self.__calcIPv4BroadcastAddress()) + + def getIPv6Address(self): + return self.__calcIPv6Address(self.__ipaddr) + + def __calcIPv6FirstAddress(self): + return (self.__ipaddr & self.__cidr) + 1 + + def getIPv6FirstAddress(self): + return self.__calcIPv6Address(self.__calcIPv6FirstAddress()) + + def __calcIPv6LastAddress(self): + return (self.__ipaddr | ~self.__cidr) - 1 + + def getIPv6LastAddress(self): + return self.__calcIPv6Address(self.__calcIPv6LastAddress()) + + def isIPv4AddressinRange(self, ip): + if "." in ip and self.isValidIPv4(ip): + inputip = self.__IPv4ToBin(ip.split(".")) + firstip = self.__calcIPv4FirstAddress() + lastip = self.__calcIPv4LastAddress() + if inputip >= firstip and inputip <= lastip: + return True + else: + return False + else: + return False + + def getIPv6Range(self): + currip = self.__calcIPv6FirstAddress() + lastip = self.__calcIPv6LastAddress() + ipaddrs = [] + while(currip != lastip): + ipaddrs.append(self.__calcIPv6Address(currip)) + currip = currip + 1 + ipaddrs.append(self.__calcIPv6Address(currip)) + return ipaddrs + + def getIPv4Range(self): + currip = self.__calcIPv4FirstAddress() + lastip = self.__calcIPv4LastAddress() + ipaddrs = [] + while(currip != lastip): + ipaddrs.append(self.__calcIPv4Address(currip)) + currip = currip + 1 + ipaddrs.append(self.__calcIPv4Address(currip)) + return ipaddrs + + def isIPv6AddressinRange(self, ip): + if ":" in ip and self.__isValidIPv6(ip.split(":")): + inputip = self.__IPv6ToBin(ip) + firstip = self.__calcIPv6FirstAddress() + lastip = self.__calcIPv6LastAddress() + if inputip >= firstip and inputip <= lastip: + return True + else: + return False + else: + return False \ No newline at end of file diff --git a/Python/documentation.txt b/Python/documentation.txt new file mode 100644 index 0000000..fc2a7ca --- /dev/null +++ b/Python/documentation.txt @@ -0,0 +1,137 @@ +Documentation for oneIP +================================= + +********************* +By Nathan Adams +License: Apache License 2.0 + +Languages: Python (others soon) +********************* + +Description: +oneIP was created to be a general purpose IP library. I felt that the libraries out there today lacked certain features or didn't work at all! +Especially since that most IP libraries are written in a single language and you have to hunt around if you are using a different language. +This project was created to address the need for one library in different languages. +It's goal was to create a very simple library while being verstiatle. + +Examples: +********************* + +Python: + +=================== +ipobj = IP("192.168.128.0/25") +print ipobj.getIPv4Range() +=================== + +=================== +ipobj = IP("2620:0:860:2::/64") +print ipobj.isIPv6AddressinRange("2621:0:860:2::1") +=================== + +C#: + +=================== +IP range = new IP("192.168.128.0/25"); +foreach (string ip in range.getIPv4Range()) +{ + Console.WriteLine(ip); +} +=================== + +Public Methods: +********************* + +getIPv4SubnetMask: +Return value: string +----------------------- +This function returns a string represtation of the subnet mask (ie "255.255.255.0") + +getIPv4NetworkAddress: +Return value: string +----------------------- +This function returns a string represtation of the network address (ie "192.168.128.1") + +getIPv4BroadcastAddress: +Return value: string +----------------------- +This function returns a string represtation of the network address (ie "192.168.128.255") + +getIPv4FirstAddress: +Return value: string +----------------------- +Given a CIDR and IP address this function will return the string represtation of the first address in that network (ie "192.168.128.1") + +getIPv4LastAddress: +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie "192.168.128.254") + +getIPv4Range: +Return value: array/list +----------------------- +Returns an array/list of all possible addresses from a given ip address in cidr notation + +@static method +toIPv4Notation +Input value: number +Return value: string +----------------------- +Given a decimal repesentation of an IP address, returns the string repesentation of it + +@static method +toIPv4Notation +Input value: number +Return value: array/list +geIPv4Octects +----------------------- +Given a decimal repesentation of an IP address, returns an array/list of octects + +getOct +Input value: number +Return value: number +----------------------- +This function allows you to input a numeric value to get the specific octect of the IP address you have set (ie octect 1 of 192.168.128.10 is 10) + +getIPv6FirstAddress +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie give "2620:0:860:2::/64" + it will return this "2620:0:860:2:0:0:0") + +getIPv6LastAddress +Return value: string +----------------------- +Given an IP address in CIDR format this function will return the string represtation of the first address in that network (ie give "2620:0:860:2::/64" + it will return this "2620:0:860:2:FFFF:FFFF:FFFF") + +* DANGER DANGER DANGER * +getIPv6Range +Return value: array/list +* DANGER DANGER DANGER * +----------------------- +Returns an array/list of all possible addresses from a given IP address in cidr notation +Here's the deal: IPv6 networks can be HUGE and if you call this function it will NOT page the results. If you are willing to wait and have the memory to store +over 1000 strings, then by all means use it. Though, you may just want to call isIPv6AddressinRange because that will NOT create a list, it just compares the +first/last address in numeric format. + +isIPv6AddressinRange +Input value: string +Return value: True/False (language independent) +----------------------- +It will return True/False depending on if the given IP is in that range + +isIPv4AddressinRange +Input value: string +Return value: True/False (language independent) +----------------------- +It will return True/False depending on if the given IP is in that range + + +Excpetions: + +InvalidIPFormat +InvalidIP +InvalidIPInput +InvalidMask +IPNotSet \ No newline at end of file