Coverage Report

Created: 2024-11-21 17:33

/root/doris/be/src/util/cidr.cpp
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#include "util/cidr.h"
19
20
#include <arpa/inet.h>
21
#include <sys/socket.h>
22
23
#include <algorithm>
24
#include <cstddef>
25
#include <exception>
26
#include <iterator>
27
#include <ostream>
28
29
#include "common/logging.h"
30
31
namespace doris {
32
33
constexpr std::uint8_t kIPv4Bits = 32;
34
constexpr std::uint8_t kIPv6Bits = 128;
35
36
19
bool CIDR::reset(const std::string& cidr_str) {
37
19
    auto slash = std::find(std::begin(cidr_str), std::end(cidr_str), '/');
38
19
    auto ip = (slash == std::end(cidr_str)) ? cidr_str
39
19
                                            : cidr_str.substr(0, slash - std::begin(cidr_str));
40
41
19
    if (inet_pton(AF_INET, ip.c_str(), _address.data())) {
42
11
        _family = AF_INET;
43
11
        _netmask_len = kIPv4Bits;
44
11
    } else if (inet_pton(AF_INET6, ip.c_str(), _address.data())) {
45
3
        _family = AF_INET6;
46
3
        _netmask_len = kIPv6Bits;
47
5
    } else {
48
5
        LOG(WARNING) << "Wrong CIDRIP format. network=" << cidr_str;
49
5
        return false;
50
5
    }
51
52
14
    if (slash == std::end(cidr_str)) {
53
7
        return true;
54
7
    }
55
56
7
    std::size_t pos;
57
7
    std::string suffix = std::string(slash + 1, std::end(cidr_str));
58
7
    int len;
59
7
    try {
60
7
        len = std::stoi(suffix, &pos);
61
7
    } catch (const std::exception& e) {
62
2
        LOG(WARNING) << "Wrong CIDR format. network=" << cidr_str << ", reason=" << e.what();
63
2
        return false;
64
2
    }
65
66
5
    if (pos != suffix.size()) {
67
0
        LOG(WARNING) << "Wrong CIDR format. network=" << cidr_str;
68
0
        return false;
69
0
    }
70
71
5
    if (len < 0 || len > _netmask_len) {
72
0
        LOG(WARNING) << "Wrong CIDR mask format. network=" << cidr_str;
73
0
        return false;
74
0
    }
75
5
    _netmask_len = len;
76
5
    return true;
77
5
}
78
79
6
bool CIDR::contains(const CIDR& ip) const {
80
6
    if ((_family != ip._family) || (_netmask_len > ip._netmask_len)) {
81
0
        return false;
82
0
    }
83
6
    auto bytes = _netmask_len / 8;
84
6
    auto cidr_begin = _address.cbegin();
85
6
    auto ip_begin = ip._address.cbegin();
86
6
    if (!std::equal(cidr_begin, cidr_begin + bytes, ip_begin, ip_begin + bytes)) {
87
2
        return false;
88
2
    }
89
4
    if ((_netmask_len % 8) == 0) {
90
2
        return true;
91
2
    }
92
2
    auto mask = (0xFF << (8 - (_netmask_len % 8))) & 0xFF;
93
2
    return (_address[bytes] & mask) == (ip._address[bytes] & mask);
94
4
}
95
96
} // end namespace doris