Skip to content

Commit cbfff3a

Browse files
libswoc: update maxmind plugin to IPSpace.
1 parent db516eb commit cbfff3a

File tree

4 files changed

+288
-13
lines changed

4 files changed

+288
-13
lines changed

include/tscpp/util/ts_ip.h

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
/** @file
2+
3+
IP address handling support.
4+
5+
@section license License
6+
7+
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.
8+
See the NOTICE file distributed with this work for additional information regarding copyright
9+
ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
"License"); you may not use this file except in compliance with the License. You may obtain a
11+
copy of the License at
12+
13+
http://www.apache.org/licenses/LICENSE-2.0
14+
15+
Unless required by applicable law or agreed to in writing, software distributed under the License
16+
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
17+
or implied. See the License for the specific language governing permissions and limitations under
18+
the License.
19+
*/
20+
21+
#pragma once
22+
23+
#include <tuple>
24+
25+
#include "swoc/swoc_ip.h"
26+
27+
namespace ts
28+
{
29+
/// Pair of addresses, each optional.
30+
/// Used in situations where both an IPv4 and IPv6 may be needed.
31+
class IPAddrPair
32+
{
33+
public:
34+
using self_type = IPAddrPair;
35+
36+
IPAddrPair() = default;
37+
bool
38+
has_value() const
39+
{
40+
return _ip4.has_value() || _ip6.has_value();
41+
}
42+
bool
43+
has_ip4() const
44+
{
45+
return _ip4.has_value();
46+
}
47+
bool
48+
has_ip6() const
49+
{
50+
return _ip6.has_value();
51+
}
52+
53+
swoc::IP4Addr const &
54+
ip4() const
55+
{
56+
return _ip4.value();
57+
}
58+
swoc::IP6Addr const &
59+
ip6() const
60+
{
61+
return _ip6.value();
62+
}
63+
64+
self_type &
65+
operator=(swoc::IP4Addr const &addr)
66+
{
67+
_ip4 = addr;
68+
return *this;
69+
}
70+
self_type &
71+
operator=(swoc::IP6Addr const &addr)
72+
{
73+
_ip6 = addr;
74+
return *this;
75+
}
76+
self_type &
77+
operator=(swoc::IPAddr const &addr)
78+
{
79+
if (addr.is_ip4()) {
80+
_ip4 = addr.ip4();
81+
} else if (addr.is_ip6()) {
82+
_ip6 = addr.ip6();
83+
}
84+
return *this;
85+
}
86+
87+
protected:
88+
std::optional<swoc::IP4Addr> _ip4;
89+
std::optional<swoc::IP6Addr> _ip6;
90+
};
91+
92+
/// Pair of services, each optional.
93+
/// Used in situations where both an IPv4 and IPv6 may be needed.
94+
class IPSrvPair
95+
{
96+
public:
97+
using self_type = IPSrvPair;
98+
99+
IPSrvPair() = default;
100+
IPSrvPair(swoc::IP4Addr const &a4, swoc::IP6Addr const &a6, in_port_t port = 0)
101+
: _ip4(swoc::IP4Srv(a4, port)), _ip6(swoc::IP6Srv(a6, port))
102+
{
103+
}
104+
IPSrvPair(IPAddrPair const &a, in_port_t port = 0)
105+
{
106+
if (a.has_ip4())
107+
_ip4 = swoc::IP4Srv(a.ip4(), port);
108+
if (a.has_ip6())
109+
_ip6 = swoc::IP6Srv(a.ip6(), port);
110+
}
111+
112+
bool
113+
has_value() const
114+
{
115+
return _ip4.has_value() || _ip6.has_value();
116+
}
117+
bool
118+
has_ip4() const
119+
{
120+
return _ip4.has_value();
121+
}
122+
bool
123+
has_ip6() const
124+
{
125+
return _ip6.has_value();
126+
}
127+
128+
swoc::IP4Srv const &
129+
ip4() const
130+
{
131+
return _ip4.value();
132+
}
133+
swoc::IP6Srv const &
134+
ip6() const
135+
{
136+
return _ip6.value();
137+
}
138+
139+
self_type &
140+
operator=(swoc::IP4Srv const &srv)
141+
{
142+
_ip4 = srv;
143+
return *this;
144+
}
145+
self_type &
146+
operator=(swoc::IP6Srv const &srv)
147+
{
148+
_ip6 = srv;
149+
return *this;
150+
}
151+
self_type &
152+
operator=(swoc::IPSrv const &srv)
153+
{
154+
if (srv.is_ip4()) {
155+
_ip4 = srv.ip4();
156+
} else if (srv.is_ip6()) {
157+
_ip6 = srv.ip6();
158+
}
159+
return *this;
160+
}
161+
162+
protected:
163+
std::optional<swoc::IP4Srv> _ip4;
164+
std::optional<swoc::IP6Srv> _ip6;
165+
};
166+
167+
/** Get the best address info for @a name.
168+
169+
* @param name Address / host.
170+
* @param ip4 [out] Best IPv4 result, if any.
171+
* @param ip6 [out] Best IPv6 result, if any.
172+
* @return @c true if an address was found, @c false if not.
173+
*
174+
* If @a name is a valid IP address it is interpreted as such. Otherwise it is presumed
175+
* to be a host name suitable for resolution using @c getaddrinfo. The "best" address is
176+
* selected by ranking the types of addresss in the order
177+
*
178+
* - Global, multi-cast, non-routable (private), link local, loopback
179+
*
180+
* For a host name, both IPv4 and IPv6 addresses may be returned. Each is judged
181+
* independently.
182+
*
183+
* Either @a ip4 or @ip6 can be @c nullptr in which that result is discarded.
184+
*
185+
* @note If @name is known or required to be an IP address, use a standard address conversion
186+
* instead, e.g. @c IPAddr::load .
187+
*
188+
* @see getaddrinfo
189+
*/
190+
IPAddrPair getbestaddrinfo(swoc::TextView name);
191+
192+
/** Get the best address info for @a name.
193+
194+
* @param name Address / host.
195+
* @param ip4 [out] Best IPv4 result, if any.
196+
* @param ip6 [out] Best IPv6 result, if any.
197+
* @return @c true if an address was found, @c false if not.
198+
*
199+
* If @a name is a valid IP address it is interpreted as such. Otherwise it is presumed
200+
* to be a host name suitable for resolution using @c getaddrinfo. The "best" address is
201+
* selected by ranking the types of addresss in the order
202+
*
203+
* - Global, multi-cast, non-routable (private), link local, loopback
204+
*
205+
* For a host name, both IPv4 and IPv6 addresses may be returned. Each is judged
206+
* independently.
207+
*
208+
* Either @a ip4 or @ip6 can be @c nullptr in which that result is discarded.
209+
*
210+
* @note If @name is known or required to be an IP address, use a standard address conversion
211+
* instead, e.g. @c IPAddr::load .
212+
*
213+
* @see getaddrinfo
214+
*/
215+
IPSrvPair getbestsrvinfo(swoc::TextView name);
216+
217+
/// An IPSpace that only tracks the presence of IP addresses.
218+
class IPAddrSet
219+
{
220+
using self_type = IPAddrSet;
221+
222+
public:
223+
/// Default construct empty set.
224+
IPAddrSet() = default;
225+
226+
/** Add addresses to the set.
227+
*
228+
* @param r Range of addresses to add.
229+
* @return @a this
230+
*/
231+
self_type &
232+
fill(swoc::IPRange const &r)
233+
{
234+
_addrs.fill(r, MARK);
235+
return *this;
236+
}
237+
238+
/// @return @c true if @a addr is in the set.
239+
bool
240+
contains(swoc::IPAddr const &addr) const
241+
{
242+
return _addrs.find(addr) != _addrs.end();
243+
}
244+
245+
/// @return Number of ranges in the set.
246+
size_t
247+
count() const
248+
{
249+
return _addrs.count();
250+
}
251+
252+
protected:
253+
/// Empty struct to use for payload.
254+
static inline constexpr struct Mark {
255+
using self_type = Mark;
256+
bool
257+
operator==(self_type const &that)
258+
{
259+
return true;
260+
}
261+
bool
262+
operator!=(self_type const &that)
263+
{
264+
return false;
265+
}
266+
} MARK{};
267+
/// The address set.
268+
swoc::IPSpace<Mark> _addrs;
269+
};
270+
271+
} // namespace ts

lib/swoc/include/swoc/IPRange.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,9 @@ class IPRange {
373373
/// @return The IPv6 range.
374374
IP6Range const & ip6() const { return _range._ip6; }
375375

376+
/// @return The range family.
377+
sa_family_t family() const { return _family; }
378+
376379
/** Compute the mask for @a this as a network.
377380
*
378381
* @return If @a this is a network, the mask for that network. Otherwise an invalid mask.

plugins/experimental/maxmind_acl/mmdb.cc

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,10 @@ Acl::loaddeny(const YAML::Node &denyNode)
242242
if (ip.IsSequence()) {
243243
// Do IP Deny processing
244244
for (auto &&i : ip) {
245-
IpAddr min, max;
246-
ats_ip_range_parse(std::string_view{i.as<std::string>()}, min, max);
247-
deny_ip_map.fill(min, max, nullptr);
248-
TSDebug(PLUGIN_NAME, "loading ip: valid: %d, fam %d ", min.isValid(), min.family());
245+
if (swoc::IPRange r; r.load(i.Scalar())) {
246+
deny_ip_map.fill(r);
247+
TSDebug(PLUGIN_NAME, "Denying ip fam %d ", r.family());
248+
}
249249
}
250250
} else {
251251
TSDebug(PLUGIN_NAME, "Invalid IP deny list yaml");
@@ -323,10 +323,10 @@ Acl::loadallow(const YAML::Node &allowNode)
323323
if (ip.IsSequence()) {
324324
// Do IP Allow processing
325325
for (auto &&i : ip) {
326-
IpAddr min, max;
327-
ats_ip_range_parse(std::string_view{i.as<std::string>()}, min, max);
328-
allow_ip_map.fill(min, max, nullptr);
329-
TSDebug(PLUGIN_NAME, "loading ip: valid: %d, fam %d ", min.isValid(), min.family());
326+
if (swoc::IPRange r; r.load(i.Scalar())) {
327+
allow_ip_map.fill(r);
328+
TSDebug(PLUGIN_NAME, "loading ip: valid: fam %d ", r.family());
329+
}
330330
}
331331
} else {
332332
TSDebug(PLUGIN_NAME, "Invalid IP allow list yaml");
@@ -749,12 +749,13 @@ Acl::eval_ip(const sockaddr *sock) const
749749
}
750750
#endif
751751

752-
if (allow_ip_map.contains(sock, nullptr)) {
752+
swoc::IPAddr addr(sock);
753+
if (allow_ip_map.contains(addr)) {
753754
// Allow map has this ip, we know we want to allow it
754755
return ALLOW_IP;
755756
}
756757

757-
if (deny_ip_map.contains(sock, nullptr)) {
758+
if (deny_ip_map.contains(addr)) {
758759
// Deny map has this ip, explicitly deny
759760
return DENY_IP;
760761
}

plugins/experimental/maxmind_acl/mmdb.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
#include <unistd.h>
3737
#include <iterator>
3838
#include <maxminddb.h>
39-
#include "tscore/IpMap.h"
39+
#include "tscpp/util/ts_ip.h"
4040

4141
#ifdef HAVE_PCRE_PCRE_H
4242
#include <pcre/pcre.h>
@@ -91,8 +91,8 @@ class Acl
9191
std::unordered_map<std::string, std::vector<plugin_regex>> allow_regex;
9292
std::unordered_map<std::string, std::vector<plugin_regex>> deny_regex;
9393

94-
IpMap allow_ip_map;
95-
IpMap deny_ip_map;
94+
ts::IPAddrSet allow_ip_map;
95+
ts::IPAddrSet deny_ip_map;
9696

9797
// Anonymous blocking default to off
9898
bool _anonymous_ip = false;

0 commit comments

Comments
 (0)