1 //--------------------------------------------------------------------------
2 // Copyright (C) 2014-2021 Cisco and/or its affiliates. All rights reserved.
3 // Copyright (C) 1998-2013 Sourcefire, Inc.
4 //
5 // This program is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License Version 2 as published
7 // by the Free Software Foundation. You may not use, modify or distribute
8 // this program under any other version of the GNU General Public License.
9 //
10 // This program is distributed in the hope that it will be useful, but
11 // WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 //--------------------------------------------------------------------------
19 // sf_cidr.h author Michael Altizer <mialtize@cisco.com>
20
21 #ifndef SF_CIDR_H
22 #define SF_CIDR_H
23
24 #include "sfip/sf_ip.h"
25
26 namespace snort
27 {
28 /*
29 * NOTE: As much as I'd love to make this a subclass of SfIp, member layout
30 * is undefined for POD inheritance.
31 */
32
33 struct SO_PUBLIC SfCidr
34 {
35 /*
36 * Constructors
37 */
38 SfCidr() = default;
39
40 /*
41 * Modifiers (incl. convenience ones that delegate to addr)
42 */
43 void clear();
44 void set(const SfCidr& src);
45 void set(const SfIp& src);
46 SfIpRet set(const void* src, int fam);
47 SfIpRet set(const char* src);
48 void set_bits(uint16_t new_bits);
49
50 /*
51 * Accessors (incl. convenience ones that delegate to addr)
52 */
53 const SfIp* get_addr() const;
54 uint16_t get_family() const;
55 uint16_t get_bits() const;
56 bool is_set() const;
57
58 /*
59 * Containment checks
60 */
61 bool fast_cont4(const SfIp& ip) const;
62 bool fast_cont6(const SfIp& ip) const;
63 SfIpRet contains(const SfIp* ip) const;
64
65 const char* ntop(SfIpString) const;
66 SfIpRet compare(const SfCidr&) const;
67
68 private:
69 SfIp addr;
70 uint16_t bits;
71 } __attribute__((__packed__));
72
73
clear()74 inline void SfCidr::clear()
75 {
76 addr.clear();
77 bits = 0;
78 }
79
set(const SfCidr & src)80 inline void SfCidr::set(const SfCidr& src)
81 {
82 addr = src.addr;
83 bits = src.bits;
84 }
85
set(const SfIp & src)86 inline void SfCidr::set(const SfIp& src)
87 {
88 addr = src;
89 bits = 128;
90 }
91
set(const void * src,int fam)92 inline SfIpRet SfCidr::set(const void* src, int fam)
93 {
94 SfIpRet ret = addr.set(src, fam);
95 if (ret != SFIP_SUCCESS)
96 return ret;
97 bits = 128;
98 return SFIP_SUCCESS;
99 }
100
set_bits(uint16_t new_bits)101 inline void SfCidr::set_bits(uint16_t new_bits)
102 {
103 if (new_bits > 128)
104 return;
105 bits = new_bits;
106 }
107
get_addr()108 inline const SfIp* SfCidr::get_addr() const
109 {
110 return &addr;
111 }
112
get_family()113 inline uint16_t SfCidr::get_family() const
114 {
115 return addr.get_family();
116 }
117
get_bits()118 inline uint16_t SfCidr::get_bits() const
119 {
120 return bits;
121 }
122
is_set()123 inline bool SfCidr::is_set() const
124 {
125 return (addr.is_set() ||
126 ((addr.get_family() == AF_INET || addr.get_family() == AF_INET6) &&
127 bits != 128));
128 }
129
fast_cont4(const SfIp & ip)130 inline bool SfCidr::fast_cont4(const SfIp& ip) const
131 {
132 uint32_t shift = 128 - bits;
133 uint32_t needle = ntohl(ip.get_ip4_value());
134 uint32_t haystack = ntohl(addr.get_ip4_value());
135
136 if (haystack == 0)
137 return true;
138
139 needle >>= shift;
140 needle <<= shift;
141
142 return haystack == needle;
143 }
144
fast_cont6(const SfIp & ip)145 inline bool SfCidr::fast_cont6(const SfIp& ip) const
146 {
147 uint32_t needle;
148 int words = bits / 32;
149 int shift, i;
150
151 for (i = 0; i < words; i++)
152 {
153 if (addr.get_ip6_ptr()[i] != ip.get_ip6_ptr()[i])
154 return false;
155 }
156
157 shift = 32 - (bits % 32);
158 if (shift == 32)
159 return true;
160
161 needle = ntohl(ip.get_ip6_ptr()[i]);
162
163 needle >>= shift;
164 needle <<= shift;
165
166 return ntohl(addr.get_ip6_ptr()[i]) == needle;
167 }
168
ntop(SfIpString ip_str)169 inline const char* SfCidr::ntop(SfIpString ip_str) const
170 {
171 return addr.ntop(ip_str);
172 }
173
compare(const SfCidr & cidr2)174 inline SfIpRet SfCidr::compare(const SfCidr& cidr2) const
175 {
176 SfIpRet ret = addr.compare(*cidr2.get_addr());
177 if(SFIP_EQUAL == ret)
178 {
179 if(bits < cidr2.get_bits()) return SFIP_LESSER;
180 if(bits > cidr2.get_bits()) return SFIP_GREATER;
181 }
182 return ret;
183 }
184 }
185 #endif
186