25#ifndef JOIN_FABRIC_NDP_MESSAGE_HPP
26#define JOIN_FABRIC_NDP_MESSAGE_HPP
38#include <netinet/icmp6.h>
39#include <net/ethernet.h>
40#include <netinet/in.h>
57 uint8_t
flags = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO;
198 const char* end = data + maxSize;
201 struct nd_router_solicit rs = {};
203 ok &=
writeBytes (cur, end, &rs,
sizeof (rs));
206 return ok ? cur - data : -1;
231 for (
auto const& prefix : packet.
prefixes)
233 if ((prefix.prefix.family () != AF_INET6) || (prefix.length > 128))
240 for (
auto const& rdnss : packet.
rdnss)
242 if (rdnss.servers.empty ())
254 for (
auto const& server : rdnss.servers)
256 if (server.family () != AF_INET6)
265 const char* end = data + maxSize;
268 struct nd_router_advert ra = {};
270 ra.nd_ra_curhoplimit = packet.
hopLimit;
271 ra.nd_ra_flags_reserved = packet.
flags;
272 ra.nd_ra_router_lifetime = htons (packet.
lifetime);
273 ra.nd_ra_reachable = htonl (packet.
reachable);
274 ra.nd_ra_retransmit = htonl (packet.
retransmit);
275 ok &=
writeBytes (cur, end, &ra,
sizeof (ra));
281 struct nd_opt_mtu mtu = {};
282 mtu.nd_opt_mtu_type =
Mtu;
283 mtu.nd_opt_mtu_len =
sizeof (mtu) >> 3;
284 mtu.nd_opt_mtu_mtu = htonl (packet.
mtu);
285 ok &=
writeBytes (cur, end, &mtu,
sizeof (mtu));
288 for (
auto const& prefix : packet.
prefixes)
292 struct nd_opt_prefix_info pi = {};
294 pi.nd_opt_pi_len =
sizeof (pi) >> 3;
295 pi.nd_opt_pi_prefix_len = prefix.length;
296 pi.nd_opt_pi_flags_reserved = prefix.flags;
297 pi.nd_opt_pi_valid_time = htonl (prefix.valid);
298 pi.nd_opt_pi_preferred_time = htonl (prefix.preferred);
299 ::memcpy (&pi.nd_opt_pi_prefix, masked.
addr (), sizeof (pi.nd_opt_pi_prefix));
300 ok &=
writeBytes (cur, end, &pi,
sizeof (pi));
303 for (
auto const& rdnss : packet.
rdnss)
305 RdnssHeader header = {};
307 header.len =
static_cast<uint8_t
> (1 + (rdnss.servers.size () * 2));
308 header.lifetime = htonl (rdnss.lifetime);
309 ok &=
writeBytes (cur, end, &header,
sizeof (header));
311 for (
auto const& server : rdnss.servers)
313 ok &=
writeBytes (cur, end, server.addr (), sizeof (
struct in6_addr));
317 return ok ? cur - data : -1;
336 const char* end = data + maxSize;
339 struct nd_neighbor_solicit ns = {};
341 ::memcpy (&ns.nd_ns_target, packet.
target.
addr (), sizeof (ns.nd_ns_target));
342 ok &=
writeBytes (cur, end, &ns,
sizeof (ns));
345 return ok ? cur - data : -1;
378 const char* end = data + maxSize;
381 struct nd_neighbor_advert na = {};
383 na.nd_na_flags_reserved = packet.
flags;
384 ::memcpy (&na.nd_na_target, packet.
target.
addr (), sizeof (na.nd_na_target));
385 ok &=
writeBytes (cur, end, &na,
sizeof (na));
388 return ok ? cur - data : -1;
400 const char* cur = data;
401 const char* end = data + size;
403 struct nd_router_solicit rs = {};
404 if (!
readBytes (cur, end, &rs,
sizeof (rs)))
409 if ((rs.nd_rs_type !=
RouterSolicit) || (rs.nd_rs_code != 0))
417 return readOptions (cur, end, [&packet] (
const uint8_t* option,
size_t size) {
434 const char* cur = data;
435 const char* end = data + size;
437 struct nd_router_advert ra = {};
438 if (!
readBytes (cur, end, &ra,
sizeof (ra)))
443 if ((ra.nd_ra_type !=
RouterAdvert) || (ra.nd_ra_code != 0))
449 packet.
hopLimit = ra.nd_ra_curhoplimit;
450 packet.
flags = ra.nd_ra_flags_reserved;
451 packet.
lifetime = ntohs (ra.nd_ra_router_lifetime);
452 packet.
reachable = ntohl (ra.nd_ra_reachable);
453 packet.
retransmit = ntohl (ra.nd_ra_retransmit);
457 packet.
rdnss.clear ();
459 return readOptions (cur, end, [&packet] (
const uint8_t* option,
size_t size) {
470 if (size ==
sizeof (
struct nd_opt_mtu))
472 struct nd_opt_mtu mtu;
473 ::memcpy (&mtu, option,
sizeof (mtu));
474 packet.
mtu = ntohl (mtu.nd_opt_mtu_mtu);
479 if (size ==
sizeof (
struct nd_opt_prefix_info))
481 struct nd_opt_prefix_info pi;
482 ::memcpy (&pi, option,
sizeof (pi));
484 if (pi.nd_opt_pi_prefix_len <= 128)
487 prefix.
prefix =
IpAddress (&pi.nd_opt_pi_prefix, sizeof (pi.nd_opt_pi_prefix));
488 prefix.
length = pi.nd_opt_pi_prefix_len;
489 prefix.
flags = pi.nd_opt_pi_flags_reserved;
490 prefix.
valid = ntohl (pi.nd_opt_pi_valid_time);
491 prefix.
preferred = ntohl (pi.nd_opt_pi_preferred_time);
492 packet.
prefixes.push_back (std::move (prefix));
498 if ((size >
sizeof (RdnssHeader)) &&
499 (((size -
sizeof (RdnssHeader)) %
sizeof (
struct in6_addr)) == 0))
502 ::memcpy (&header, option,
sizeof (header));
505 rdnss.
lifetime = ntohl (header.lifetime);
506 rdnss.
servers.reserve ((size -
sizeof (RdnssHeader)) /
sizeof (
struct in6_addr));
508 for (
size_t offset =
sizeof (RdnssHeader); offset < size;
509 offset +=
sizeof (
struct in6_addr))
511 rdnss.
servers.emplace_back (option + offset,
sizeof (
struct in6_addr));
514 packet.
rdnss.push_back (std::move (rdnss));
533 const char* cur = data;
534 const char* end = data + size;
536 struct nd_neighbor_solicit ns = {};
537 if (!
readBytes (cur, end, &ns,
sizeof (ns)))
548 packet.
target =
IpAddress (&ns.nd_ns_target, sizeof (ns.nd_ns_target));
557 return readOptions (cur, end, [&packet] (
const uint8_t* option,
size_t size) {
574 const char* cur = data;
575 const char* end = data + size;
577 struct nd_neighbor_advert na = {};
578 if (!
readBytes (cur, end, &na,
sizeof (na)))
589 packet.
target =
IpAddress (&na.nd_na_target, sizeof (na.nd_na_target));
596 packet.
flags = na.nd_na_flags_reserved;
599 return readOptions (cur, end, [&packet] (
const uint8_t* option,
size_t size) {
645 return writeBytes (cur, end, option,
sizeof (option));
655 template <
typename Handler>
656 static int readOptions (
const char* cur,
const char* end, Handler&& handler)
673 const size_t size =
static_cast<size_t> (option[1]) << 3;
679 handler (option, size);
IPv6, IPv4 address class.
Definition ip_address.hpp:52
int prefix() const
get prefix length from netmask address.
Definition ip_address.cpp:1286
int family() const
get address family.
Definition ip_address.cpp:1250
bool isMulticast() const
check if IP address is multicast.
Definition ip_address.cpp:1358
bool isWildcard() const
check if IP address is a wildcard address.
Definition ip_address.cpp:1295
const void * addr() const
get the internal address structure.
Definition ip_address.cpp:1259
MAC address class.
Definition mac_address.hpp:47
bool isWildcard() const
check if MAC address is a wildcard address.
Definition mac_address.cpp:182
const uint8_t * addr() const
get the internal MAC address array address.
Definition mac_address.cpp:164
NDP message codec.
Definition ndp_message.hpp:163
static constexpr size_t maxNeighborAdvertisementSize
biggest neighbor advertisement the codec writes, link layer address option included.
Definition ndp_message.hpp:702
static constexpr size_t maxRouterSolicitationSize
biggest router solicitation the codec writes, link layer address option included.
Definition ndp_message.hpp:694
static constexpr size_t _maxOptionSize
biggest option, its length field counts units of 8 octets.
Definition ndp_message.hpp:687
static bool writeLinkAddress(char *&cur, const char *end, const MacAddress &link, OptionType type=SourceLinkAddress)
write a link layer address option into a buffer.
Definition ndp_message.hpp:634
static constexpr size_t _maxDnsServers
most recursive DNS servers a single option can carry.
Definition ndp_message.hpp:690
ssize_t serialize(const RouterSolicitation &packet, char *data, size_t maxSize) const
serialize a router solicitation into a buffer.
Definition ndp_message.hpp:195
OptionType
NDP option types.
Definition ndp_message.hpp:180
@ Mtu
Definition ndp_message.hpp:184
@ PrefixInformation
Definition ndp_message.hpp:183
@ SourceLinkAddress
Definition ndp_message.hpp:181
@ TargetLinkAddress
Definition ndp_message.hpp:182
@ RecursiveDnsServer
Definition ndp_message.hpp:185
ssize_t serialize(const NeighborAdvertisement &packet, char *data, size_t maxSize) const
serialize a neighbor advertisement into a buffer.
Definition ndp_message.hpp:355
int deserialize(RouterAdvertisement &packet, const char *data, size_t size) const
deserialize a router advertisement from a buffer.
Definition ndp_message.hpp:432
static int readOptions(const char *cur, const char *end, Handler &&handler)
walk through the options of a message, RFC 4861 section 4.6.
Definition ndp_message.hpp:656
ssize_t serialize(const NeighborAdvertisement &packet, char *data, size_t maxSize, const MacAddress &link) const
serialize a neighbor advertisement into a buffer with the given link layer address.
Definition ndp_message.hpp:368
MessageType
NDP message types, RFC 4861 section 4.
Definition ndp_message.hpp:169
@ RouterAdvert
Definition ndp_message.hpp:171
@ RouterSolicit
Definition ndp_message.hpp:170
@ NeighborAdvert
Definition ndp_message.hpp:173
@ NeighborSolicit
Definition ndp_message.hpp:172
ssize_t serialize(const RouterAdvertisement &packet, char *data, size_t maxSize) const
serialize a router advertisement into a buffer.
Definition ndp_message.hpp:216
int deserialize(NeighborSolicitation &packet, const char *data, size_t size) const
deserialize a neighbor solicitation from a buffer.
Definition ndp_message.hpp:531
ssize_t serialize(const RouterAdvertisement &packet, char *data, size_t maxSize, const MacAddress &link) const
serialize a router advertisement into a buffer with the given link layer address.
Definition ndp_message.hpp:229
static constexpr size_t maxNeighborSolicitationSize
biggest neighbor solicitation the codec writes, link layer address option included.
Definition ndp_message.hpp:698
ssize_t serialize(const NeighborSolicitation &packet, char *data, size_t maxSize) const
serialize a neighbor solicitation into a buffer.
Definition ndp_message.hpp:327
struct __attribute__((packed)) RdnssHeader
recursive DNS server option header, RFC 8106 section 5.1.
Definition ndp_message.hpp:611
static constexpr size_t _optionHeaderSize
size of an option type and length fields.
Definition ndp_message.hpp:684
int deserialize(RouterSolicitation &packet, const char *data, size_t size) const
deserialize a router solicitation from a buffer.
Definition ndp_message.hpp:398
Definition acceptor.hpp:32
bool readBytes(const char *&cur, const char *end, void *out, size_t size) noexcept
read bytes from a buffer.
Definition utils.hpp:276
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
bool writeBytes(char *&cur, const char *end, const void *in, size_t size) noexcept
write bytes to a buffer.
Definition utils.hpp:298
prefix carried by a router advertisement, RFC 4861 section 4.6.2.
Definition ndp_message.hpp:49
uint32_t preferred
time in seconds addresses generated from the prefix remain preferred.
Definition ndp_message.hpp:63
uint8_t length
number of leading bits of the prefix that are valid.
Definition ndp_message.hpp:54
uint32_t valid
time in seconds the prefix is valid for on-link determination.
Definition ndp_message.hpp:60
uint8_t flags
prefix flags.
Definition ndp_message.hpp:57
IpAddress prefix
prefix.
Definition ndp_message.hpp:51
recursive DNS servers carried by a router advertisement, RFC 8106 section 5.1.
Definition ndp_message.hpp:70
uint32_t lifetime
time in seconds the servers may be used for.
Definition ndp_message.hpp:72
std::vector< IpAddress > servers
server addresses.
Definition ndp_message.hpp:75
neighbor advertisement, RFC 4861 section 4.4.
Definition ndp_message.hpp:145
IpAddress src
address the advertisement came from, set by the transport.
Definition ndp_message.hpp:147
IpAddress target
address the advertisement is about.
Definition ndp_message.hpp:153
uint32_t flags
advertisement flags, in network byte order as ND_NA_FLAG_* are defined.
Definition ndp_message.hpp:150
MacAddress link
link layer address of the target, wildcard if not carried.
Definition ndp_message.hpp:156
neighbor solicitation, RFC 4861 section 4.3.
Definition ndp_message.hpp:130
MacAddress link
link layer address of the sender, wildcard if not carried.
Definition ndp_message.hpp:138
IpAddress src
address the solicitation came from, set by the transport.
Definition ndp_message.hpp:132
IpAddress target
address of the solicited neighbor.
Definition ndp_message.hpp:135
router advertisement, RFC 4861 section 4.2.
Definition ndp_message.hpp:94
uint32_t retransmit
time in milliseconds between retransmitted neighbor solicitations, zero if unspecified.
Definition ndp_message.hpp:111
uint32_t mtu
link MTU, zero if not carried.
Definition ndp_message.hpp:117
IpAddress src
address the advertisement came from, set by the transport.
Definition ndp_message.hpp:96
uint8_t hopLimit
hop limit hosts should use, zero if unspecified.
Definition ndp_message.hpp:99
std::vector< NdpPrefix > prefixes
prefixes.
Definition ndp_message.hpp:120
uint8_t flags
router flags.
Definition ndp_message.hpp:102
uint32_t reachable
time in milliseconds a neighbor is assumed reachable, zero if unspecified.
Definition ndp_message.hpp:108
MacAddress link
link layer address of the router, wildcard if not carried.
Definition ndp_message.hpp:114
std::vector< NdpRdnss > rdnss
recursive DNS servers, one entry per option.
Definition ndp_message.hpp:123
uint16_t lifetime
lifetime in seconds of the router as a default router, zero if it is not one.
Definition ndp_message.hpp:105
router solicitation, RFC 4861 section 4.1.
Definition ndp_message.hpp:82
MacAddress link
link layer address of the sender, wildcard if not carried.
Definition ndp_message.hpp:87
IpAddress src
address the solicitation came from, set by the transport.
Definition ndp_message.hpp:84