mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 08:25:20 +09:00
sd-radv: use ICMP6Packet and sd_ndisc_router_solicit
Then, sd-radv can reject invalid Router Solicit messages, e.g. that have invalid options. No effective functional change, just refactoring.
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "iovec-util.h"
|
||||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "ndisc-router-solicit-internal.h"
|
||||
#include "network-common.h"
|
||||
#include "radv-internal.h"
|
||||
#include "random-util.h"
|
||||
@@ -237,64 +238,51 @@ static int radv_send_router(sd_radv *ra, const struct in6_addr *dst, usec_t life
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
sd_radv *ra = ASSERT_PTR(userdata);
|
||||
struct in6_addr src;
|
||||
triple_timestamp timestamp;
|
||||
static int radv_process_packet(sd_radv *ra, ICMP6Packet *packet) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(ra->event);
|
||||
assert(ra);
|
||||
assert(packet);
|
||||
|
||||
ssize_t buflen = next_datagram_size_fd(fd);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(buflen) || ERRNO_IS_NEG_DISCONNECT(buflen))
|
||||
return 0;
|
||||
if (buflen < 0) {
|
||||
log_radv_errno(ra, buflen, "Failed to determine datagram size to read, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
if (icmp6_packet_get_type(packet) != ND_ROUTER_SOLICIT)
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG), "Received ICMP6 packet with unexpected type, ignoring.");
|
||||
|
||||
_cleanup_free_ char *buf = new0(char, buflen);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
_cleanup_(sd_ndisc_router_solicit_unrefp) sd_ndisc_router_solicit *rs = NULL;
|
||||
rs = ndisc_router_solicit_new(packet);
|
||||
if (!rs)
|
||||
return log_oom_debug();
|
||||
|
||||
r = icmp6_receive(fd, buf, buflen, &src, ×tamp);
|
||||
if (ERRNO_IS_NEG_TRANSIENT(r) || ERRNO_IS_NEG_DISCONNECT(r))
|
||||
return 0;
|
||||
r = ndisc_router_solicit_parse(ra, rs);
|
||||
if (r < 0)
|
||||
switch (r) {
|
||||
case -EADDRNOTAVAIL:
|
||||
log_radv(ra, "Received RS from neither link-local nor null address, ignoring.");
|
||||
return 0;
|
||||
return r;
|
||||
|
||||
case -EMULTIHOP:
|
||||
log_radv(ra, "Received RS with invalid hop limit, ignoring.");
|
||||
return 0;
|
||||
struct in6_addr src = {};
|
||||
r = sd_ndisc_router_solicit_get_sender_address(rs, &src);
|
||||
if (r < 0 && r != -ENODATA) /* null address is allowed */
|
||||
return log_radv_errno(ra, r, "Failed to get sender address of RS, ignoring: %m");
|
||||
|
||||
case -EPFNOSUPPORT:
|
||||
log_radv(ra, "Received invalid source address from ICMPv6 socket, ignoring.");
|
||||
return 0;
|
||||
|
||||
default:
|
||||
log_radv_errno(ra, r, "Unexpected error receiving from ICMPv6 socket, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((size_t) buflen < sizeof(struct nd_router_solicit)) {
|
||||
log_radv(ra, "Too short packet received, ignoring");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: if the sender address is null, check that the message does not have the source link-layer
|
||||
* address option. See RFC 4861 Section 6.1.1. */
|
||||
|
||||
const char *addr = IN6_ADDR_TO_STRING(&src);
|
||||
r = radv_send_router(ra, &src, ra->lifetime_usec);
|
||||
if (r < 0)
|
||||
log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", addr);
|
||||
else
|
||||
log_radv(ra, "Sent solicited Router Advertisement to %s.", addr);
|
||||
return log_radv_errno(ra, r, "Unable to send solicited Router Advertisement to %s, ignoring: %m", IN6_ADDR_TO_STRING(&src));
|
||||
|
||||
log_radv(ra, "Sent solicited Router Advertisement to %s.", IN6_ADDR_TO_STRING(&src));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int radv_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
_cleanup_(icmp6_packet_unrefp) ICMP6Packet *packet = NULL;
|
||||
sd_radv *ra = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
r = icmp6_packet_receive(fd, &packet);
|
||||
if (r < 0) {
|
||||
log_radv_errno(ra, r, "Failed to receive ICMPv6 packet, ignoring: %m");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void) radv_process_packet(ra, packet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user