Skip to content

Add support for raw + af_packet sockets#63

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

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

Conversation

@danielinux
Copy link
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

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
Copilot AI review requested due to automatic review settings March 3, 2026 17:22
Copy link
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
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
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
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.

Comment on lines +1233 to +1250
va_list ap;
uintptr_t arg;
void *argp;
struct ifreq *ifr;
int i;

va_start(ap, request);
arg = va_arg(ap, uintptr_t);
va_end(ap);
argp = (void *)arg;

if (in_the_stack) {
return host_ioctl ? host_ioctl(fd, request, arg) : -1;
}

if (request == SIOCGIFINDEX || request == SIOCGIFHWADDR || request == SIOCGIFADDR) {
struct wolfip_fd_entry *entry = wolfip_entry_from_public(fd);
if (!entry) {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

ioctl varargs are read as unsigned long, but callers pass a pointer for requests like SIOCGIFINDEX/SIOCGARP. Reading a pointer argument with the wrong va_arg type is undefined behavior and can break on some ABIs. Read the vararg as void * (or uintptr_t) and forward that same pointer to host_ioctl.

Suggested change
va_list ap;
uintptr_t arg;
void *argp;
struct ifreq *ifr;
int i;
va_start(ap, request);
arg = va_arg(ap, uintptr_t);
va_end(ap);
argp = (void *)arg;
if (in_the_stack) {
return host_ioctl ? host_ioctl(fd, request, arg) : -1;
}
if (request == SIOCGIFINDEX || request == SIOCGIFHWADDR || request == SIOCGIFADDR) {
struct wolfip_fd_entry *entry = wolfip_entry_from_public(fd);
if (!entry) {
void *argp;
struct ifreq *ifr;
int i;
va_start(ap, request);
argp = va_arg(ap, void *);
va_end(ap);
if (in_the_stack) {
return host_ioctl ? host_ioctl(fd, request, argp) : -1;
}
if (request == SIOCGIFINDEX || request == SIOCGIFHWADDR || request == SIOCGIFADDR) {
struct wolfip_fd_entry *entry = wolfip_entry_from_public(fd);
if (!entry) {
return host_ioctl ? host_ioctl(fd, request, argp) : -1;

Copilot uses AI. Check for mistakes.
ret = wolfIP_sock_bind(IPSTACK, internal_fd,
(const struct wolfIP_sockaddr *)addr, addrlen);
}
if (ret < 0) {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

wolfIP APIs return negative error codes (e.g., -WOLFIP_EINVAL). Assigning errno = ret sets errno to a negative value. Set errno to -ret (positive) to match POSIX expectations.

Suggested change
if (ret < 0) {
errno = -ret;

Copilot uses AI. Check for mistakes.
Comment on lines +1541 to +1547
}
if (ret != -EAGAIN)
break;
if (nonblock) {
errno = EAGAIN;
pthread_mutex_unlock(&wolfIP_mutex);
return -1;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

This wrapper mixes host EAGAIN with wolfIP's -WOLFIP_EAGAIN and also assigns errno = ret (negative). Use wolfIP's return convention consistently: compare against -WOLFIP_EAGAIN and set errno to -ret when returning -1.

Copilot uses AI. Check for mistakes.
Comment on lines +1562 to +1564
} while (1);
errno = ret;
pthread_mutex_unlock(&wolfIP_mutex);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

This wrapper mixes host EAGAIN with wolfIP's -WOLFIP_EAGAIN and also assigns errno = ret (negative). Use wolfIP's return convention consistently: compare against -WOLFIP_EAGAIN and set errno to -ret when returning -1.

Copilot uses AI. Check for mistakes.
Comment on lines +6947 to +6955
while (desc) {
uint8_t *frame = p->txmem + desc->pos + sizeof(*desc);
unsigned int tx_if = p->if_idx;
if (tx_if >= s->if_count)
tx_if = 0;
if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, tx_if,
(struct wolfIP_eth_frame *)frame, desc->len) != 0) {
desc = fifo_next(&p->txbuf, desc);
continue;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The loop advances desc with fifo_next() when a packet is filtered, but later always removes the head element with fifo_pop(). If desc is not the head, this can send one packet while popping a different one (queue corruption / wrong packet dropped). Since fifo_pop() only pops the head, the safe options are to (a) process only the head (on filter reject: break;), or (b) explicitly drop the head on filter reject (pop it) rather than skipping ahead.

Suggested change
while (desc) {
uint8_t *frame = p->txmem + desc->pos + sizeof(*desc);
unsigned int tx_if = p->if_idx;
if (tx_if >= s->if_count)
tx_if = 0;
if (wolfIP_filter_notify_eth(WOLFIP_FILT_SENDING, s, tx_if,
(struct wolfIP_eth_frame *)frame, desc->len) != 0) {
desc = fifo_next(&p->txbuf, desc);
continue;
/* Drop filtered packet from the head of the FIFO. */
fifo_pop(&p->txbuf);
}
else {
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);
}

Copilot uses AI. Check for mistakes.
Comment on lines +6955 to +6957
continue;
}
{
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The loop advances desc with fifo_next() when a packet is filtered, but later always removes the head element with fifo_pop(). If desc is not the head, this can send one packet while popping a different one (queue corruption / wrong packet dropped). Since fifo_pop() only pops the head, the safe options are to (a) process only the head (on filter reject: break;), or (b) explicitly drop the head on filter reject (pop it) rather than skipping ahead.

Copilot uses AI. Check for mistakes.
if (!ps)
return -WOLFIP_EINVAL;
if (sll && addrlen && *addrlen < sizeof(struct wolfIP_sockaddr_ll))
return -WOLFIP_EINVAL;
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

Same issue as the raw socket path: returning plain -1 makes the error ambiguous for callers. Prefer a -WOLFIP_* error code consistent with other recv/send failures.

Suggested change
return -WOLFIP_EINVAL;
return -WOLFIP_EMSGSIZE;

Copilot uses AI. Check for mistakes.
Comment on lines +4756 to +4761
return 0;
}
return -WOLFIP_EINVAL;
}
#endif
#if WOLFIP_PACKET_SOCKETS
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

For packet sockets, setsockopt currently returns success for any option and even ignores optval/optlen. This can mask real caller errors and diverges from the raw/INET behavior (which returns -WOLFIP_EINVAL for unsupported options). If no options are supported yet, return -WOLFIP_EINVAL (or selectively implement supported options) and validate optval/optlen accordingly.

Suggested change
return 0;
}
return -WOLFIP_EINVAL;
}
#endif
#if WOLFIP_PACKET_SOCKETS
/* No socket options are currently supported for packet sockets.
* To avoid masking caller errors and to match raw/INET behavior,
* reject all setsockopt calls on packet sockets.
*/
(void)s;
return -WOLFIP_EINVAL;

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants