Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UDP address name resolution is limited to dotted IPv4 rather than being capable of IPv4, IPv6, and hostname lookup #2891

Closed
robwiss opened this issue Jan 19, 2018 · 2 comments

Comments

@robwiss
Copy link

robwiss commented Jan 19, 2018

Issue description

The udp transport requires addresses passed into it be in IPv4 dotted notation. Take this sample program:

#include <assert.h>
#include <cstdio>
#include <zmq.h>

int main(int argc, char** argv) {
  char address[4096];
  sprintf(address, "udp://%s:5555", argv[1]);

  void* ctx = zmq_ctx_new();
  void* skt = zmq_socket(ctx, ZMQ_DISH);
  int rc = zmq_bind(skt, address);
  assert(0 == rc);
  printf("Success\n");
}

this is ok:

$ ./udp_bind_test 127.0.0.1
Success

but this is not ok

$ ./udp_bind_test localhost
udp_bind_test: udp_bind_test.cpp:12: int main(int, char**): Assertion `0 == rc' failed.
Aborted (core dumped)

This is different from the behavior of the tcp transport, which allows binding to localhost and many other types of address names.

I believe the issue stems from zmq::udp_address_t::resolve(const char *name_, bool bind_) in src/udp_address.cpp. This function expects the endpoint name to be a ":" separated address and port. After splitting the name argument into addr_str and port_str, addr_str is translated to a in_addr_t struct using inet_addr(). The manpage for inet_addr, man inet_addr says:

The inet_addr() function converts the Internet host address cp from IPv4 numbers-and-dots notation into binary data in network byte order. If the input is invalid, INADDR_NONE (usually -1) is returned. Use of this function is problematic because -1 is a valid address (255.255.255.255). Avoid its use in favor of inet_aton(), inet_pton(3), or getaddrinfo(3) which provide a cleaner way to indicate error return.

Were getaddrinfo used instead of inet_addr (as it is in the zmq::tcp_address_t::resolve_interface (const char *interface_, bool ipv6_, bool is_src_) function from src/tcp_address.cpp) a name like "localhost" or even an IPv6 address would work. From the getaddrinfo manpage:

int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
node specifies either a numerical network address (for IPv4, numbers-and-dots notation as supported by inet_aton(3); for IPv6, hexadecimal string format as supported by inet_pton(3)), or a network hostname, whose network addresses are looked up and resolved.
service sets the port in each returned address structure. If this argument is a service name (see services(5)), it is translated to the corresponding port number. This argument can also be specified as a decimal number, which is simply converted to binary.

Is there a reason the udp resolve function cannot be switched from using inet_addr() to getaddrinfo() so as to support name lookups and possibly also IPv6?

Environment

  • libzmq version (commit hash if unreleased): 4.2.3
  • OS: CentOS 6.9
@bluca
Copy link
Member

bluca commented Jan 19, 2018

No particular reason, it's just work-in-progress hence why it's marked as DRAFT. IPv6 (especially for multicast) is not yet supported. PRs welcome!

@bluca
Copy link
Member

bluca commented May 9, 2018

Fixed by #3075 and #3081

@bluca bluca closed this as completed May 9, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants