udp_address.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MPL-2.0 */
2 
3 #include "precompiled.hpp"
4 #include <string>
5 #include <sstream>
6 
7 #include "macros.hpp"
8 #include "udp_address.hpp"
9 #include "stdint.hpp"
10 #include "err.hpp"
11 #include "ip.hpp"
12 
13 #ifndef ZMQ_HAVE_WINDOWS
14 #include <sys/types.h>
15 #include <arpa/inet.h>
16 #include <netdb.h>
17 #include <net/if.h>
18 #include <ctype.h>
19 #endif
20 
22  _bind_interface (-1), _is_multicast (false)
23 {
24  _bind_address = ip_addr_t::any (AF_INET);
25  _target_address = ip_addr_t::any (AF_INET);
26 }
27 
29 {
30 }
31 
32 int zmq::udp_address_t::resolve (const char *name_, bool bind_, bool ipv6_)
33 {
34  // No IPv6 support yet
35  bool has_interface = false;
36 
37  _address = name_;
38 
39  // If we have a semicolon then we should have an interface specifier in the
40  // URL
41  const char *src_delimiter = strrchr (name_, ';');
42  if (src_delimiter) {
43  const std::string src_name (name_, src_delimiter - name_);
44 
45  ip_resolver_options_t src_resolver_opts;
46 
47  src_resolver_opts
48  .bindable (true)
49  // Restrict hostname/service to literals to avoid any DNS
50  // lookups or service-name irregularity due to
51  // indeterminate socktype.
52  .allow_dns (false)
53  .allow_nic_name (true)
54  .ipv6 (ipv6_)
55  .expect_port (false);
56 
57  ip_resolver_t src_resolver (src_resolver_opts);
58 
59  const int rc = src_resolver.resolve (&_bind_address, src_name.c_str ());
60 
61  if (rc != 0) {
62  return -1;
63  }
64 
65  if (_bind_address.is_multicast ()) {
66  // It doesn't make sense to have a multicast address as a source
67  errno = EINVAL;
68  return -1;
69  }
70 
71  // This is a hack because we need the interface index when binding
72  // multicast IPv6, we can't do it by address. Unfortunately for the
73  // time being we don't have a generic platform-independent function to
74  // resolve an interface index from an address, so we only support it
75  // when an actual interface name is provided.
76  if (src_name == "*") {
77  _bind_interface = 0;
78  } else {
79 #ifdef HAVE_IF_NAMETOINDEX
80  _bind_interface = if_nametoindex (src_name.c_str ());
81  if (_bind_interface == 0) {
82  // Error, probably not an interface name.
83  _bind_interface = -1;
84  }
85 #endif
86  }
87 
88  has_interface = true;
89  name_ = src_delimiter + 1;
90  }
91 
92  ip_resolver_options_t resolver_opts;
93 
94  resolver_opts.bindable (bind_)
95  .allow_dns (true)
96  .allow_nic_name (bind_)
97  .expect_port (true)
98  .ipv6 (ipv6_);
99 
100  ip_resolver_t resolver (resolver_opts);
101 
102  const int rc = resolver.resolve (&_target_address, name_);
103  if (rc != 0) {
104  return -1;
105  }
106 
107  _is_multicast = _target_address.is_multicast ();
108  const uint16_t port = _target_address.port ();
109 
110  if (has_interface) {
111  // If we have an interface specifier then the target address must be a
112  // multicast address
113  if (!_is_multicast) {
114  errno = EINVAL;
115  return -1;
116  }
117 
118  _bind_address.set_port (port);
119  } else {
120  // If we don't have an explicit interface specifier then the URL is
121  // ambiguous: if the target address is multicast then it's the
122  // destination address and the bind address is ANY, if it's unicast
123  // then it's the bind address when 'bind_' is true and the destination
124  // otherwise
125  if (_is_multicast || !bind_) {
126  _bind_address = ip_addr_t::any (_target_address.family ());
127  _bind_address.set_port (port);
128  _bind_interface = 0;
129  } else {
130  // If we were asked for a bind socket and the address
131  // provided was not multicast then it was really meant as
132  // a bind address and the target_address is useless.
133  _bind_address = _target_address;
134  }
135  }
136 
137  if (_bind_address.family () != _target_address.family ()) {
138  errno = EINVAL;
139  return -1;
140  }
141 
142  // For IPv6 multicast we *must* have an interface index since we can't
143  // bind by address.
144  if (ipv6_ && _is_multicast && _bind_interface < 0) {
145  errno = ENODEV;
146  return -1;
147  }
148 
149  return 0;
150 }
151 
153 {
154  return _bind_address.family ();
155 }
156 
158 {
159  return _is_multicast;
160 }
161 
163 {
164  return &_bind_address;
165 }
166 
168 {
169  return _bind_interface;
170 }
171 
173 {
174  return &_target_address;
175 }
176 
178 {
179  // XXX what do (factor TCP code?)
180  addr_ = _address;
181  return 0;
182 }
zmq::ip_addr_t::any
static ip_addr_t any(int family_)
Definition: ip_resolver.cpp:68
ip.hpp
zmq::ip_resolver_options_t::ipv6
ip_resolver_options_t & ipv6(bool ipv6_)
Definition: ip_resolver.cpp:121
udp_address.hpp
zmq::udp_address_t::_bind_address
ip_addr_t _bind_address
Definition: udp_address.hpp:38
EINVAL
#define EINVAL
Definition: errno.hpp:25
zmq::udp_address_t::is_mcast
bool is_mcast() const
Definition: udp_address.cpp:157
zmq::udp_address_t::~udp_address_t
virtual ~udp_address_t()
Definition: udp_address.cpp:28
precompiled.hpp
zmq::udp_address_t::bind_addr
const ip_addr_t * bind_addr() const
Definition: udp_address.cpp:162
zmq::udp_address_t::bind_if
int bind_if() const
Definition: udp_address.cpp:167
string
GLsizei const GLchar *const * string
Definition: glcorearb.h:3083
errno
int errno
zmq::ip_resolver_options_t::bindable
ip_resolver_options_t & bindable(bool bindable_)
Definition: ip_resolver.cpp:106
zmq::udp_address_t::resolve
int resolve(const char *name_, bool bind_, bool ipv6_)
Definition: udp_address.cpp:32
zmq::ip_addr_t
Definition: ip_resolver.hpp:16
macros.hpp
stdint.hpp
zmq::ip_resolver_options_t::allow_dns
ip_resolver_options_t & allow_dns(bool allow_)
Definition: ip_resolver.cpp:138
zmq::udp_address_t::_target_address
ip_addr_t _target_address
Definition: udp_address.hpp:40
name_
string name_
Definition: googletest.cc:182
zmq::ip_resolver_t::resolve
int resolve(ip_addr_t *ip_addr_, const char *name_)
Definition: ip_resolver.cpp:187
zmq::udp_address_t::target_addr
const ip_addr_t * target_addr() const
Definition: udp_address.cpp:172
zmq::ip_resolver_options_t::expect_port
ip_resolver_options_t & expect_port(bool expect_)
Definition: ip_resolver.cpp:131
zmq::ip_resolver_t
Definition: ip_resolver.hpp:62
zmq::ip_resolver_options_t::allow_nic_name
ip_resolver_options_t & allow_nic_name(bool allow_)
Definition: ip_resolver.cpp:114
zmq::udp_address_t::family
int family() const
Definition: udp_address.cpp:152
zmq::ip_resolver_options_t
Definition: ip_resolver.hpp:34
err.hpp
zmq::udp_address_t::udp_address_t
udp_address_t()
Definition: udp_address.cpp:21
zmq::udp_address_t::to_string
virtual int to_string(std::string &addr_)
Definition: udp_address.cpp:177
false
#define false
Definition: cJSON.c:70


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:07:00