Skip to content

Add support for raw + af_packet sockets#63

Open
danielinux wants to merge 12 commits intowolfSSL:masterfrom
danielinux:rawsockets
Open

Add support for raw + af_packet sockets#63
danielinux wants to merge 12 commits intowolfSSL:masterfrom
danielinux:rawsockets

Conversation

@danielinux
Copy link
Copy Markdown
Member

Add support for raw sockets and packet sockets.

  • Added support for BSD wrapper in posix systems.
  • Added 'raw_ping' and 'packet_ping' examples to craft ICMP echo requests / receive replies using the new sockets
  • Added automated tests to github workflow

Superseeds #10

Copilot AI review requested due to automatic review settings March 3, 2026 17:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds raw IP socket and AF_PACKET-style packet socket support to wolfIP, including POSIX preload shim enhancements and new example utilities for pinging via the new socket types.

Changes:

  • Add RAW and PACKET socket types to the wolfIP socket API, including send/recv/bind/connect/poll support.
  • Extend the POSIX LD_PRELOAD BSD socket shim with ioctl() handling for interface/ARP queries needed by packet sockets.
  • Add new raw_ping / packet_ping examples and run them in CI.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
wolfip.h Adds socket constants, socket marks, and sockaddr_ll support plus ARP lookup API.
src/wolfip.c Implements raw sockets + packet sockets, routing/ARP for raw TX, and capture paths for RX.
src/test/unit/unit.c Adds unit tests covering raw/packet socket send/recv behaviors.
src/test/raw_ping.c New raw-socket ping example for CI/manual testing.
src/test/packet_ping.c New AF_PACKET ping example using ioctl-derived interface info.
src/port/posix/bsd_socket.c Adds ioctl() interception and fd bookkeeping for raw/packet sockets.
config.h Enables raw/packet sockets by default and sets default max counts.
Makefile Builds the new ping example binaries.
.github/workflows/linux.yml Runs raw_ping and packet_ping under LD_PRELOAD in CI.
Comments suppressed due to low confidence (2)

src/test/raw_ping.c:55

  • The checksum helper handles odd-length buffers incorrectly: for a trailing byte it should be added as the high-order byte of the final 16-bit word (i.e., byte << 8, zero-padded), not as a low-order byte. This matches how Internet checksums are computed (and how the stack’s checksum helpers handle odd lengths).
    if (len == 1) {
        sum += *(unsigned char *)buf;
    }

src/test/packet_ping.c:99

  • The checksum helper adds the trailing byte for odd-length buffers without shifting it into the high-order position of the final 16-bit word. For correctness with arbitrary payload sizes, treat the last byte as byte << 8 (zero-padded) when len is odd.
    if (len == 1) {
        sum += *(unsigned char *)buf;
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@danielinux danielinux mentioned this pull request Mar 3, 2026
Copilot AI review requested due to automatic review settings March 3, 2026 18:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings March 3, 2026 21:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add support for raw sockets and packet sockets.

- Added support for BSD wrapper in posix systems.
- Added 'raw_ping' and 'packet_ping' examples to craft ICMP echo
  requests / receive replies using the new sockets
- Added automated tests to github workflow
- ioctl(): read vararg as void* to avoid UB when callers pass pointers
- bsd_socket.c: fix errno assignments to use -ret (positive) per POSIX
- bsd_socket.c: use -WOLFIP_EAGAIN instead of -EAGAIN in recvfrom
- wolfip.c: fix packet socket TX filter loop to pop head on reject
  instead of advancing via fifo_next() (queue corruption fix)
- wolfip.c: return -WOLFIP_EMSGSIZE on buffer-too-small in recvfrom
  for raw, packet, and ICMP socket paths
- wolfip.c: packet setsockopt now rejects unsupported options with
  -WOLFIP_EINVAL instead of silently succeeding
- wolfip.c: getsockopt RECVTTL returns enabled state (1/0), not TTL
- wolfip.c: arp_lookup_ex returns -WOLFIP_ENOENT on miss
- wolfip.h: add WOLFIP_EMSGSIZE and WOLFIP_ENOENT error codes
- wolfip.c: fix IS_IP_BCAST -> wolfIP_ip_is_broadcast() after rebase
- Add 7 new unit tests covering EMSGSIZE paths, setsockopt rejection,
  raw socket options, getsockopt behavior, packet TX via poll, and
  arp_lookup_ex error codes
- Update existing tests to match new error return values
Copilot AI review requested due to automatic review settings April 12, 2026 16:29
- Wrap test_raw_socket_close_clears_entry and
  test_raw_socket_recv_too_short_drop_returns_einval in
  #if WOLFIP_RAWSOCKETS guards: struct rawsocket is only defined when
  the feature is enabled, so accessing s.rawsockets[] and struct
  members caused compile errors when WOLFIP_RAWSOCKETS=0
- Fix ioctl() vararg: read as uintptr_t then cast to void* to avoid
  undefined behavior on ABIs where pointer != integer size
- Pre-declare loop variable in raw_try_recv() to avoid C99-style
  for-init declaration inconsistent with the rest of the codebase
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2296 to +2297
fifo_push(&p->rxbuf, record, record_len);
p->events |= CB_EVENT_READABLE;
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

packet_try_recv() uses fifo_space() as a pre-check and then ignores fifo_push()'s return value. Since fifo_space() can overestimate available enqueue space due to alignment/wrap, fifo_push() may fail but CB_EVENT_READABLE is still set, leading to spurious wakeups with no data actually queued. Only set READABLE when fifo_push() succeeds (and consider using fifo_can_push_len() to match fifo_push() semantics).

Suggested change
fifo_push(&p->rxbuf, record, record_len);
p->events |= CB_EVENT_READABLE;
if (fifo_push(&p->rxbuf, record, record_len))
p->events |= CB_EVENT_READABLE;

Copilot uses AI. Check for mistakes.
Comment on lines +5615 to +5616
if (desc->len > len)
return -WOLFIP_EMSGSIZE;
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the raw-socket recvfrom path, when the caller buffer is too small the function returns -WOLFIP_EMSGSIZE but does not dequeue the pending frame or clear CB_EVENT_READABLE. This differs from the ICMP path (which pops the frame on EMSGSIZE) and can cause repeated EMSGSIZE returns with the socket permanently readable. Consider popping the frame (and updating rs->events) on EMSGSIZE to match existing datagram semantics.

Suggested change
if (desc->len > len)
return -WOLFIP_EMSGSIZE;
if (desc->len > len) {
fifo_pop(&rs->rxbuf);
if (fifo_peek(&rs->rxbuf) == NULL)
rs->events &= ~CB_EVENT_READABLE;
return -WOLFIP_EMSGSIZE;
}

Copilot uses AI. Check for mistakes.
Comment on lines +5650 to +5651
if (desc->len - 1 > len)
return -WOLFIP_EMSGSIZE;
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the packet-socket recvfrom path, when the caller buffer is too small the function returns -WOLFIP_EMSGSIZE without dequeuing the frame or clearing CB_EVENT_READABLE. This can leave the same frame at the head forever, causing repeated EMSGSIZE and a permanently-readable socket. Consider dropping the frame (and clearing ps->events when the queue becomes empty) on EMSGSIZE, consistent with the ICMP recvfrom behavior.

Suggested change
if (desc->len - 1 > len)
return -WOLFIP_EMSGSIZE;
if (desc->len - 1 > len) {
fifo_pop(&ps->rxbuf);
if (fifo_peek(&ps->rxbuf) == NULL)
ps->events &= ~CB_EVENT_READABLE;
return -WOLFIP_EMSGSIZE;
}

Copilot uses AI. Check for mistakes.
Comment on lines +8623 to +8627
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, tx_if);
if (ll && ll->send)
ll->send(ll, ip, desc->len);
}
fifo_pop(&r->txbuf);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wolfIP_poll() transmits raw-socket TX frames by popping from r->txbuf, but it never sets CB_EVENT_WRITABLE afterward. Since callbacks clear r->events to 0, a thread blocked in the POSIX wrapper waiting for POLLOUT on a full raw TX FIFO may never get another writable notification once space becomes available, leading to a potential deadlock. After draining/popping TX descriptors, set r->events |= CB_EVENT_WRITABLE when the TX FIFO transitions from full->has-space (or is empty / fifo_can_push_len() indicates writable).

Copilot uses AI. Check for mistakes.
Comment on lines +8651 to +8656
{
struct wolfIP_ll_dev *ll = wolfIP_ll_at(s, tx_if);
if (ll && ll->send)
ll->send(ll, frame, desc->len);
}
fifo_pop(&p->txbuf);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wolfIP_poll() transmits packet-socket TX frames by popping from p->txbuf, but it never sets CB_EVENT_WRITABLE afterward. Because poll callbacks clear p->events, a thread waiting for POLLOUT (e.g., via the POSIX wrapper) can block indefinitely once the TX FIFO was full, since no further writable event will be generated when space frees up. After popping TX descriptors, set p->events |= CB_EVENT_WRITABLE when the TX FIFO becomes writable again (e.g., empty or fifo_can_push_len() indicates capacity).

Copilot uses AI. Check for mistakes.
Comment on lines 361 to +362
void wolfIP_ipconfig_get_ex(struct wolfIP *s, unsigned int if_idx, ip4 *ip, ip4 *mask, ip4 *gw);
int wolfIP_arp_lookup_ex(struct wolfIP *s, unsigned int if_idx, ip4 ip, uint8_t *mac);
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wolfIP_arp_lookup_ex() is declared unconditionally in the public header, but its implementation in src/wolfip.c is compiled only under #ifdef ETHERNET. In non-ETHERNET builds this can lead to an undefined reference for consumers. Either wrap the prototype in the same conditional or provide a stub implementation that returns an appropriate error when ETHERNET is disabled.

Suggested change
void wolfIP_ipconfig_get_ex(struct wolfIP *s, unsigned int if_idx, ip4 *ip, ip4 *mask, ip4 *gw);
int wolfIP_arp_lookup_ex(struct wolfIP *s, unsigned int if_idx, ip4 ip, uint8_t *mac);
void wolfIP_ipconfig_get_ex(struct wolfIP *s, unsigned int if_idx, ip4 *ip, ip4 *mask, ip4 *gw);
#ifdef ETHERNET
int wolfIP_arp_lookup_ex(struct wolfIP *s, unsigned int if_idx, ip4 ip, uint8_t *mac);
#endif

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants