This file is indexed.

/usr/include/tins/address_range.h is in libtins-dev 3.4-2+b1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
/*
 * Copyright (c) 2016, Matias Fontanini
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following disclaimer
 *   in the documentation and/or other materials provided with the
 *   distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#ifndef TINS_ADDRESS_RANGE
#define TINS_ADDRESS_RANGE

#include <stdexcept>
#include <iterator>
#include "endianness.h"
#include "internals.h"

namespace Tins {
/**
 * \brief AddressRange iterator class.
 */
template<typename Address>
class AddressRangeIterator : public std::iterator<std::forward_iterator_tag, const Address> {
public:
    typedef typename std::iterator<std::forward_iterator_tag, const Address>::value_type value_type;

    struct end_iterator {

    };

    /**
     * Constructs an iterator.
     *
     * \param first The address held by this iterator.
     */
    AddressRangeIterator(const value_type& address)
    : address_(address), reached_end_(false) {

    }

    /**
     * Constructs an iterator.
     *
     * \param first The address held by this iterator.
     */
    AddressRangeIterator(const value_type& address, end_iterator)
    : address_(address) {
        reached_end_ = Internals::increment(address_);
    }

    /**
     * Retrieves the current address pointed by this iterator.
     */
    const value_type& operator*() const {
        return address_;
    }

    /**
     * Retrieves a pointer to the current address pointed by this iterator.
     */
    const value_type* operator->() const {
        return& address_;
    }

    /**
     * Compares two iterators for equality.
     *
     * \param rhs The iterator with which to compare.
     */
    bool operator==(const AddressRangeIterator& rhs) const {
        return reached_end_ == rhs.reached_end_ && address_ == rhs.address_;
    }

    /**
     * Compares two iterators for inequality.
     *
     * \param rhs The iterator with which to compare.
     */
    bool operator!=(const AddressRangeIterator& rhs) const {
        return !(*this == rhs);
    }

    /**
     * Increments this iterator.
     */
    AddressRangeIterator& operator++() {
        reached_end_ = Internals::increment(address_);
        return* this;
    }

    /**
     * Increments this iterator.
     */
    AddressRangeIterator operator++(int) {
        AddressRangeIterator copy(*this);
        (*this)++;
        return copy;
    }
private:
    Address address_;
    bool reached_end_;
};

/**
 * \brief Represents a range of addresses.
 *
 * This class provides a begin()/end() interface which allows
 * iterating through every address stored in it. 
 *
 * Note that when iterating a range that was created using
 * operator/(IPv4Address, int) and the analog for IPv6, the 
 * network and broadcast addresses are discarded:
 *
 * \code
 * auto range = IPv4Address("192.168.5.0") / 24;
 * for(const auto& addr : range) {
 *     // process 192.168.5.1-254, .0 and .255 are discarded
 *     process(addr);
 * }
 *
 * // That's only valid for iteration, not for AddressRange<>::contains
 * 
 * assert(range.contains("192.168.5.0")); // works
 * assert(range.contains("192.168.5.255")); // works
 * \endcode
 *
 * Ranges created using AddressRange(address_type, address_type) 
 * will allow the iteration over the entire range:
 *
 * \code
 * AddressRange<IPv4Address> range("192.168.5.0", "192.168.5.255");
 * for(const auto& addr : range) {
 *     // process 192.168.5.0-255, no addresses are discarded
 *     process(addr);
 * }
 * 
 * assert(range.contains("192.168.5.0")); // still valid
 * assert(range.contains("192.168.5.255")); // still valid
 * \endcode
 * 
 */
template<typename Address>
class AddressRange {
public:
    /**
     * The type of addresses stored in the range.
     */
    typedef Address address_type;

    /**
     * The iterator type.
     */
    typedef AddressRangeIterator<address_type> const_iterator;

    /**
     * \brief The iterator type.
     *
     * This is the same type as const_iterator, since the
     * addresses stored in this range are read only.
     */
    typedef const_iterator iterator;

    /**
     * \brief Constructs an address range from two addresses.
     *
     * The range will consist of the addresses [first, last].
     *
     * If only_hosts is true, then the network and broadcast addresses
     * will not be available when iterating the range. 
     *
     * If last < first, an std::runtime_error exception is thrown.
     * 
     * \param first The first address in the range.
     * \param last The last address(inclusive) in the range.
     * \param only_hosts Indicates whether only host addresses
     * should be accessed when using iterators.
     */
    AddressRange(const address_type& first, const address_type& last, bool only_hosts = false)
    : first_(first), last_(last), only_hosts_(only_hosts){
        if (last_ < first_) {
            throw std::runtime_error("Invalid address range");
        }
    }

    /**
     * \brief Creates an address range from a base address
     * and a network mask.
     *
     * \param first The base address.
     * \param mask The network mask to be used.
     */
    static AddressRange from_mask(const address_type& first, const address_type& mask) {
        return AddressRange<address_type>(
            first, 
            Internals::last_address_from_mask(first, mask), 
            true
        );
    }

    /**
     * \brief Indicates whether an address is included in this range.
     * \param addr The address to test.
     * \return a bool indicating whether the address is in the range.
     */
    bool contains(const address_type& addr) const {
        return (first_ < addr && addr < last_) || addr == first_ || addr == last_;
    }

    /**
     * \brief Returns an interator to the beginning of this range.
     * \brief const_iterator pointing to the beginning of this range.
     */
    const_iterator begin() const {
        address_type addr = first_;
        if (only_hosts_) {
            Internals::increment(addr);
        }
        return const_iterator(addr);
    }

    /**
     * \brief Returns an interator to the end of this range.
     * \brief const_iterator pointing to the end of this range.
     */
    const_iterator end() const {
        address_type addr = last_;
        if (only_hosts_) {
            Internals::decrement(addr);
        }
        return const_iterator(addr, typename const_iterator::end_iterator());
    }

    /**
     * \brief Indicates whether this range is iterable.
     *
     * Iterable ranges are those for which there is at least one 
     * address that could represent a host. For IPv4 ranges, a /31 or
     * /32 ranges does not contain any, therefore it's not iterable.
     * The same is true for /127 and /128 IPv6 ranges.
     *
     * If is_iterable returns false for a range, then iterating it
     * through the iterators returned by begin() and end() is 
     * undefined. 
     * 
     * \return bool indicating whether this range is iterable.
     */
    bool is_iterable() const {
        // Since first < last, it's iterable
        if (!only_hosts_) {
            return true;
        }
        // We need that distance(first, last) >= 4
        address_type addr(first_);
        for (int i = 0; i < 3; ++i) {
            // If there's overflow before the last iteration, we're done
            if (Internals::increment(addr) && i != 2) {
                return false;
            }
        }
        // If addr <= last, it's OK.
        return addr < last_ || addr == last_;
    }
private:
    address_type first_, last_;
    bool only_hosts_;
};

/**
 * An IPv4 address range.
 */
typedef AddressRange<IPv4Address> IPv4Range;

/**
 * An IPv6 address range.
 */
typedef AddressRange<IPv6Address> IPv6Range;

/**
 * \brief Constructs an AddressRange from a base address and a mask.
 * \param addr The range's first address.
 * \param mask The bit-length of the prefix.
 */
template<size_t n>
AddressRange<HWAddress<n> > operator/(const HWAddress<n>& addr, int mask) {
    if (mask > 48) {
        throw std::logic_error("Prefix length cannot exceed 48");
    }
    HWAddress<n> last_addr;
    typename HWAddress<n>::iterator it = last_addr.begin();
    while (mask > 8) {
        *it = 0xff;
        ++it;
        mask -= 8;
    }
    *it = 0xff << (8 - mask);
    return AddressRange<HWAddress<6> >::from_mask(addr, last_addr);
}

/**
 * \brief Constructs an IPv6Range from a base IPv6Address and a mask.
 * \param addr The range's first address.
 * \param mask The bit-length of the prefix.
 */
IPv6Range operator/(const IPv6Address& addr, int mask);

/**
 * \brief Constructs an IPv4Range from a base IPv4Address and a mask.
 * \param addr The range's first address.
 * \param mask The bit-length of the prefix.
 */
IPv4Range operator/(const IPv4Address& addr, int mask);
} // namespace Tins

#endif // TINS_ADDRESS_RANGE