10 #ifndef ZMQ_HAVE_WINDOWS
11 #include <sys/types.h>
12 #include <arpa/inet.h>
13 #include <netinet/tcp.h>
25 return generic.sa_family;
30 if (family () == AF_INET) {
33 return IN_MULTICAST (ntohl (ipv4.sin_addr.s_addr));
36 return IN6_IS_ADDR_MULTICAST (&ipv6.sin6_addr) != 0;
41 if (family () == AF_INET6) {
42 return ntohs (ipv6.sin6_port);
44 return ntohs (ipv4.sin_port);
54 return static_cast<zmq_socklen_t> (family () == AF_INET6 ?
sizeof (ipv6)
60 if (family () == AF_INET6) {
61 ipv6.sin6_port = htons (port_);
63 ipv4.sin_port = htons (port_);
72 if (family_ == AF_INET) {
73 sockaddr_in *ip4_addr = &addr.
ipv4;
74 memset (ip4_addr, 0,
sizeof (*ip4_addr));
75 ip4_addr->sin_family = AF_INET;
76 ip4_addr->sin_addr.s_addr = htonl (INADDR_ANY);
77 }
else if (family_ == AF_INET6) {
78 sockaddr_in6 *ip6_addr = &addr.
ipv6;
80 memset (ip6_addr, 0,
sizeof (*ip6_addr));
81 ip6_addr->sin6_family = AF_INET6;
82 #ifdef ZMQ_HAVE_VXWORKS
83 struct in6_addr newaddr = IN6ADDR_ANY_INIT;
84 memcpy (&ip6_addr->sin6_addr, &newaddr, sizeof (in6_addr));
86 memcpy (&ip6_addr->sin6_addr, &in6addr_any, sizeof (in6addr_any));
89 assert (0 ==
"unsupported address family");
96 _bindable_wanted (
false),
97 _nic_name_allowed (
false),
99 _port_expected (
false),
100 _dns_allowed (
false),
101 _path_allowed (
false)
108 _bindable_wanted = bindable_;
116 _nic_name_allowed = allow_;
123 _ipv6_wanted = ipv6_;
133 _port_expected = expect_;
140 _dns_allowed = allow_;
147 _path_allowed = allow_;
154 return _bindable_wanted;
159 return _nic_name_allowed;
169 return _port_expected;
179 return _path_allowed;
192 if (_options.expect_port ()) {
195 const char *delim = strrchr (
name_,
':');
205 if (port_str ==
"*") {
206 if (_options.bindable ()) {
213 }
else if (port_str ==
"0") {
219 port =
static_cast<uint16_t
> (atoi (port_str.c_str ()));
231 if (_options.allow_path ()) {
232 const size_t pos = addr.find (
'/');
233 if (pos != std::string::npos)
234 addr = addr.substr (0, pos);
242 const size_t brackets_length = 2;
243 if (addr.size () >= brackets_length && addr[0] ==
'['
244 && addr[addr.size () - 1] ==
']') {
245 addr = addr.substr (1, addr.size () - brackets_length);
250 const std::size_t pos = addr.rfind (
'%');
251 uint32_t zone_id = 0;
253 if (pos != std::string::npos) {
255 if (if_str.empty ()) {
259 addr = addr.substr (0, pos);
261 if (isalpha (if_str.at (0))) {
262 zone_id = do_if_nametoindex (if_str.c_str ());
264 zone_id =
static_cast<uint32_t
> (atoi (if_str.c_str ()));
273 bool resolved =
false;
274 const char *addr_str = addr.c_str ();
276 if (_options.bindable () && addr ==
"*") {
278 *ip_addr_ =
ip_addr_t::any (_options.ipv6 () ? AF_INET6 : AF_INET);
282 if (!resolved && _options.allow_nic_name ()) {
284 const int rc = resolve_nic_name (ip_addr_, addr_str);
288 }
else if (
errno != ENODEV) {
294 const int rc = resolve_getaddrinfo (ip_addr_, addr_str);
308 if (ip_addr_->
family () == AF_INET6) {
309 ip_addr_->
ipv6.sin6_scope_id = zone_id;
312 assert (resolved ==
true);
319 #if defined ZMQ_HAVE_OPENVMS && defined __ia64
320 __addrinfo64 *res =
NULL;
323 addrinfo *res =
NULL;
327 memset (&
req, 0,
sizeof (
req));
331 req.ai_family = _options.ipv6 () ? AF_INET6 : AF_INET;
334 req.ai_socktype = SOCK_STREAM;
338 if (_options.bindable ()) {
339 req.ai_flags |= AI_PASSIVE;
342 if (!_options.allow_dns ()) {
343 req.ai_flags |= AI_NUMERICHOST;
346 #if defined AI_V4MAPPED
350 if (
req.ai_family == AF_INET6) {
351 req.ai_flags |= AI_V4MAPPED;
357 int rc = do_getaddrinfo (addr_,
NULL, &
req, &res);
359 #if defined AI_V4MAPPED
362 if (rc == EAI_BADFLAGS && (
req.ai_flags & AI_V4MAPPED)) {
363 req.ai_flags &= ~AI_V4MAPPED;
364 rc = do_getaddrinfo (addr_,
NULL, &
req, &res);
368 #if defined ZMQ_HAVE_WINDOWS
371 if ((
req.ai_family == AF_INET6) && (rc == WSAHOST_NOT_FOUND)) {
372 req.ai_family = AF_INET;
373 rc = do_getaddrinfo (addr_,
NULL, &
req, &res);
383 if (_options.bindable ()) {
395 zmq_assert (
static_cast<size_t> (res->ai_addrlen) <= sizeof (*ip_addr_));
396 memcpy (ip_addr_, res->ai_addr, res->ai_addrlen);
399 do_freeaddrinfo (res);
404 #ifdef ZMQ_HAVE_SOLARIS
405 #include <sys/sockio.h>
411 const int fd =
open_socket (AF_INET, SOCK_DGRAM, 0);
416 ifn.lifn_family = AF_INET;
418 int rc = ioctl (fd, SIOCGLIFNUM, (
char *) &ifn);
422 const size_t ifr_size =
sizeof (
struct lifreq) * ifn.lifn_count;
423 char *ifr = (
char *) malloc (ifr_size);
428 ifc.lifc_family = AF_INET;
430 ifc.lifc_len = ifr_size;
432 rc = ioctl (fd, SIOCGLIFCONF, (
char *) &ifc);
437 lifreq *ifrp = ifc.lifc_req;
438 for (
int n = 0;
n < (int) (ifc.lifc_len / sizeof (lifreq));
n++, ifrp++) {
439 if (!strcmp (nic_, ifrp->lifr_name)) {
440 rc = ioctl (fd, SIOCGLIFADDR, (
char *) ifrp);
442 if (ifrp->lifr_addr.ss_family == AF_INET) {
443 ip_addr_->
ipv4 = *(sockaddr_in *) &ifrp->lifr_addr;
461 #elif defined ZMQ_HAVE_AIX || defined ZMQ_HAVE_HPUX \
462 || defined ZMQ_HAVE_ANDROID || defined ZMQ_HAVE_VXWORKS
463 #include <sys/ioctl.h>
464 #ifdef ZMQ_HAVE_VXWORKS
470 #if defined ZMQ_HAVE_AIX || defined ZMQ_HAVE_HPUX
472 if (_options.ipv6 ()) {
480 open_socket (_options.ipv6 () ? AF_INET6 : AF_INET, SOCK_DGRAM, 0);
486 strncpy (ifr.ifr_name, nic_, sizeof (ifr.ifr_name));
489 const int rc = ioctl (sd, SIOCGIFADDR, (caddr_t) &ifr,
sizeof (ifr));
499 const int family = ifr.ifr_addr.sa_family;
500 if (family == (_options.ipv6 () ? AF_INET6 : AF_INET)
501 && !strcmp (nic_, ifr.ifr_name)) {
502 memcpy (ip_addr_, &ifr.ifr_addr,
503 (family == AF_INET) ? sizeof (
struct sockaddr_in)
504 :
sizeof (
struct sockaddr_in6));
513 #elif ((defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD \
514 || defined ZMQ_HAVE_OSX || defined ZMQ_HAVE_OPENBSD \
515 || defined ZMQ_HAVE_QNXNTO || defined ZMQ_HAVE_NETBSD \
516 || defined ZMQ_HAVE_DRAGONFLY || defined ZMQ_HAVE_GNU) \
517 && defined ZMQ_HAVE_IFADDRS)
528 const int max_attempts = 10;
529 const int backoff_msec = 1;
530 for (
int i = 0;
i < max_attempts;
i++) {
531 rc = getifaddrs (&ifa);
534 usleep ((backoff_msec <<
i) * 1000);
547 for (
const ifaddrs *ifp = ifa; ifp !=
NULL; ifp = ifp->ifa_next) {
548 if (ifp->ifa_addr ==
NULL)
551 const int family = ifp->ifa_addr->sa_family;
552 if (family == (_options.ipv6 () ? AF_INET6 : AF_INET)
553 && !strcmp (nic_, ifp->ifa_name)) {
554 memcpy (ip_addr_, ifp->ifa_addr,
555 (family == AF_INET) ? sizeof (
struct sockaddr_in)
556 :
sizeof (
struct sockaddr_in6));
572 #elif (defined ZMQ_HAVE_WINDOWS)
574 #include <netioapi.h>
576 int zmq::ip_resolver_t::get_interface_name (
unsigned long index_,
579 #ifdef ZMQ_HAVE_WINDOWS_UWP
580 char *
buffer = (
char *) malloc (1024);
582 char *
buffer =
static_cast<char *
> (malloc (IF_MAX_STRING_SIZE));
586 char *if_name_result =
NULL;
588 #if _WIN32_WINNT > _WIN32_WINNT_WINXP && !defined ZMQ_HAVE_WINDOWS_UWP
592 if (if_name_result ==
NULL) {
601 int zmq::ip_resolver_t::wchar_to_utf8 (
const WCHAR *src_,
char **dest_)
const
604 const int buffer_len =
605 WideCharToMultiByte (CP_UTF8, 0, src_, -1,
NULL, 0,
NULL, 0);
607 char *
buffer =
static_cast<char *
> (malloc (buffer_len));
611 WideCharToMultiByte (CP_UTF8, 0, src_, -1,
buffer, buffer_len,
NULL, 0);
626 const int max_attempts = 10;
629 IP_ADAPTER_ADDRESSES *addresses;
630 unsigned long out_buf_len =
sizeof (IP_ADAPTER_ADDRESSES);
633 addresses =
static_cast<IP_ADAPTER_ADDRESSES *
> (malloc (out_buf_len));
637 GetAdaptersAddresses (AF_UNSPEC,
638 GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
639 | GAA_FLAG_SKIP_DNS_SERVER,
640 NULL, addresses, &out_buf_len);
641 if (rc == ERROR_BUFFER_OVERFLOW) {
648 }
while ((rc == ERROR_BUFFER_OVERFLOW) && (iterations < max_attempts));
651 for (
const IP_ADAPTER_ADDRESSES *current_addresses = addresses;
652 current_addresses; current_addresses = current_addresses->Next) {
653 char *if_name =
NULL;
654 char *if_friendly_name =
NULL;
657 get_interface_name (current_addresses->IfIndex, &if_name);
658 const int str_rc2 = wchar_to_utf8 (current_addresses->FriendlyName,
662 if (((str_rc1 == 0) && (!strcmp (nic_, if_name)))
663 || ((str_rc2 == 0) && (!strcmp (nic_, if_friendly_name)))) {
665 for (
const IP_ADAPTER_UNICAST_ADDRESS *current_unicast_address =
666 current_addresses->FirstUnicastAddress;
667 current_unicast_address;
668 current_unicast_address = current_unicast_address->Next) {
669 const ADDRESS_FAMILY family =
670 current_unicast_address->Address.lpSockaddr->sa_family;
672 if (family == (_options.ipv6 () ? AF_INET6 : AF_INET)) {
674 ip_addr_, current_unicast_address->Address.lpSockaddr,
675 (family == AF_INET) ? sizeof (
struct sockaddr_in)
676 :
sizeof (
struct sockaddr_in6));
689 free (if_friendly_name);
717 const char *service_,
718 const struct addrinfo *hints_,
719 struct addrinfo **res_)
721 return getaddrinfo (node_, service_, hints_, res_);
732 #ifdef HAVE_IF_NAMETOINDEX
733 return if_nametoindex (ifname_);