diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ip.cpp | 182 | ||||
-rw-r--r-- | src/ip.hpp | 11 | ||||
-rw-r--r-- | src/tcp_connecter.cpp | 17 | ||||
-rw-r--r-- | src/tcp_connecter.hpp | 1 | ||||
-rw-r--r-- | src/tcp_listener.cpp | 11 | ||||
-rw-r--r-- | src/tcp_listener.hpp | 1 |
6 files changed, 103 insertions, 120 deletions
@@ -36,12 +36,6 @@ // On Solaris platform, network interface name can be queried by ioctl. static int resolve_nic_name (in_addr* addr_, char const *interface_) { - // * resolves to INADDR_ANY - if (!interface_ || (strlen (interface_) == 1 && *interface_ == '*')) { - addr_->s_addr = htonl (INADDR_ANY); - return 0; - } - // Create a socket. int fd = socket (AF_INET, SOCK_DGRAM, 0); zmq_assert (fd != -1); @@ -87,14 +81,9 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) free (ifr); close (fd); - // If interface was not found among interface names, we assume it's - // specified in the form of IP address. if (!found) { - rc = inet_pton (AF_INET, interface_, addr_); - if (rc != 1) { - errno = EINVAL; - return -1; - } + errno = ENODEV; + return -1; } return 0; @@ -111,12 +100,6 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) static int resolve_nic_name (in_addr* addr_, char const *interface_) { - // * resolves to INADDR_ANY - if (!interface_ || (strlen (interface_) == 1 && *interface_ == '*')) { - addr_->s_addr = htonl (INADDR_ANY); - return 0; - } - // Create a socket. int sd = socket (AF_INET, SOCK_DGRAM, 0); zmq_assert (sd != -1); @@ -129,48 +112,17 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) // Fetch interface address. int rc = ioctl (sd, SIOCGIFADDR, (caddr_t) &ifr, sizeof (struct ifreq)); - if(rc != -1) { - struct sockaddr *sa = (struct sockaddr *) &ifr.ifr_addr; - *addr_ = ((sockaddr_in*)sa)->sin_addr; - } - else { - - // Assume interface_ is in IP format xxx.xxx.xxx.xxx. - rc = inet_pton (AF_INET, interface_, addr_); - if (rc != 0) { - errno = EINVAL; - return -1; - } - } - // Clean up. close (sd); - return 0; -} - -#elif defined ZMQ_HAVE_WINDOWS - -static int resolve_nic_name (in_addr* addr_, char const *interface_) -{ - // * resolves to INADDR_ANY - if (!interface_ || (strlen (interface_) == 1 && *interface_ == '*')) { - addr_->s_addr = htonl (INADDR_ANY); - return 0; - } - - // Windows doesn't use sensible NIC names. Thus, we expect IP address of - // the NIC instead. - in_addr addr; - ((sockaddr_in*) addr_)->sin_family = AF_INET; - addr.S_un.S_addr = inet_addr ((const char *) interface_); - if (addr.S_un.S_addr == INADDR_NONE) { - errno = EINVAL; + if (rc == -1) { + errno = ENODEV; return -1; } - *addr_ = addr; - return 0; + struct sockaddr *sa = (struct sockaddr *) &ifr.ifr_addr; + *addr_ = ((sockaddr_in*)sa)->sin_addr; + return 0; } #elif ((defined ZMQ_HAVE_LINUX || defined ZMQ_HAVE_FREEBSD ||\ @@ -183,15 +135,6 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) // using getifaddrs function. static int resolve_nic_name (in_addr* addr_, char const *interface_) { - // * resolves to INADDR_ANY - if (!interface_ || (strlen (interface_) == 1 && *interface_ == '*')) { - addr_->s_addr = htonl (INADDR_ANY); - return 0; - } - - // Initialuse the output parameter. - memset (addr_, 0, sizeof (in_addr)); - // Get the addresses. ifaddrs* ifa = NULL; int rc = getifaddrs (&ifa); @@ -211,14 +154,9 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) // Clean-up; freeifaddrs (ifa); - // If interface was not found among interface names, we assume it's - // specified in the form of IP address. if (!found) { - rc = inet_pton (AF_INET, interface_, addr_); - if (rc != 1) { - errno = EINVAL; - return -1; - } + errno = ENODEV; + return -1; } return 0; @@ -226,56 +164,87 @@ static int resolve_nic_name (in_addr* addr_, char const *interface_) #else -// On other platforms interface name is interpreted as raw IP address. +// On other platforms we assume there are no sane interface names. +// This is true especially of Windows. static int resolve_nic_name (in_addr* addr_, char const *interface_) { - // * resolves to INADDR_ANY - if (!interface_ || (strlen (interface_) == 1 && *interface_ == '*')) { - addr_->s_addr = htonl (INADDR_ANY); - return 0; - } - - // Convert IP address into sockaddr_in structure. - int rc = inet_pton (AF_INET, interface_, addr_); - zmq_assert (rc != 0); - errno_assert (rc == 1); - - return 0; + errno = ENODEV; + return -1; } #endif -int zmq::resolve_ip_interface (sockaddr_storage* addr_, char const *interface_) +int zmq::resolve_ip_interface (sockaddr_storage* addr_, socklen_t *addr_len_, + char const *interface_) { - sockaddr_in *addr = (sockaddr_in*) addr_; - - // Find the ':' that separates NIC name from port. - const char *delimiter = strchr (interface_, ':'); + // Find the end ':' that separates NIC name from service. + const char *delimiter = strrchr (interface_, ':'); if (!delimiter) { errno = EINVAL; return -1; } - // Clean the structure and fill in protocol family. - memset (addr, 0, sizeof (sockaddr_in)); - addr->sin_family = AF_INET; + // Separate the name/port. + std::string interface (interface_, delimiter - interface_); + std::string service (delimiter + 1); - // Resolve the name of the NIC. - std::string nic_name (interface_, delimiter - interface_); - if (resolve_nic_name (&addr->sin_addr, nic_name.c_str ()) != 0) - return -1; + // Initialize the output parameter. + memset (addr_, 0, sizeof (*addr_)); - // Resolve the port. - addr->sin_port = htons ((uint16_t) atoi (delimiter + 1)); - if (!addr->sin_port) { + // Initialise IPv4-format family/port. + sockaddr_in ip4_addr; + ip4_addr.sin_family = AF_INET; + ip4_addr.sin_port = htons ((uint16_t) atoi (service.c_str())); + + + // Initialize temporary output pointers with ip4_addr + sockaddr *out_addr = (sockaddr *) &ip4_addr; + size_t out_addrlen = sizeof (ip4_addr); + + // 0 is not a valid port. + if (!ip4_addr.sin_port) { errno = EINVAL; return -1; } + // * resolves to INADDR_ANY. + if (interface.compare("*") == 0) { + ip4_addr.sin_addr.s_addr = htonl (INADDR_ANY); + zmq_assert (out_addrlen <= sizeof (*addr_)); + memcpy (addr_, out_addr, out_addrlen); + *addr_len_ = out_addrlen; + return 0; + } + + // Try to resolve the string as a NIC name. + int rc = resolve_nic_name (&ip4_addr.sin_addr, interface.c_str()); + if (rc != 0 && errno != ENODEV) + return rc; + if (rc == 0) { + zmq_assert (out_addrlen <= sizeof (*addr_)); + memcpy (addr_, out_addr, out_addrlen); + *addr_len_ = out_addrlen; + return 0; + } + + // There's no such interface name. Assume literal address. + rc = inet_pton (AF_INET, interface.c_str(), &ip4_addr.sin_addr); + + if (rc == 0) { + errno = ENODEV; + return -1; + } + if (rc < 0) + return -1; + + zmq_assert (out_addrlen <= sizeof (*addr_)); + memcpy (addr_, out_addr, out_addrlen); + *addr_len_ = out_addrlen; return 0; } -int zmq::resolve_ip_hostname (sockaddr_storage *addr_, const char *hostname_) +int zmq::resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_, + const char *hostname_) { sockaddr_in *addr = (sockaddr_in*) addr_; @@ -294,6 +263,8 @@ int zmq::resolve_ip_hostname (sockaddr_storage *addr_, const char *hostname_) addrinfo req; memset (&req, 0, sizeof (req)); req.ai_family = AF_INET; + *addr_len_ = sizeof (*addr_); + addrinfo *res; int rc = getaddrinfo (hostname.c_str (), NULL, &req, &res); if (rc) { @@ -316,15 +287,18 @@ int zmq::resolve_ip_hostname (sockaddr_storage *addr_, const char *hostname_) #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS -int zmq::resolve_local_path (sockaddr_un *addr_, const char *path_) +int zmq::resolve_local_path (sockaddr_storage *addr_, socklen_t *addr_len_, + const char *path_) { - if (strlen (path_) >= sizeof (addr_->sun_path)) + sockaddr_un *un = (sockaddr_un*) addr_; + if (strlen (path_) >= sizeof (un->sun_path)) { errno = ENAMETOOLONG; return -1; } - strcpy (addr_->sun_path, path_); - addr_->sun_family = AF_UNIX; + strcpy (un->sun_path, path_); + un->sun_family = AF_UNIX; + *addr_len_ = sizeof (sockaddr_un); return 0; } @@ -41,15 +41,18 @@ namespace zmq // Resolves network interface name in <nic-name>:<port> format. Symbol "*" // (asterisk) resolves to INADDR_ANY (all network interfaces). - int resolve_ip_interface (sockaddr_storage *addr_, char const *interface_); + int resolve_ip_interface (sockaddr_storage *addr_, socklen_t *addr_len_, + char const *interface_); // This function resolves a string in <hostname>:<port-number> format. // Hostname can be either the name of the host or its IP address. - int resolve_ip_hostname (sockaddr_storage *addr_, const char *hostname_); + int resolve_ip_hostname (sockaddr_storage *addr_, socklen_t *addr_len_, + const char *hostname_); #if !defined ZMQ_HAVE_WINDOWS && !defined ZMQ_HAVE_OPENVMS - // This function sets up the sockaddr_un structure with the pathname_ - int resolve_local_path (sockaddr_un *addr_, const char* pathname_); + // This function sets up address for UNIX domain transport. + int resolve_local_path (sockaddr_storage *addr_, socklen_t *addr_len_, + const char* pathname_); #endif } diff --git a/src/tcp_connecter.cpp b/src/tcp_connecter.cpp index 436da88..ebd9b9d 100644 --- a/src/tcp_connecter.cpp +++ b/src/tcp_connecter.cpp @@ -34,6 +34,7 @@ zmq::tcp_connecter_t::tcp_connecter_t () : s (retired_fd) { memset (&addr, 0, sizeof (addr)); + addr_len = 0; } zmq::tcp_connecter_t::~tcp_connecter_t () @@ -45,7 +46,7 @@ zmq::tcp_connecter_t::~tcp_connecter_t () int zmq::tcp_connecter_t::set_address (const char *protocol_, const char *addr_) { if (strcmp (protocol_, "tcp") == 0) - return resolve_ip_hostname (&addr, addr_); + return resolve_ip_hostname (&addr, &addr_len, addr_); errno = EPROTONOSUPPORT; return -1; @@ -74,7 +75,7 @@ int zmq::tcp_connecter_t::open () wsa_assert (rc != SOCKET_ERROR); // Connect to the remote peer. - rc = ::connect (s, (sockaddr*) &addr, sizeof (addr)); + rc = ::connect (s, (sockaddr*) &addr, addr_len); // Connect was successfull immediately. if (rc == 0) @@ -153,9 +154,9 @@ zmq::tcp_connecter_t::~tcp_connecter_t () int zmq::tcp_connecter_t::set_address (const char *protocol_, const char *addr_) { if (strcmp (protocol_, "tcp") == 0) - return resolve_ip_hostname (&addr, addr_); + return resolve_ip_hostname (&addr, &addr_len, addr_); else if (strcmp (protocol_, "ipc") == 0) - return resolve_local_path (( struct sockaddr_un*)&addr, addr_); + return resolve_local_path (&addr, &addr_len, addr_); errno = EPROTONOSUPPORT; return -1; @@ -182,18 +183,20 @@ int zmq::tcp_connecter_t::open () // Disable Nagle's algorithm. int flag = 1; - rc = setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof (int)); + rc = setsockopt (s, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, + sizeof (int)); errno_assert (rc == 0); #ifdef ZMQ_HAVE_OPENVMS // Disable delayed acknowledgements. flag = 1; - rc = setsockopt (s, IPPROTO_TCP, TCP_NODELACK, (char*) &flag, sizeof (int)); + rc = setsockopt (s, IPPROTO_TCP, TCP_NODELACK, (char*) &flag, + sizeof (int)); errno_assert (rc != SOCKET_ERROR); #endif // Connect to the remote peer. - rc = ::connect (s, (struct sockaddr*) &addr, sizeof (addr)); + rc = ::connect (s, (struct sockaddr*) &addr, addr_len); // Connect was successfull immediately. if (rc == 0) diff --git a/src/tcp_connecter.hpp b/src/tcp_connecter.hpp index 23a6e9c..eee13ef 100644 --- a/src/tcp_connecter.hpp +++ b/src/tcp_connecter.hpp @@ -59,6 +59,7 @@ namespace zmq // Address to connect to. sockaddr_storage addr; + socklen_t addr_len; // Underlying socket. fd_t s; diff --git a/src/tcp_listener.cpp b/src/tcp_listener.cpp index c26201c..3d15abe 100644 --- a/src/tcp_listener.cpp +++ b/src/tcp_listener.cpp @@ -33,6 +33,7 @@ zmq::tcp_listener_t::tcp_listener_t () : s (retired_fd) { memset (&addr, 0, sizeof (addr)); + addr_len = 0; } zmq::tcp_listener_t::~tcp_listener_t () @@ -50,7 +51,7 @@ int zmq::tcp_listener_t::set_address (const char *protocol_, const char *addr_) } // Convert the interface into sockaddr_in structure. - int rc = resolve_ip_interface (&addr, addr_); + int rc = resolve_ip_interface (&addr, &addr_len, addr_); if (rc != 0) return rc; @@ -73,7 +74,7 @@ int zmq::tcp_listener_t::set_address (const char *protocol_, const char *addr_) wsa_assert (rc != SOCKET_ERROR); // Bind the socket to the network interface and port. - rc = bind (s, (struct sockaddr*) &addr, sizeof (addr)); + rc = bind (s, (struct sockaddr*) &addr, addr_len); if (rc == SOCKET_ERROR) { wsa_error_to_errno (); return -1; @@ -158,7 +159,7 @@ int zmq::tcp_listener_t::set_address (const char *protocol_, const char *addr_) if (strcmp (protocol_, "tcp") == 0 ) { // Resolve the sockaddr to bind to. - int rc = resolve_ip_interface (&addr, addr_); + int rc = resolve_ip_interface (&addr, &addr_len, addr_); if (rc != 0) return -1; @@ -180,7 +181,7 @@ int zmq::tcp_listener_t::set_address (const char *protocol_, const char *addr_) errno_assert (rc != -1); // Bind the socket to the network interface and port. - rc = bind (s, (struct sockaddr*) &addr, sizeof (addr)); + rc = bind (s, (struct sockaddr*) &addr, addr_len); if (rc != 0) { close (); return -1; @@ -202,7 +203,7 @@ int zmq::tcp_listener_t::set_address (const char *protocol_, const char *addr_) ::unlink (addr_); // Convert the address into sockaddr_un structure. - int rc = resolve_local_path ((struct sockaddr_un*) &addr, addr_); + int rc = resolve_local_path (&addr, &addr_len, addr_); if (rc != 0) return -1; diff --git a/src/tcp_listener.hpp b/src/tcp_listener.hpp index 87748d0..3b60719 100644 --- a/src/tcp_listener.hpp +++ b/src/tcp_listener.hpp @@ -54,6 +54,7 @@ namespace zmq // Address to listen on. sockaddr_storage addr; + socklen_t addr_len; // Underlying socket. fd_t s; |