mirror of
https://github.com/Dasharo/systemd.git
synced 2026-03-06 15:02:31 -08:00
Merge pull request #32267 from yuwata/sd-ndisc-router-solicit
sd-radv: introduce sd_ndisc_router_solicit and use it
This commit is contained in:
@@ -31,6 +31,7 @@ sources = files(
|
||||
'sd-ndisc-neighbor.c',
|
||||
'sd-ndisc-redirect.c',
|
||||
'sd-ndisc-router.c',
|
||||
'sd-ndisc-router-solicit.c',
|
||||
'sd-radv.c',
|
||||
)
|
||||
|
||||
|
||||
18
src/libsystemd-network/ndisc-router-solicit-internal.h
Normal file
18
src/libsystemd-network/ndisc-router-solicit-internal.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "sd-radv.h"
|
||||
|
||||
#include "icmp6-packet.h"
|
||||
#include "set.h"
|
||||
|
||||
struct sd_ndisc_router_solicit {
|
||||
unsigned n_ref;
|
||||
|
||||
ICMP6Packet *packet;
|
||||
|
||||
Set *options;
|
||||
};
|
||||
|
||||
sd_ndisc_router_solicit* ndisc_router_solicit_new(ICMP6Packet *packet);
|
||||
int ndisc_router_solicit_parse(sd_radv *ra, sd_ndisc_router_solicit *rs);
|
||||
83
src/libsystemd-network/sd-ndisc-router-solicit.c
Normal file
83
src/libsystemd-network/sd-ndisc-router-solicit.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "sd-radv.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "ndisc-option.h"
|
||||
#include "ndisc-router-solicit-internal.h"
|
||||
#include "radv-internal.h"
|
||||
|
||||
static sd_ndisc_router_solicit* ndisc_router_solicit_free(sd_ndisc_router_solicit *rs) {
|
||||
if (!rs)
|
||||
return NULL;
|
||||
|
||||
icmp6_packet_unref(rs->packet);
|
||||
set_free(rs->options);
|
||||
return mfree(rs);
|
||||
}
|
||||
|
||||
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_ndisc_router_solicit, sd_ndisc_router_solicit, ndisc_router_solicit_free);
|
||||
|
||||
sd_ndisc_router_solicit* ndisc_router_solicit_new(ICMP6Packet *packet) {
|
||||
sd_ndisc_router_solicit *rs;
|
||||
|
||||
assert(packet);
|
||||
|
||||
rs = new(sd_ndisc_router_solicit, 1);
|
||||
if (!rs)
|
||||
return NULL;
|
||||
|
||||
*rs = (sd_ndisc_router_solicit) {
|
||||
.n_ref = 1,
|
||||
.packet = icmp6_packet_ref(packet),
|
||||
};
|
||||
|
||||
return rs;
|
||||
}
|
||||
|
||||
int ndisc_router_solicit_parse(sd_radv *ra, sd_ndisc_router_solicit *rs) {
|
||||
int r;
|
||||
|
||||
assert(rs);
|
||||
assert(rs->packet);
|
||||
|
||||
if (rs->packet->raw_size < sizeof(struct nd_router_solicit))
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"Too small to be a router solicit, ignoring.");
|
||||
|
||||
const struct nd_router_solicit *a = (const struct nd_router_solicit*) rs->packet->raw_packet;
|
||||
assert(a);
|
||||
assert(a->nd_rs_type == ND_ROUTER_SOLICIT);
|
||||
assert(a->nd_rs_code == 0);
|
||||
|
||||
r = ndisc_parse_options(rs->packet, &rs->options);
|
||||
if (r < 0)
|
||||
return log_radv_errno(ra, r, "Failed to parse NDisc options in router solicit, ignoring datagram: %m");
|
||||
|
||||
/* RFC 4861 section 4.1.
|
||||
* Source link-layer address:
|
||||
* The link-layer address of the sender, if known. MUST NOT be included if the Source
|
||||
* Address is the unspecified address. Otherwise, it SHOULD be included on link
|
||||
* layers that have addresses. */
|
||||
if (ndisc_option_get_mac(rs->options, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, NULL) >= 0&&
|
||||
sd_ndisc_router_solicit_get_sender_address(rs, NULL) == -ENODATA)
|
||||
return log_radv_errno(ra, SYNTHETIC_ERRNO(EBADMSG),
|
||||
"Router Solicitation message from null address unexpectedly contains source link-layer address option, ignoring datagaram.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_ndisc_router_solicit_get_sender_address(sd_ndisc_router_solicit *rs, struct in6_addr *ret) {
|
||||
assert_return(rs, -EINVAL);
|
||||
|
||||
return icmp6_packet_get_sender_address(rs->packet, ret);
|
||||
}
|
||||
|
||||
int sd_ndisc_router_solicit_get_sender_mac(sd_ndisc_router_solicit *rs, struct ether_addr *ret) {
|
||||
assert_return(rs, -EINVAL);
|
||||
|
||||
return ndisc_option_get_mac(rs->options, SD_NDISC_OPTION_SOURCE_LL_ADDRESS, ret);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ _not_installed_headers = [
|
||||
'sd-ndisc-protocol.h',
|
||||
'sd-ndisc-redirect.h',
|
||||
'sd-ndisc-router.h',
|
||||
'sd-ndisc-router-solicit.h',
|
||||
'sd-netlink.h',
|
||||
'sd-network.h',
|
||||
'sd-radv.h',
|
||||
|
||||
40
src/systemd/sd-ndisc-router-solicit.h
Normal file
40
src/systemd/sd-ndisc-router-solicit.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#ifndef foosdndiscroutersolicitfoo
|
||||
#define foosdndiscroutersolicitfoo
|
||||
|
||||
/***
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <https://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "_sd-common.h"
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
typedef struct sd_ndisc_router_solicit sd_ndisc_router_solicit;
|
||||
|
||||
sd_ndisc_router_solicit *sd_ndisc_router_solicit_ref(sd_ndisc_router_solicit *rs);
|
||||
sd_ndisc_router_solicit *sd_ndisc_router_solicit_unref(sd_ndisc_router_solicit *rs);
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_ndisc_router_solicit, sd_ndisc_router_solicit_unref);
|
||||
|
||||
int sd_ndisc_router_solicit_get_sender_address(sd_ndisc_router_solicit *rs, struct in6_addr *ret);
|
||||
int sd_ndisc_router_solicit_get_sender_mac(sd_ndisc_router_solicit *rs, struct ether_addr *ret);
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
#endif
|
||||
@@ -26,7 +26,8 @@
|
||||
|
||||
#include "_sd-common.h"
|
||||
#include "sd-event.h"
|
||||
#include "sd-ndisc.h"
|
||||
#include "sd-ndisc-protocol.h"
|
||||
#include "sd-ndisc-router-solicit.h"
|
||||
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user