xref: /titanic_41/usr/src/cmd/lms/tools/ATNetworkTool.h (revision 617e2443dfc17fe44fd44c0675d6aad2ffc9df42)
1 /*******************************************************************************
2  * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  - Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *
10  *  - Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  *  - Neither the name of Intel Corp. nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *******************************************************************************/
30 
31 #ifndef _AT_NETWORK_TOOL_H_
32 #define _AT_NETWORK_TOOL_H_
33 
34 #include <string>
35 #include <set>
36 #include <vector>
37 #include <map>
38 #include <cstring>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <arpa/inet.h>
42 #include <netinet/in.h>
43 
44 class ATAddress
45 {
46 private:
47 	struct sockaddr_storage ip;
48 
49 public:
50 
ATAddress()51 	ATAddress()
52 	{
53 		memset(&(this->ip), 0, sizeof(struct sockaddr_storage));
54 	};
55 
ATAddress(const ATAddress & y)56 	ATAddress(const ATAddress &y)
57 	{
58 		memcpy(&(this->ip), y.addr(), sizeof(struct sockaddr_storage));
59 	};
60 
ATAddress(const struct sockaddr * yip)61 	ATAddress(const struct sockaddr *yip)
62 	{
63 		memset(&(this->ip), 0, sizeof(struct sockaddr_storage));
64 		memcpy(&(this->ip), yip, saSize(yip));
65 	};
66 
ATAddress(const ATAddress & y,in_port_t yport)67 	ATAddress(const ATAddress &y, in_port_t yport)
68 	{
69 		memcpy(&(this->ip), y.addr(), sizeof(struct sockaddr_storage));
70 		ATAddress::saSetPort((const struct sockaddr *)&(this->ip), yport);
71 	};
72 
ATAddress(const struct sockaddr * yip,in_port_t yport)73 	ATAddress(const struct sockaddr *yip, in_port_t yport)
74 	{
75 		memset(&(this->ip), 0, sizeof(struct sockaddr_storage));
76 		memcpy(&(this->ip), yip, saSize(yip));
77 		ATAddress::saSetPort((const struct sockaddr *)&(this->ip), yport);
78 	};
79 
saSetPort(const struct sockaddr * ip,in_port_t yport)80 	static void saSetPort(const struct sockaddr *ip, in_port_t yport)
81 	{
82 		switch (ip->sa_family) {
83 		case AF_INET6:
84 			((struct sockaddr_in6 *)ip)->sin6_port = htons(yport);
85 			break;
86 
87 		case AF_INET:
88 			((struct sockaddr_in *)ip)->sin_port = htons(yport);
89 			break;
90 		}
91 	}
92 
saIsInet(const struct sockaddr * ip)93 	static bool saIsInet(const struct sockaddr *ip)
94 	{
95 		return ((ip->sa_family == AF_INET) || (ip->sa_family == AF_INET6));
96 	};
97 
saSize(const struct sockaddr * ip)98 	static unsigned int saSize(const struct sockaddr *ip)
99 	{
100 		switch (ip->sa_family) {
101 		case AF_INET6:
102 			return sizeof(struct sockaddr_in6);
103 			break;
104 
105 		case AF_INET:
106 			return sizeof(struct sockaddr_in);
107 			break;
108 
109 		default:
110 			return 0;
111 		}
112 	};
113 
saInPort(const struct sockaddr * ip)114 	static in_port_t saInPort(const struct sockaddr *ip)
115 	{
116 		switch (ip->sa_family) {
117 		case AF_INET6:
118 			return ntohs(((struct sockaddr_in6 *)ip)->sin6_port);
119 			break;
120 
121 		case AF_INET:
122 			return ntohs(((struct sockaddr_in *)ip)->sin_port);
123 			break;
124 
125 		default:
126 			return 0;
127 		}
128 	};
129 
saInAddr(const struct sockaddr * ip,size_t & asize)130 	static const void *saInAddr(const struct sockaddr *ip, size_t &asize)
131 	{
132 		switch (ip->sa_family) {
133 		case AF_INET6:
134 			asize = sizeof(in6_addr);
135 			return (const void *)&(((struct sockaddr_in6 *)ip)->sin6_addr);
136 			break;
137 
138 		case AF_INET:
139 			asize = sizeof(in_addr);
140 			return (const void *)&(((struct sockaddr_in *)ip)->sin_addr);
141 			break;
142 
143 		default:
144 			asize = 0;
145 			return NULL;
146 		}
147 	};
148 
saInNtoP(const struct sockaddr * ip,char * buf,size_t buflen)149 	static const char *saInNtoP(const struct sockaddr *ip, char *buf, size_t buflen)
150 	{
151 		if (!ATAddress::saIsInet(ip)) {
152 			return NULL;
153 		}
154 
155 		size_t asize;
156 		const void *src = ATAddress::saInAddr(ip, asize);
157 		if (NULL == src) {
158 			return NULL;
159 		}
160 		return inet_ntop(ip->sa_family, src, buf, buflen);
161 	};
162 
family()163 	sa_family_t family() const { return ip.ss_family; };
164 
isInet()165 	bool isInet() const { return ((ip.ss_family == AF_INET) || (ip.ss_family == AF_INET6)); };
166 
size()167 	unsigned int size() const
168 	{
169 		return ATAddress::saSize((const struct sockaddr *)&(this->ip));
170 	};
171 
addr()172 	const struct sockaddr *addr() const
173 	{
174 		return (const struct sockaddr *)&ip;
175 	};
176 
inPort()177 	in_port_t inPort() const
178 	{
179 		return ATAddress::saInPort((const struct sockaddr *)&(this->ip));
180 	};
181 
inAddr(size_t & asize)182 	const void *inAddr(size_t &asize) const
183 	{
184 		return ATAddress::saInAddr((const struct sockaddr *)&(this->ip), asize);
185 	};
186 
inNtoP(char * buf,size_t buflen)187 	const char *inNtoP(char *buf, size_t buflen)
188 	{
189 		return ATAddress::saInNtoP((const struct sockaddr *)&(this->ip), buf, buflen);
190 	};
191 
192 	ATAddress &operator=(const ATAddress &y)
193 	{
194 		if (this != &y) {
195 			memcpy(&(this->ip), y.addr(), sizeof(struct sockaddr_storage));
196 		}
197 		return *this;
198 	};
199 
200 	ATAddress &operator=(const struct sockaddr &yip)
201 	{
202 		memset(&(this->ip), 0, sizeof(struct sockaddr_storage));
203 		memcpy(&(this->ip), &yip, saSize(&yip));
204 		return *this;
205 	};
206 
compare(const ATAddress & y)207 	int compare(const ATAddress &y) const
208 	{
209 		if (this->family() != y.family()) {
210 			return (this->family() - y.family());
211 		}
212 
213 		size_t asize = 0;
214 		const void *a = this->inAddr(asize);
215 		const void *b = y.inAddr(asize);
216 		if ((0 != asize) && (NULL != a) && (NULL != b)) {
217 			int adiff = memcmp(a, b, asize);
218 			if (adiff != 0) {
219 				return adiff;
220 			}
221 		}
222 
223 		in_port_t ap = this->inPort();
224 		in_port_t bp = y.inPort();
225 		if ((ap == 0) || (bp == 0)) {
226 			return 0;
227 		}
228 		if (ap != bp) {
229 			return (ap - bp);
230 		}
231 
232 		return memcmp(&(this->ip), y.addr(), this->size());
233 	};
234 
235 	bool operator<(const ATAddress &y) const
236 	{
237 		if (this == &y) {
238 			return false;
239 		}
240 		return (this->compare(y) < 0);
241 	};
242 
243 	bool operator>(const ATAddress &y) const
244 	{
245 		if (this == &y) {
246 			return false;
247 		}
248 		return (this->compare(y) > 0);
249 	};
250 
251 	bool operator==(const ATAddress &y) const
252 	{
253 		if (this == &y) {
254 			return true;
255 		}
256 		if (this->family() != y.family()) {
257 			return false;
258 		}
259 		return (memcmp(&(this->ip), y.addr(), this->size()) == 0);
260 	};
261 
262 	bool operator!=(const ATAddress &y) const
263 	{
264 		if (this == &y) {
265 			return false;
266 		}
267 		if (this->family() != y.family()) {
268 			return true;
269 		}
270 		return (memcmp(&(this->ip), y.addr(), this->size()) != 0);
271 	};
272 
273 	static bool IsAddressIP(const char *address, int family = AF_INET)
274 	{
275 		struct sockaddr_storage inaddr;
276 
277 		if (address == NULL) {
278 			return false;
279 		}
280 		return (0 < inet_pton(family, address, &inaddr));
281 	};
282 };
283 
284 
285 typedef std::set<ATAddress> ATAddressList;
286 typedef std::map<ATAddress, std::string> ATDomainMap;
287 typedef std::vector<int> ATSocketList;
288 
289 class ATNetworkTool
290 {
291 public:
292 	static const int DefaultBacklog = 5;
293 	static const int DefaultFamily = AF_INET;
294 	static const int AF_XINETX = AF_MAX + 10;
295 
296 	/* Gets Domain name from Hostname
297 	 * @param name hostname
298 	 * @param domain [out] domain name
299 	 * @return bool true if success, false if domain unknown
300 	 */
301 	static bool GetHostNameDomain(const char *name, std::string &domain);
302 
303 	/* Gets Domain name from IP
304 	 * @param ip address
305 	 * @param domain [out] domain name
306 	 * @param error [out] error code
307 	 * @return bool true if success, false if domain unknown
308 	 */
309 	static bool GetIPDomain(const ATAddress &ip, std::string &domain, int &error);
310 
311 	/* Gets Domain name from host entry
312 	 * @param hent pointer to host entry structure
313 	 * @param domain [out] domain name
314 	 * @return bool true if success, false if domain unknown
315 	 */
316 	static bool GetHentDomain(struct hostent *hent, std::string &domain);
317 
318 	/* Gets Domain name from socket
319 	 * @param sock checked socket
320 	 * @param domain [out] domain name
321 	 * @param error [out] error code
322 	 * @return int ==1 if success, <0 on error, ==0 if no domain
323 	 */
324 	static int GetSockDomain(int sock, std::string &domain, int &error);
325 
326 	/* Gets all local (IPv4/6) from local running network interfaces
327 	 * @param addresses [out] set of local IP addresses
328 	 * @param error [out] error code
329 	 * @param family filtered address family
330 	 * @param withloopback true if get loopback addresses too
331 	 * @return int ==0 if success, !=0 on error
332 	 */
333 	static int GetLocalIPs(ATAddressList &addresses, int &error,
334 				int family = ATNetworkTool::AF_XINETX,
335 				bool withloopback = false);
336 
337 	/* Gets all local domains from local running network interfaces
338 	 * @param domains [out] map of <local IP address> => <domain name>
339 	 * @param error [out] error code
340 	 * @param family filtered address family
341 	 * @return int ==0 if success, !=0 on error
342 	 */
343 	static int GetLocalNetDomains(ATDomainMap &domains, int &error,
344 				int family = ATNetworkTool::AF_XINETX);
345 
346 	/* Gets all (IPv4/6) network interfaces of socket peer
347 	 * @param addresses [out] set of peer IP addresses
348 	 * @param error [out] error code
349 	 * @param family filtered address family
350 	 * @param zeroport set port to 0 in result list
351 	 * @return int ==0 if success, !=0 on error
352 	 */
353 	static int GetSockPeerIPs(int sock, ATAddressList &addresses,
354 				int &error,
355 				int family = ATNetworkTool::AF_XINETX,
356 				bool zeroport = false);
357 
358 	/* Checks if socket peer is (IPv4/6) local address
359 	 * @param sock checked socket
360 	 * @param error [out] error code
361 	 * @param family filtered address family
362 	 * @return int ==1 if peer is local, ==0 if remote, <0 on error
363 	 */
364 	static int IsSockPeerLocal(int sock, int &error,
365 				int family = ATNetworkTool::AF_XINETX);
366 
367 	/* Closes socket
368 	 * @param s socket to close
369 	 * @return int ==0 if success, !=0 on error
370 	 */
371 	static int CloseSocket(int s);
372 
373 	/* Sets/removes O_NONBLOCKING flag to socket
374 	 * @param s socket
375 	 * @param block - true to set flag, false to remove flag
376 	 * @return int ==0 if success, !=0 on error
377 	 */
378 	static int SetNonBlocking(int s, bool block = true);
379 
380 	/* Creates socket
381 	 * @param addr socket parameters
382 	 * @param error [out] error code
383 	 * @return int !=-1 socket, ==-1 on error
384 	 */
385 	static int CreateSocket(const struct addrinfo *addr, int &error);
386 
387 	/* Creates socket
388 	 * @param addr socket address
389 	 * @param addrlen socket address length
390 	 * @param error [out] error code
391 	 * @param family socket expected family
392 	 * @param socktype socket type
393 	 * @param protocol socket protocol
394 	 * @return int !=-1 socket, ==-1 on error
395 	 */
396 	static int CreateSocket(const struct sockaddr *addr, socklen_t addrlen,
397 				int &error,
398 				int family = ATNetworkTool::DefaultFamily,
399 				int socktype = SOCK_STREAM, int protocol = 0);
400 
401 	/* Creates server listening socket
402 	 * @param addr socket parameters
403 	 * @param error [out] error code
404 	 * @param nonblocking true for nonblocking socket
405 	 * @param backlog listening backlog
406 	 * @return int !=-1 socket, ==-1 on error
407 	 */
408 	static int CreateServerSocket(const struct addrinfo *addr,
409 				int &error, bool nonblocking = true,
410 				int backlog = ATNetworkTool::DefaultBacklog);
411 
412 	/* Creates server listening sockets
413 	 * @param sockets [out] list of created server listening sockets
414 	 * @param port listening port
415 	 * @param error [out] error code
416 	 * @param loopback true to listen only on loopback
417 	 * @param nonblocking true for nonblocking sockets
418 	 * @param family sockets expected family
419 	 * @param socktype sockets type
420 	 * @param protocol sockets protocol
421 	 * @param backlog listening backlog
422 	 * @param one true if want create only one socket
423 	 * @return int >=0 number of created server sockets, ==-1 on error
424 	 */
425 	static int CreateServerSockets(ATSocketList &sockets, in_port_t port,
426 				int &error,
427 				bool loopback = false, bool nonblocking = true,
428 				int family = ATNetworkTool::AF_XINETX,
429 				int socktype = SOCK_STREAM, int protocol = 0,
430 				int backlog = ATNetworkTool::DefaultBacklog,
431 				bool one = false);
432 	static int CreateServerSockets(ATSocketList &sockets, const char *port,
433 				int &error,
434 				bool loopback = false, bool nonblocking = true,
435 				int family = ATNetworkTool::AF_XINETX,
436 				int socktype = SOCK_STREAM, int protocol = 0,
437 				int backlog = ATNetworkTool::DefaultBacklog,
438 				bool one = false);
439 
440 	/* Creates one server listening socket
441 	 * @param port listening port
442 	 * @param error [out] error code
443 	 * @param loopback true to listen only on loopback
444 	 * @param nonblocking true for nonblocking sockets
445 	 * @param family sockets expected family
446 	 * @param socktype sockets type
447 	 * @param protocol sockets protocol
448 	 * @param backlog listening backlog
449 	 * @return int !=-1 socket, ==-1 on error
450 	 */
451 	static int CreateServerSocket(in_port_t port,
452 				int &error,
453 				bool loopback = false, bool nonblocking = true,
454 				int family = ATNetworkTool::AF_XINETX,
455 				int socktype = SOCK_STREAM, int protocol = 0,
456 				int backlog = ATNetworkTool::DefaultBacklog);
457 	static int CreateServerSocket(const char *port,
458 				int &error,
459 				bool loopback = false, bool nonblocking = true,
460 				int family = ATNetworkTool::AF_XINETX,
461 				int socktype = SOCK_STREAM, int protocol = 0,
462 				int backlog = ATNetworkTool::DefaultBacklog);
463 
464 	/* Connects to local socket
465 	 * @param sock socket to connect to
466 	 * @param error [out] error code
467 	 * @param loopback true to use loopback, false to use any local address
468 	 * @param socktype sockets type
469 	 * @param protocol sockets protocol
470 	 * @return int !=-1 socket, ==-1 on error
471 	 */
472 	static int ConnectToSocket(int sock,
473 				int &error, bool loopback = true,
474 				int socktype = SOCK_STREAM, int protocol = 0);
475 
476 	/* Connects to address
477 	 * @param addr destination address parameters
478 	 * @param error [out] error code
479 	 * @param loopback true to use loopback, false to use any local address
480 	 * @return int !=-1 socket, ==-1 on error
481 	 */
482 	static int ConnectSocket(struct addrinfo *addr,
483 				int &error, bool loopback = false);
484 
485 	/* Connects to address
486 	 * @param addr destination address
487 	 * @param addrlen socket address length
488 	 * @param error [out] error code
489 	 * @param loopback true to use loopback, false to use any local address
490 	 * @param family sockets expected family
491 	 * @param socktype sockets type
492 	 * @param protocol sockets protocol
493 	 * @return int !=-1 socket, ==-1 on error
494 	 */
495 	static int ConnectSocket(const struct sockaddr *addr, socklen_t addrlen,
496 				int &error, bool loopback = false,
497 				int family = ATNetworkTool::AF_XINETX,
498 				int socktype = SOCK_STREAM, int protocol = 0);
499 
500 	/* Connects to address
501 	 * @param hostname name of destination host
502 	 * @param port destination port
503 	 * @param error [out] error code
504 	 * @param family sockets expected family
505 	 * @param socktype sockets type
506 	 * @param protocol sockets protocol
507 	 * @return int !=-1 socket, ==-1 on error
508 	 */
509 	static int Connect(const char *host, in_port_t port,
510 				int &error,
511 				int family = ATNetworkTool::AF_XINETX,
512 				int socktype = SOCK_STREAM, int protocol = 0);
513 	static int Connect(const char *host, const char *port,
514 				int &error,
515 				int family = ATNetworkTool::AF_XINETX,
516 				int socktype = SOCK_STREAM, int protocol = 0);
517 
518 	/* Connects to loopback port
519 	 * @param port destination port
520 	 * @param error [out] error code
521 	 * @param family sockets expected family
522 	 * @param socktype sockets type
523 	 * @param protocol sockets protocol
524 	 * @return int !=-1 socket, ==-1 on error
525 	 */
526 	static int ConnectLoopback(in_port_t port,
527 				int &error,
528 				int family = ATNetworkTool::AF_XINETX,
529 				int socktype = SOCK_STREAM, int protocol = 0);
530 	static int ConnectLoopback(const char *port,
531 				int &error,
532 				int family = ATNetworkTool::AF_XINETX,
533 				int socktype = SOCK_STREAM, int protocol = 0);
534 
535 	/* Returns local port associated with socket
536 	 * @param sock socket
537 	 * @return unsigned int port number, or 0 - on error
538 	 */
539 	static unsigned int GetLocalPort(int sock);
540 
541 	/* Accepts connection on sockets - returns address or error
542 	 * @param s socket accepting connection
543 	 * @param address [out] peer address of accepted connection
544 	 * @param error [out] error code
545 	 * @param nonblocking true for nonblocking sockets
546 	 * @return int !=-1 socket, ==-1 on error
547 	 */
548 	static int Accept(int s, ATAddress &address,
549 			  int &error, bool nonblocking = true);
550 };
551 
552 #endif //_AT_NETWORK_TOOL_H_
553 
554