Left: | ||
Right: |
OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # | 2 # |
3 # Copyright 2007 Google Inc. | 3 # Copyright 2007 Google Inc. |
4 # Licensed to PSF under a Contributor Agreement. | 4 # Licensed to PSF under a Contributor Agreement. |
5 # | 5 # |
6 # Licensed under the Apache License, Version 2.0 (the "License"); | 6 # Licensed under the Apache License, Version 2.0 (the "License"); |
7 # you may not use this file except in compliance with the License. | 7 # you may not use this file except in compliance with the License. |
8 # You may obtain a copy of the License at | 8 # You may obtain a copy of the License at |
9 # | 9 # |
10 # http://www.apache.org/licenses/LICENSE-2.0 | 10 # http://www.apache.org/licenses/LICENSE-2.0 |
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
832 def _get_networks_key(self): | 832 def _get_networks_key(self): |
833 """Network-only key function. | 833 """Network-only key function. |
834 | 834 |
835 Returns an object that identifies this address' network and | 835 Returns an object that identifies this address' network and |
836 netmask. This function is a suitable "key" argument for sorted() | 836 netmask. This function is a suitable "key" argument for sorted() |
837 and list.sort(). | 837 and list.sort(). |
838 | 838 |
839 """ | 839 """ |
840 return (self._version, self.network, self.netmask) | 840 return (self._version, self.network, self.netmask) |
841 | 841 |
842 def _ip_int_from_prefix(self, prefixlen=None): | 842 def _ip_int_from_prefix(self, prefixlen): |
843 """Turn the prefix length netmask into a int for comparison. | 843 """Turn the prefix length into a bitwise netmask. |
844 | 844 |
845 Args: | 845 Args: |
846 prefixlen: An integer, the prefix length. | 846 prefixlen: An integer, the prefix length. |
847 | 847 |
848 Returns: | 848 Returns: |
849 An integer. | 849 An integer. |
850 | 850 |
851 """ | 851 """ |
852 if not prefixlen and prefixlen != 0: | |
853 prefixlen = self._prefixlen | |
854 return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) | 852 return self._ALL_ONES ^ (self._ALL_ONES >> prefixlen) |
855 | 853 |
856 def _prefix_from_ip_int(self, ip_int, mask=32): | 854 def _prefix_from_ip_int(self, ip_int): |
857 """Return prefix length from the decimal netmask. | 855 """Return prefix length from a bitwise netmask. |
858 | 856 |
859 Args: | 857 Args: |
860 ip_int: An integer, the IP address. | 858 ip_int: An integer, the netmask in expanded bitwise format. |
861 mask: The netmask. Defaults to 32. | |
862 | 859 |
863 Returns: | 860 Returns: |
864 An integer, the prefix length. | 861 An integer, the prefix length. |
865 | 862 |
863 Raises: | |
864 NetmaskValueError: If the input is not a valid netmask. | |
865 | |
866 """ | 866 """ |
867 while mask: | 867 prefixlen = self._max_prefixlen |
868 if ip_int & 1 == 1: | 868 while prefixlen: |
869 if ip_int & 1: | |
869 break | 870 break |
870 ip_int >>= 1 | 871 ip_int >>= 1 |
871 mask -= 1 | 872 prefixlen -= 1 |
872 | 873 |
873 return mask | 874 if ip_int == (1 << prefixlen) - 1: |
875 return prefixlen | |
876 else: | |
877 raise NetmaskValueError('Bit pattern does not match 1*0*') | |
874 | 878 |
875 def _ip_string_from_prefix(self, prefixlen=None): | 879 def _prefix_from_prefix_string(self, prefixlen_str): |
876 """Turn a prefix length into a dotted decimal string. | 880 """Turn a prefix length string into an integer. |
877 | 881 |
878 Args: | 882 Args: |
879 prefixlen: An integer, the netmask prefix length. | 883 prefixlen_str: A decimal string containing the prefix length. |
880 | 884 |
881 Returns: | 885 Returns: |
882 A string, the dotted decimal netmask string. | 886 The prefix length as an integer. |
887 | |
888 Raises: | |
889 NetmaskValueError: If the input is malformed or out of range. | |
883 | 890 |
884 """ | 891 """ |
885 if not prefixlen: | 892 try: |
886 prefixlen = self._prefixlen | 893 if not _BaseV4._DECIMAL_DIGITS.issuperset(prefixlen_str): |
887 return self._string_from_ip_int(self._ip_int_from_prefix(prefixlen)) | 894 raise ValueError |
895 prefixlen = int(prefixlen_str) | |
896 if not (0 <= prefixlen <= self._max_prefixlen): | |
897 raise ValueError | |
898 except ValueError: | |
899 raise NetmaskValueError('%s is not a valid prefix length' % | |
900 prefixlen_str) | |
901 return prefixlen | |
902 | |
903 def _prefix_from_ip_string(self, ip_str): | |
904 """Turn a netmask/hostmask string into a prefix length. | |
905 | |
906 Args: | |
907 ip_str: A netmask or hostmask, formatted as an IP address. | |
908 | |
909 Returns: | |
910 The prefix length as an integer. | |
911 | |
912 Raises: | |
913 NetmaskValueError: If the input is not a netmask or hostmask. | |
914 | |
915 """ | |
916 # Parse the netmask/hostmask like an IP address. | |
917 try: | |
918 ip_int = self._ip_int_from_string(ip_str) | |
919 except AddressValueError: | |
920 raise NetmaskValueError('%s is not a valid netmask' % ip_str) | |
921 | |
922 # Try matching a netmask (1*0*). Note that the two ambiguous cases | |
Peter Moody
2013/09/20 21:33:45
(1*0*).
I'm having a hard time understanding wha
pmarks
2013/09/20 22:36:35
Clarified the regexp notation.
| |
923 # (all-ones and all-zeroes) are treated as netmasks. | |
924 try: | |
925 return self._prefix_from_ip_int(ip_int) | |
926 except NetmaskValueError: | |
927 pass | |
928 | |
929 # Invert the bits, and try matching a hostmask (0+1+) instead. | |
930 ip_int ^= self._ALL_ONES | |
931 try: | |
932 return self._prefix_from_ip_int(ip_int) | |
933 except NetmaskValueError: | |
934 raise NetmaskValueError('%s is not a valid netmask' % ip_str) | |
888 | 935 |
889 def iter_subnets(self, prefixlen_diff=1, new_prefix=None): | 936 def iter_subnets(self, prefixlen_diff=1, new_prefix=None): |
890 """The subnets which join to make the current subnet. | 937 """The subnets which join to make the current subnet. |
891 | 938 |
892 In the case that self contains only one IP | 939 In the case that self contains only one IP |
893 (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 | 940 (self._prefixlen == 32 for IPv4 or self._prefixlen == 128 |
894 for IPv6), return a list with just ourself. | 941 for IPv6), return a list with just ourself. |
895 | 942 |
896 Args: | 943 Args: |
897 prefixlen_diff: An integer, the amount the prefix length | 944 prefixlen_diff: An integer, the amount the prefix length |
(...skipping 22 matching lines...) Expand all Loading... | |
920 if new_prefix < self._prefixlen: | 967 if new_prefix < self._prefixlen: |
921 raise ValueError('new prefix must be longer') | 968 raise ValueError('new prefix must be longer') |
922 if prefixlen_diff != 1: | 969 if prefixlen_diff != 1: |
923 raise ValueError('cannot set prefixlen_diff and new_prefix') | 970 raise ValueError('cannot set prefixlen_diff and new_prefix') |
924 prefixlen_diff = new_prefix - self._prefixlen | 971 prefixlen_diff = new_prefix - self._prefixlen |
925 | 972 |
926 if prefixlen_diff < 0: | 973 if prefixlen_diff < 0: |
927 raise ValueError('prefix length diff must be > 0') | 974 raise ValueError('prefix length diff must be > 0') |
928 new_prefixlen = self._prefixlen + prefixlen_diff | 975 new_prefixlen = self._prefixlen + prefixlen_diff |
929 | 976 |
930 if not self._is_valid_netmask(str(new_prefixlen)): | 977 if new_prefixlen > self._max_prefixlen: |
931 raise ValueError( | 978 raise ValueError( |
932 'prefix length diff %d is invalid for netblock %s' % ( | 979 'prefix length diff %d is invalid for netblock %s' % ( |
933 new_prefixlen, str(self))) | 980 new_prefixlen, str(self))) |
934 | 981 |
935 first = IPNetwork('%s/%s' % (str(self.network), | 982 first = IPNetwork('%s/%s' % (str(self.network), |
936 str(self._prefixlen + prefixlen_diff)), | 983 str(self._prefixlen + prefixlen_diff)), |
937 version=self._version) | 984 version=self._version) |
938 | 985 |
939 yield first | 986 yield first |
940 current = first | 987 current = first |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1220 ._ip: 16909060 | 1267 ._ip: 16909060 |
1221 .ip: IPv4Address('1.2.3.4') | 1268 .ip: IPv4Address('1.2.3.4') |
1222 .network: IPv4Address('1.2.3.0') | 1269 .network: IPv4Address('1.2.3.0') |
1223 .hostmask: IPv4Address('0.0.0.31') | 1270 .hostmask: IPv4Address('0.0.0.31') |
1224 .broadcast: IPv4Address('1.2.3.31') | 1271 .broadcast: IPv4Address('1.2.3.31') |
1225 .netmask: IPv4Address('255.255.255.224') | 1272 .netmask: IPv4Address('255.255.255.224') |
1226 .prefixlen: 27 | 1273 .prefixlen: 27 |
1227 | 1274 |
1228 """ | 1275 """ |
1229 | 1276 |
1230 # the valid octets for host and netmasks. only useful for IPv4. | |
1231 _valid_mask_octets = set((255, 254, 252, 248, 240, 224, 192, 128, 0)) | |
1232 | |
1233 def __init__(self, address, strict=False): | 1277 def __init__(self, address, strict=False): |
1234 """Instantiate a new IPv4 network object. | 1278 """Instantiate a new IPv4 network object. |
1235 | 1279 |
1236 Args: | 1280 Args: |
1237 address: A string or integer representing the IP [& network]. | 1281 address: A string or integer representing the IP [& network]. |
1238 '192.168.1.1/24' | 1282 '192.168.1.1/24' |
1239 '192.168.1.1/255.255.255.0' | 1283 '192.168.1.1/255.255.255.0' |
1240 '192.168.1.1/0.0.0.255' | 1284 '192.168.1.1/0.0.0.255' |
1241 are all functionally the same in IPv4. Similarly, | 1285 are all functionally the same in IPv4. Similarly, |
1242 '192.168.1.1' | 1286 '192.168.1.1' |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1285 # which converts into a formatted IP prefix string. | 1329 # which converts into a formatted IP prefix string. |
1286 addr = str(address).split('/') | 1330 addr = str(address).split('/') |
1287 | 1331 |
1288 if len(addr) > 2: | 1332 if len(addr) > 2: |
1289 raise AddressValueError(address) | 1333 raise AddressValueError(address) |
1290 | 1334 |
1291 self._ip = self._ip_int_from_string(addr[0]) | 1335 self._ip = self._ip_int_from_string(addr[0]) |
1292 self.ip = IPv4Address(self._ip) | 1336 self.ip = IPv4Address(self._ip) |
1293 | 1337 |
1294 if len(addr) == 2: | 1338 if len(addr) == 2: |
1295 mask = addr[1].split('.') | 1339 try: |
1296 if len(mask) == 4: | 1340 # Check for a netmask in prefix length form. |
1297 # We have dotted decimal netmask. | 1341 self._prefixlen = self._prefix_from_prefix_string(addr[1]) |
1298 if self._is_valid_netmask(addr[1]): | 1342 except NetmaskValueError: |
1299 self.netmask = IPv4Address(self._ip_int_from_string( | 1343 # Check for a netmask or hostmask in dotted-quad form. |
1300 addr[1])) | 1344 # This may raise NetmaskValueError. |
1301 elif self._is_hostmask(addr[1]): | 1345 self._prefixlen = self._prefix_from_ip_string(addr[1]) |
1302 self.netmask = IPv4Address( | |
1303 self._ip_int_from_string(addr[1]) ^ self._ALL_ONES) | |
1304 else: | |
1305 raise NetmaskValueError('%s is not a valid netmask' | |
1306 % addr[1]) | |
1307 | |
1308 self._prefixlen = self._prefix_from_ip_int(int(self.netmask)) | |
1309 else: | |
1310 # We have a netmask in prefix length form. | |
1311 if not self._is_valid_netmask(addr[1]): | |
1312 raise NetmaskValueError(addr[1]) | |
1313 self._prefixlen = int(addr[1]) | |
1314 self.netmask = IPv4Address(self._ip_int_from_prefix( | |
1315 self._prefixlen)) | |
1316 else: | 1346 else: |
1317 self._prefixlen = self._max_prefixlen | 1347 self._prefixlen = self._max_prefixlen |
1318 self.netmask = IPv4Address(self._ip_int_from_prefix( | 1348 |
1319 self._prefixlen)) | 1349 self.netmask = IPv4Address(self._ip_int_from_prefix(self._prefixlen)) |
1350 | |
1320 if strict: | 1351 if strict: |
1321 if self.ip != self.network: | 1352 if self.ip != self.network: |
1322 raise ValueError('%s has host bits set' % | 1353 raise ValueError('%s has host bits set' % |
1323 self.ip) | 1354 self.ip) |
1324 if self._prefixlen == (self._max_prefixlen - 1): | 1355 if self._prefixlen == (self._max_prefixlen - 1): |
1325 self.iterhosts = self.__iter__ | 1356 self.iterhosts = self.__iter__ |
1326 | 1357 |
1327 def _is_hostmask(self, ip_str): | |
1328 """Test if the IP string is a hostmask (rather than a netmask). | |
1329 | |
1330 Args: | |
1331 ip_str: A string, the potential hostmask. | |
1332 | |
1333 Returns: | |
1334 A boolean, True if the IP string is a hostmask. | |
1335 | |
1336 """ | |
1337 bits = ip_str.split('.') | |
1338 try: | |
1339 parts = [int(x) for x in bits if int(x) in self._valid_mask_octets] | |
1340 except ValueError: | |
1341 return False | |
1342 if len(parts) != len(bits): | |
1343 return False | |
1344 if parts[0] < parts[-1]: | |
1345 return True | |
1346 return False | |
1347 | |
1348 def _is_valid_netmask(self, netmask): | |
1349 """Verify that the netmask is valid. | |
1350 | |
1351 Args: | |
1352 netmask: A string, either a prefix or dotted decimal | |
1353 netmask. | |
1354 | |
1355 Returns: | |
1356 A boolean, True if the prefix represents a valid IPv4 | |
1357 netmask. | |
1358 | |
1359 """ | |
1360 mask = netmask.split('.') | |
1361 if len(mask) == 4: | |
1362 if [x for x in mask if int(x) not in self._valid_mask_octets]: | |
1363 return False | |
1364 if [y for idx, y in enumerate(mask) if idx > 0 and | |
1365 y > mask[idx - 1]]: | |
1366 return False | |
1367 return True | |
1368 try: | |
1369 netmask = int(netmask) | |
1370 except ValueError: | |
1371 return False | |
1372 return 0 <= netmask <= self._max_prefixlen | |
1373 | |
1374 # backwards compatibility | 1358 # backwards compatibility |
1375 IsRFC1918 = lambda self: self.is_private | 1359 IsRFC1918 = lambda self: self.is_private |
1376 IsMulticast = lambda self: self.is_multicast | 1360 IsMulticast = lambda self: self.is_multicast |
1377 IsLoopback = lambda self: self.is_loopback | 1361 IsLoopback = lambda self: self.is_loopback |
1378 IsLinkLocal = lambda self: self.is_link_local | 1362 IsLinkLocal = lambda self: self.is_link_local |
1379 | 1363 |
1380 | 1364 |
1381 class _BaseV6(object): | 1365 class _BaseV6(object): |
1382 | 1366 |
1383 """Base IPv6 object. | 1367 """Base IPv6 object. |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1854 # which converts into a formatted IP prefix string. | 1838 # which converts into a formatted IP prefix string. |
1855 addr = str(address).split('/') | 1839 addr = str(address).split('/') |
1856 | 1840 |
1857 if len(addr) > 2: | 1841 if len(addr) > 2: |
1858 raise AddressValueError(address) | 1842 raise AddressValueError(address) |
1859 | 1843 |
1860 self._ip = self._ip_int_from_string(addr[0]) | 1844 self._ip = self._ip_int_from_string(addr[0]) |
1861 self.ip = IPv6Address(self._ip) | 1845 self.ip = IPv6Address(self._ip) |
1862 | 1846 |
1863 if len(addr) == 2: | 1847 if len(addr) == 2: |
1864 if self._is_valid_netmask(addr[1]): | 1848 # This may raise NetmaskValueError |
1865 self._prefixlen = int(addr[1]) | 1849 self._prefixlen = self._prefix_from_prefix_string(addr[1]) |
1866 else: | |
1867 raise NetmaskValueError(addr[1]) | |
1868 else: | 1850 else: |
1869 self._prefixlen = self._max_prefixlen | 1851 self._prefixlen = self._max_prefixlen |
1870 | 1852 |
1871 self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen)) | 1853 self.netmask = IPv6Address(self._ip_int_from_prefix(self._prefixlen)) |
1872 | 1854 |
1873 if strict: | 1855 if strict: |
1874 if self.ip != self.network: | 1856 if self.ip != self.network: |
1875 raise ValueError('%s has host bits set' % | 1857 raise ValueError('%s has host bits set' % |
1876 self.ip) | 1858 self.ip) |
1877 if self._prefixlen == (self._max_prefixlen - 1): | 1859 if self._prefixlen == (self._max_prefixlen - 1): |
1878 self.iterhosts = self.__iter__ | 1860 self.iterhosts = self.__iter__ |
1879 | 1861 |
1880 def _is_valid_netmask(self, prefixlen): | |
1881 """Verify that the netmask/prefixlen is valid. | |
1882 | |
1883 Args: | |
1884 prefixlen: A string, the netmask in prefix length format. | |
1885 | |
1886 Returns: | |
1887 A boolean, True if the prefix represents a valid IPv6 | |
1888 netmask. | |
1889 | |
1890 """ | |
1891 try: | |
1892 prefixlen = int(prefixlen) | |
1893 except ValueError: | |
1894 return False | |
1895 return 0 <= prefixlen <= self._max_prefixlen | |
1896 | |
1897 @property | 1862 @property |
1898 def with_netmask(self): | 1863 def with_netmask(self): |
1899 return self.with_prefixlen | 1864 return self.with_prefixlen |
OLD | NEW |