ip_check.cc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <sys/socket.h>
  15. #include <exceptions/exceptions.h>
  16. #include <boost/lexical_cast.hpp>
  17. #include <acl/ip_check.h>
  18. using namespace std;
  19. using namespace isc;
  20. namespace isc {
  21. namespace acl {
  22. namespace internal {
  23. uint8_t
  24. createMask(size_t prefixlen) {
  25. if (prefixlen == 0) {
  26. return (0);
  27. } else if (prefixlen <= 8) {
  28. // In the following discussion:
  29. //
  30. // w is the width of the data type in bits.
  31. // m is the value of prefixlen, the number of most signifcant bits we
  32. // want to set.
  33. // ** is exponentiation (i.e. 2**n is 2 raised to the power of n).
  34. //
  35. // We note that the value of 2**m - 1 gives a value with the least
  36. // significant m bits set. For a data type of width w, this means that
  37. // the most signficant (w-m) bits are clear.
  38. //
  39. // Hence the value 2**(w-m) - 1 gives a result with the least signficant
  40. // w-m bits set and the most significant m bits clear. The 1's
  41. // complement of this value gives is the result we want.
  42. //
  43. // Final note: at this point in the logic, m is non-zero, so w-m < w.
  44. // This means 1<<(w-m) will fit into a variable of width w bits. In
  45. // other words, in the expression below, no term will cause an integer
  46. // overflow.
  47. return (~((1 << (8 - prefixlen)) - 1));
  48. }
  49. // Mask size is too large. (Note that prefixlen is unsigned, so can't be
  50. // negative.)
  51. isc_throw(isc::OutOfRange, "prefixlen argument must be between 0 and 8");
  52. }
  53. pair<string, int>
  54. splitIPAddress(const string& ipprefix) {
  55. // Split string into its components - an address and a prefix length.
  56. // We initialize by assuming that there is no slash in the string given.
  57. string address = ipprefix;
  58. string prefixlen = "";
  59. const size_t slashpos = ipprefix.find('/');
  60. if ((ipprefix.size() == 0) || (slashpos == 0) ||
  61. (slashpos == (ipprefix.size() - 1))) {
  62. // Nothing in prefix, or it starts with or ends with a slash.
  63. isc_throw(isc::InvalidParameter, "address prefix of " << ipprefix <<
  64. " is not valid");
  65. } else if (slashpos != string::npos) {
  66. // There is a slash somewhere in the string, split the string on it.
  67. // Don't worry about multiple slashes - if there are some, they will
  68. // appear in the prefixlen segment and will be detected when an attempt
  69. // is made to convert it to a number.
  70. address = ipprefix.substr(0, slashpos);
  71. prefixlen = ipprefix.substr(slashpos + 1);
  72. }
  73. // Set the default value for the prefix length. As the type of the address
  74. // is not known at the point this function is called, the maximum
  75. // allowable value is also not known. The value of 0 is reserved for
  76. // a "match any address" match.
  77. int prefix_size = -1;
  78. // If there is a prefixlength, attempt to convert it.
  79. if (!prefixlen.empty()) {
  80. try {
  81. prefix_size = boost::lexical_cast<int>(prefixlen);
  82. if (prefix_size < 0) {
  83. isc_throw(isc::InvalidParameter, "address prefix of " <<
  84. ipprefix << " is not valid");
  85. }
  86. } catch (boost::bad_lexical_cast&) {
  87. isc_throw(isc::InvalidParameter, "prefix length of '" <<
  88. prefixlen << "' is not valid");
  89. }
  90. }
  91. return (make_pair(address, prefix_size));
  92. }
  93. } // namespace internal
  94. namespace {
  95. const uint8_t*
  96. getSockAddrData(const struct sockaddr& sa) {
  97. const void* sa_ptr = &sa;
  98. const void* data_ptr;
  99. if (sa.sa_family == AF_INET) {
  100. const struct sockaddr_in* sin =
  101. static_cast<const struct sockaddr_in*>(sa_ptr);
  102. data_ptr = &sin->sin_addr;
  103. } else if (sa.sa_family == AF_INET6) {
  104. const struct sockaddr_in6* sin6 =
  105. static_cast<const struct sockaddr_in6*>(sa_ptr);
  106. data_ptr = &sin6->sin6_addr;
  107. } else {
  108. isc_throw(BadValue, "Unsupported address family for IPAddress: " <<
  109. static_cast<int>(sa.sa_family));
  110. }
  111. return (static_cast<const uint8_t*>(data_ptr));
  112. }
  113. }
  114. IPAddress::IPAddress(const struct sockaddr& sa) :
  115. family(sa.sa_family),
  116. data(getSockAddrData(sa)),
  117. length(family == AF_INET ?
  118. sizeof(struct in_addr) : sizeof(struct in6_addr))
  119. {}
  120. } // namespace acl
  121. } // namespace isc