]>
Commit | Line | Data |
---|---|---|
41d93087 | 1 | /* |
41d93087 | 2 | * DEBUG: section 14 IP Storage and Handling |
3 | * AUTHOR: Amos Jeffries | |
4 | * | |
5 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
6 | * ---------------------------------------------------------- | |
7 | * | |
8 | * Squid is the result of efforts by numerous individuals from the | |
9 | * Internet community. Development is led by Duane Wessels of the | |
10 | * National Laboratory for Applied Network Research and funded by the | |
11 | * National Science Foundation. Squid is Copyrighted (C) 1998 by | |
12 | * the Regents of the University of California. Please see the | |
13 | * COPYRIGHT file for full details. Squid incorporates software | |
14 | * developed and/or copyrighted by other sources. Please see the | |
15 | * CREDITS file for full details. | |
16 | * | |
b7ac5457 | 17 | * This Ip::Address code is copyright (C) 2007 by Treehouse Networks Ltd |
41d93087 | 18 | * of New Zealand. It is published and Lisenced as an extension of |
19 | * squid under the same conditions as the main squid application. | |
20 | * | |
21 | * This program is free software; you can redistribute it and/or modify | |
22 | * it under the terms of the GNU General Public License as published by | |
23 | * the Free Software Foundation; either version 2 of the License, or | |
24 | * (at your option) any later version. | |
25 | * | |
26 | * This program is distributed in the hope that it will be useful, | |
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
29 | * GNU General Public License for more details. | |
30 | * | |
31 | * You should have received a copy of the GNU General Public License | |
32 | * along with this program; if not, write to the Free Software | |
33 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
34 | * | |
35 | */ | |
b7ac5457 AJ |
36 | #ifndef _SQUID_IP_IPADDRESS_H |
37 | #define _SQUID_IP_IPADDRESS_H | |
e1f7507e | 38 | |
41d93087 | 39 | #if HAVE_SYS_SOCKET_H |
40 | #include <sys/socket.h> | |
41 | #endif | |
42 | #if HAVE_NETINET_IN_H | |
43 | #include <netinet/in.h> | |
44 | #endif | |
cdb86165 FC |
45 | #if HAVE_NETINET_IP_H |
46 | #include <netinet/ip.h> | |
47 | #endif | |
1191b93b | 48 | #if _SQUID_MSWIN_ |
41d93087 | 49 | #include <ws2tcpip.h> |
50 | #endif | |
489520a9 | 51 | #if HAVE_NETDB_H |
41d93087 | 52 | #include <netdb.h> |
53 | #endif | |
54 | ||
27e059d4 | 55 | #if HAVE_IOSFWD |
41d93087 | 56 | #include <iosfwd> |
27e059d4 AJ |
57 | #endif |
58 | #if HAVE_OSTREAM | |
a031cbf8 | 59 | #include <ostream> |
27e059d4 | 60 | #endif |
41d93087 | 61 | |
63bd4bf7 A |
62 | namespace Ip |
63 | { | |
b7ac5457 | 64 | |
41d93087 | 65 | /// Length of buffer that needs to be allocated to old a null-terminated IP-string |
66 | // Yuck. But there are still structures that need it to be an 'integer constant'. | |
67 | #define MAX_IPSTRLEN 75 | |
68 | ||
69 | /** | |
70 | * Holds and manipulates IPv4, IPv6, and Socket Addresses. | |
71 | */ | |
b7ac5457 | 72 | class Address |
41d93087 | 73 | { |
74 | ||
75 | public: | |
76 | /** @name Constructors and Destructor */ | |
77 | /*@{*/ | |
3cbeddcf | 78 | Address() { SetEmpty(); } |
b7ac5457 | 79 | Address(const Address &); |
41d93087 | 80 | |
81 | /** | |
82 | * This constructor takes its own copy of the object pointed to for memory-safe usage later. | |
83 | * The caller must itself perform and ptr memory-management needed. | |
84 | * | |
85 | \deprecated Use of pointers can be nasty. Consider this a last-resort. | |
86 | * Prefer the by-reference (&) version instead. | |
87 | */ | |
b7ac5457 | 88 | Address(Address *); |
41d93087 | 89 | |
b7ac5457 | 90 | Address(const struct in_addr &); |
b7ac5457 | 91 | Address(const struct sockaddr_in &); |
b7ac5457 | 92 | Address(const struct in6_addr &); |
b7ac5457 | 93 | Address(const struct sockaddr_in6 &); |
b7ac5457 AJ |
94 | Address(const struct hostent &); |
95 | Address(const struct addrinfo &); | |
96 | Address(const char*); | |
3cbeddcf | 97 | ~Address() {} |
41d93087 | 98 | /*@}*/ |
99 | ||
100 | /** @name Assignment Operators */ | |
101 | /*@{*/ | |
b7ac5457 AJ |
102 | Address& operator =(const Address &s); |
103 | Address& operator =(struct sockaddr_in const &s); | |
104 | Address& operator =(struct sockaddr_storage const &s); | |
105 | Address& operator =(struct in_addr const &s); | |
b7ac5457 AJ |
106 | Address& operator =(struct in6_addr const &s); |
107 | Address& operator =(struct sockaddr_in6 const &s); | |
41d93087 | 108 | bool operator =(const struct hostent &s); |
109 | bool operator =(const struct addrinfo &s); | |
110 | bool operator =(const char *s); | |
111 | /*@}*/ | |
112 | ||
113 | /** @name Boolean Operators */ | |
114 | /*@{*/ | |
b7ac5457 AJ |
115 | bool operator ==(Address const &s) const; |
116 | bool operator !=(Address const &s) const; | |
117 | bool operator >=(Address const &rhs) const; | |
118 | bool operator <=(Address const &rhs) const; | |
119 | bool operator >(Address const &rhs) const; | |
120 | bool operator <(Address const &rhs) const; | |
41d93087 | 121 | |
122 | public: | |
123 | /* methods */ | |
124 | ||
125 | /** Test whether content can be used as an IPv4 address | |
3392646b AJ |
126 | \retval true if content was received as an IPv4-Mapped address |
127 | \retval false if content was received as a non-mapped IPv6 native address. | |
41d93087 | 128 | */ |
129 | bool IsIPv4() const; | |
130 | ||
131 | /** Test whether content can be used as an IPv6 address. | |
0906f01d CT |
132 | \retval true if content is a non IPv4-mapped address. |
133 | \retval false if content is IPv4-mapped. | |
41d93087 | 134 | */ |
135 | bool IsIPv6() const; | |
136 | ||
137 | /** Test whether content can be used as a Socket address. | |
3392646b AJ |
138 | \retval true if address AND port are both set |
139 | \retval true if content was received as a Socket address with port | |
140 | \retval false if port in unset (zero) | |
41d93087 | 141 | */ |
142 | bool IsSockAddr() const; | |
143 | ||
144 | /** Content-neutral test for whether the specific IP case ANY_ADDR is stored. | |
b7ac5457 | 145 | * This is the default content of a new undefined Ip::Address object. |
3392646b AJ |
146 | \retval true IPv4 0.0.0.0 |
147 | \retval true IPv6 :: | |
148 | \retval false anything else. | |
41d93087 | 149 | */ |
150 | bool IsAnyAddr() const; | |
151 | ||
152 | /** Content-neutral test for whether the specific IP case NO_ADDR is stored. | |
3392646b AJ |
153 | \retval true IPv4 255.255.255.255 |
154 | \retval true IPv6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | |
155 | \retval false anything else. | |
41d93087 | 156 | */ |
157 | bool IsNoAddr() const; | |
158 | ||
159 | /** Content-neutral test for whether the specific IP case LOCALHOST is stored. | |
b7ac5457 | 160 | * This is the default content of a new undefined Ip::Address object. |
3392646b AJ |
161 | \retval true IPv4 127.0.0.1 |
162 | \retval true IPv6 ::1 | |
163 | \retval false anything else. | |
41d93087 | 164 | */ |
165 | bool IsLocalhost() const; | |
166 | ||
a98c2da5 | 167 | /** Test whether content is an IPv6 Site-Local address. |
dd19b634 | 168 | \retval true if address begins with fd00::/8. |
a98c2da5 | 169 | \retval false if --disable-ipv6 has been compiled. |
dd19b634 | 170 | \retval false if address does not match fd00::/8 |
a98c2da5 AJ |
171 | */ |
172 | bool IsSiteLocal6() const; | |
173 | ||
174 | /** Test whether content is an IPv6 address with SLAAC EUI-64 embeded. | |
175 | \retval true if address matches ::ff:fe00:0 | |
176 | \retval false if --disable-ipv6 has been compiled. | |
177 | \retval false if address does not match ::ff:fe00:0 | |
178 | */ | |
179 | bool IsSlaac() const; | |
180 | ||
41d93087 | 181 | /*@}*/ |
182 | ||
183 | /** Retrieve the Port if stored. | |
3392646b AJ |
184 | \retval 0 Port is unset or an error occured. |
185 | \retval n Port associated with this address in host native -endian. | |
41d93087 | 186 | */ |
f45dd259 | 187 | unsigned short GetPort() const; |
41d93087 | 188 | |
189 | /** Set the Port value for an address. | |
190 | * Replaces any previously existing Port value. | |
3392646b AJ |
191 | \param port Port being assigned in host native -endian. |
192 | \retval 0 Port is unset or an error occured. | |
193 | \retval n Port associated with this address in host native -endian. | |
41d93087 | 194 | */ |
f45dd259 | 195 | unsigned short SetPort(unsigned short port); |
41d93087 | 196 | |
197 | /// Set object to contain the specific IP case ANY_ADDR (format-neutral). | |
198 | /// see IsAnyAddr() for more detail. | |
199 | void SetAnyAddr(); | |
200 | ||
201 | /// Set object to contain the specific IP case NO_ADDR (format-neutral). | |
d85b8894 | 202 | /// see IsNoAddr() for more detail. |
41d93087 | 203 | void SetNoAddr(); |
204 | ||
205 | /// Set object to contain the specific IP case LOCALHOST (format-neutral). | |
d85b8894 | 206 | /// see IsLocalhost() for more detail. |
41d93087 | 207 | void SetLocalhost(); |
208 | ||
209 | /// Fast reset of the stored content to what would be after default constructor. | |
210 | void SetEmpty(); | |
211 | ||
212 | /** Require an IPv4-only address for this usage. | |
213 | * Converts the object to prefer only IPv4 output. | |
214 | \retval true Content can be IPv4 | |
215 | \retval false Content CANNOT be IPv4 | |
216 | */ | |
217 | bool SetIPv4(); | |
218 | ||
219 | /** | |
220 | * Valid results IF and only IF the stored IP address is actually a network bitmask | |
3392646b | 221 | \retval N number of bits which are set in the bitmask stored. |
41d93087 | 222 | */ |
df9617b9 | 223 | int GetCIDR() const; |
41d93087 | 224 | |
225 | /** Apply a mask to the stored address. | |
3392646b | 226 | \param mask Netmask format to be bit-mask-AND'd over the stored address. |
41d93087 | 227 | */ |
881c4733 | 228 | int ApplyMask(const Address &mask); |
41d93087 | 229 | |
230 | /** Apply a mask to the stored address. | |
231 | * CIDR will be converted appropriate to map the stored content. | |
3392646b AJ |
232 | \param cidr CIDR Mask being applied. As an integer in host format. |
233 | \param mtype Type of CIDR mask being applied (AF_INET or AF_INET6) | |
41d93087 | 234 | */ |
055421ee | 235 | bool ApplyMask(const unsigned int cidr, int mtype); |
41d93087 | 236 | |
41d93087 | 237 | /** Return the ASCII equivalent of the address |
238 | * Semantically equivalent to the IPv4 inet_ntoa() | |
239 | * eg. 127.0.0.1 (IPv4) or ::1 (IPv6) | |
240 | * But for memory safety it requires a buffer as input | |
241 | * instead of producing one magically. | |
242 | * If buffer is not large enough the data is truncated silently. | |
3392646b AJ |
243 | \param buf Allocated buffer to write address to |
244 | \param len byte length of buffer available for writing. | |
245 | \param force (optional) require the IPA in a specific format. | |
246 | \return pointer to buffer received. | |
41d93087 | 247 | */ |
b62b752c | 248 | char* NtoA(char *buf, const unsigned int blen, int force = AF_UNSPEC) const; |
41d93087 | 249 | |
250 | /** Return the ASCII equivalent of the address:port combination | |
251 | * Provides a URL formatted version of the content. | |
252 | * If buffer is not large enough the data is truncated silently. | |
253 | * eg. 127.0.0.1:80 (IPv4) or [::1]:80 (IPv6) | |
3392646b AJ |
254 | \param buf Allocated buffer to write address:port to |
255 | \param len byte length of buffer available for writing. | |
256 | \return pointer to buffer received. | |
41d93087 | 257 | */ |
258 | char* ToURL(char *buf, unsigned int len) const; | |
259 | ||
260 | /** Return a properly hostname formatted copy of the address | |
261 | * Provides a URL formatted version of the content. | |
262 | * If buffer is not large enough the data is truncated silently. | |
263 | * eg. 127.0.0.1 (IPv4) or [::1] (IPv6) | |
3392646b AJ |
264 | \param buf Allocated buffer to write address to |
265 | \param len byte length of buffer available for writing. | |
de12d836 | 266 | \return amount of buffer filled. |
41d93087 | 267 | */ |
268 | unsigned int ToHostname(char *buf, const unsigned int len) const; | |
269 | ||
3392646b | 270 | /** |
41d93087 | 271 | * Convert the content into a Reverse-DNS string. |
272 | * The buffer sent MUST be allocated large enough to hold the resulting string. | |
273 | * Name truncation will occur if buf does not have enough space. | |
274 | * The constant MAX_IPSTRLEN is defined to provide for sizing arrays correctly. | |
d85b8894 AJ |
275 | \param show_type may be one of: AF_INET, AF_INET6 for the format of rDNS string wanted. |
276 | * AF_UNSPEC the default displays the IP in its most advanced native form. | |
277 | \param buf buffer to receive the text string output. | |
41d93087 | 278 | */ |
d85b8894 | 279 | bool GetReverseString(char buf[MAX_IPSTRLEN], int show_type = AF_UNSPEC) const; |
41d93087 | 280 | |
281 | /** Test how two IP relate to each other. | |
3392646b AJ |
282 | \retval 0 IP are equal |
283 | \retval 1 IP rhs is greater (numerically) than that stored. | |
284 | \retval -1 IP rhs is less (numerically) than that stored. | |
41d93087 | 285 | */ |
b7ac5457 | 286 | int matchIPAddr(const Address &rhs) const; |
41d93087 | 287 | |
607a7bd4 AR |
288 | /** Compare taking IP, port, protocol, etc. into account. Returns an |
289 | integer less than, equal to, or greater than zero if the object | |
290 | is found, respectively, to be less than, to match, or to be greater | |
291 | than rhs. The exact ordering algorithm is not specified and may change. | |
292 | */ | |
a67d2b2e | 293 | int compareWhole(const Ip::Address &rhs) const; |
607a7bd4 | 294 | |
41d93087 | 295 | /** |
b7ac5457 | 296 | * Get RFC 3493 addrinfo structure from the Ip::Address data |
41d93087 | 297 | * for protocol-neutral socket operations. |
298 | * Should be passed a NULL pointer of type struct addrinfo* it will | |
299 | * allocate memory for the structures involved. (see FreeAddrInfo to clear). | |
300 | * Defaults to a TCP streaming socket, if other values (such as UDP) are needed | |
301 | * the caller MUST override these default settings. | |
302 | * Some situations may also require an actual call to the system getaddrinfo() | |
303 | * to pull relevant OS details for the socket. | |
3392646b | 304 | \par |
b7ac5457 | 305 | * Ip::Address allocated objects MUST be destructed by Ip::Address::FreeAddrInfo |
41d93087 | 306 | * System getaddrinfo() allocated objects MUST be freed with system freeaddrinfo() |
41d93087 | 307 | * |
3392646b AJ |
308 | \param ai structure to be filled out. |
309 | \param force a specific sockaddr type is needed. default: don't care. | |
41d93087 | 310 | */ |
41d93087 | 311 | void GetAddrInfo(struct addrinfo *&ai, int force = AF_UNSPEC) const; |
41d93087 | 312 | |
313 | /** | |
b7ac5457 | 314 | * Equivalent to the sysem call freeaddrinfo() but for Ip::Address allocated data |
41d93087 | 315 | */ |
b7ac5457 | 316 | static void FreeAddrInfo(struct addrinfo *&ai); |
41d93087 | 317 | |
318 | /** | |
319 | * Initializes an empty addrinfo properly for use. | |
320 | * It is intended for use in cases such as getsockopt() where the addrinfo is | |
321 | * about to be changed and the stored details may not match the new ones coming. | |
3392646b | 322 | \param ai addrinfo struct to be initialized as AF_UNSPEC with large address buffer |
41d93087 | 323 | */ |
b7ac5457 | 324 | static void InitAddrInfo(struct addrinfo *&ai); |
41d93087 | 325 | |
326 | /** | |
327 | * Lookup a Host by Name. Equivalent to system call gethostbyname(char*) | |
3392646b AJ |
328 | \param s The textual FQDN of the host being located. |
329 | \retval true lookup was successful and an IPA was located. | |
330 | \retval false lookup failed or FQDN has no IP associated. | |
41d93087 | 331 | */ |
332 | bool GetHostByName(const char *s); | |
333 | ||
334 | public: | |
335 | /* FIXME: When C => C++ conversion is done will be fully private. | |
336 | * Legacy Transition Methods. | |
337 | * These are here solely to simplify the transition | |
338 | * when moving from converted code to unconverted | |
339 | * these functions can be used to convert this object | |
340 | * and pull out the data needed by the unconverted code | |
341 | * they are intentionaly hard to use, use GetAddrInfo() instead. | |
342 | * these functiosn WILL NOT be in the final public API after transition. | |
343 | */ | |
344 | ||
0e1a47f0 | 345 | void GetSockAddr(struct sockaddr_storage &addr, const int family) const; |
41d93087 | 346 | void GetSockAddr(struct sockaddr_in &) const; |
41d93087 | 347 | bool GetInAddr(struct in_addr &) const; /* false if could not convert IPv6 down to IPv4 */ |
41d93087 | 348 | void GetSockAddr(struct sockaddr_in6 &) const; |
41d93087 | 349 | void GetInAddr(struct in6_addr &) const; |
41d93087 | 350 | |
351 | private: | |
352 | /* Conversion for dual-type internals */ | |
353 | ||
d85b8894 | 354 | bool GetReverseString4(char buf[MAX_IPSTRLEN], const struct in_addr &dat) const; |
41d93087 | 355 | |
d85b8894 | 356 | bool GetReverseString6(char buf[MAX_IPSTRLEN], const struct in6_addr &dat) const; |
41d93087 | 357 | |
358 | void Map4to6(const struct in_addr &src, struct in6_addr &dest) const; | |
359 | ||
360 | void Map6to4(const struct in6_addr &src, struct in_addr &dest) const; | |
41d93087 | 361 | |
362 | // Worker behind GetHostName and char* converters | |
363 | bool LookupHostIP(const char *s, bool nodns); | |
364 | ||
365 | /* variables */ | |
41d93087 | 366 | struct sockaddr_in6 m_SocketAddr; |
c0248e14 HN |
367 | |
368 | private: | |
369 | /* Internally used constants */ | |
370 | static const unsigned int STRLEN_IP4A = 16; // aaa.bbb.ccc.ddd\0 | |
371 | static const unsigned int STRLEN_IP4R = 28; // ddd.ccc.bbb.aaa.in-addr.arpa.\0 | |
372 | static const unsigned int STRLEN_IP4S = 21; // ddd.ccc.bbb.aaa:ppppp\0 | |
373 | static const unsigned int MAX_IP4_STRLEN = STRLEN_IP4R; | |
c0248e14 HN |
374 | static const unsigned int STRLEN_IP6A = 42; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/0 |
375 | 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 | |
376 | static const unsigned int STRLEN_IP6S = 48; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:00000/0 | |
377 | static const unsigned int MAX_IP6_STRLEN = STRLEN_IP6R; | |
378 | static const struct in6_addr v4_localhost; | |
379 | static const struct in6_addr v4_anyaddr; | |
0eb08770 | 380 | static const struct in6_addr v4_noaddr; |
c0248e14 | 381 | static const struct in6_addr v6_noaddr; |
41d93087 | 382 | }; |
383 | ||
384 | inline std::ostream & | |
b7ac5457 | 385 | operator << (std::ostream &os, const Address &ipa) |
41d93087 | 386 | { |
387 | char buf[MAX_IPSTRLEN]; | |
388 | os << ipa.ToURL(buf,MAX_IPSTRLEN); | |
389 | return os; | |
390 | } | |
391 | ||
41d93087 | 392 | // WAS _sockaddr_in_list in an earlier incarnation |
b7ac5457 | 393 | class Address_list |
41d93087 | 394 | { |
395 | public: | |
b7ac5457 AJ |
396 | Address_list() { next = NULL; }; |
397 | ~Address_list() { if (next) delete next; next = NULL; }; | |
41d93087 | 398 | |
b7ac5457 AJ |
399 | Address s; |
400 | Address_list *next; | |
41d93087 | 401 | }; |
402 | ||
e5519212 | 403 | } // namespace Ip |
b7ac5457 AJ |
404 | |
405 | extern void parse_IpAddress_list_token(Ip::Address_list **, char *); | |
41d93087 | 406 | |
b7ac5457 | 407 | #endif /* _SQUID_IP_IPADDRESS_H */ |