summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ip.cpp182
-rw-r--r--src/ip.hpp11
-rw-r--r--src/tcp_connecter.cpp17
-rw-r--r--src/tcp_connecter.hpp1
-rw-r--r--src/tcp_listener.cpp11
-rw-r--r--src/tcp_listener.hpp1
6 files changed, 103 insertions, 120 deletions
diff --git a/src/ip.cpp b/src/ip.cpp
index cf05fa6..7ee8641 100644
--- a/src/ip.cpp
+++ b/src/ip.cpp
@@ -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;
}
diff --git a/src/ip.hpp b/src/ip.hpp
index 0144546..9d9f5c0 100644
--- a/src/ip.hpp
+++ b/src/ip.hpp
@@ -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;