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