]>
Commit | Line | Data |
---|---|---|
41d93087 | 1 | /* |
f70aedc4 | 2 | * Copyright (C) 1996-2021 The Squid Software Foundation and contributors |
bbc27441 AJ |
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. | |
41d93087 | 7 | */ |
bbc27441 AJ |
8 | |
9 | /* DEBUG: section 14 IP Storage and Handling */ | |
10 | ||
4dd643d5 AJ |
11 | #ifndef _SQUID_SRC_IP_ADDRESS_H |
12 | #define _SQUID_SRC_IP_ADDRESS_H | |
e1f7507e | 13 | |
1a7cfe02 AJ |
14 | #include "ip/forward.h" |
15 | ||
074d6a40 AJ |
16 | #include <iosfwd> |
17 | #include <ostream> | |
41d93087 | 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 | |
cdb86165 FC |
24 | #if HAVE_NETINET_IP_H |
25 | #include <netinet/ip.h> | |
26 | #endif | |
7aa9bb3e | 27 | #if HAVE_WS2TCPIP_H |
41d93087 | 28 | #include <ws2tcpip.h> |
29 | #endif | |
489520a9 | 30 | #if HAVE_NETDB_H |
41d93087 | 31 | #include <netdb.h> |
32 | #endif | |
33 | ||
63bd4bf7 A |
34 | namespace Ip |
35 | { | |
b7ac5457 | 36 | |
41d93087 | 37 | /** |
38 | * Holds and manipulates IPv4, IPv6, and Socket Addresses. | |
39 | */ | |
b7ac5457 | 40 | class Address |
41d93087 | 41 | { |
42 | ||
43 | public: | |
4c218615 | 44 | /** @name Constructors */ |
41d93087 | 45 | /*@{*/ |
4dd643d5 | 46 | Address() { setEmpty(); } |
b7ac5457 | 47 | Address(const struct in_addr &); |
b7ac5457 | 48 | Address(const struct sockaddr_in &); |
b7ac5457 | 49 | Address(const struct in6_addr &); |
b7ac5457 | 50 | Address(const struct sockaddr_in6 &); |
b7ac5457 AJ |
51 | Address(const struct hostent &); |
52 | Address(const struct addrinfo &); | |
53 | Address(const char*); | |
41d93087 | 54 | /*@}*/ |
55 | ||
56 | /** @name Assignment Operators */ | |
57 | /*@{*/ | |
b7ac5457 AJ |
58 | Address& operator =(struct sockaddr_in const &s); |
59 | Address& operator =(struct sockaddr_storage const &s); | |
60 | Address& operator =(struct in_addr const &s); | |
b7ac5457 AJ |
61 | Address& operator =(struct in6_addr const &s); |
62 | Address& operator =(struct sockaddr_in6 const &s); | |
41d93087 | 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 | /*@{*/ | |
b7ac5457 AJ |
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; | |
41d93087 | 76 | |
77 | public: | |
78 | /* methods */ | |
79 | ||
80 | /** Test whether content can be used as an IPv4 address | |
3392646b AJ |
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. | |
41d93087 | 83 | */ |
4dd643d5 | 84 | bool isIPv4() const; |
41d93087 | 85 | |
86 | /** Test whether content can be used as an IPv6 address. | |
0906f01d CT |
87 | \retval true if content is a non IPv4-mapped address. |
88 | \retval false if content is IPv4-mapped. | |
41d93087 | 89 | */ |
4dd643d5 | 90 | bool isIPv6() const; |
41d93087 | 91 | |
92 | /** Test whether content can be used as a Socket address. | |
3392646b AJ |
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) | |
41d93087 | 96 | */ |
4dd643d5 | 97 | bool isSockAddr() const; |
41d93087 | 98 | |
99 | /** Content-neutral test for whether the specific IP case ANY_ADDR is stored. | |
b7ac5457 | 100 | * This is the default content of a new undefined Ip::Address object. |
3392646b AJ |
101 | \retval true IPv4 0.0.0.0 |
102 | \retval true IPv6 :: | |
103 | \retval false anything else. | |
41d93087 | 104 | */ |
4dd643d5 | 105 | bool isAnyAddr() const; |
41d93087 | 106 | |
107 | /** Content-neutral test for whether the specific IP case NO_ADDR is stored. | |
3392646b AJ |
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. | |
41d93087 | 111 | */ |
4dd643d5 | 112 | bool isNoAddr() const; |
41d93087 | 113 | |
114 | /** Content-neutral test for whether the specific IP case LOCALHOST is stored. | |
b7ac5457 | 115 | * This is the default content of a new undefined Ip::Address object. |
3392646b AJ |
116 | \retval true IPv4 127.0.0.1 |
117 | \retval true IPv6 ::1 | |
118 | \retval false anything else. | |
41d93087 | 119 | */ |
4dd643d5 | 120 | bool isLocalhost() const; |
41d93087 | 121 | |
a98c2da5 | 122 | /** Test whether content is an IPv6 Site-Local address. |
dd19b634 | 123 | \retval true if address begins with fd00::/8. |
a98c2da5 | 124 | \retval false if --disable-ipv6 has been compiled. |
dd19b634 | 125 | \retval false if address does not match fd00::/8 |
a98c2da5 | 126 | */ |
4dd643d5 | 127 | bool isSiteLocal6() const; |
a98c2da5 | 128 | |
2f8abb64 | 129 | /** Test whether content is an IPv6 address with SLAAC EUI-64 embedded. |
a98c2da5 AJ |
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 | */ | |
4dd643d5 | 134 | bool isSiteLocalAuto() const; |
a98c2da5 | 135 | |
41d93087 | 136 | /*@}*/ |
137 | ||
138 | /** Retrieve the Port if stored. | |
61beade2 | 139 | \retval 0 Port is unset or an error occurred. |
3392646b | 140 | \retval n Port associated with this address in host native -endian. |
41d93087 | 141 | */ |
4dd643d5 | 142 | unsigned short port() const; |
41d93087 | 143 | |
144 | /** Set the Port value for an address. | |
145 | * Replaces any previously existing Port value. | |
3392646b | 146 | \param port Port being assigned in host native -endian. |
61beade2 | 147 | \retval 0 Port is unset or an error occurred. |
3392646b | 148 | \retval n Port associated with this address in host native -endian. |
41d93087 | 149 | */ |
4dd643d5 | 150 | unsigned short port(unsigned short port); |
41d93087 | 151 | |
152 | /// Set object to contain the specific IP case ANY_ADDR (format-neutral). | |
4dd643d5 AJ |
153 | /// see isAnyAddr() for more detail. |
154 | void setAnyAddr(); | |
41d93087 | 155 | |
156 | /// Set object to contain the specific IP case NO_ADDR (format-neutral). | |
4dd643d5 AJ |
157 | /// see isNoAddr() for more detail. |
158 | void setNoAddr(); | |
41d93087 | 159 | |
160 | /// Set object to contain the specific IP case LOCALHOST (format-neutral). | |
4dd643d5 AJ |
161 | /// see isLocalhost() for more detail. |
162 | void setLocalhost(); | |
41d93087 | 163 | |
164 | /// Fast reset of the stored content to what would be after default constructor. | |
4dd643d5 | 165 | void setEmpty(); |
41d93087 | 166 | |
167 | /** Require an IPv4-only address for this usage. | |
168 | * Converts the object to prefer only IPv4 output. | |
f53969cc SM |
169 | \retval true Content can be IPv4 |
170 | \retval false Content CANNOT be IPv4 | |
41d93087 | 171 | */ |
4dd643d5 | 172 | bool setIPv4(); |
41d93087 | 173 | |
174 | /** | |
175 | * Valid results IF and only IF the stored IP address is actually a network bitmask | |
3392646b | 176 | \retval N number of bits which are set in the bitmask stored. |
41d93087 | 177 | */ |
4dd643d5 | 178 | int cidr() const; |
41d93087 | 179 | |
180 | /** Apply a mask to the stored address. | |
3392646b | 181 | \param mask Netmask format to be bit-mask-AND'd over the stored address. |
41d93087 | 182 | */ |
4dd643d5 | 183 | int applyMask(const Address &mask); |
41d93087 | 184 | |
185 | /** Apply a mask to the stored address. | |
186 | * CIDR will be converted appropriate to map the stored content. | |
3392646b AJ |
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) | |
41d93087 | 189 | */ |
4dd643d5 | 190 | bool applyMask(const unsigned int cidr, int mtype); |
41d93087 | 191 | |
36c774f7 EB |
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 | ||
41d93087 | 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. | |
3392646b AJ |
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. | |
41d93087 | 207 | */ |
4dd643d5 | 208 | char* toStr(char *buf, const unsigned int blen, int force = AF_UNSPEC) const; |
41d93087 | 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) | |
3392646b AJ |
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. | |
41d93087 | 217 | */ |
4dd643d5 | 218 | char* toUrl(char *buf, unsigned int len) const; |
41d93087 | 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) | |
3392646b AJ |
224 | \param buf Allocated buffer to write address to |
225 | \param len byte length of buffer available for writing. | |
de12d836 | 226 | \return amount of buffer filled. |
41d93087 | 227 | */ |
4dd643d5 | 228 | unsigned int toHostStr(char *buf, const unsigned int len) const; |
41d93087 | 229 | |
fd9c47d1 AR |
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 | ||
3392646b | 236 | /** |
41d93087 | 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. | |
d85b8894 AJ |
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. | |
41d93087 | 244 | */ |
4dd643d5 | 245 | bool getReverseString(char buf[MAX_IPSTRLEN], int show_type = AF_UNSPEC) const; |
41d93087 | 246 | |
247 | /** Test how two IP relate to each other. | |
3392646b AJ |
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. | |
41d93087 | 251 | */ |
b7ac5457 | 252 | int matchIPAddr(const Address &rhs) const; |
41d93087 | 253 | |
607a7bd4 AR |
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 | */ | |
a67d2b2e | 259 | int compareWhole(const Ip::Address &rhs) const; |
607a7bd4 | 260 | |
41d93087 | 261 | /** |
b7ac5457 | 262 | * Get RFC 3493 addrinfo structure from the Ip::Address data |
41d93087 | 263 | * for protocol-neutral socket operations. |
264 | * Should be passed a NULL pointer of type struct addrinfo* it will | |
851614a8 | 265 | * allocate memory for the structures involved. (see FreeAddr() to clear). |
41d93087 | 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. | |
3392646b | 270 | \par |
851614a8 | 271 | * Ip::Address allocated objects MUST be destructed by Ip::Address::FreeAddr |
41d93087 | 272 | * System getaddrinfo() allocated objects MUST be freed with system freeaddrinfo() |
41d93087 | 273 | * |
3392646b AJ |
274 | \param ai structure to be filled out. |
275 | \param force a specific sockaddr type is needed. default: don't care. | |
41d93087 | 276 | */ |
4dd643d5 | 277 | void getAddrInfo(struct addrinfo *&ai, int force = AF_UNSPEC) const; |
41d93087 | 278 | |
279 | /** | |
b7ac5457 | 280 | * Equivalent to the sysem call freeaddrinfo() but for Ip::Address allocated data |
41d93087 | 281 | */ |
851614a8 | 282 | static void FreeAddr(struct addrinfo *&ai); |
41d93087 | 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. | |
3392646b | 288 | \param ai addrinfo struct to be initialized as AF_UNSPEC with large address buffer |
41d93087 | 289 | */ |
851614a8 | 290 | static void InitAddr(struct addrinfo *&ai); |
41d93087 | 291 | |
292 | /** | |
293 | * Lookup a Host by Name. Equivalent to system call gethostbyname(char*) | |
3392646b | 294 | \param s The textual FQDN of the host being located. |
f53969cc SM |
295 | \retval true lookup was successful and an IPA was located. |
296 | \retval false lookup failed or FQDN has no IP associated. | |
41d93087 | 297 | */ |
298 | bool GetHostByName(const char *s); | |
299 | ||
7976fed3 EB |
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 | ||
41d93087 | 304 | public: |
9837567d | 305 | /* XXX: When C => C++ conversion is done will be fully private. |
41d93087 | 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 | |
4dd643d5 | 311 | * they are intentionaly hard to use, use getAddrInfo() instead. |
2f8abb64 | 312 | * these functions WILL NOT be in the final public API after transition. |
41d93087 | 313 | */ |
314 | ||
4dd643d5 AJ |
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; | |
41d93087 | 320 | |
321 | private: | |
322 | /* Conversion for dual-type internals */ | |
323 | ||
4dd643d5 | 324 | bool getReverseString4(char buf[MAX_IPSTRLEN], const struct in_addr &dat) const; |
41d93087 | 325 | |
4dd643d5 | 326 | bool getReverseString6(char buf[MAX_IPSTRLEN], const struct in6_addr &dat) const; |
41d93087 | 327 | |
4dd643d5 | 328 | void map4to6(const struct in_addr &src, struct in6_addr &dest) const; |
41d93087 | 329 | |
4dd643d5 | 330 | void map6to4(const struct in6_addr &src, struct in_addr &dest) const; |
41d93087 | 331 | |
332 | // Worker behind GetHostName and char* converters | |
4dd643d5 | 333 | bool lookupHostIP(const char *s, bool nodns); |
41d93087 | 334 | |
335 | /* variables */ | |
4dd643d5 | 336 | struct sockaddr_in6 mSocketAddr_; |
c0248e14 HN |
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; | |
c0248e14 HN |
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; | |
0eb08770 | 350 | static const struct in6_addr v4_noaddr; |
c0248e14 | 351 | static const struct in6_addr v6_noaddr; |
41d93087 | 352 | }; |
353 | ||
354 | inline std::ostream & | |
b7ac5457 | 355 | operator << (std::ostream &os, const Address &ipa) |
41d93087 | 356 | { |
357 | char buf[MAX_IPSTRLEN]; | |
4dd643d5 | 358 | os << ipa.toUrl(buf,MAX_IPSTRLEN); |
41d93087 | 359 | return os; |
360 | } | |
361 | ||
41d93087 | 362 | // WAS _sockaddr_in_list in an earlier incarnation |
b7ac5457 | 363 | class Address_list |
41d93087 | 364 | { |
365 | public: | |
b7ac5457 AJ |
366 | Address_list() { next = NULL; }; |
367 | ~Address_list() { if (next) delete next; next = NULL; }; | |
41d93087 | 368 | |
b7ac5457 AJ |
369 | Address s; |
370 | Address_list *next; | |
41d93087 | 371 | }; |
372 | ||
e5519212 | 373 | } // namespace Ip |
b7ac5457 | 374 | |
82afb125 | 375 | void parse_IpAddress_list_token(Ip::Address_list **, char *); |
41d93087 | 376 | |
4dd643d5 | 377 | #endif /* _SQUID_SRC_IP_ADDRESS_H */ |
f53969cc | 378 |