Line data Source code
1 : // Network Address -- classes functions to ease handling IP addresses
2 : // Copyright (C) 2012-2017 Made to Order Software Corp.
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 :
18 : // self
19 : //
20 : #include "libaddr/addr.h"
21 :
22 : // C++ lib
23 : //
24 : #include <algorithm>
25 : #include <sstream>
26 : #include <iostream>
27 :
28 : // C lib
29 : //
30 : #include <ifaddrs.h>
31 : #include <netdb.h>
32 :
33 :
34 :
35 : namespace addr
36 : {
37 :
38 :
39 :
40 :
41 :
42 :
43 : /** \brief Return true if the range has a 'from' address defined.
44 : *
45 : * By default the 'from' and 'to' addresses of an addr_range are legal
46 : * but considered undefined. After you called the set_from() function
47 : * once, this function will always return true.
48 : *
49 : * \return false until 'set_from()' is called at least once.
50 : */
51 277 : bool addr_range::has_from() const
52 : {
53 277 : return f_has_from;
54 : }
55 :
56 :
57 : /** \brief Return true if the range has a 'to' address defined.
58 : *
59 : * By default the 'from' and 'to' addresses of an addr_range are legal
60 : * but considered undefined. After you called the set_to() function
61 : * once, this function will always return true.
62 : *
63 : * \return false until 'set_to()' is called at least once.
64 : */
65 277 : bool addr_range::has_to() const
66 : {
67 277 : return f_has_to;
68 : }
69 :
70 :
71 : /** \brief Determine whether an addr_range object is considered a range.
72 : *
73 : * This function returns false until both, set_from() and set_to(),
74 : * were called.
75 : *
76 : * Note that the order in which the two functions get called is not
77 : * important, although we generally expect set_from() to be called
78 : * first, it does not matter.
79 : *
80 : * \return true if both, 'from' and 'to', were set.
81 : */
82 974 : bool addr_range::is_range() const
83 : {
84 974 : return f_has_from && f_has_to;
85 : }
86 :
87 :
88 : /** \brief Check whether this range is empty.
89 : *
90 : * If you defined the 'from' and 'to' addresses of the range, then you
91 : * can check whether the range is empty or not.
92 : *
93 : * A range is considered empty if 'from' is larger than 'to' because
94 : * in that case nothing can appear in between (no IP can at the same
95 : * time be larger than 'from' and smaller than 'to' if 'from > to'
96 : * is true.)
97 : *
98 : * \return true if 'from > to' and is_range() returns true.
99 : *
100 : * \sa is_range()
101 : * \sa has_from()
102 : * \sa has_to()
103 : */
104 283 : bool addr_range::is_empty() const
105 : {
106 283 : if(!is_range())
107 : {
108 275 : return false;
109 : }
110 8 : return f_from > f_to;
111 : }
112 :
113 :
114 : /** \brief Check whether \p rhs is part of this range.
115 : *
116 : * If the address specified in rhs is part of this range, then the function
117 : * returns true. The 'from' and 'to' addresses are considered inclusive,
118 : * so if rhs is equal to 'from' or 'to', then the function returns true.
119 : *
120 : * If 'from' is larger than 'to' then the function already returns false
121 : * since the range represents an empty range.
122 : *
123 : * \exception addr_invalid_state_exception
124 : * The addr_range object must be a range or this function throws this
125 : * exception. To test whether you can call this function, first call
126 : * the is_range() function. If it returns true, then is_in() is available.
127 : *
128 : * \param[in] rhs The address to check for inclusion.
129 : *
130 : * \return true if rhs is considered part of this range.
131 : */
132 408 : bool addr_range::is_in(addr const & rhs) const
133 : {
134 408 : if(!is_range())
135 : {
136 10 : throw addr_invalid_state_exception("addr_range::is_in(): range is not complete (from or to missing.)");
137 : }
138 :
139 398 : if(f_from <= f_to)
140 : {
141 : //
142 276 : return rhs >= f_from && rhs <= f_to;
143 : }
144 : //else -- from/to are swapped... this represents an empty range
145 :
146 122 : return false;
147 : }
148 :
149 :
150 : /** \brief Set 'from' address.
151 : *
152 : * This function saves the 'from' address in this range object.
153 : *
154 : * Once this function was called at least once, the has_from() returns true.
155 : *
156 : * \param[in] from The address to save as the 'from' address.
157 : */
158 131710 : void addr_range::set_from(addr const & from)
159 : {
160 131710 : f_has_from = true;
161 131710 : f_from = from;
162 131710 : }
163 :
164 :
165 : /** \brief Get 'from' address.
166 : *
167 : * This function return the 'from' address as set by the set_from()
168 : * functions.
169 : *
170 : * The get_from() function can be called even if the has_from()
171 : * function returns false. It will return a default address
172 : * (a new 'addr' object.)
173 : *
174 : * \return The address saved as the 'from' address.
175 : */
176 369 : addr & addr_range::get_from()
177 : {
178 369 : return f_from;
179 : }
180 :
181 :
182 : /** \brief Get the 'from' address when addr_range is constant.
183 : *
184 : * This function return the 'from' address as set by the set_from()
185 : * functions.
186 : *
187 : * The get_from() function can be called even if the has_from()
188 : * function returns false. It will return a default address
189 : * (a new 'addr' object.)
190 : *
191 : * \return The address saved as the 'from' address.
192 : */
193 131669 : addr const & addr_range::get_from() const
194 : {
195 131669 : return f_from;
196 : }
197 :
198 :
199 : /** \brief Set 'to' address.
200 : *
201 : * This function saves the 'to' address in this range object.
202 : *
203 : * Once this function was called at least once, the has_to() returns true.
204 : *
205 : * \param[in] to The address to save as the 'to' address.
206 : */
207 8 : void addr_range::set_to(addr const & to)
208 : {
209 8 : f_has_to = true;
210 8 : f_to = to;
211 8 : }
212 :
213 :
214 : /** \brief Get the 'to' address.
215 : *
216 : * This function return the 'to' address as set by the set_to()
217 : * function.
218 : *
219 : * The get_from() function can be called even if the has_from()
220 : * function returns false. It will return a default address
221 : * (a new 'addr' object.)
222 : *
223 : * \return The address saved as the 'to' address.
224 : */
225 9 : addr & addr_range::get_to()
226 : {
227 9 : return f_to;
228 : }
229 :
230 :
231 : /** \brief Get the 'to' address when addr_range is constant.
232 : *
233 : * This function return the 'to' address as set by the set_to()
234 : * function.
235 : *
236 : * The get_to() function can be called even if the has_to()
237 : * function returns false. It will return a default address
238 : * (a new 'addr' object.)
239 : *
240 : * \return The address saved as the 'to' address.
241 : */
242 7 : addr const & addr_range::get_to() const
243 : {
244 7 : return f_to;
245 : }
246 :
247 :
248 : /** \brief Compute a new range with the part that is shared between both inputs.
249 : *
250 : * This function computers a range which encompasses all the addresses found
251 : * in \p this range and \p rhs range.
252 : *
253 : * If the two range do not intersect, then the resulting range will be an
254 : * empty range (see is_empty() for details).
255 : *
256 : * The new range receives the largest 'from' address from both inputs and
257 : * the smallest 'to' address from both inputs.
258 : *
259 : * \param[in] rhs The other range to compute the intersection with.
260 : *
261 : * \return The resulting intersection range.
262 : */
263 2 : addr_range addr_range::intersection(addr_range const & rhs) const
264 : {
265 2 : addr_range result;
266 :
267 2 : result.set_from(f_from > rhs.f_from ? f_from : rhs.f_from);
268 2 : result.set_to (f_to < rhs.f_to ? f_to : rhs.f_to);
269 :
270 2 : return result;
271 : }
272 :
273 :
274 :
275 :
276 :
277 :
278 :
279 6 : }
280 : // snap_addr namespace
281 : // vim: ts=4 sw=4 et
|