Branch data Line data Source code
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 : :
15 : : #include <sys/types.h>
16 : : #include <sys/socket.h>
17 : :
18 : : #include <exceptions/exceptions.h>
19 : :
20 : : #include <boost/lexical_cast.hpp>
21 : :
22 : : #include <acl/ip_check.h>
23 : :
24 : : using namespace std;
25 : : using namespace isc;
26 : :
27 : : namespace isc {
28 : : namespace acl {
29 : : namespace internal {
30 : :
31 : : uint8_t
32 : 20 : createMask(size_t prefixlen) {
33 : :
34 [ + + ]: 20 : if (prefixlen == 0) {
35 : : return (0);
36 : :
37 [ + + ]: 19 : } else if (prefixlen <= 8) {
38 : :
39 : : // In the following discussion:
40 : : //
41 : : // w is the width of the data type in bits.
42 : : // m is the value of prefixlen, the number of most signifcant bits we
43 : : // want to set.
44 : : // ** is exponentiation (i.e. 2**n is 2 raised to the power of n).
45 : : //
46 : : // We note that the value of 2**m - 1 gives a value with the least
47 : : // significant m bits set. For a data type of width w, this means that
48 : : // the most signficant (w-m) bits are clear.
49 : : //
50 : : // Hence the value 2**(w-m) - 1 gives a result with the least signficant
51 : : // w-m bits set and the most significant m bits clear. The 1's
52 : : // complement of this value gives is the result we want.
53 : : //
54 : : // Final note: at this point in the logic, m is non-zero, so w-m < w.
55 : : // This means 1<<(w-m) will fit into a variable of width w bits. In
56 : : // other words, in the expression below, no term will cause an integer
57 : : // overflow.
58 : 18 : return (~((1 << (8 - prefixlen)) - 1));
59 : : }
60 : :
61 : : // Mask size is too large. (Note that prefixlen is unsigned, so can't be
62 : : // negative.)
63 [ + - ]: 21 : isc_throw(isc::OutOfRange, "prefixlen argument must be between 0 and 8");
64 : : }
65 : :
66 : : pair<string, int>
67 : 165 : splitIPAddress(const string& ipprefix) {
68 : :
69 : : // Split string into its components - an address and a prefix length.
70 : : // We initialize by assuming that there is no slash in the string given.
71 : 330 : string address = ipprefix;
72 [ + - ]: 330 : string prefixlen = "";
73 : :
74 [ + - ]: 165 : const size_t slashpos = ipprefix.find('/');
75 [ + - ][ + + ]: 165 : if ((ipprefix.size() == 0) || (slashpos == 0) ||
[ + + ][ + + ]
76 : : (slashpos == (ipprefix.size() - 1))) {
77 : : // Nothing in prefix, or it starts with or ends with a slash.
78 [ + - ][ + - ]: 18 : isc_throw(isc::InvalidParameter, "address prefix of " << ipprefix <<
[ + - ][ + - ]
79 : : " is not valid");
80 : :
81 [ + + ]: 156 : } else if (slashpos != string::npos) {
82 : : // There is a slash somewhere in the string, split the string on it.
83 : : // Don't worry about multiple slashes - if there are some, they will
84 : : // appear in the prefixlen segment and will be detected when an attempt
85 : : // is made to convert it to a number.
86 [ + - ]: 152 : address = ipprefix.substr(0, slashpos);
87 [ + - ]: 152 : prefixlen = ipprefix.substr(slashpos + 1);
88 : : }
89 : :
90 : : // Set the default value for the prefix length. As the type of the address
91 : : // is not known at the point this function is called, the maximum
92 : : // allowable value is also not known. The value of 0 is reserved for
93 : : // a "match any address" match.
94 : 156 : int prefix_size = -1;
95 : :
96 : : // If there is a prefixlength, attempt to convert it.
97 [ + + ]: 156 : if (!prefixlen.empty()) {
98 : : try {
99 : 57 : prefix_size = boost::lexical_cast<int>(prefixlen);
100 [ + + ]: 57 : if (prefix_size < 0) {
101 [ + - ][ + - ]: 8 : isc_throw(isc::InvalidParameter, "address prefix of " <<
[ + - ][ + - ]
102 : : ipprefix << " is not valid");
103 : : }
104 [ + + ]: 42 : } catch (boost::bad_lexical_cast&) {
105 [ - + ][ - + ]: 38 : isc_throw(isc::InvalidParameter, "prefix length of '" <<
[ - + ][ - + ]
106 : : prefixlen << "' is not valid");
107 : : }
108 : : }
109 : :
110 [ + - ]: 399 : return (make_pair(address, prefix_size));
111 : : }
112 : : } // namespace internal
113 : :
114 : : namespace {
115 : : const uint8_t*
116 : 136 : getSockAddrData(const struct sockaddr& sa) {
117 : 136 : const void* sa_ptr = &sa;
118 : : const void* data_ptr;
119 [ + + ]: 136 : if (sa.sa_family == AF_INET) {
120 : : const struct sockaddr_in* sin =
121 : 97 : static_cast<const struct sockaddr_in*>(sa_ptr);
122 : 97 : data_ptr = &sin->sin_addr;
123 [ + + ]: 39 : } else if (sa.sa_family == AF_INET6) {
124 : : const struct sockaddr_in6* sin6 =
125 : 38 : static_cast<const struct sockaddr_in6*>(sa_ptr);
126 : 38 : data_ptr = &sin6->sin6_addr;
127 : : } else {
128 [ + - ][ + - ]: 2 : isc_throw(BadValue, "Unsupported address family for IPAddress: " <<
129 : : static_cast<int>(sa.sa_family));
130 : : }
131 : 135 : return (static_cast<const uint8_t*>(data_ptr));
132 : : }
133 : : }
134 : :
135 : 136 : IPAddress::IPAddress(const struct sockaddr& sa) :
136 : : family(sa.sa_family),
137 : 136 : data(getSockAddrData(sa)),
138 : : length(family == AF_INET ?
139 [ + + ]: 135 : sizeof(struct in_addr) : sizeof(struct in6_addr))
140 : 135 : {}
141 : : } // namespace acl
142 : 120 : } // namespace isc
|