odhcpd: backport fixes from Git HEAD (2025-10-10)
A lot of recent commits in odhcpd main branch are structural/semantic changes, so instead of adding those changes to 24.10 branch it's better to focus on the fixes. Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
This commit is contained in:
+61
@@ -0,0 +1,61 @@
|
||||
From f0d855358b86a36efbfeb5a9de5a1d2a4d9d80fe Mon Sep 17 00:00:00 2001
|
||||
From: Haoyi Ci <cihaoyi@outlook.com>
|
||||
Date: Thu, 2 Oct 2025 16:14:05 +0800
|
||||
Subject: [PATCH] ndp: Allow NS loopback for master iface
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This commit modifies handle_solicit() in ndp.c to correct IPv6 relay
|
||||
handling of Neighbor Solicitation (NS) requests when no upstream
|
||||
solicitation is received.
|
||||
|
||||
Background: In IPv6 relay mode, odhcpd discovers local devices only upon
|
||||
receiving upstream NS packets. If no upstream NS arrives (e.g. because the
|
||||
upstream router’s neighbor cache is still valid or no solicitation was
|
||||
ever sent), OpenWrt may attempt neighbor resolution via the master (WAN)
|
||||
interface instead of the LAN, leaving local devices undiscoverable and
|
||||
breaking connectivity.
|
||||
|
||||
- When an NS packet is sent by the host's master interface, do not
|
||||
immediately return; instead continue searching slave interfaces for the
|
||||
target neighbor.
|
||||
- When odhcpd responds to NS packets, add a check to prevent replying to
|
||||
NS packets that were sent by the host itself.
|
||||
|
||||
Signed-off-by: Haoyi Ci cihaoyi@outlook.com
|
||||
Link: https://github.com/openwrt/odhcpd/pull/240
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
---
|
||||
src/ndp.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/src/ndp.c
|
||||
+++ b/src/ndp.c
|
||||
@@ -332,6 +332,7 @@ static void handle_solicit(void *addr, v
|
||||
struct interface *c;
|
||||
char ipbuf[INET6_ADDRSTRLEN];
|
||||
uint8_t mac[6];
|
||||
+ bool is_self_sent;
|
||||
|
||||
/* Solicitation is for duplicate address detection */
|
||||
bool ns_is_dad = IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src);
|
||||
@@ -354,7 +355,8 @@ static void handle_solicit(void *addr, v
|
||||
syslog(LOG_DEBUG, "Got a NS for %s on %s", ipbuf, iface->name);
|
||||
|
||||
odhcpd_get_mac(iface, mac);
|
||||
- if (!memcmp(ll->sll_addr, mac, sizeof(mac)))
|
||||
+ is_self_sent = !memcmp(ll->sll_addr, mac, sizeof(mac));
|
||||
+ if (is_self_sent && !iface->master)
|
||||
return; /* Looped back */
|
||||
|
||||
avl_for_each_element(&interfaces, c, avl) {
|
||||
@@ -366,7 +368,7 @@ static void handle_solicit(void *addr, v
|
||||
/* Catch global-addressed NS and answer them manually.
|
||||
* The kernel won't answer these and cannot route them either. */
|
||||
if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
|
||||
- IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src)) {
|
||||
+ IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_src) && !is_self_sent) {
|
||||
bool is_proxy_neigh = netlink_get_interface_proxy_neigh(iface->ifindex,
|
||||
&req->nd_ns_target) == 1;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
From 5eac9c56ff3b0a013c5241f449ca144f70bf4c02 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=C3=81lvaro=20Fern=C3=A1ndez=20Rojas?= <noltari@gmail.com>
|
||||
Date: Tue, 7 Oct 2025 10:30:15 +0200
|
||||
Subject: [PATCH] router: fix SLAAC on subnets > 64
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
---
|
||||
src/router.c | 22 +++++++++++-----------
|
||||
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/src/router.c
|
||||
+++ b/src/router.c
|
||||
@@ -448,13 +448,13 @@ struct nd_opt_dnr_info {
|
||||
|
||||
/* IPv6 RA PIOs */
|
||||
static struct ra_pio *router_find_ra_pio(struct interface *iface,
|
||||
- struct nd_opt_prefix_info *p)
|
||||
+ struct odhcpd_ipaddr *addr)
|
||||
{
|
||||
for (size_t i = 0; i < iface->pio_cnt; i++) {
|
||||
struct ra_pio *cur_pio = &iface->pios[i];
|
||||
|
||||
- if (p->nd_opt_pi_prefix_len == cur_pio->length &&
|
||||
- !odhcpd_bmemcmp(&p->nd_opt_pi_prefix, &cur_pio->prefix, cur_pio->length))
|
||||
+ if (addr->prefix == cur_pio->length &&
|
||||
+ !odhcpd_bmemcmp(&addr->addr.in6, &cur_pio->prefix, cur_pio->length))
|
||||
return cur_pio;
|
||||
}
|
||||
|
||||
@@ -462,12 +462,12 @@ static struct ra_pio *router_find_ra_pio
|
||||
}
|
||||
|
||||
static void router_add_ra_pio(struct interface *iface,
|
||||
- struct nd_opt_prefix_info *p)
|
||||
+ struct odhcpd_ipaddr *addr)
|
||||
{
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
struct ra_pio *new_pios, *pio;
|
||||
|
||||
- pio = router_find_ra_pio(iface, p);
|
||||
+ pio = router_find_ra_pio(iface, addr);
|
||||
if (pio) {
|
||||
if (pio->lifetime) {
|
||||
pio->lifetime = 0;
|
||||
@@ -490,8 +490,8 @@ static void router_add_ra_pio(struct int
|
||||
pio = &iface->pios[iface->pio_cnt];
|
||||
iface->pio_cnt++;
|
||||
|
||||
- memcpy(&pio->prefix, &p->nd_opt_pi_prefix, sizeof(pio->prefix));
|
||||
- pio->length = p->nd_opt_pi_prefix_len;
|
||||
+ memcpy(&pio->prefix, &addr->addr.in6, sizeof(pio->prefix));
|
||||
+ pio->length = addr->prefix;
|
||||
pio->lifetime = 0;
|
||||
|
||||
iface->pio_update = true;
|
||||
@@ -538,10 +538,10 @@ static void router_clear_ra_pio(time_t n
|
||||
}
|
||||
|
||||
static void router_stale_ra_pio(struct interface *iface,
|
||||
- struct nd_opt_prefix_info *p,
|
||||
+ struct odhcpd_ipaddr *addr,
|
||||
time_t now)
|
||||
{
|
||||
- struct ra_pio *pio = router_find_ra_pio(iface, p);
|
||||
+ struct ra_pio *pio = router_find_ra_pio(iface, addr);
|
||||
char ipv6_str[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!pio || pio->lifetime)
|
||||
@@ -774,12 +774,12 @@ static int send_router_advert(struct int
|
||||
p->nd_opt_pi_preferred_time = 0;
|
||||
p->nd_opt_pi_valid_time = 0;
|
||||
|
||||
- router_stale_ra_pio(iface, p, now);
|
||||
+ router_stale_ra_pio(iface, addr, now);
|
||||
} else {
|
||||
p->nd_opt_pi_preferred_time = htonl(preferred_lt);
|
||||
p->nd_opt_pi_valid_time = htonl(valid_lt);
|
||||
|
||||
- router_add_ra_pio(iface, p);
|
||||
+ router_add_ra_pio(iface, addr);
|
||||
}
|
||||
}
|
||||
|
||||
+285
@@ -0,0 +1,285 @@
|
||||
From d402cdae431668f55f9d82b7072b0afa3b8090df Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Groat <stephen.groat@datadoghq.com>
|
||||
Date: Wed, 8 Oct 2025 11:54:51 -0700
|
||||
Subject: [PATCH] ndp: fix macOS IPv6 compatibility by using link-local source
|
||||
addresses
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
macOS ignores NDP packets that don't originate from link-local addresses,
|
||||
causing IPv6 connectivity issues with odhcpd. This change ensures NDP
|
||||
packets (Neighbor Advertisements and ICMP Echo Requests) are sent using
|
||||
link-local source addresses for RFC 4861 compliance.
|
||||
|
||||
Changes:
|
||||
* Add ndp_from_link_local configuration flag (defaults to true)
|
||||
* Add odhcpd_send_with_src() to allow explicit source address control
|
||||
* Add odhcpd_try_send_with_src() helper to eliminate code duplication
|
||||
* Add odhcpd_get_interface_linklocal_addr() with caching for performance
|
||||
* Update send_na() and ping6() to use link-local source addresses when
|
||||
enabled
|
||||
* Add RFC 4861, §4.2 comments explaining the mandated behavior
|
||||
* Maintain backward compatibility with fallback behavior
|
||||
|
||||
Fixes: openwrt/openwrt#7561 #202
|
||||
Signed-off-by: Stephen Groat <stephengroat@gmail.com>
|
||||
Link: https://github.com/openwrt/odhcpd/pull/242
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
---
|
||||
README.md | 1 +
|
||||
src/config.c | 7 ++++
|
||||
src/ndp.c | 12 ++++---
|
||||
src/odhcpd.c | 91 ++++++++++++++++++++++++++++++++++++++++------------
|
||||
src/odhcpd.h | 11 +++++++
|
||||
5 files changed, 97 insertions(+), 25 deletions(-)
|
||||
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -114,6 +114,7 @@ and may also receive information from ub
|
||||
| ra_pref64 |string | - | Announce PREF64 option for NAT64 prefix (RFC8781) [IPv6 prefix] |
|
||||
| ndproxy_routing |bool | 1 | Learn routes from NDP |
|
||||
| ndproxy_slave |bool | 0 | NDProxy external slave |
|
||||
+| ndp_from_link_local |bool | 1 | Use link-local source addresses for NDP operations (RFC 4861, §4.2 compliance) and macOS compatibility |
|
||||
| prefix_filter |string |`::/0` | Only advertise on-link prefixes within the provided IPv6 prefix; others are filtered out. [IPv6 prefix] |
|
||||
| ntp |list |`<local address>`| NTP servers to announce accepts IPv4 and IPv6 |
|
||||
|
||||
--- a/src/config.c
|
||||
+++ b/src/config.c
|
||||
@@ -117,6 +117,7 @@ enum {
|
||||
IFACE_ATTR_PD_CER,
|
||||
IFACE_ATTR_NDPROXY_ROUTING,
|
||||
IFACE_ATTR_NDPROXY_SLAVE,
|
||||
+ IFACE_ATTR_NDP_FROM_LINK_LOCAL,
|
||||
IFACE_ATTR_PREFIX_FILTER,
|
||||
IFACE_ATTR_MAX_PREFERRED_LIFETIME,
|
||||
IFACE_ATTR_MAX_VALID_LIFETIME,
|
||||
@@ -171,6 +172,7 @@ static const struct blobmsg_policy iface
|
||||
[IFACE_ATTR_RA_PREF64] = { .name = "ra_pref64", .type = BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL },
|
||||
+ [IFACE_ATTR_NDP_FROM_LINK_LOCAL] = { .name = "ndp_from_link_local", .type = BLOBMSG_TYPE_BOOL },
|
||||
[IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_MAX_PREFERRED_LIFETIME] = { .name = "max_preferred_lifetime", .type = BLOBMSG_TYPE_STRING },
|
||||
[IFACE_ATTR_MAX_VALID_LIFETIME] = { .name = "max_valid_lifetime", .type = BLOBMSG_TYPE_STRING },
|
||||
@@ -271,6 +273,8 @@ static void set_interface_defaults(struc
|
||||
iface->ra = MODE_DISABLED;
|
||||
iface->ndp = MODE_DISABLED;
|
||||
iface->learn_routes = 1;
|
||||
+ iface->ndp_from_link_local = true;
|
||||
+ iface->cached_linklocal_valid = false;
|
||||
iface->dhcp_leasetime = 43200;
|
||||
iface->max_preferred_lifetime = ND_PREFERRED_LIMIT;
|
||||
iface->max_valid_lifetime = ND_VALID_LIMIT;
|
||||
@@ -1451,6 +1455,9 @@ int config_parse_interface(void *data, s
|
||||
if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE]))
|
||||
iface->external = blobmsg_get_bool(c);
|
||||
|
||||
+ if ((c = tb[IFACE_ATTR_NDP_FROM_LINK_LOCAL]))
|
||||
+ iface->ndp_from_link_local = blobmsg_get_bool(c);
|
||||
+
|
||||
if ((c = tb[IFACE_ATTR_PREFIX_FILTER]))
|
||||
odhcpd_parse_addr6_prefix(blobmsg_get_string(c),
|
||||
&iface->pio_filter_addr,
|
||||
--- a/src/ndp.c
|
||||
+++ b/src/ndp.c
|
||||
@@ -280,7 +280,7 @@ static void ndp_netevent_cb(unsigned lon
|
||||
/* Send an ICMP-ECHO. This is less for actually pinging but for the
|
||||
* neighbor cache to be kept up-to-date. */
|
||||
static void ping6(struct in6_addr *addr,
|
||||
- const struct interface *iface)
|
||||
+ struct interface *iface)
|
||||
{
|
||||
struct sockaddr_in6 dest = { .sin6_family = AF_INET6, .sin6_addr = *addr , };
|
||||
struct icmp6_hdr echo = { .icmp6_type = ICMP6_ECHO_REQUEST };
|
||||
@@ -291,13 +291,16 @@ static void ping6(struct in6_addr *addr,
|
||||
syslog(LOG_DEBUG, "Pinging for %s on %s", ipbuf, iface->name);
|
||||
|
||||
netlink_setup_route(addr, 128, iface->ifindex, NULL, 128, true);
|
||||
- odhcpd_send(iface->ndp_ping_fd, &dest, &iov, 1, iface);
|
||||
+
|
||||
+ /* Use link-local address as source for RFC 4861 compliance and macOS compatibility */
|
||||
+ odhcpd_try_send_with_src(iface->ndp_ping_fd, &dest, &iov, 1, iface);
|
||||
+
|
||||
netlink_setup_route(addr, 128, iface->ifindex, NULL, 128, false);
|
||||
}
|
||||
|
||||
/* Send a Neighbor Advertisement. */
|
||||
static void send_na(struct in6_addr *to_addr,
|
||||
- const struct interface *iface, struct in6_addr *for_addr,
|
||||
+ struct interface *iface, struct in6_addr *for_addr,
|
||||
const uint8_t *mac)
|
||||
{
|
||||
struct sockaddr_in6 dest = { .sin6_family = AF_INET6, .sin6_addr = *to_addr };
|
||||
@@ -319,7 +322,8 @@ static void send_na(struct in6_addr *to_
|
||||
inet_ntop(AF_INET6, to_addr, ipbuf, sizeof(ipbuf));
|
||||
syslog(LOG_DEBUG, "Answering NS to %s on %s", ipbuf, iface->ifname);
|
||||
|
||||
- odhcpd_send(iface->ndp_ping_fd, &dest, &iov, 1, iface);
|
||||
+ /* Use link-local address as source for RFC 4861 compliance and macOS compatibility */
|
||||
+ odhcpd_try_send_with_src(iface->ndp_ping_fd, &dest, &iov, 1, iface);
|
||||
}
|
||||
|
||||
/* Handle solicitations */
|
||||
--- a/src/odhcpd.c
|
||||
+++ b/src/odhcpd.c
|
||||
@@ -189,10 +189,10 @@ int odhcpd_get_flags(const struct interf
|
||||
}
|
||||
|
||||
|
||||
-/* Forwards a packet on a specific interface */
|
||||
-ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest,
|
||||
+/* Forwards a packet on a specific interface with optional source address */
|
||||
+ssize_t odhcpd_send_with_src(int socket, struct sockaddr_in6 *dest,
|
||||
struct iovec *iov, size_t iov_len,
|
||||
- const struct interface *iface)
|
||||
+ const struct interface *iface, const struct in6_addr *src_addr)
|
||||
{
|
||||
/* Construct headers */
|
||||
uint8_t cmsg_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))] = {0};
|
||||
@@ -214,6 +214,10 @@ ssize_t odhcpd_send(int socket, struct s
|
||||
struct in6_pktinfo *pktinfo = (struct in6_pktinfo*)CMSG_DATA(chdr);
|
||||
pktinfo->ipi6_ifindex = iface->ifindex;
|
||||
|
||||
+ /* Set source address if provided */
|
||||
+ if (src_addr)
|
||||
+ pktinfo->ipi6_addr = *src_addr;
|
||||
+
|
||||
/* Also set scope ID if link-local */
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&dest->sin6_addr)
|
||||
|| IN6_IS_ADDR_MC_LINKLOCAL(&dest->sin6_addr))
|
||||
@@ -232,30 +236,75 @@ ssize_t odhcpd_send(int socket, struct s
|
||||
return sent;
|
||||
}
|
||||
|
||||
+/* Forwards a packet on a specific interface */
|
||||
+ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest,
|
||||
+ struct iovec *iov, size_t iov_len,
|
||||
+ const struct interface *iface)
|
||||
+{
|
||||
+ return odhcpd_send_with_src(socket, dest, iov, iov_len, iface, NULL);
|
||||
+}
|
||||
+
|
||||
|
||||
-static int odhcpd_get_linklocal_interface_address(int ifindex, struct in6_addr *lladdr)
|
||||
+int odhcpd_get_interface_linklocal_addr(struct interface *iface, struct in6_addr *addr)
|
||||
{
|
||||
- int ret = -1;
|
||||
- struct sockaddr_in6 addr;
|
||||
- socklen_t alen = sizeof(addr);
|
||||
- int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
+ /* Return cached address if valid */
|
||||
+ if (iface->cached_linklocal_valid) {
|
||||
+ *addr = iface->cached_linklocal_addr;
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
- if (sock < 0)
|
||||
- return -1;
|
||||
+ /* First try to get link-local address from interface addresses */
|
||||
+ for (size_t i = 0; i < iface->addr6_len; ++i) {
|
||||
+ if (IN6_IS_ADDR_LINKLOCAL(&iface->addr6[i].addr.in6)) {
|
||||
+ *addr = iface->addr6[i].addr.in6;
|
||||
+ /* Cache the result for future use */
|
||||
+ iface->cached_linklocal_addr = *addr;
|
||||
+ iface->cached_linklocal_valid = true;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- memset(&addr, 0, sizeof(addr));
|
||||
- addr.sin6_family = AF_INET6;
|
||||
- inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &addr.sin6_addr);
|
||||
- addr.sin6_scope_id = ifindex;
|
||||
-
|
||||
- if (!connect(sock, (struct sockaddr*)&addr, sizeof(addr)) &&
|
||||
- !getsockname(sock, (struct sockaddr*)&addr, &alen)) {
|
||||
- *lladdr = addr.sin6_addr;
|
||||
- ret = 0;
|
||||
+ /* Fallback to socket-based method */
|
||||
+ struct sockaddr_in6 sockaddr;
|
||||
+ socklen_t alen = sizeof(sockaddr);
|
||||
+ int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
|
||||
+
|
||||
+ if (sock >= 0) {
|
||||
+ memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
+ sockaddr.sin6_family = AF_INET6;
|
||||
+ inet_pton(AF_INET6, ALL_IPV6_ROUTERS, &sockaddr.sin6_addr);
|
||||
+ sockaddr.sin6_scope_id = iface->ifindex;
|
||||
+
|
||||
+ if (!connect(sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) &&
|
||||
+ !getsockname(sock, (struct sockaddr*)&sockaddr, &alen)) {
|
||||
+ *addr = sockaddr.sin6_addr;
|
||||
+ /* Cache the result for future use */
|
||||
+ iface->cached_linklocal_addr = *addr;
|
||||
+ iface->cached_linklocal_valid = true;
|
||||
+ close(sock);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ close(sock);
|
||||
}
|
||||
|
||||
- close(sock);
|
||||
- return ret;
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/* Try to send with link-local source address for RFC 4861 compliance and macOS compatibility.
|
||||
+ * RFC 4861, §4.2 mandates that Neighbor Advertisement source address MUST be
|
||||
+ * the link-local address assigned to the interface from which this message is sent. */
|
||||
+ssize_t odhcpd_try_send_with_src(int socket, struct sockaddr_in6 *dest,
|
||||
+ struct iovec *iov, size_t iov_len,
|
||||
+ struct interface *iface)
|
||||
+{
|
||||
+ struct in6_addr src_addr;
|
||||
+
|
||||
+ if (iface->ndp_from_link_local && odhcpd_get_interface_linklocal_addr(iface, &src_addr) == 0) {
|
||||
+ return odhcpd_send_with_src(socket, dest, iov, iov_len, iface, &src_addr);
|
||||
+ } else {
|
||||
+ /* Fall back to default behavior if no link-local address is available or flag is disabled */
|
||||
+ return odhcpd_send(socket, dest, iov, iov_len, iface);
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -303,7 +352,7 @@ int odhcpd_get_interface_dns_addr(const
|
||||
return 0;
|
||||
}
|
||||
|
||||
- return odhcpd_get_linklocal_interface_address(iface->ifindex, addr);
|
||||
+ return odhcpd_get_interface_linklocal_addr(iface, addr);
|
||||
}
|
||||
|
||||
struct interface* odhcpd_get_interface_by_index(int ifindex)
|
||||
--- a/src/odhcpd.h
|
||||
+++ b/src/odhcpd.h
|
||||
@@ -333,6 +333,9 @@ struct interface {
|
||||
|
||||
// NDP
|
||||
int learn_routes;
|
||||
+ bool ndp_from_link_local;
|
||||
+ struct in6_addr cached_linklocal_addr;
|
||||
+ bool cached_linklocal_valid;
|
||||
|
||||
// RA
|
||||
uint8_t ra_flags;
|
||||
@@ -469,11 +472,19 @@ int odhcpd_register(struct odhcpd_event
|
||||
int odhcpd_deregister(struct odhcpd_event *event);
|
||||
void odhcpd_process(struct odhcpd_event *event);
|
||||
|
||||
+ssize_t odhcpd_send_with_src(int socket, struct sockaddr_in6 *dest,
|
||||
+ struct iovec *iov, size_t iov_len,
|
||||
+ const struct interface *iface, const struct in6_addr *src_addr);
|
||||
ssize_t odhcpd_send(int socket, struct sockaddr_in6 *dest,
|
||||
struct iovec *iov, size_t iov_len,
|
||||
const struct interface *iface);
|
||||
+ssize_t odhcpd_try_send_with_src(int socket, struct sockaddr_in6 *dest,
|
||||
+ struct iovec *iov, size_t iov_len,
|
||||
+ struct interface *iface);
|
||||
int odhcpd_get_interface_dns_addr(const struct interface *iface,
|
||||
struct in6_addr *addr);
|
||||
+int odhcpd_get_interface_linklocal_addr(struct interface *iface,
|
||||
+ struct in6_addr *addr);
|
||||
int odhcpd_get_interface_config(const char *ifname, const char *what);
|
||||
int odhcpd_get_mac(const struct interface *iface, uint8_t mac[6]);
|
||||
int odhcpd_get_flags(const struct interface *iface);
|
||||
@@ -0,0 +1,44 @@
|
||||
From 30780debd691aee7567784daf1fdfd8db500a485 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?David=20H=C3=A4rdeman?= <david@hardeman.nu>
|
||||
Date: Thu, 9 Oct 2025 11:08:14 +0200
|
||||
Subject: [PATCH] odhcpd: fix a compilation error
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
odhcpd_get_interface_dns_addr() calls odhcpd_get_interface_linklocal_addr(),
|
||||
the former takes a const struct interface ptr, the latter takes a non-const
|
||||
struct interface ptr.
|
||||
|
||||
The end result is an unhappy compiler.
|
||||
|
||||
Signed-off-by: David Härdeman <david@hardeman.nu>
|
||||
Link: https://github.com/openwrt/odhcpd/pull/272
|
||||
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
|
||||
---
|
||||
src/odhcpd.c | 2 +-
|
||||
src/odhcpd.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/src/odhcpd.c
|
||||
+++ b/src/odhcpd.c
|
||||
@@ -314,7 +314,7 @@ ssize_t odhcpd_try_send_with_src(int soc
|
||||
* - use an IPv6 ULA address if the already selected IPv6 address is not an ULA address
|
||||
* - use the IPv6 address with the longest preferred lifetime
|
||||
*/
|
||||
-int odhcpd_get_interface_dns_addr(const struct interface *iface, struct in6_addr *addr)
|
||||
+int odhcpd_get_interface_dns_addr(struct interface *iface, struct in6_addr *addr)
|
||||
{
|
||||
time_t now = odhcpd_time();
|
||||
ssize_t m = -1;
|
||||
--- a/src/odhcpd.h
|
||||
+++ b/src/odhcpd.h
|
||||
@@ -481,7 +481,7 @@ ssize_t odhcpd_send(int socket, struct s
|
||||
ssize_t odhcpd_try_send_with_src(int socket, struct sockaddr_in6 *dest,
|
||||
struct iovec *iov, size_t iov_len,
|
||||
struct interface *iface);
|
||||
-int odhcpd_get_interface_dns_addr(const struct interface *iface,
|
||||
+int odhcpd_get_interface_dns_addr(struct interface *iface,
|
||||
struct in6_addr *addr);
|
||||
int odhcpd_get_interface_linklocal_addr(struct interface *iface,
|
||||
struct in6_addr *addr);
|
||||
Reference in New Issue
Block a user