]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ip/Address.h
Merged from parent (trunk r10600).
[thirdparty/squid.git] / src / ip / Address.h
1 /*
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 *
17 * This Ip::Address code is copyright (C) 2007 by Treehouse Networks Ltd
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 */
36 #ifndef _SQUID_IP_IPADDRESS_H
37 #define _SQUID_IP_IPADDRESS_H
38
39 #include "config.h"
40
41 #if HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44 #if HAVE_NETINET_IN_H
45 #include <netinet/in.h>
46 #endif
47 #ifdef _SQUID_MSWIN_
48 #include <ws2tcpip.h>
49 #endif
50 #if HAVE_NETDB_H
51 #include <netdb.h>
52 #endif
53
54 #if HAVE_IOSFWD
55 #include <iosfwd>
56 #endif
57 #if HAVE_OSTREAM
58 #include <ostream>
59 #endif
60
61 namespace Ip
62 {
63
64 /* FreeBSD hack:
65 * This OS has at least one version that defines these as private
66 * kernel macros commented as being 'non-standard'.
67 * We need to use them, much nicer than the OS-provided __u*_*[]
68 * UPDATE: OpenBSD 4.3 has the same.
69 * UPDATE: MacOSX has the same.
70 */
71 #if USE_IPV6 && ( defined(_SQUID_FREEBSD_) || defined(_SQUID_OPENBSD_) || defined(_SQUID_APPLE_) || defined(_SQUID_NETBSD_))
72 //#define s6_addr8 __u6_addr.__u6_addr8
73 //#define s6_addr16 __u6_addr.__u6_addr16
74 #define s6_addr32 __u6_addr.__u6_addr32
75 #endif
76
77 /* OpenBSD also hide v6only socket option we need for comm layer. :-( */
78 #if !defined(IPV6_V6ONLY) && defined(_SQUID_OPENBSD_)
79 #define IPV6_V6ONLY 27 // from OpenBSD 4.3 headers. (NP: does not match non-BSD OS values)
80 #endif
81
82 /* Bug 2500: Solaris 10/11 require s6_addr* defines. */
83 #if USE_IPV6 && defined(_SQUID_SOLARIS_)
84 //#define s6_addr8 _S6_un._S6_u8
85 //#define s6_addr16 _S6_un._S6_u16
86 #define s6_addr32 _S6_un._S6_u32
87 #endif
88
89 /// Length of buffer that needs to be allocated to old a null-terminated IP-string
90 // Yuck. But there are still structures that need it to be an 'integer constant'.
91 #define MAX_IPSTRLEN 75
92
93 /**
94 * Holds and manipulates IPv4, IPv6, and Socket Addresses.
95 */
96 class Address
97 {
98
99 public:
100 /** @name Constructors and Destructor */
101 /*@{*/
102 Address();
103 Address(const Address &);
104
105 /**
106 * This constructor takes its own copy of the object pointed to for memory-safe usage later.
107 * The caller must itself perform and ptr memory-management needed.
108 *
109 \deprecated Use of pointers can be nasty. Consider this a last-resort.
110 * Prefer the by-reference (&) version instead.
111 */
112 Address(Address *);
113
114 Address(const struct in_addr &);
115
116 Address(const struct sockaddr_in &);
117 #if USE_IPV6
118
119 Address(const struct in6_addr &);
120
121 Address(const struct sockaddr_in6 &);
122 #endif
123
124 Address(const struct hostent &);
125 Address(const struct addrinfo &);
126 Address(const char*);
127 /// Default destructor.
128 ~Address();
129 /*@}*/
130
131 /** @name Assignment Operators */
132 /*@{*/
133 Address& operator =(const Address &s);
134 Address& operator =(struct sockaddr_in const &s);
135 Address& operator =(struct sockaddr_storage const &s);
136 Address& operator =(struct in_addr const &s);
137 #if USE_IPV6
138 Address& operator =(struct in6_addr const &s);
139 Address& operator =(struct sockaddr_in6 const &s);
140 #endif
141 bool operator =(const struct hostent &s);
142 bool operator =(const struct addrinfo &s);
143 bool operator =(const char *s);
144 /*@}*/
145
146 /** @name Boolean Operators */
147 /*@{*/
148 bool operator ==(Address const &s) const;
149 bool operator !=(Address const &s) const;
150 bool operator >=(Address const &rhs) const;
151 bool operator <=(Address const &rhs) const;
152 bool operator >(Address const &rhs) const;
153 bool operator <(Address const &rhs) const;
154
155 public:
156 /* methods */
157
158 /** Test whether content can be used as an IPv4 address
159 \retval true if content was received as an IPv4 address
160 \retval true if content was received as an IPv4-Mapped address
161 \retval false if content was received as a non-mapped IPv6 native address.
162 */
163 bool IsIPv4() const;
164
165 /** Test whether content can be used as an IPv6 address.
166 \retval true if --enable-ipv6 has been compiled.
167 \retval false if --disable-ipv6 has been compiled.
168 \retval false if --with-ipv6-split-stack has been compiled AND content is IPv4-mapped.
169 */
170 bool IsIPv6() const;
171
172 /** Test whether content can be used as a Socket address.
173 \retval true if address AND port are both set
174 \retval true if content was received as a Socket address with port
175 \retval false if port in unset (zero)
176 */
177 bool IsSockAddr() const;
178
179 /** Content-neutral test for whether the specific IP case ANY_ADDR is stored.
180 * This is the default content of a new undefined Ip::Address object.
181 \retval true IPv4 0.0.0.0
182 \retval true IPv6 ::
183 \retval false anything else.
184 */
185 bool IsAnyAddr() const;
186
187 /** Content-neutral test for whether the specific IP case NO_ADDR is stored.
188 \retval true IPv4 255.255.255.255
189 \retval true IPv6 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
190 \retval false anything else.
191 */
192 bool IsNoAddr() const;
193
194 /** Content-neutral test for whether the specific IP case LOCALHOST is stored.
195 * This is the default content of a new undefined Ip::Address object.
196 \retval true IPv4 127.0.0.1
197 \retval true IPv6 ::1
198 \retval false anything else.
199 */
200 bool IsLocalhost() const;
201
202 /** Test whether content is an IPv6 Site-Local address.
203 \retval true if address begins with fe80::/10.
204 \retval false if --disable-ipv6 has been compiled.
205 \retval false if address does not match fe80::/10
206 */
207 bool IsSiteLocal6() const;
208
209 /** Test whether content is an IPv6 address with SLAAC EUI-64 embeded.
210 \retval true if address matches ::ff:fe00:0
211 \retval false if --disable-ipv6 has been compiled.
212 \retval false if address does not match ::ff:fe00:0
213 */
214 bool IsSlaac() const;
215
216 /*@}*/
217
218 /** Retrieve the Port if stored.
219 \retval 0 Port is unset or an error occured.
220 \retval n Port associated with this address in host native -endian.
221 */
222 u_short GetPort() const;
223
224 /** Set the Port value for an address.
225 * Replaces any previously existing Port value.
226 \param port Port being assigned in host native -endian.
227 \retval 0 Port is unset or an error occured.
228 \retval n Port associated with this address in host native -endian.
229 */
230 u_short SetPort(u_short port);
231
232 /// Set object to contain the specific IP case ANY_ADDR (format-neutral).
233 /// see IsAnyAddr() for more detail.
234 void SetAnyAddr();
235
236 /// Set object to contain the specific IP case NO_ADDR (format-neutral).
237 /// see IsNoAddr() for more detail.
238 void SetNoAddr();
239
240 /// Set object to contain the specific IP case LOCALHOST (format-neutral).
241 /// see IsLocalhost() for more detail.
242 void SetLocalhost();
243
244 /// Fast reset of the stored content to what would be after default constructor.
245 void SetEmpty();
246
247 /** Require an IPv4-only address for this usage.
248 * Converts the object to prefer only IPv4 output.
249 \retval true Content can be IPv4
250 \retval false Content CANNOT be IPv4
251 */
252 bool SetIPv4();
253
254 /**
255 * Valid results IF and only IF the stored IP address is actually a network bitmask
256 \retval N number of bits which are set in the bitmask stored.
257 */
258 int GetCIDR() const;
259
260 /** Apply a mask to the stored address.
261 \param mask Netmask format to be bit-mask-AND'd over the stored address.
262 */
263 const int ApplyMask(const Address &mask);
264
265 /** Apply a mask to the stored address.
266 * CIDR will be converted appropriate to map the stored content.
267 \param cidr CIDR Mask being applied. As an integer in host format.
268 \param mtype Type of CIDR mask being applied (AF_INET or AF_INET6)
269 */
270 bool ApplyMask(const unsigned int cidr, int mtype = AF_UNSPEC);
271
272
273 /** Return the ASCII equivalent of the address
274 * Semantically equivalent to the IPv4 inet_ntoa()
275 * eg. 127.0.0.1 (IPv4) or ::1 (IPv6)
276 * But for memory safety it requires a buffer as input
277 * instead of producing one magically.
278 * If buffer is not large enough the data is truncated silently.
279 \param buf Allocated buffer to write address to
280 \param len byte length of buffer available for writing.
281 \param force (optional) require the IPA in a specific format.
282 \return pointer to buffer received.
283 */
284 char* NtoA(char *buf, unsigned int len, int force = AF_UNSPEC) const;
285
286 /** Return the ASCII equivalent of the address:port combination
287 * Provides a URL formatted version of the content.
288 * If buffer is not large enough the data is truncated silently.
289 * eg. 127.0.0.1:80 (IPv4) or [::1]:80 (IPv6)
290 \param buf Allocated buffer to write address:port to
291 \param len byte length of buffer available for writing.
292 \return pointer to buffer received.
293 */
294 char* ToURL(char *buf, unsigned int len) const;
295
296 /** Return a properly hostname formatted copy of the address
297 * Provides a URL formatted version of the content.
298 * If buffer is not large enough the data is truncated silently.
299 * eg. 127.0.0.1 (IPv4) or [::1] (IPv6)
300 \param buf Allocated buffer to write address to
301 \param len byte length of buffer available for writing.
302 \return pointer to buffer received.
303 */
304 unsigned int ToHostname(char *buf, const unsigned int len) const;
305
306 /**
307 * Convert the content into a Reverse-DNS string.
308 * The buffer sent MUST be allocated large enough to hold the resulting string.
309 * Name truncation will occur if buf does not have enough space.
310 * The constant MAX_IPSTRLEN is defined to provide for sizing arrays correctly.
311 \param show_type may be one of: AF_INET, AF_INET6 for the format of rDNS string wanted.
312 * AF_UNSPEC the default displays the IP in its most advanced native form.
313 \param buf buffer to receive the text string output.
314 */
315 bool GetReverseString(char buf[MAX_IPSTRLEN], int show_type = AF_UNSPEC) const;
316
317 /** Test how two IP relate to each other.
318 \retval 0 IP are equal
319 \retval 1 IP rhs is greater (numerically) than that stored.
320 \retval -1 IP rhs is less (numerically) than that stored.
321 */
322 int matchIPAddr(const Address &rhs) const;
323
324 /** Compare taking IP, port, protocol, etc. into account. Returns an
325 integer less than, equal to, or greater than zero if the object
326 is found, respectively, to be less than, to match, or to be greater
327 than rhs. The exact ordering algorithm is not specified and may change.
328 */
329 int compareWhole(const Ip::Address &rhs) const;
330
331 /**
332 * Get RFC 3493 addrinfo structure from the Ip::Address data
333 * for protocol-neutral socket operations.
334 * Should be passed a NULL pointer of type struct addrinfo* it will
335 * allocate memory for the structures involved. (see FreeAddrInfo to clear).
336 * Defaults to a TCP streaming socket, if other values (such as UDP) are needed
337 * the caller MUST override these default settings.
338 * Some situations may also require an actual call to the system getaddrinfo()
339 * to pull relevant OS details for the socket.
340 \par
341 * Ip::Address allocated objects MUST be destructed by Ip::Address::FreeAddrInfo
342 * System getaddrinfo() allocated objects MUST be freed with system freeaddrinfo()
343 \par
344 * Some OS require that IPv4 addresses are pre-mapped by the client.
345 * The configure option --with-ipv4-mapping=yes will enable this.
346 *
347 \param ai structure to be filled out.
348 \param force a specific sockaddr type is needed. default: don't care.
349 */
350 #if IPV6_SPECIAL_V4MAPPING
351 void GetAddrInfo(struct addrinfo *&ai, int force = AF_INET6) const;
352 #else
353 void GetAddrInfo(struct addrinfo *&ai, int force = AF_UNSPEC) const;
354 #endif
355
356 /**
357 * Equivalent to the sysem call freeaddrinfo() but for Ip::Address allocated data
358 */
359 static void FreeAddrInfo(struct addrinfo *&ai);
360
361 /**
362 * Initializes an empty addrinfo properly for use.
363 * It is intended for use in cases such as getsockopt() where the addrinfo is
364 * about to be changed and the stored details may not match the new ones coming.
365 \param ai addrinfo struct to be initialized as AF_UNSPEC with large address buffer
366 */
367 static void InitAddrInfo(struct addrinfo *&ai);
368
369 /**
370 * Lookup a Host by Name. Equivalent to system call gethostbyname(char*)
371 \param s The textual FQDN of the host being located.
372 \retval true lookup was successful and an IPA was located.
373 \retval false lookup failed or FQDN has no IP associated.
374 */
375 bool GetHostByName(const char *s);
376
377 public:
378 /* FIXME: When C => C++ conversion is done will be fully private.
379 * Legacy Transition Methods.
380 * These are here solely to simplify the transition
381 * when moving from converted code to unconverted
382 * these functions can be used to convert this object
383 * and pull out the data needed by the unconverted code
384 * they are intentionaly hard to use, use GetAddrInfo() instead.
385 * these functiosn WILL NOT be in the final public API after transition.
386 */
387
388 void GetSockAddr(struct sockaddr_storage &addr, const int family) const;
389 void GetSockAddr(struct sockaddr_in &) const;
390 bool GetInAddr(struct in_addr &) const; /* false if could not convert IPv6 down to IPv4 */
391 #if USE_IPV6
392 void GetSockAddr(struct sockaddr_in6 &) const;
393 void GetInAddr(struct in6_addr &) const;
394 #endif
395
396 private:
397 /* Conversion for dual-type internals */
398
399 bool GetReverseString4(char buf[MAX_IPSTRLEN], const struct in_addr &dat) const;
400
401 #if USE_IPV6
402
403 bool GetReverseString6(char buf[MAX_IPSTRLEN], const struct in6_addr &dat) const;
404
405 void Map4to6(const struct in_addr &src, struct in6_addr &dest) const;
406
407 void Map6to4(const struct in6_addr &src, struct in_addr &dest) const;
408 #endif
409
410 // Worker behind GetHostName and char* converters
411 bool LookupHostIP(const char *s, bool nodns);
412
413 /* variables */
414 #if USE_IPV6
415 struct sockaddr_in6 m_SocketAddr;
416 #else
417 struct sockaddr_in m_SocketAddr;
418 #endif
419
420 private:
421 /* Internally used constants */
422 static const unsigned int STRLEN_IP4A = 16; // aaa.bbb.ccc.ddd\0
423 static const unsigned int STRLEN_IP4R = 28; // ddd.ccc.bbb.aaa.in-addr.arpa.\0
424 static const unsigned int STRLEN_IP4S = 21; // ddd.ccc.bbb.aaa:ppppp\0
425 static const unsigned int MAX_IP4_STRLEN = STRLEN_IP4R;
426 #if USE_IPV6
427 static const unsigned int STRLEN_IP6A = 42; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/0
428 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
429 static const unsigned int STRLEN_IP6S = 48; // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:00000/0
430 static const unsigned int MAX_IP6_STRLEN = STRLEN_IP6R;
431 static const struct in6_addr v4_localhost;
432 static const struct in6_addr v4_anyaddr;
433 static const struct in6_addr v4_noaddr;
434 static const struct in6_addr v6_noaddr;
435 #endif
436 };
437
438
439 inline std::ostream &
440 operator << (std::ostream &os, const Address &ipa)
441 {
442 char buf[MAX_IPSTRLEN];
443 os << ipa.ToURL(buf,MAX_IPSTRLEN);
444 return os;
445 }
446
447 // WAS _sockaddr_in_list in an earlier incarnation
448 class Address_list
449 {
450 public:
451 Address_list() { next = NULL; };
452 ~Address_list() { if (next) delete next; next = NULL; };
453
454 Address s;
455 Address_list *next;
456 };
457
458 }; // namespace Ip
459
460 extern void parse_IpAddress_list_token(Ip::Address_list **, char *);
461
462 #endif /* _SQUID_IP_IPADDRESS_H */