]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | /* DEBUG: section 14 IP Storage and Handling */ | |
10 | ||
11 | #ifndef _SQUID_SRC_IP_ADDRESS_H | |
12 | #define _SQUID_SRC_IP_ADDRESS_H | |
13 | ||
14 | #include "ip/forward.h" | |
15 | ||
16 | #include <iosfwd> | |
17 | #include <ostream> | |
18 | #if HAVE_SYS_SOCKET_H | |
19 | #include <sys/socket.h> | |
20 | #endif | |
21 | #if HAVE_NETINET_IN_H | |
22 | #include <netinet/in.h> | |
23 | #endif | |
24 | #if HAVE_NETINET_IP_H | |
25 | #include <netinet/ip.h> | |
26 | #endif | |
27 | #if HAVE_WS2TCPIP_H | |
28 | #include <ws2tcpip.h> | |
29 | #endif | |
30 | #if HAVE_NETDB_H | |
31 | #include <netdb.h> | |
32 | #endif | |
33 | ||
34 | namespace Ip | |
35 | { | |
36 | ||
37 | /** | |
38 | * Holds and manipulates IPv4, IPv6, and Socket Addresses. | |
39 | */ | |
40 | class Address | |
41 | { | |
42 | ||
43 | public: | |
44 | /** @name Constructors */ | |
45 | /*@{*/ | |
46 | Address() { setEmpty(); } | |
47 | Address(const struct in_addr &); | |
48 | Address(const struct sockaddr_in &); | |
49 | Address(const struct in6_addr &); | |
50 | Address(const struct sockaddr_in6 &); | |
51 | Address(const struct hostent &); | |
52 | Address(const struct addrinfo &); | |
53 | Address(const char*); | |
54 | /*@}*/ | |
55 | ||
56 | /** @name Assignment Operators */ | |
57 | /*@{*/ | |
58 | Address& operator =(struct sockaddr_in const &s); | |
59 | Address& operator =(struct sockaddr_storage const &s); | |
60 | Address& operator =(struct in_addr const &s); | |
61 | Address& operator =(struct in6_addr const &s); | |
62 | Address& operator =(struct sockaddr_in6 const &s); | |
63 | bool operator =(const struct hostent &s); | |
64 | bool operator =(const struct addrinfo &s); | |
65 | bool operator =(const char *s); | |
66 | /*@}*/ | |
67 | ||
68 | /** @name Boolean Operators */ | |
69 | /*@{*/ | |
70 | bool operator ==(Address const &s) const; | |
71 | bool operator !=(Address const &s) const; | |
72 | bool operator >=(Address const &rhs) const; | |
73 | bool operator <=(Address const &rhs) const; | |
74 | bool operator >(Address const &rhs) const; | |
75 | bool operator <(Address const &rhs) const; | |
76 | ||
77 | public: | |
78 | /* methods */ | |
79 | ||
80 | /** Test whether content can be used as an IPv4 address | |
81 | \retval true if content was received as an IPv4-Mapped address | |
82 | \retval false if content was received as a non-mapped IPv6 native address. | |
83 | */ | |
84 | bool isIPv4() const; | |
85 | ||
86 | /** Test whether content can be used as an IPv6 address. | |
87 | \retval true if content is a non IPv4-mapped address. | |
88 | \retval false if content is IPv4-mapped. | |
89 | */ | |
90 | bool isIPv6() const; | |
91 | ||
92 | /** Test whether content can be used as a Socket address. | |
93 | \retval true if address AND port are both set | |
94 | \retval true if content was received as a Socket address with port | |
95 | \retval false if port in unset (zero) | |
96 | */ | |
97 | bool isSockAddr() const; | |
98 | ||
99 | /** Content-neutral test for whether the specific IP case ANY_ADDR is stored. | |
100 | * This is the default content of a new undefined Ip::Address object. | |
101 | \retval true IPv4 0.0.0.0 | |
102 | \retval true IPv6 :: | |
103 | \retval false anything else. | |
104 | */ | |
105 | bool isAnyAddr() const; | |
106 | ||
107 | /** Content-neutral test for whether the specific IP case NO_ADDR is stored. | |
108 | \retval true IPv4 255.255.255.255 | |
109 | \retval true IPv6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | |
110 | \retval false anything else. | |
111 | */ | |
112 | bool isNoAddr() const; | |
113 | ||
114 | /** Content-neutral test for whether the specific IP case LOCALHOST is stored. | |
115 | * This is the default content of a new undefined Ip::Address object. | |
116 | \retval true IPv4 127.0.0.1 | |
117 | \retval true IPv6 ::1 | |
118 | \retval false anything else. | |
119 | */ | |
120 | bool isLocalhost() const; | |
121 | ||
122 | /** Test whether content is an IPv6 Site-Local address. | |
123 | \retval true if address begins with fd00::/8. | |
124 | \retval false if --disable-ipv6 has been compiled. | |
125 | \retval false if address does not match fd00::/8 | |
126 | */ | |
127 | bool isSiteLocal6() const; | |
128 | ||
129 | /** Test whether content is an IPv6 address with SLAAC EUI-64 embedded. | |
130 | \retval true if address matches ::ff:fe00:0 | |
131 | \retval false if --disable-ipv6 has been compiled. | |
132 | \retval false if address does not match ::ff:fe00:0 | |
133 | */ | |
134 | bool isSiteLocalAuto() const; | |
135 | ||
136 | /*@}*/ | |
137 | ||
138 | /** Retrieve the Port if stored. | |
139 | \retval 0 Port is unset or an error occurred. | |
140 | \retval n Port associated with this address in host native -endian. | |
141 | */ | |
142 | unsigned short port() const; | |
143 | ||
144 | /** Set the Port value for an address. | |
145 | * Replaces any previously existing Port value. | |
146 | \param port Port being assigned in host native -endian. | |
147 | \retval 0 Port is unset or an error occurred. | |
148 | \retval n Port associated with this address in host native -endian. | |
149 | */ | |
150 | unsigned short port(unsigned short port); | |
151 | ||
152 | /// Set object to contain the specific IP case ANY_ADDR (format-neutral). | |
153 | /// see isAnyAddr() for more detail. | |
154 | void setAnyAddr(); | |
155 | ||
156 | /// Set object to contain the specific IP case NO_ADDR (format-neutral). | |
157 | /// see isNoAddr() for more detail. | |
158 | void setNoAddr(); | |
159 | ||
160 | /// Set object to contain the specific IP case LOCALHOST (format-neutral). | |
161 | /// see isLocalhost() for more detail. | |
162 | void setLocalhost(); | |
163 | ||
164 | /// Fast reset of the stored content to what would be after default constructor. | |
165 | void setEmpty(); | |
166 | ||
167 | /** Require an IPv4-only address for this usage. | |
168 | * Converts the object to prefer only IPv4 output. | |
169 | \retval true Content can be IPv4 | |
170 | \retval false Content CANNOT be IPv4 | |
171 | */ | |
172 | bool setIPv4(); | |
173 | ||
174 | /** | |
175 | * Valid results IF and only IF the stored IP address is actually a network bitmask | |
176 | \retval N number of bits which are set in the bitmask stored. | |
177 | */ | |
178 | int cidr() const; | |
179 | ||
180 | /** Apply a mask to the stored address. | |
181 | \param mask Netmask format to be bit-mask-AND'd over the stored address. | |
182 | */ | |
183 | int applyMask(const Address &mask); | |
184 | ||
185 | /** Apply a mask to the stored address. | |
186 | * CIDR will be converted appropriate to map the stored content. | |
187 | \param cidr CIDR Mask being applied. As an integer in host format. | |
188 | \param mtype Type of CIDR mask being applied (AF_INET or AF_INET6) | |
189 | */ | |
190 | bool applyMask(const unsigned int cidr, int mtype); | |
191 | ||
192 | /// Apply so-called 'privacy masking' to IPv4 addresses, | |
193 | /// except localhost IP. | |
194 | /// IPv6 clients use 'privacy addressing' instead. | |
195 | void applyClientMask(const Address &mask); | |
196 | ||
197 | /** Return the ASCII equivalent of the address | |
198 | * Semantically equivalent to the IPv4 inet_ntoa() | |
199 | * eg. 127.0.0.1 (IPv4) or ::1 (IPv6) | |
200 | * But for memory safety it requires a buffer as input | |
201 | * instead of producing one magically. | |
202 | * If buffer is not large enough the data is truncated silently. | |
203 | \param buf Allocated buffer to write address to | |
204 | \param len byte length of buffer available for writing. | |
205 | \param force (optional) require the IPA in a specific format. | |
206 | \return pointer to buffer received. | |
207 | */ | |
208 | char* toStr(char *buf, const unsigned int blen, int force = AF_UNSPEC) const; | |
209 | ||
210 | /** Return the ASCII equivalent of the address:port combination | |
211 | * Provides a URL formatted version of the content. | |
212 | * If buffer is not large enough the data is truncated silently. | |
213 | * eg. 127.0.0.1:80 (IPv4) or [::1]:80 (IPv6) | |
214 | \param buf Allocated buffer to write address:port to | |
215 | \param len byte length of buffer available for writing. | |
216 | \return pointer to buffer received. | |
217 | */ | |
218 | char* toUrl(char *buf, unsigned int len) const; | |
219 | ||
220 | /** Return a properly hostname formatted copy of the address | |
221 | * Provides a URL formatted version of the content. | |
222 | * If buffer is not large enough the data is truncated silently. | |
223 | * eg. 127.0.0.1 (IPv4) or [::1] (IPv6) | |
224 | \param buf Allocated buffer to write address to | |
225 | \param len byte length of buffer available for writing. | |
226 | \return amount of buffer filled. | |
227 | */ | |
228 | unsigned int toHostStr(char *buf, const unsigned int len) const; | |
229 | ||
230 | /// Empties the address and then slowly imports the IP from a possibly | |
231 | /// [bracketed] portless host. For the semi-reverse operation, see | |
232 | /// toHostStr() which does export the port. | |
233 | /// \returns whether the conversion was successful | |
234 | bool fromHost(const char *hostWithoutPort); | |
235 | ||
236 | /** | |
237 | * Convert the content into a Reverse-DNS string. | |
238 | * The buffer sent MUST be allocated large enough to hold the resulting string. | |
239 | * Name truncation will occur if buf does not have enough space. | |
240 | * The constant MAX_IPSTRLEN is defined to provide for sizing arrays correctly. | |
241 | \param show_type may be one of: AF_INET, AF_INET6 for the format of rDNS string wanted. | |
242 | * AF_UNSPEC the default displays the IP in its most advanced native form. | |
243 | \param buf buffer to receive the text string output. | |
244 | */ | |
245 | bool getReverseString(char buf[MAX_IPSTRLEN], int show_type = AF_UNSPEC) const; | |
246 | ||
247 | /** Test how two IP relate to each other. | |
248 | \retval 0 IP are equal | |
249 | \retval 1 IP rhs is greater (numerically) than that stored. | |
250 | \retval -1 IP rhs is less (numerically) than that stored. | |
251 | */ | |
252 | int matchIPAddr(const Address &rhs) const; | |
253 | ||
254 | /** Compare taking IP, port, protocol, etc. into account. Returns an | |
255 | integer less than, equal to, or greater than zero if the object | |
256 | is found, respectively, to be less than, to match, or to be greater | |
257 | than rhs. The exact ordering algorithm is not specified and may change. | |
258 | */ | |
259 | int compareWhole(const Ip::Address &rhs) const; | |
260 | ||
261 | /** | |
262 | * Get RFC 3493 addrinfo structure from the Ip::Address data | |
263 | * for protocol-neutral socket operations. | |
264 | * Should be passed a NULL pointer of type struct addrinfo* it will | |
265 | * allocate memory for the structures involved. (see FreeAddr() to clear). | |
266 | * Defaults to a TCP streaming socket, if other values (such as UDP) are needed | |
267 | * the caller MUST override these default settings. | |
268 | * Some situations may also require an actual call to the system getaddrinfo() | |
269 | * to pull relevant OS details for the socket. | |
270 | \par | |
271 | * Ip::Address allocated objects MUST be destructed by Ip::Address::FreeAddr | |
272 | * System getaddrinfo() allocated objects MUST be freed with system freeaddrinfo() | |
273 | * | |
274 | \param ai structure to be filled out. | |
275 | \param force a specific sockaddr type is needed. default: don't care. | |
276 | */ | |
277 | void getAddrInfo(struct addrinfo *&ai, int force = AF_UNSPEC) const; | |
278 | ||
279 | /** | |
280 | * Equivalent to the sysem call freeaddrinfo() but for Ip::Address allocated data | |
281 | */ | |
282 | static void FreeAddr(struct addrinfo *&ai); | |
283 | ||
284 | /** | |
285 | * Initializes an empty addrinfo properly for use. | |
286 | * It is intended for use in cases such as getsockopt() where the addrinfo is | |
287 | * about to be changed and the stored details may not match the new ones coming. | |
288 | \param ai addrinfo struct to be initialized as AF_UNSPEC with large address buffer | |
289 | */ | |
290 | static void InitAddr(struct addrinfo *&ai); | |
291 | ||
292 | /** | |
293 | * Lookup a Host by Name. Equivalent to system call gethostbyname(char*) | |
294 | \param s The textual FQDN of the host being located. | |
295 | \retval true lookup was successful and an IPA was located. | |
296 | \retval false lookup failed or FQDN has no IP associated. | |
297 | */ | |
298 | bool GetHostByName(const char *s); | |
299 | ||
300 | /// \returns an Address with true isNoAddr() | |
301 | /// \see isNoAddr() for more details | |
302 | static const Address &NoAddr() { static const Address noAddr(v6_noaddr); return noAddr; } | |
303 | ||
304 | public: | |
305 | /* XXX: When C => C++ conversion is done will be fully private. | |
306 | * Legacy Transition Methods. | |
307 | * These are here solely to simplify the transition | |
308 | * when moving from converted code to unconverted | |
309 | * these functions can be used to convert this object | |
310 | * and pull out the data needed by the unconverted code | |
311 | * they are intentionaly hard to use, use getAddrInfo() instead. | |
312 | * these functions WILL NOT be in the final public API after transition. | |
313 | */ | |
314 | ||
315 | void getSockAddr(struct sockaddr_storage &addr, const int family) const; | |
316 | void getSockAddr(struct sockaddr_in &) const; | |
317 | bool getInAddr(struct in_addr &) const; /* false if could not convert IPv6 down to IPv4 */ | |
318 | void getSockAddr(struct sockaddr_in6 &) const; | |
319 | void getInAddr(struct in6_addr &) const; | |
320 | ||
321 | private: | |
322 | /* Conversion for dual-type internals */ | |
323 | ||
324 | bool getReverseString4(char buf[MAX_IPSTRLEN], const struct in_addr &dat) const; | |
325 | ||
326 | bool getReverseString6(char buf[MAX_IPSTRLEN], const struct in6_addr &dat) const; | |
327 | ||
328 | void map4to6(const struct in_addr &src, struct in6_addr &dest) const; | |
329 | ||
330 | void map6to4(const struct in6_addr &src, struct in_addr &dest) const; | |
331 | ||
332 | // Worker behind GetHostName and char* converters | |
333 | bool lookupHostIP(const char *s, bool nodns); | |
334 | ||
335 | /* variables */ | |
336 | struct sockaddr_in6 mSocketAddr_; | |
337 | ||
338 | private: | |
339 | /* Internally used constants */ | |
340 | static const unsigned int STRLEN_IP4A = 16; // aaa.bbb.ccc.ddd\0 | |
341 | static const unsigned int STRLEN_IP4R = 28; // ddd.ccc.bbb.aaa.in-addr.arpa.\0 | |
342 | static const unsigned int STRLEN_IP4S = 21; // ddd.ccc.bbb.aaa:ppppp\0 | |
343 | static const unsigned int MAX_IP4_STRLEN = STRLEN_IP4R; | |
344 | static const unsigned int STRLEN_IP6A = 42; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/0 | |
345 | static const unsigned int STRLEN_IP6R = 75; // f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f f.f.f.f ipv6.arpa./0 | |
346 | static const unsigned int STRLEN_IP6S = 48; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:00000/0 | |
347 | static const unsigned int MAX_IP6_STRLEN = STRLEN_IP6R; | |
348 | static const struct in6_addr v4_localhost; | |
349 | static const struct in6_addr v4_anyaddr; | |
350 | static const struct in6_addr v4_noaddr; | |
351 | static const struct in6_addr v6_noaddr; | |
352 | }; | |
353 | ||
354 | inline std::ostream & | |
355 | operator << (std::ostream &os, const Address &ipa) | |
356 | { | |
357 | char buf[MAX_IPSTRLEN]; | |
358 | os << ipa.toUrl(buf,MAX_IPSTRLEN); | |
359 | return os; | |
360 | } | |
361 | ||
362 | // WAS _sockaddr_in_list in an earlier incarnation | |
363 | class Address_list | |
364 | { | |
365 | public: | |
366 | Address_list() { next = NULL; }; | |
367 | ~Address_list() { if (next) delete next; next = NULL; }; | |
368 | ||
369 | Address s; | |
370 | Address_list *next; | |
371 | }; | |
372 | ||
373 | } // namespace Ip | |
374 | ||
375 | void parse_IpAddress_list_token(Ip::Address_list **, char *); | |
376 | ||
377 | #endif /* _SQUID_SRC_IP_ADDRESS_H */ | |
378 |