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