igmp_input() validated the IGMP checksum with:
if (net_chksum((FAR uint16_t *)igmp, IGMP_HDRLEN) != 0)
but net_chksum() returns the raw one's complement sum of the 16-bit
words (it does NOT take the one's complement of that sum). For a valid
IGMP packet whose checksum field holds ~S (as written by igmp_send()),
the sum of all 16-bit words is S + ~S = 0xffff, never 0.
So the existing check `!= 0` was always true for any well-formed IGMP
message, sending every valid packet down the "Checksum error" path to
be silently dropped and breaking IGMP membership query/report processing.
Compare against 0xffff instead, matching the convention used by the
other transport input handlers:
- ipv4_input.c: (ipv4_chksum(IPv4BUF) != 0xffff)
- tcp_input.c: (tcp_chksum(dev) != 0xffff)
This is also consistent with the sender side in igmp_send.c, which
stores `igmp->chksum = ~igmp_chksum(...)`.
Signed-off-by: zhekunren <zhekunren@qq.com>
Assisted-by: GLM-5.2 <noreply@z.ai>
igmp_input() verified the packet length with:
if (dev->d_len < NET_LL_HDRLEN(dev) + (iphdrlen + IGMP_HDRLEN))
but dev->d_len at this point holds the IPv4 total length (IP header plus
payload) without the link-layer header, consistent with the convention
established in ipv4_in()/ipv6_in() (which do `dev->d_len -=
NET_LL_HDRLEN(dev)`) and used by all other transport input handlers
(icmp, tcp, udp), none of which reference NET_LL_HDRLEN.
Adding NET_LL_HDRLEN(dev) to the right-hand side made the check always
true for valid IGMP packets:
iphdrlen + IGMP_HDRLEN < NET_LL_HDRLEN + iphdrlen + IGMP_HDRLEN
(= 0 < NET_LL_HDRLEN)
so every well-formed IGMP message hit the "Length error" path and was
silently dropped, breaking IGMP membership query/report processing.
Drop the extra NET_LL_HDRLEN(dev) so the check matches the other
protocol handlers.
Signed-off-by: zhekunren <zhekunren@qq.com>
The condition work_available(&conn->work) && tx_unacked != 0
prevented tcp_update_retrantimer from being called when the work
queue was still busy, leaving conn->timer stale or zero on
subsequent sends. This caused the RTT estimation to compute a
false RTT (m = rto - 0 = rto), creating a positive feedback loop
that inflated the RTO to extreme values (e.g., 232 half-seconds
= ~116 seconds).
Fix: remove the work_available check so that tcp_update_retrantimer
is always called when there is unacknowledged data. The decision to
re-queue the work is handled internally by tcp_update_timer.
Signed-off-by: zhekunren <zhekunren@qq.com>
IPv6 input currently lets fragmented packets continue into the IP filter path before reassembly. Forwarded IP filter rules can inspect L4 fields, but non-first IPv6 fragments do not carry the transport header.
Consume IPv6 fragments through the existing reassembly/drop helper before NAT66 or IP filter processing. This keeps plain IPv6 forwarding unchanged when neither L4-dependent feature is enabled, while avoiding filtering incomplete fragments.
Signed-off-by: shichunma <shichunma@bestechnic.com>
NAT66 needs transport headers to create or match address and port mappings. Consume IPv6 fragments through local reassembly before NAT66 processing so forwarded fragmented traffic is not translated fragment-by-fragment without L4 context.
Also dispatch inbound NAT66 using the parsed IPv6 next-header value, matching the outbound path and allowing packets with extension headers before the transport header to be translated.
Signed-off-by: shichunma <shichunma@bestechnic.com>
Allow non-local IPv4 fragments to reach the forwarding path before local fragment reassembly. This lets routers forward fragmented datagrams without requiring local reassembly state.
Keep NAT44 and IP filter builds on the existing reassembly path because those features can depend on L4 headers. Preserve the original fragment offset and MF flag when fragout must split an already-fragmented packet for a smaller egress MTU.
Signed-off-by: shichunma <shichunma@bestechnic.com>
During the Toybox port to NuttX, Claude noticed that changes in the
menuconfig weren't taking affect. This issue exists for a long time on
NuttX, in fact BayLibre's presentation from 2017 make jokes about our
building system not been reliable:
https://www.youtube.com/watch?v=XUJK2htXxKw&t=320s
Stale archive members from $(AR)'s additive-only behavior can linger
after Kconfig toggles change which files provide a symbol, causing dead
weight or "multiple definition" link errors on incremental builds.
Fixed by splitting ARCHIVE into two macros: ARCHIVE keeps the original
additive behavior for apps/libapps.a, which many independent
subdirectories contribute to across a build, while the new
ARCHIVE_REBUILD deletes then archives for the far more common case
of a single Makefile building its own self-contained $(OBJS)
- all 39 such call sites now use it.
Assisted-By: Claude Sonnet 5
Signed-off-by: Alan C. Assis <acassis@gmail.com>
tcp_start_monitor() is called from accept() (net/inet/inet_sockif.c) for
each newly accepted connection. When the peer had already closed the
connection before accept() ran, the monitor takes an early-return path so
that any read-ahead data buffered on the connection can still be drained;
it returns OK in that case. accept() (net/socket/accept.c) then marks the
new socket _SF_CONNECTED unconditionally.
If the peer aborts the connection with an RST immediately after the
three-way handshake completes (for example any close with SO_LINGER
{1, 0}), the connection is moved to TCP_CLOSED with no buffered data, yet
accept() still hands back a socket that reports _SS_ISCONNECTED. A
subsequent blocking send() on that socket passes the connected check,
registers a send callback and waits on its semaphore forever: the only
TCP_ABORT event was delivered before the callback existed, and no further
ACK, POLL or disconnect event is generated for a closed connection, so the
waiter is never woken.
Any server that writes before reading can hit this; the telnet daemon
(netutils/telnetd) is one example, where the accepted session task blocks
in send() and never completes.
Only return OK from the already-closed path when there is actually
read-ahead data to drain. Otherwise the connection is dead, so fall
through to the -ENOTCONN return: accept() then fails cleanly instead of
handing back a socket wedged on a connection that will never make progress.
The graceful-close-with-pending-data case (the reason the OK path exists)
is preserved by the conn->readahead check.
Signed-off-by: Ricard Rosson <ricard@groundbits.com>
Assisted-by: Claude (Anthropic Claude Code)
There was another small issue on sixlowpan_input.c code, it was
processing protosize and 8-bit instead of 16-bit.
It was working because the max tcp->tcpoffset was 0xf0, so
protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
Will be protosize = 15 * 4 = 60 and will fit inside 8-bit.
Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit checks if the incoming 6LoWPAN frame header len + the
IPv6_HDRLEN will fit inside the b->io_len.
Signed-off-by: Alan C. Assis <acassis@gmail.com>
The sim host usrsock backend only accepted INET/NETLINK domains and
translated socket addresses through plain struct sockaddr. That prevents
simulated applications from using POSIX AF_LOCAL sockets through the
standard socket API when CONFIG_NET_USRSOCK is used.
Add AF_LOCAL address conversion for struct sockaddr_un, allow PF_LOCAL
sockets through usrsock, handle NuttX socket type flags, and poll host
descriptors from the sim usrsock work item so nonblocking
connect/read/write readiness is reported back to NuttX. Use
sockaddr_storage for native address translation so larger address
structures are not truncated.
Testing:
- Host: Ubuntu 22.04 x86_64.
- Board/config: sim:nsh with CONFIG_NET_USRSOCK=y and
CONFIG_EXAMPLES_HELLO=y.
- make clean && make -j16.
- Ran a temporary hello example that connected to host AF_UNIX
SOCK_STREAM and SOCK_SEQPACKET sockets through NuttX socket(),
connect(), write(), and read(). Both received pong and printed
"AF_LOCAL usrsock test passed".
Assisted-by: Claude:Claude-Fable-5
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
The group address in the IGMP header is declared as uint16_t grpaddr[2],
so it decays to a pointer. Comparing it against INADDR_ANY compares the
address of a struct member against 0, which is always false. The General
Query branch is therefore unreachable and GCC discards it entirely.
Commit 09bb292fa2 ("net/igmp: fix build warning on GCC 12.2.0") replaced
the original
if (igmp->grpaddr == 0)
with
if (net_ipv4addr_cmp(igmp->grpaddr, INADDR_ANY) != 0)
but net_ipv4addr_cmp(a, b) expands to (a == b) and INADDR_ANY expands to
((in_addr_t)0), so the emitted comparison is unchanged. The -Waddress
diagnostic disappeared only because the comparison now originates inside
a macro expanded from a header included via -isystem, and GCC suppresses
warnings from system-header macros. The defect was hidden, not fixed.
That commit also rewrote the unicast query test from group->grpaddr != 0,
which was well-formed, into the same pointer comparison, making it
unconditionally true.
Convert the header field with net_ip4addr_conv32() once, and compare the
resulting in_addr_t. The conversion was already being done in the
group-specific branch, so this only hoists it and reuses it.
Impact: a General Query (destination 224.0.0.1, group address 0) is the
periodic query every IGMP querier sends. It currently falls through to
the group-specific branch, where igmp_grpallocfind() allocates a group
for 0.0.0.0 and schedules a report for it, while joined groups never have
their report timers restarted. The querier then ages out the membership
and multicast delivery to the device stops.
Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Align the NuttX open(2) flag constants with the Linux asm-generic
values so that the FUSE wire protocol and other cross-platform
interfaces work without conversion.
All code that used '(flags & O_RDONLY)' as a bitmask check (always 0
now that O_RDONLY=0) has been updated to use '(flags & O_ACCMODE)'
comparisons.
The NUTTX_O_* constants in include/nuttx/fs/hostfs.h are updated to
match, and the sim hostfs open flag mapping is fixed.
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
devif_conn_event() saves list->nxtconn before invoking the current
callback. If the callback mutates its callback list, the saved local
successor may no longer match the post-callback list topology.
Align devif_conn_event() with devif_dev_event(): protect the current
callback with DEVIF_CB_DONT_FREE, refresh next after the callback
returns, and defer freeing the current node until iteration is safe.
Signed-off-by: shichunma <shichunma@bestechnic.com>
POSIX leaves the signedness of time_t and clock_t unspecified, but
mainstream implementations (Linux glibc/musl, the BSDs, macOS, RTEMS,
Zephyr's POSIX layer, Windows _time64) expose time_t as signed 64-bit.
NuttX has historically used uint64_t only because it was tied to the
CONFIG_SYSTEM_TIME64 knob; with that gone, switch:
time_t : uint64_t -> int64_t
clock_t : uint64_t -> int64_t
CLOCK_MAX: UINT64_MAX -> INT64_MAX
This lets (time_t)-1 sentinels, negative tick deltas, and host-side
headers behave as on every other POSIX system without source churn.
Headers updated:
- include/sys/types.h, include/limits.h, include/nuttx/clock.h
- include/nuttx/fs/hostfs.h (nuttx_time_t alias)
- include/nuttx/{mqueue.h,wdog.h,wqueue.h,timers/clkcnt.h}
Because clock_t is now signed 64-bit, the NuttX-internal sclock_t
alias becomes redundant: every sclock_t/SCLOCK_MAX use is folded
back to clock_t/CLOCK_MAX (notably in sched/wdog, sched/mqueue,
sched/sched, sched/clock, sched/timer, libs/libc/time, fs/vfs and
the drivers/arch consumers below).
Tick/period constants (NSEC_PER_SEC, USEC_PER_SEC, MSEC_PER_SEC,
SEC_PER_MIN, ...) in include/nuttx/clock.h are retyped from "long"
literals to INT64_C(...) so that 64-bit arithmetic no longer
depends on the host's long width.
Strip now-redundant (time_t)/(clock_t)/(unsigned long) casts and
unsigned-only branches across the tree:
- arch RTC / oneshot / tickless lowerhalfs:
arm: cxd56xx, efm32, imxrt, lc823450, max326xx, sam34, sama5,
samd5e5, samv7, stm32, stm32f7, stm32h7, stm32l4, stm32wb,
xmc4
mips: pic32mz sparc: bm3803 x86_64: intel64
risc-v/xtensa: espressif (esp_i2c[_slave], esp_rtc,
esp32c3{_i2c,_rtc,_wifi_adapter}, esp32{,s2,s3}_*),
mpfs_perf
- drivers: audio/tone, input/aw86225, power/pm/{activity,
stability}_governor, rpmsg/rpmsg_ping,
timers/{ds3231,mcp794xx,pcf85263,rx8010},
wireless/ieee80211/bcm43xxx, wireless/spirit/spirit_spi
- core: fs/vfs/{fs_poll,fs_timerfd}, mm/iob/iob_alloc,
libs/libc/{netdb/lib_dnscache,time/{lib_calendar2utc,
lib_time}}, net/icmp/icmp_pmtu, net/icmpv6/icmpv6_pmtu,
net/ipfrag, net/tcp/{tcp.h,tcp_timer},
net/utils/net_snoop, net/mld/mld_query (drop the now-dead
mld_mrc2mrd helper since signed math handles it directly),
sched/clock/{clock,clock_initialize},
sched/sched/{sched_profil,sched_setparam,sched_setscheduler},
sched/pthread/pthread_create,
sched/wdog/{wd_gettime,wd_start,wdog.h},
sched/timer/timer_gettime, sched/mqueue/*
Flip the few in-tree printf format strings that assumed an
unsigned 64-bit tv_sec:
* drivers/rpmsg/rpmsg_ping.c PRIu64 -> PRId64
* arch/xtensa/src/esp32{,s2,s3}/esp32*_oneshot_lowerhalf.c
PRIu32 (already wrong) -> PRId64
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
An IPV6 Router advertisement can have an MTU max option.
This option should not increase the d_pktsize for a given interface
since that max size might have been set based on CONFIG or buffer size.
Signed-off-by: daniellizewski <daniellizewski@geotab.com>
bluetooth_sendto() uses netdev_findbyindex(conn->bc_ldev + 1) to find
the Bluetooth network device for an HCI socket. netdev_findbyindex
searches by global interface index, but bc_ldev is a 0-based count of
Bluetooth devices only — it bears no fixed relationship to the global
interface index. If any netdev other than a Bluetooth device is
registered before it (e.g. loopback or Ethernet), the Bluetooth device
will not be at global index bc_ldev + 1 and the lookup will return NULL
or the wrong device.
Fix this by replacing netdev_findbyindex with a netdev_foreach walk
using a small callback (bluetooth_dev_byidx_callback) that counts only
NET_LL_BLUETOOTH devices and returns the bc_ldev-th one, regardless of
what else is registered or in what order.
Signed-off-by: Stephen Fox <stephenfox@geotab.com>
Add ninfo() in netdev_txnotify_dev() to log the network interface
name when TX notification is triggered, aiding network debugging.
Signed-off-by: Jerry Ma <shichunma@bestechnic.com>
This commit fixes sixlowpan_uncompresshdr_hc06() to avoid that the
frame data be bigger than the iob->io_len.
Signed-off-by: Alan C. Assis <acassis@gmail.com>
This commit make ICMPv6 on NuttX compliant with RFC4861 ignoring
a Neighbor Discovery packet when its optlen is 0.
Signed-off-by: Alan C. Assis <acassis@gmail.com>
Make nat_port_select() return an error code and report the selected
external port through an output parameter.
This separates selection failure from the valid ICMP echo identifier
value zero, so outbound NAT entry creation no longer rejects ICMP echo
requests that use id zero.
Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
Rework ipv4_input() packet classification to make the control flow
clearer and keep the common local-unicast case first.
This change:
- handles local packets first
- keeps broadcast/multicast handling in dedicated branches
It also prevents broadcast and multicast packets from falling through
into the unicast forward path.
Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
RFC 3171 reserves 224.0.0.0/24 for link-local IPv4 multicast
scope, so packets in this range must not be forwarded by routers,
regardless of the TTL value.
IPv6 also defines multicast scopes that must not be forwarded beyond
the local topology. In particular, interface-local and link-local
multicast destinations must not be routed across interfaces.
Add IPv4/IPv6 scope checks so non-forwardable multicast packets are
rejected before entering the multicast forwarding path.
Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
Return ntotal (total bytes written) instead of ret (result of last
write call). This matches the expected semantics and is consistent
with net_writeroute_ipv4().
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Add kmm_free(alloc) before returning NULL when neigh is NULL in
netlink_get_neighbor(). Without this, the allocated memory is
leaked on the error path.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
In both convert_ipv4entry() and convert_ipv6entry(), the IPPROTO_UDP
case was incorrectly comparing against XT_MATCH_NAME_TCP instead of
XT_MATCH_NAME_UDP. This caused UDP filter rules to never match.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Remove a redundant net_unlock() call in the early return path of
mld_gendog_work(). The network lock is already released at the
common exit path, causing a double-unlock.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Change && to || in the fromlen validation of icmpv6_recvmsg().
The original condition (fromlen == NULL && *fromlen < sizeof(...))
would never be true when fromlen is NULL due to short-circuit
evaluation. The correct logic is: reject if fromlen is NULL or
the buffer is too small.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Replace return with break inside the loop in icmp_findconn() to
ensure any post-loop cleanup logic is properly executed before
returning.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Move the NULL check for radio pointer before the DEBUGASSERT that
dereferences it. Previously DEBUGASSERT(radio->r_dev.d_lltype == ...)
was executed before verifying radio != NULL, which would crash when
the device is not found.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
Move conn_unlock() call outside the if block in psock_udp_sendto()
to ensure the connection lock is always released before returning,
preventing a potential deadlock when the condition is not met.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
debug.h is a NuttX-specific, non-POSIX header. Placing it in the
top-level include/ directory creates naming conflicts with external
projects that define their own debug.h.
This commit moves the canonical header to include/nuttx/debug.h,
following the NuttX convention for non-POSIX/non-standard headers,
and updates all in-tree references.
A backward-compatibility shim is left at include/debug.h that
emits a deprecation #warning and re-includes <nuttx/debug.h>,
allowing out-of-tree code to continue building while migrating.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Release nat_lock before returning -ENOENT from the IPv4 and IPv6
outbound NAT paths when NAT entry creation fails.
Signed-off-by: Shunchao Hu <ankohuu@gmail.com>
Move conn_unlock() after the data event handling in can_callback()
and udp_callback(). Previously, the connection lock was released
immediately after devif_conn_event(), leaving the subsequent
can_data_event()/net_dataevent() and read-ahead buffer operations
unprotected. This could lead to a race condition where another
context modifies the connection state while data is being stored.
Hold the lock until the entire callback processing is complete to
ensure thread safety.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
case: when rndis receive a packet and this packet is going to be forwarded.
1. first lock happen when ipv4_dev_forward call ipv4_nat_outbound;
2. next lock is: ipv4_nat_outbound_entry_find --> nat_port_select --> tcp_selectport
--> nat_port_inuse
Signed-off-by: Jerry Ma <shichunma@bestechnic.com>
Correct duplicate "is is" word found in 181 files throughout the
codebase.
In most cases "is is" was changed to "is", but in contexts like
"MCU is is sleep mode" it was corrected to "MCU in sleep mode".
Also fixes a "the the" typo in net/inet/inet_sockif.c.
This is a pure style/documentation fix that improves code readability.
Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
Fix 269 occurrences of duplicate "the" word typo found in 209 files
across source code, header files, and configuration.
Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
Intermediate files of make depend like .ddc and .dds may remain
when make is interrupted. Remove them using make distclean.
Signed-off-by: SPRESENSE <41312067+SPRESENSE@users.noreply.github.com>
Some compilers like Tasking do not support anonymous unions/structs.
Add explicit names to the anonymous union and struct members in
snoop_packet_header_s and update all references accordingly.
Signed-off-by: zhangyuan29 <zhangyuan29@xiaomi.com>
This reverts commit fa652f9c24.
When testing iperf on boards such as ESP32-C6, ESP32-C3, and ESP32,
blocking issues are encountered, so the patch is reverted.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
The main content of this submission is to limit both the TX/RX buffers
of TCP/UDP to throttled IOBs, avoiding impacts on the sending and
receiving of control-type messages.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
the lock in the "bluetooth_conn" was not initialized, which resulted in
a blocking situation when attempting to hold the lock for the first
time.
Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>