1 /******************************************************************************* 2 3 Declaration of and wrappers for the addrinfo address lookup API. 4 5 Copyright: 6 Copyright (c) 2009-2016 dunnhumby Germany GmbH. 7 All rights reserved. 8 9 License: 10 Boost Software License Version 1.0. See LICENSE_BOOST.txt for details. 11 Alternatively, this file may be distributed under the terms of the Tango 12 3-Clause BSD License (see LICENSE_BSD.txt for details). 13 14 *******************************************************************************/ 15 16 module ocean.sys.socket.AddrInfo; 17 18 import ocean.core.Array: concat; 19 import ocean.core.TypeConvert; 20 import ocean.core.Verify; 21 import ocean.meta.types.Qualifiers; 22 23 import core.stdc.errno: errno, EAFNOSUPPORT; 24 import core.stdc.string: strlen; 25 import core.sys.posix.arpa.inet: inet_ntop, inet_pton, ntohs, htons, htonl; 26 import core.sys.posix.netinet.in_: sockaddr, socklen_t, 27 sockaddr_in, AF_INET, INET_ADDRSTRLEN, 28 sockaddr_in6, AF_INET6, INET6_ADDRSTRLEN, 29 SOCK_STREAM, IPPROTO_TCP; 30 31 32 /******************************************************************************* 33 34 Address information struct as returned by getaddrinfo(). 35 36 *******************************************************************************/ 37 38 struct addrinfo 39 { 40 /*************************************************************************** 41 42 getaddrinfo() flags. 43 44 ***************************************************************************/ 45 46 enum Flags 47 { 48 None = 0, 49 AI_PASSIVE = 1 << 0, /// Socket address is intended for `bind`. 50 AI_CANONNAME = 1 << 1, /// Request for canonical name. 51 AI_NUMERICHOST = 1 << 2, /// Don't use name resolution. 52 AI_V4MAPPED = 1 << 3, /// IPv4 mapped addresses are acceptable. 53 AI_ALL = 1 << 4, /// Return IPv4 mapped and IPv6 addresses. 54 AI_ADDRCONFIG = 1 << 5, /// Use configuration of this host to choose returned address type. 55 AI_IDN = 1 << 6, /// IDN encode input (assuming it is encoded in the current locale's character set) before looking it up. 56 AI_CANONIDN = 1 << 7, /// Translate canonical name from IDN format. 57 AI_IDN_ALLOW_UNASSIGNED = 1 << 8, /// Don't reject unassigned Unicode code points. 58 AI_IDN_USE_STD3_ASCII_RULES = 1 << 9 /// Validate strings according to STD3 rules. 59 60 } 61 62 /*************************************************************************** 63 64 Error codes returned by getaddrinfo() (not passed via errno). 65 66 ***************************************************************************/ 67 68 enum ErrorCode 69 { 70 Success = 0, 71 EAI_BADFLAGS = -1, /// Invalid value for ai_flags field. 72 EAI_NONAME = -2, /// NAME or SERVICE is unknown. 73 EAI_AGAIN = -3, /// Temporary failure in name resolution. 74 EAI_FAIL = -4, /// Non-recoverable failure in name res. 75 EAI_FAMILY = -6, /// `ai_family` not supported. 76 EAI_SOCKTYPE = -7, /// `ai_socktype` not supported. 77 EAI_SERVICE = -8, /// SERVICE not supported for `ai_socktype`. 78 EAI_MEMORY = -10, /// Memory allocation failure. 79 EAI_SYSTEM = -11, /// System error returned in `errno`. 80 EAI_OVERFLOW = -12, /// Argument buffer overflow. 81 EAI_NODATA = -5, /// No address associated with NAME. 82 EAI_ADDRFAMILY = -9, /// Address family for NAME not supported. 83 EAI_INPROGRESS = -100, /// Processing request in progress. 84 EAI_CANCELED = -101, /// Request canceled. 85 EAI_NOTCANCELED = -102, /// Request not canceled. 86 EAI_ALLDONE = -103, /// All requests done. 87 EAI_INTR = -104, /// Interrupted by a signal. 88 EAI_IDN_ENCODE = -105, /// IDN encoding failed. 89 } 90 91 /*************************************************************************** 92 93 Data fields. 94 95 ***************************************************************************/ 96 97 Flags ai_flags; 98 int ai_family, 99 ai_socktype, 100 ai_protocol; 101 socklen_t ai_addrlen; // The manpage says size_t: WRONG! 102 sockaddr* ai_addr; 103 char* ai_canonname; 104 typeof(&this) ai_next; 105 106 alias .INET6_ADDRSTRLEN INET6_ADDRSTRLEN; 107 alias .INET_ADDRSTRLEN INET_ADDRSTRLEN; 108 109 /*************************************************************************** 110 111 Obtains the current IP address in standard notation. 112 113 Params: 114 dst = destination buffer 115 116 Returns: 117 a slice to the resulting IP address string in dst on success or null 118 on error. On error errno is set appropriately. 119 120 Errors: 121 EAFNOSUPPORT: The address family is not supported (AF_INET/IPv4 or 122 AF_INET6/IPv6). 123 124 In: 125 - this.ai_addr must not be null: this instance should have been 126 obtained by getaddrinfo() or manually initialised. 127 - dst.length must be at least the required address length for the 128 address family, INET_ADDRSTRLEN for IPv4 or INET6_ADDRSTRLEN for 129 IPv6. 130 131 Out: 132 If the resulting slice is not null, it slices dst from the 133 beginning. 134 135 ***************************************************************************/ 136 137 mstring ipAddress ( mstring dst ) 138 out (result) 139 { 140 if (result.length) assert (result.ptr is dst.ptr); 141 } 142 do 143 { 144 void sanity_check ( ) 145 { 146 verify(this.ai_addr !is null); 147 148 switch (this.ai_family) 149 { 150 case AF_INET: 151 verify( 152 dst.length >= INET_ADDRSTRLEN, 153 "dst.length expected to be at least " 154 ~ INET_ADDRSTRLEN.stringof 155 ); 156 break; 157 158 case AF_INET6: 159 verify( 160 dst.length >= INET6_ADDRSTRLEN, 161 "dst.length expected to be at least " 162 ~ INET6_ADDRSTRLEN.stringof 163 ); 164 break; 165 166 default: // will fail with EAFNOSUPPORT anyway 167 } 168 } 169 170 sanity_check(); 171 172 void* addr; 173 174 switch (this.ai_family) 175 { 176 case AF_INET: 177 addr = &(*cast (sockaddr_in*) this.ai_addr).sin_addr; 178 break; 179 180 case AF_INET6: 181 addr = &(*cast (sockaddr_in6*) this.ai_addr).sin6_addr; 182 break; 183 184 default: 185 .errno = EAFNOSUPPORT; // inet_ntop() would do the same 186 return null; 187 } 188 189 auto address_p = .inet_ntop(this.ai_family, addr, dst.ptr, 190 castFrom!(size_t).to!(int)(dst.length)); 191 // inet_ntop returns const pointer even if spec says it will always 192 // use `dst` memory. Using `dst` directly to avoid casts. 193 return address_p ? dst.ptr[0 .. strlen(dst.ptr)] : null; 194 } 195 196 /************************************************************************** 197 198 Obtains the current port number. 199 200 Returns: 201 the current port number. 202 203 Errors: 204 EAFNOSUPPORT: The address family is not supported (AF_INET/IPv4 or 205 AF_INET6/IPv6). 206 207 In: 208 this.ai_addr must not be null: this instance should have been 209 obtained by getaddrinfo() or manually initialised. 210 211 **************************************************************************/ 212 213 ushort port ( ) 214 { 215 verify(this.ai_addr !is null); 216 .errno = 0; 217 218 switch (this.ai_family) 219 { 220 case AF_INET: 221 return .ntohs((cast (sockaddr_in*) this.ai_addr).sin_port); 222 223 case AF_INET6: 224 return .ntohs((cast (sockaddr_in6*) this.ai_addr).sin6_port); 225 226 default: 227 .errno = EAFNOSUPPORT; 228 return 0; 229 } 230 } 231 232 /************************************************************************** 233 234 Obtains the current canonical name. 235 236 Returns: 237 the current canonical name or null. 238 239 **************************************************************************/ 240 241 char[] canonname ( ) 242 { 243 return this.ai_canonname? this.ai_canonname[0 .. strlen(this.ai_canonname)] : null; 244 } 245 246 /************************************************************************** 247 248 'foreach' iteration over the linked list of instances of this struct; 249 starting with this instance. 250 251 Do not change any of the pointer struct members. 252 253 **************************************************************************/ 254 255 int opApply ( scope int delegate ( ref typeof (this) info ) dg ) 256 { 257 int result = 0; 258 259 for (typeof(&this) info = &this; info && !result; info = info.ai_next) 260 { 261 result = dg(*info); 262 } 263 264 return result; 265 } 266 } 267 268 extern (C) 269 { 270 /************************************************************************** 271 272 Obtains the error message for errcode. 273 274 Params: 275 errcode = error code returned by getaddrinfo() 276 277 Returns: 278 the error message for errcode. 279 280 **************************************************************************/ 281 282 public char* gai_strerror(addrinfo.ErrorCode errcode); 283 284 /************************************************************************** 285 286 Given node and service, which identify an Internet host and a service, 287 getaddrinfo() returns one or more addrinfo structures, each of which 288 contains an Internet address that can be specified in a call to bind(2) 289 or connect(2). The getaddrinfo() function combines the functionality 290 provided by the getservbyname(3) and getservbyport(3) functions into a 291 single interface, but unlike the latter functions, getaddrinfo() is 292 reentrant and allows programs to eliminate IPv4-versus-IPv6 dependen‐ 293 cies. 294 295 The addrinfo structure used by getaddrinfo() contains the following 296 fields: 297 298 struct addrinfo { 299 int ai_flags; 300 int ai_family; 301 int ai_socktype; 302 int ai_protocol; 303 size_t ai_addrlen; 304 struct sockaddr *ai_addr; 305 char *ai_canonname; 306 struct addrinfo *ai_next; 307 }; 308 309 The hints argument points to an addrinfo structure that specifies crite‐ 310 ria for selecting the socket address structures returned in the list 311 pointed to by res. If hints is not NULL it points to an addrinfo struc‐ 312 ture whose ai_family, ai_socktype, and ai_protocol specify criteria that 313 limit the set of socket addresses returned by getaddrinfo(), as follows: 314 315 ai_family This field specifies the desired address family for the 316 returned addresses. Valid values for this field include 317 AF_INET and AF_INET6. The value AF_UNSPEC indicates that 318 getaddrinfo() should return socket addresses for any address 319 family (either IPv4 or IPv6, for example) that can be used 320 with node and service. 321 322 ai_socktype This field specifies the preferred socket type, for example 323 SOCK_STREAM or SOCK_DGRAM. Specifying 0 in this field indi‐ 324 cates that socket addresses of any type can be returned by 325 getaddrinfo(). 326 327 ai_protocol This field specifies the protocol for the returned socket 328 addresses. Specifying 0 in this field indicates that socket 329 addresses with any protocol can be returned by getad‐ 330 drinfo(). 331 332 ai_flags This field specifies additional options, described below. 333 Multiple flags are specified by bitwise OR-ing them 334 together. 335 336 All the other fields in the structure pointed to by hints must contain 337 either 0 or a null pointer, as appropriate. Specifying hints as NULL is 338 equivalent to setting ai_socktype and ai_protocol to 0; ai_family to 339 AF_UNSPEC; and ai_flags to (AI_V4MAPPED | AI_ADDRCONFIG). 340 341 node specifies either a numerical network address (for IPv4, numbers- 342 and-dots notation as supported by inet_aton(3); for IPv6, hexadecimal 343 string format as supported by inet_pton(3)), or a network hostname, 344 contains the AI_NUMERICHOST flag then node must be a numerical network 345 address. The AI_NUMERICHOST flag suppresses any potentially lengthy 346 network host address lookups. 347 348 If the AI_PASSIVE flag is specified in hints.ai_flags, and node is NULL, 349 then the returned socket addresses will be suitable for bind(2)ing a 350 socket that will accept(2) connections. The returned socket address 351 will contain the "wildcard address" (INADDR_ANY for IPv4 addresses, 352 IN6ADDR_ANY_INIT for IPv6 address). The wildcard address is used by 353 applications (typically servers) that intend to accept connections on 354 any of the hosts's network addresses. If node is not NULL, then the 355 AI_PASSIVE flag is ignored. 356 357 If the AI_PASSIVE flag is not set in hints.ai_flags, then the returned 358 socket addresses will be suitable for use with connect(2), sendto(2), or 359 sendmsg(2). If node is NULL, then the network address will be set to 360 the loopback interface address (INADDR_LOOPBACK for IPv4 addresses, 361 IN6ADDR_LOOPBACK_INIT for IPv6 address); this is used by applications 362 that intend to communicate with peers running on the same host. 363 364 service sets the port in each returned address structure. If this argu‐ 365 ment is a service name (see services(5)), it is translated to the corre‐ 366 sponding port number. This argument can also be specified as a decimal 367 number, which is simply converted to binary. If service is NULL, then 368 the port number of the returned socket addresses will be left uninitial‐ 369 ized. If AI_NUMERICSERV is specified in hints.ai_flags and service is 370 not NULL, then service must point to a string containing a numeric port 371 number. This flag is used to inhibit the invocation of a name resolu‐ 372 tion service in cases where it is known not to be required. 373 374 Either node or service, but not both, may be NULL. 375 376 The getaddrinfo() function allocates and initializes a linked list of 377 addrinfo structures, one for each network address that matches node and 378 service, subject to any restrictions imposed by hints, and returns a 379 pointer to the start of the list in res. The items in the linked list 380 are linked by the ai_next field. 381 382 There are several reasons why the linked list may have more than one 383 addrinfo structure, including: the network host is multihomed, accessi‐ 384 ble over multiple protocols (e.g. both AF_INET and AF_INET6); or the 385 same service is available from multiple socket types (one SOCK_STREAM 386 address and another SOCK_DGRAM address, for example). Normally, the 387 application should try using the addresses in the order in which they 388 are returned. The sorting function used within getaddrinfo() is defined 389 in RFC 3484; the order can be tweaked for a particular system by editing 390 /etc/gai.conf (available since glibc 2.5). 391 392 If hints.ai_flags includes the AI_CANONNAME flag, then the ai_canonname 393 field of the first of the addrinfo structures in the returned list is 394 set to point to the official name of the host. 395 396 The remaining fields of each returned addrinfo structure are initialized 397 as follows: 398 399 * The ai_family, ai_socktype, and ai_protocol fields return the socket 400 creation parameters (i.e., these fields have the same meaning as the 401 corresponding arguments of socket(2)). For example, ai_family might 402 return AF_INET or AF_INET6; ai_socktype might return SOCK_DGRAM or 403 SOCK_STREAM; and ai_protocol returns the protocol for the socket. 404 405 * A pointer to the socket address is placed in the ai_addr field, and 406 the length of the socket address, in bytes, is placed in the 407 ai_addrlen field. 408 409 If hints.ai_flags includes the AI_ADDRCONFIG flag, then IPv4 addresses 410 are returned in the list pointed to by res only if the local system has 411 at least one IPv4 address configured, and IPv6 addresses are only 412 returned if the local system has at least one IPv6 address configured. 413 414 If hint.ai_flags specifies the AI_V4MAPPED flag, and hints.ai_family was 415 specified as AF_INET6, and no matching IPv6 addresses could be found, 416 then return IPv4-mapped IPv6 addresses in the list pointed to by res. 417 If both AI_V4MAPPED and AI_ALL are specified in hints.ai_flags, then 418 return both IPv6 and IPv4-mapped IPv6 addresses in the list pointed to 419 by res. AI_ALL is ignored if AI_V4MAPPED is not also specified. 420 421 The freeaddrinfo() function frees the memory that was allocated for the 422 dynamically allocated linked list res. 423 424 Extensions to getaddrinfo() for Internationalized Domain Names 425 Starting with glibc 2.3.4, getaddrinfo() has been extended to selec‐ 426 tively allow the incoming and outgoing hostnames to be transparently 427 converted to and from the Internationalized Domain Name (IDN) format 428 (see RFC 3490, Internationalizing Domain Names in Applications (IDNA)). 429 Four new flags are defined: 430 431 AI_IDN If this flag is specified, then the node name given in node is 432 converted to IDN format if necessary. The source encoding is 433 that of the current locale. 434 435 If the input name contains non-ASCII characters, then the IDN 436 encoding is used. Those parts of the node name (delimited by 437 dots) that contain non-ASCII characters are encoded using ASCII 438 Compatible Encoding (ACE) before being passed to the name resolu‐ 439 tion functions. 440 441 AI_CANONIDN 442 After a successful name lookup, and if the AI_CANONNAME flag was 443 specified, getaddrinfo() will return the canonical name of the 444 node corresponding to the addrinfo structure value passed back. 445 The return value is an exact copy of the value returned by the 446 name resolution function. 447 448 If the name is encoded using ACE, then it will contain the xn-- 449 prefix for one or more components of the name. To convert these 450 components into a readable form the AI_CANONIDN flag can be 451 passed in addition to AI_CANONNAME. The resulting string is 452 encoded using the current locale's encoding. 453 454 AI_IDN_ALLOW_UNASSIGNED, AI_IDN_USE_STD3_ASCII_RULES 455 Setting these flags will enable the IDNA_ALLOW_UNASSIGNED (allow 456 unassigned Unicode code points) and IDNA_USE_STD3_ASCII_RULES 457 (check output to make sure it is a STD3 conforming hostname) 458 flags respectively to be used in the IDNA handling. 459 460 461 getaddrinfo() returns 0 if it succeeds, or one of the following nonzero 462 error codes: 463 464 EAI_ADDRFAMILY 465 The specified network host does not have any network addresses in 466 the requested address family. 467 468 EAI_AGAIN 469 The name server returned a temporary failure indication. Try 470 again later. 471 472 EAI_BADFLAGS 473 hints.ai_flags contains invalid flags; or, hints.ai_flags 474 included AI_CANONNAME and name was NULL. 475 476 EAI_FAIL 477 The name server returned a permanent failure indication. 478 479 EAI_FAMILY 480 The requested address family is not supported. 481 482 EAI_MEMORY 483 Out of memory. 484 485 EAI_NODATA 486 The specified network host exists, but does not have any network 487 addresses defined. 488 489 EAI_NONAME 490 The node or service is not known; or both node and service are 491 NULL; or AI_NUMERICSERV was specified in hints.ai_flags and ser‐ 492 vice was not a numeric port-number string. 493 494 EAI_SERVICE 495 The requested service is not available for the requested socket 496 type. It may be available through another socket type. For 497 example, this error could occur if service was "shell" (a service 498 only available on stream sockets), and either hints.ai_protocol 499 was IPPROTO_UDP, or hints.ai_socktype was SOCK_DGRAM; or the 500 error could occur if service was not NULL, and hints.ai_socktype 501 was SOCK_RAW (a socket type that does not support the concept of 502 services). 503 504 EAI_SOCKTYPE 505 The requested socket type is not supported. This could occur, 506 for example, if hints.ai_socktype and hints.ai_protocol are 507 inconsistent (e.g., SOCK_DGRAM and IPPROTO_TCP, respectively). 508 509 EAI_SYSTEM 510 Other system error, check errno for details. 511 512 The gai_strerror() function translates these error codes to a human 513 readable string, suitable for error reporting. 514 515 **************************************************************************/ 516 517 private addrinfo.ErrorCode getaddrinfo(char* node, char* service, 518 addrinfo* hints, addrinfo** res); 519 520 private void freeaddrinfo(addrinfo* res); 521 522 } 523 524 /****************************************************************************** 525 526 Wraps getaddrinfo()/freeaddrinfo() and manages an addrinfo instance. 527 528 ******************************************************************************/ 529 530 class AddrInfo : AddrInfoC 531 { 532 /************************************************************************** 533 534 String nul-termination buffers. 535 536 **************************************************************************/ 537 538 private mstring node, service; 539 540 /************************************************************************** 541 542 Returns: 543 the current address info as most recently obtained. 544 545 **************************************************************************/ 546 547 public override addrinfo* info ( ) 548 { 549 return this.info_; 550 } 551 552 /************************************************************************** 553 554 Gets the address info for a TCP/IP node and/or service. 555 556 Params: 557 node = node name (may be null) 558 service = service name (may be null) 559 ipv6 = false: get the IPv4, true: get the IPv6 address 560 flags = getaddrinfo() flags 561 562 Returns: 563 0 on success or an error code on failure, see addrinfo.ErrorCode. 564 565 **************************************************************************/ 566 567 public ErrorCode getTcpIp ( cstring node, cstring service, bool ipv6, 568 addrinfo.Flags flags = addrinfo.Flags.None ) 569 { 570 return super.getTcpIp(this.node.toCstr(node), 571 this.service.toCstr(service), ipv6, flags); 572 } 573 574 /************************************************************************** 575 576 Gets the address info for an IP node and/or service. 577 578 Params: 579 node = node name (may be null) 580 service = service name (may be null) 581 ipv6 = false: get the IPv4, true: get the IPv6 address 582 type = socket type (0 for any type) 583 protocol = socket protocol (0 for any protocol) 584 flags = getaddrinfo() flags 585 586 Returns: 587 0 on success or an error code on failure, see addrinfo.ErrorCode. 588 589 **************************************************************************/ 590 591 public ErrorCode getIp ( cstring node, cstring service, 592 bool ipv6, int type, int protocol, 593 addrinfo.Flags flags = addrinfo.Flags.None ) 594 { 595 return super.getIp(this.node.toCstr(node), this.service.toCstr(service), 596 ipv6, type, protocol, flags); 597 } 598 599 /************************************************************************** 600 601 Gets the address info for a node and/or service. 602 603 Params: 604 node = node name (may be null) 605 service = service name (may be null) 606 family = socket family (0 for any family) 607 type = socket type (0 for any type) 608 protocol = socket protocol (0 for any protocol) 609 flags = getaddrinfo() flags 610 611 Returns: 612 0 on success or an error code on failure, see addrinfo.ErrorCode. 613 614 **************************************************************************/ 615 616 public ErrorCode get ( cstring node, cstring service, 617 int family, int type, int protocol, 618 addrinfo.Flags flags = addrinfo.Flags.None ) 619 { 620 return super.get(this.node.toCstr(node), this.service.toCstr(service), 621 family, type, protocol, flags); 622 } 623 624 /************************************************************************** 625 626 Gets the address info for a node and/or service. 627 628 Params: 629 node = node name (may be null) 630 service = service name (may be null) 631 hints = addrinfo instance specifying the socket family, type, 632 protocol and flags or null to get all available addresses 633 634 Returns: 635 0 on success or an error code on failure, see addrinfo.ErrorCode. 636 637 **************************************************************************/ 638 639 public ErrorCode get ( cstring node, cstring service, addrinfo* hints = null ) 640 { 641 return super.get(this.node.toCstr(node), this.service.toCstr(service), 642 hints); 643 } 644 } 645 646 /************************************************************************** 647 648 Appends a nul-terminator to src, storing the result in dst. 649 650 Params: 651 dst = destination string buffer 652 src = string to nul-terminate 653 654 Returns: 655 dst.ptr or null if src is empty. 656 657 **************************************************************************/ 658 659 private char* toCstr ( ref mstring dst, cstring src ) 660 { 661 return src.length? dst.concat(src, "\0"[]).ptr : null; 662 } 663 664 /****************************************************************************** 665 666 Wraps getaddrinfo()/freeaddrinfo() and manages an addrinfo instance; uses 667 C strings as arguments. This class is memory-friendly when used with 'scope' 668 instances. 669 670 ******************************************************************************/ 671 672 class AddrInfoC 673 { 674 alias addrinfo.Flags Flags; 675 alias addrinfo.ErrorCode ErrorCode; 676 677 /************************************************************************** 678 679 addrinfo instance. 680 681 **************************************************************************/ 682 683 private addrinfo* info_ = null; 684 685 /************************************************************************** 686 687 IP address conversion buffer 688 689 **************************************************************************/ 690 691 static assert (INET6_ADDRSTRLEN > INET_ADDRSTRLEN); 692 693 char[INET6_ADDRSTRLEN] ip_address_buf; 694 695 /************************************************************************** 696 697 Destructor. 698 699 **************************************************************************/ 700 701 ~this ( ) 702 { 703 if (this.info_) 704 { 705 freeaddrinfo(this.info_); 706 } 707 } 708 709 /************************************************************************** 710 711 Gets the address info for a TCP/IP node and/or service. 712 713 Params: 714 node = node name (may be null) 715 service = service name (may be null) 716 ipv6 = false: get the IPv4, true: get the IPv6 address 717 flags = getaddrinfo() flags 718 719 Returns: 720 0 on success or an error code on failure, see addrinfo.ErrorCode. 721 722 **************************************************************************/ 723 724 public ErrorCode getTcpIp ( char* node, char* service, bool ipv6, 725 addrinfo.Flags flags = addrinfo.Flags.None ) 726 { 727 return this.getIp(node, service, ipv6, SOCK_STREAM, IPPROTO_TCP, flags); 728 } 729 730 /************************************************************************** 731 732 Gets the address info for an IP node and/or service. 733 734 Params: 735 node = node name (may be null) 736 service = service name (may be null) 737 ipv6 = false: get the IPv4, true: get the IPv6 address 738 type = socket type (0 for any type) 739 protocol = socket protocol (0 for any protocol) 740 flags = getaddrinfo() flags 741 742 Returns: 743 0 on success or an error code on failure, see addrinfo.ErrorCode. 744 745 **************************************************************************/ 746 747 public ErrorCode getIp ( char* node, char* service, 748 bool ipv6, int type, int protocol, 749 addrinfo.Flags flags = addrinfo.Flags.None ) 750 { 751 return this.get(node, service, ipv6? AF_INET6 : AF_INET, type, protocol); 752 } 753 754 755 /************************************************************************** 756 757 Gets the address info for a node and/or service. 758 759 Params: 760 node = node name (may be null) 761 service = service name (may be null) 762 family = socket family (0 for any family) 763 type = socket type (0 for any type) 764 protocol = socket protocol (0 for any protocol) 765 flags = getaddrinfo() flags 766 767 Returns: 768 0 on success or an error code on failure, see addrinfo.ErrorCode. 769 770 **************************************************************************/ 771 772 public ErrorCode get ( char* node, char* service, 773 int family, int type, int protocol, 774 addrinfo.Flags flags = addrinfo.Flags.None ) 775 { 776 auto hints = addrinfo(flags, family, type, protocol); 777 778 return this.get(node, service, &hints); 779 } 780 781 /************************************************************************** 782 783 Gets the address info for a node and/or service. 784 785 Params: 786 node = node name (may be null) 787 service = service name (may be null) 788 hints = addrinfo instance specifying the socket family, type, 789 protocol and flags or null to get all available addresses 790 791 Returns: 792 0 on success or an error code on failure, see addrinfo.ErrorCode. 793 794 **************************************************************************/ 795 796 public ErrorCode get ( char* node, char* service, addrinfo* hints = null ) 797 { 798 if (this.info_) 799 { 800 freeaddrinfo(this.info_); 801 802 this.info_ = null; 803 } 804 805 return .getaddrinfo(node, service, hints, &this.info_); 806 } 807 808 /************************************************************************** 809 810 Returns: 811 the current address info as most recently obtained or null if the 812 last get() failed or get() has not been called yet. 813 814 **************************************************************************/ 815 816 public addrinfo* info ( ) 817 { 818 return this.info_; 819 } 820 821 /*************************************************************************** 822 823 Obtains the current IP address in standard notation. 824 825 Returns: 826 a slice to the resulting IP address string in dst on success or null 827 either on error or if the last get() failed or get() has not been 828 called yet; errno is then 0. On success a nul-terminator follows the 829 sliced string so its .ptr is a C string. On error errno is set 830 appropriately. 831 832 Errors: 833 EAFNOSUPPORT: The address family is not supported (AF_INET/IPv4 or 834 AF_INET6/IPv6). 835 836 ***************************************************************************/ 837 838 public char[] ip_address ( ) 839 { 840 .errno = 0; 841 842 return this.info_? this.info_.ipAddress(this.ip_address_buf) : null; 843 } 844 845 /*************************************************************************** 846 847 Returns: 848 the current port or 0 if the last get() failed or get() has not been 849 called yet. 850 851 ***************************************************************************/ 852 853 public ushort port ( ) 854 { 855 return this.info_? this.info_.port : cast(ushort) 0; 856 } 857 858 /*************************************************************************** 859 860 Returns: 861 the official host name or null if the last get() failed or get() has 862 not been called yet with Flags.AI_CANONNAME set. On success a 863 nul-terminator follows the sliced string so its .ptr is a C string. 864 865 ***************************************************************************/ 866 867 public char[] canonname ( ) 868 { 869 return this.info_? this.info_.canonname : null; 870 } 871 872 /*************************************************************************** 873 874 Returns: 875 the official host name as a nul-terminated C string or null if the 876 last get() failed or get() has not been called yet with 877 Flags.AI_CANONNAME set. 878 879 ***************************************************************************/ 880 881 public char* canonname_c ( ) 882 { 883 return this.info_? this.info_.ai_canonname : null; 884 } 885 }