https://www.rfc-editor.org/rfc/rfc8415.html#section-12
........ The IAID is chosen by the client. For any given use of an
IA by the client, the IAID for that IA MUST be consistent across
restarts of the DHCP client. The client may maintain consistency by
either storing the IAID in non-volatile storage or using an algorithm
that will consistently produce the same IAID as long as the
configuration of the client has not changed.
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/140
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
res variable is used on multiple states and it can be modified from the
default value during the argument parsing, so it should be properly reset
at INIT state.
Signed-off-by: Alvaro Fernandez Rojas <alvaro-fernandez@airbus.com>
There is a chance that the socket receives packets it should not
process between its initial creation and when ra_init is finished.
Flush these from the buffer by calling recvmsg and throwing away
everything that is received.
This solves a race condition on a multi-interface device, where
several odhcp6c instances are started, and an RA for one interface
ends up in the queue for another interface's odhcp6c socket.
Signed-off-by: Lincoln Ramsay <a1291762@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/133
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
It's declared as a boolean in the OpenWrt wiki, and the package script
doesn't pass any value.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
As reported by @nxhack at https://github.com/openwrt/odhcp6c/issues/131,
allow_slaac_only was assigned an incorrect default value when it was moved
from odhcp6c.c to config.c.
Fixes: 1048fc4fb6 ("reconfigure: move all configuration functions to a new file")
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
ip6ifaceid is now properly passed to odhcp6c in OpenWrt scripts, which is
broken if we don't support 'eui64' and 'random' options.
Instead of printing help and exiting when an invalid fixed address is
configured, let's just log an error and pretend that no interface ID was
passed to odhcp6c.
Closes https://github.com/openwrt/openwrt/issues/20976
Link: https://github.com/openwrt/odhcp6c/pull/130
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Fix shadowed local variables and enable warning to prevent more shadowed
variables in the future.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
§3 Precedence of API URIs
"
A device may learn about Captive Portal API URIs through more than one of (or
indeed all of) the above options. Implementations can select their own
precedence order (e.g., prefer one of the IPv6 options before the DHCPv4 option,
or vice versa, et cetera).
If the URIs learned via more than one option described in Section 2 are not all
identical, this condition should be logged for the device owner or
administrator; it is a network configuration error if the learned URIs are not
all identical.
"
We log the 'network configuration error' but proceed in an attempt to be useful
(since the RFC makes no mention of disregarding the URI) and prefer DHCPv6,
since this is the DHCPv6 client.
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/127
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
https://www.rfc-editor.org/rfc/rfc8910.html
RFC8908 defines a captive portal client (CPC) that handles the API URI returned.
The captive portal (CP) option presence signals a portal that requires
authentication beyond what odhcp6c currently handles.
It's possible that a user connecting through an openwrt gateway encounters the
portal anyway (though this behaviour depends on the portal), but if this is not
the case, with this addition we can:
- surface a message in a UI as to presence of the CP
- signal that users install a CPC (a chicken/egg problem behind a CP)
- provide the API URI for downstream consumers.
This should ease the use of travel router scenarios.
Downstream consumers of the API URI can find it via the CAPTIVE_PORTAL_URI
environment/ubus property.
The strengths of having this option handled means downstream consumers get one
unified environment variable since ra.c does not yet handle CUSTOM_* the way
DHCPv6 does.
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/127
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
The calling script which sets odhcp6c up is currently passed -s as routine,
but synchronize its current location with its calling script, which should make
cross-referencing easier.
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/126
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
MIPS64, PowerPC64 and RISCV64 are popular OpenWrt archs.
Refactor the sizes build step to generate the table programatically.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
When the upstream DHCPv6 server does not provide IA_NA or IA_PD options, odhcp6c
enters into stateless mode, which will not be exited from until SIGUSR2 signal
is received.
This change enforces DHCPv6 restart on receipt of a RA that:
a) advertises the presence of DHCPv6 server on the network, containing
either M or O flags
b) has a PI (prefix information) option that contains a new prefix
thus allowing the switch to DHCPv6 stateful mode when RA PI options suggest that
the upstream DHCPv6 server now manages a new prefix.
Restart is useful even when DHCPv6 client is already in stateful mode, so the
DHCPv6 server will be able to refresh the client's IA_NA and IA_PD options
before renewal timeout is triggered, hence avoiding the usage of potentially
deprecated addresses.
Signed-off-by: Alin Nastac <alin.nastac@gmail.com>
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/119
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Properly guard odhcp6c.h attributes with `#ifndef` to avoid redefining them
when including external headers.
Also convert the remaining __attribute__ usages to the custom declarations.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/120
Add cmake build and source directories to suppress the following warning:
CMake Warning:
No source or binary directory provided. Both will be assumed to be the
same as the current working directory, but note that this warning will
become a fatal error in future CMake releases.
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
ubus coerces u8 to boolean, and one workaround suitable is to amend u8
values (despite them being and containing only a u8 int) to u32 values. ubus
coerces u8 to booleans due to historical reasons. Any calls to e.g.
ubus call odhcp6c.eth1 get_state
(and subsequently downstream dependencies which use this invocation)
return booleans(!) where there shall be a number.
Amended calls to blobmsg_add_u8 into blobmsg_add_u32 to resolve this.
Amended calls to blobmsg_add_u16 into blobmsg_add_u32 also.
Apparently u8 and u16 get padded to u32 anyway.
See @nbd168 https://github.com/openwrt/libubox/pull/25#issuecomment-3512957433
"
I'd prefer to just deprecate treating u8 as integer and deprecate using u16 in
blobmsg entirely. That way we can avoid a lot of compatibility mess and JSON
conversion issues. Due to padding, u8, u16 and u32 attributes have the same
effective size anyway, so there isn't really a good reason to use them for
integer values.
"
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/117
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
A header file in the Linux kernel on powerpc uses the variable name
_unused. This causes the following compile error:
```
In file included from /staging_dir/toolchain-powerpc_8548_gcc-14.3.0_musl/include/signal.h:48,
from /staging_dir/target-powerpc_8548_musl/usr/include/libubox/uloop.h:25,
from /staging_dir/target-powerpc_8548_musl/usr/include/libubus.h:24,
from /build_dir/target-powerpc_8548_musl/odhcp6c-2025.11.04~b3e1db42/src/ubus.h:67,
from /build_dir/target-powerpc_8548_musl/odhcp6c-2025.11.04~b3e1db42/src/ubus.c:73:
/staging_dir/toolchain-powerpc_8548_gcc-14.3.0_musl/include/bits/signal.h:27:30: error: expected identifier or '(' before '[' token
27 | unsigned long _unused[4];
| ^
ninja: build stopped: subcommand failed.
make[3]: *** [Makefile:62: /build_dir/target-powerpc_8548_musl/odhcp6c-2025.11.04~b3e1db42/.built] Error 1
```
Use _o_unused instead to avoid such conflicts.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
follow-up to b65ff293a9
The previous logic checked that the DHCPV6_OPT_STATUS was more than 2 bytes,
which meant that it would only be evaluated if the options *also* contained a
status message. We should handle this option being exactly 2 bytes, so that
DHCPV6_OPT_STATUS lacking a status message are correctly handled.
The relevant RFC section does not state that status message can be absent
https://www.rfc-editor.org/rfc/rfc8415#section-21.13
but the status message field is variable length and sets no mandates on its
size.
This ensures differing interpretations of this portion are handled adequately.
It's not uncommon that various options behave in this 'can be zero length' way,
so let's handle this option similarly.
Signed-off-by: Paul Donald <newtwen+github@gmail.com>
Link: https://github.com/openwrt/odhcp6c/pull/113
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>