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