addr.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. # Copyright (C) 2010 Internet Systems Consortium.
  2. #
  3. # Permission to use, copy, modify, and distribute this software for any
  4. # purpose with or without fee is hereby granted, provided that the above
  5. # copyright notice and this permission notice appear in all copies.
  6. #
  7. # THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
  8. # DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
  9. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
  10. # INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  12. # FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  13. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  14. # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. """Module where address representations live."""
  16. import socket
  17. import re
  18. # These regular expressions are not validating. They are supposed to
  19. # guess which kind of address it is and throw away just obvious nonsense.
  20. # It is expected that inet_pton will complain if it isn't an address, so
  21. # they can have false positives.
  22. isv4 = re.compile(r'^([0-9]{1,3}\.){3}[0-9]{1,3}$')
  23. isv6 = re.compile(r'^([0-9a-f]{,4}:){,7}[0-9a-f]{,4}$', re.IGNORECASE)
  24. class InvalidAddress(ValueError):
  25. """Exception for invalid addresses."""
  26. pass
  27. class IPAddr:
  28. """Stores an IPv4 or IPv6 address."""
  29. family = None
  30. addr = None
  31. def __init__(self, addr):
  32. """
  33. Creates the address object from a string representation. It raises
  34. an InvalidAddr exception if the provided string isn't valid address.
  35. """
  36. try:
  37. if isv4.match(addr):
  38. a = socket.inet_pton(socket.AF_INET, addr)
  39. self.family = socket.AF_INET
  40. self.addr = a
  41. elif isv6.match(addr):
  42. a = socket.inet_pton(socket.AF_INET6, addr)
  43. self.family = socket.AF_INET6
  44. self.addr = a
  45. else:
  46. raise InvalidAddress(addr +
  47. ' is not a valid IPv4 nor IPv6 address')
  48. except socket.error as e:
  49. raise InvalidAddress(str(e))
  50. def __str__(self):
  51. return socket.inet_ntop(self.family, self.addr)