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 51 ATAddress() 52 { 53 memset(&(this->ip), 0, sizeof(struct sockaddr_storage)); 54 }; 55 56 ATAddress(const ATAddress &y) 57 { 58 memcpy(&(this->ip), y.addr(), sizeof(struct sockaddr_storage)); 59 }; 60 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 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 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 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 93 static bool saIsInet(const struct sockaddr *ip) 94 { 95 return ((ip->sa_family == AF_INET) || (ip->sa_family == AF_INET6)); 96 }; 97 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 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 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 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 163 sa_family_t family() const { return ip.ss_family; }; 164 165 bool isInet() const { return ((ip.ss_family == AF_INET) || (ip.ss_family == AF_INET6)); }; 166 167 unsigned int size() const 168 { 169 return ATAddress::saSize((const struct sockaddr *)&(this->ip)); 170 }; 171 172 const struct sockaddr *addr() const 173 { 174 return (const struct sockaddr *)&ip; 175 }; 176 177 in_port_t inPort() const 178 { 179 return ATAddress::saInPort((const struct sockaddr *)&(this->ip)); 180 }; 181 182 const void *inAddr(size_t &asize) const 183 { 184 return ATAddress::saInAddr((const struct sockaddr *)&(this->ip), asize); 185 }; 186 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 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