35 #include <system_error>
38 #include <sys/ioctl.h>
39 #include <arpa/inet.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
49 using namespace scc::net;
53 m_addr->sin6_family = AF_INET6;
54 m_addr->sin6_port = 0;
55 m_addr->sin6_flowinfo = 0;
56 m_addr->sin6_addr = in6addr_any;
57 m_addr->sin6_scope_id = 0;
77 if (a->sa_family == AF_INET)
79 const sockaddr_in* x =
reinterpret_cast<const sockaddr_in*
>(a);
82 uint32_t h = x->sin_addr.s_addr;
83 unsigned char* b =
reinterpret_cast<unsigned char*
>(&h);
84 m_addr->sin6_addr.s6_addr[10] = 0xff;
85 m_addr->sin6_addr.s6_addr[11] = 0xff;
86 m_addr->sin6_addr.s6_addr[12] = b[0];
87 m_addr->sin6_addr.s6_addr[13] = b[1];
88 m_addr->sin6_addr.s6_addr[14] = b[2];
89 m_addr->sin6_addr.s6_addr[15] = b[3];
91 m_addr->sin6_port = x->sin_port;
93 else if (a->sa_family == AF_INET6)
95 memcpy(m_addr, a,
sizeof(sockaddr_in6));
101 memcpy(m_addr, b.m_addr,
sizeof(sockaddr_in6));
106 memcpy(m_addr, b.m_addr,
sizeof(sockaddr_in6));
112 memcpy(m_addr, b.m_addr,
sizeof(sockaddr_in6));
118 memcpy(m_addr, b.m_addr,
sizeof(sockaddr_in6));
129 InetAddr::operator
const sockaddr*()
const
131 return reinterpret_cast<const sockaddr*
>(m_addr);
134 InetAddr::operator sockaddr*()
136 return reinterpret_cast<sockaddr*
>(m_addr);
141 return sizeof(sockaddr_in6);
146 m_addr->sin6_addr = in6addr_any;
151 m_addr->sin6_addr = in6addr_loopback;
156 m_addr->sin6_port = htons(p);
161 return ntohs(m_addr->sin6_port);
167 m_addr->sin6_scope_id = s;
172 return m_addr->sin6_scope_id;
179 if (inet_pton(AF_INET6, h.c_str(), &a) <= 0) {
180 std::ostringstream os;
181 os <<
"InetAddr::host('" << h <<
"'): invalid address";
182 throw std::runtime_error(os.str());
185 m_addr->sin6_addr = a;
190 char buf[INET6_ADDRSTRLEN];
192 if (inet_ntop(AF_INET6, &m_addr->sin6_addr, buf, INET6_ADDRSTRLEN) ==
nullptr)
194 std::stringstream st;
196 throw std::system_error(errno, std::system_category(), st.str());
199 return std::string(buf);
203 static bool btest(
const unsigned char* b,
unsigned t,
int len)
205 for (; len > 0; len--, b++)
219 const unsigned char* ad = m_addr->sin6_addr.s6_addr;
220 if (btest(ad, 0, 10) && ad[10] == 0xff && ad[11] == 0xff)
224 if (btest(ad+12, 0, 4))
228 else if (ad[12] == 127)
232 else if (ad[12] >= 224 && ad[12] <= 239)
247 if (btest(ad, 0, 16))
251 else if (btest(ad, 0, 15) && ad[15] == 1)
255 else if (ad[0] == 0xff)
259 if ((ad[1] & 0x10) == 0x10)
263 if ((ad[1] & 0x20) == 0x10)
267 if ((ad[1] & 0x40) == 0x10)
283 if ((ad[1] & 0xf0) == 0x00)
285 if (btest(ad+2, 0, 13) && ad[15] == 1)
289 if (btest(ad+2, 0, 13) && ad[15] == 2)
300 if (ad[0] == 0xfe && ad[1] == 0x80 && btest(ad+2, 0, 6))
310 if ((ad[0] & 0xfe) == 0xfc)
322 return os.write(sa.
str().c_str(), sa.
str().size());
339 s <<
" port: " <<
port() <<
" scope_id: " <<
scope_id();
353 s <<
" type-unicast";
360 s <<
" scope-iface-local";
363 s <<
" scope-link-local";
366 s <<
" scope-realm-local";
369 s <<
" scope-admin-local";
372 s <<
" scope-site-local";
375 s <<
" scope-org-local";
378 s <<
" scope-global";
385 s <<
" mcast-flags-rendezvous";
388 s <<
" mcast-flags-prefix";
391 s <<
" mcast-flags-dynamic";
398 s <<
" mcast-all-nodes";
401 s <<
" mcast-all-routers";
408 s <<
" unique-local-address";
420 SocketBase::reset(AF_INET6, SOCK_STREAM, 0);
436 std::stringstream st;
438 throw std::system_error(ec, st.str());
449 std::stringstream st;
450 st <<
"accept(peer)";
451 throw std::system_error(ec, st.str());
456 std::shared_ptr<InetTcpSock> InetTcpSock::accept_shared()
462 std::stringstream st;
464 throw std::system_error(ec, st.str());
469 std::shared_ptr<InetTcpSock> InetTcpSock::accept_shared(
InetAddr& peer)
475 std::stringstream st;
476 st <<
"accept(peer)";
477 throw std::system_error(ec, st.str());
486 SocketBase::reset(AF_INET6, SOCK_DGRAM, 0);
498 const sockaddr_in6* a{group_addr};
500 mr.ipv6mr_multiaddr = a->sin6_addr;
501 mr.ipv6mr_interface = interface;
503 socklen_t len =
sizeof(mr);
505 if (::setsockopt(
fd(), IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mr, len))
507 std::stringstream st;
508 st <<
"mcast join group setsockopt()";
509 throw std::system_error(errno, std::system_category(), st.str());
515 const sockaddr_in6* a{group_addr};
517 mr.ipv6mr_multiaddr = a->sin6_addr;
518 mr.ipv6mr_interface = interface;
520 socklen_t len =
sizeof(mr);
522 if (::setsockopt(
fd(), IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mr, len))
524 std::stringstream st;
525 st <<
"mcast leave group setsockopt()";
526 throw std::system_error(errno, std::system_category(), st.str());
532 unsigned v{interface};
533 socklen_t len =
sizeof(v);
535 if (::setsockopt(
fd(), IPPROTO_IPV6, IPV6_MULTICAST_IF, &v, len))
537 std::stringstream st;
538 st <<
"mcast interface setsockopt()";
539 throw std::system_error(errno, std::system_category(), st.str());
545 unsigned x = loop ? 1 : 0;
546 socklen_t len =
sizeof(x);
548 if (::setsockopt(
fd(), IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &x, len))
550 std::stringstream st;
551 st <<
"mcast loopback setsockopt()";
552 throw std::system_error(errno, std::system_category(), st.str());
559 socklen_t len =
sizeof(v);
561 if (::setsockopt(
fd(), IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &v, len))
563 std::stringstream st;
564 st <<
"mcast hops setsockopt()";
565 throw std::system_error(errno, std::system_category(), st.str());
virtual unsigned len() const
Socket address length in bytes.
unsigned port() const
Get the port.
InetAddr & operator=(const InetAddr &)
ipv6 internet address, copy assigned.
uint32_t scope_id() const
Get the scope id of the address.
void any_host()
Set to "any" host address ::
void local_host()
Set to local (loopback) address ::1.
virtual std::string host() const
Get host.
virtual ~InetAddr()
ipv6 internet address destructor.
virtual std::string str() const
Readable address string.
InetAddr()
ipv6 internet address, initialized with "any" address
int flags() const
Return the address flags.
Internet transmission control protocol (tcp) socket.
virtual void reset()
Close the connection and reset the socket.
InetTcpSock accept()
Accept a connection from an anonymous peer.
InetTcpSock()
Create an IPv6 stream socket.
InetAddr get_addr()
Get the socket address.
virtual void reset()
Reset the socket.
InetUdpSock()
Create an IPv6 datagram socket.
void mcast_leave_group(const InetAddr &, unsigned=0)
Leave a multicast group.
InetAddr get_addr()
Get the socket address.
void mcast_interface(unsigned=0)
Set the default interface for outgoing multicast messages.
void mcast_loopback(bool=true)
Enable or disable multicast loopback.
void mcast_hops(unsigned=1)
Hop limit for outgoing multicast messages.
void mcast_join_group(const InetAddr &, unsigned=0)
Join a multicast group.
int fd() const
Return the underlying socket handle.
int accept(sockaddr *, int len, std::error_code &) noexcept
Accept a connection.
@ unicast
Unicast address.
@ link_local
Traffic is restricted to the local link.
@ realm_local
Traffic is restricted to the local realm.
@ scope_mask
Scope for multicast addresses mask.
@ mcast_all_nodes
Reaches all nodes in the scope, e.g. ff0X::1.
@ mcast_rendezvous
Address has a rendezvous point embedded.
@ mcast_flags_mask
Multicast flags mask.
@ admin_local
Traffic is restricted to the local admin.
@ unicast_special_mask
Some special unicast addresses.
@ global
Global traffic is allowed.
@ org_local
Traffic is restricted to the local organization.
@ mcast_all_routers
Reaches all routers in the scope, e.g. ff0X::2.
@ loopback
Loopback address.
@ prot_mask
Protocol mask.
@ if_local
Traffic is restricted to the local interface.
@ mcast_reserved_mask
Some reserved multicast addresses.
@ mcast_dynamic
Dynamic (temporary) address, otherwise permanent (assigned).
@ site_local
Traffic is restricted to the local site.
@ multicast
Multicast address.
@ unique_local_address
Address which can be used freely within a site: e.g. fd00::/8.
@ mcast_prefix
Prefix-based address.
std::ostream & operator<<(std::ostream &os, const InetAddr &sa)
Print the socket address details to an output stream.
Internet tcp and udp networking.
Low-level tcp and udp sockets.