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