Skip to content

RFC 2292 struct and constant definitions#4954

Open
Skyb0rg007 wants to merge 2 commits intorust-lang:mainfrom
Skyb0rg007:icmpv6-filters
Open

RFC 2292 struct and constant definitions#4954
Skyb0rg007 wants to merge 2 commits intorust-lang:mainfrom
Skyb0rg007:icmpv6-filters

Conversation

@Skyb0rg007
Copy link
Copy Markdown

@Skyb0rg007 Skyb0rg007 commented Jan 30, 2026

Description

This PR adds the structs and constants as defined by RFC 2292 - Advanced Sockets API for IPv6.
These constants are available for use in get/setsockopt on supported Unix platforms.
The operations defined on the icmp6_filter struct are defined as C macros, so the implementations are not included here.

Sources

https://github.com/bminor/glibc/blob/04e750e75b73957cf1c791535a3f4319534a52fc/inet/netinet/icmp6.h
https://github.com/kraj/musl/blob/kraj/master/include/netinet/icmp6.h
https://github.com/freebsd/freebsd-src/blob/9ae367d11de8abbdf53884836c9ba30908c5c8db/sys/netinet/icmp6.h

Also in the RFC: https://datatracker.ietf.org/doc/html/rfc2292#section-3.2

Checklist

Unfortunately I could not get the libc-tests working locally, so this PR is marked as draft.

  • Relevant tests in libc-test/semver have been updated
  • No placeholder or unstable values like *LAST or *MAX are
    included (see #3131)
  • Tested locally (cd libc-test && cargo test --target mytarget);
    especially relevant for platforms that may not be checked in CI

@rustbot label +stable-nominated

@rustbot rustbot added the stable-nominated This PR should be considered for cherry-pick to libc's stable release branch label Jan 30, 2026
@Skyb0rg007 Skyb0rg007 force-pushed the icmpv6-filters branch 15 times, most recently from b8f20e4 to 16f3cea Compare February 3, 2026 20:32
@Skyb0rg007
Copy link
Copy Markdown
Author

Alright, I need help. On *BSD platforms (FreeBSD, macOS, etc), struct in6_addr is defined as the union of uint32_t[4], uint16_t[8], and uint8_t[16], so Rust encodes it as [u8; 16] with repr(align(4)).

But the nd_(router|neighbor)_(solicit|advert) structures are marked as __packed (so their C alignment is 1), even though they include a in6_addr. Rust won't allow using repr(packed) on a struct containing a repr(align(...)) attribute, so I'm stuck.

Linux doesn't mark these structs as __packed, so there's no issue there.

@Skyb0rg007 Skyb0rg007 force-pushed the icmpv6-filters branch 13 times, most recently from 742cf17 to 6d97ed6 Compare February 4, 2026 20:49
@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@Skyb0rg007 Skyb0rg007 force-pushed the icmpv6-filters branch 2 times, most recently from 8700997 to 7f5c749 Compare February 18, 2026 21:25
@Skyb0rg007
Copy link
Copy Markdown
Author

I see that some C macros such as the CMSG_ macros were added this package as const functions. It may make sense to add the ICMP6_FILTER_ macros too, especially since the icmp6_filter struct’s field name is different on Solaris.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

@rustbot

This comment has been minimized.

This PR adds the icmp6_filter struct and constants as defined
by RFC 2292 - Advanced Sockets API for IPv6.
These constants are available for use in get/setsockopt
on supported Unix platforms.
The operations defined on the icmp6_filter struct are defined
as C macros, so the implementations are not included here.
See the RFC for definitions and use.
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Mar 26, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

Copy link
Copy Markdown
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

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

Sorry for the delay, thank you for the changes here. The contents themselves look good, but I think they should be moved out of the root unix module.

View changes since this review

Comment thread src/unix/mod.rs
Comment on lines +256 to +259
#[cfg(not(any(target_os = "linux", target_os = "emscripten")))]
pub ip6r0_reserved: u32,
#[cfg(any(target_os = "linux", target_os = "emscripten"))]
pub ip6r0_reserved: u8,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

For any reserved/padding fields, please make them private and wrap them in Padding

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Because these fields are part of a networking protocol, I don't think it makes sense to make these private. These fields were certainly just padding when the protocol was written, but in theory a new version of the IPv6 routing header could make use of these fields.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is there any use reading/writing them currently? My concern here is that if they do wind up being used, the fields may go through changes in C that we can't really mirror on the Rust side. E.g. they could rename the fields, possibly with a shim like #define ip6r0_new_nice_field_name ip6r0_reserved, or do something like split the u32 field into two u16s which is fine in C but breaking in Rust.

Open to thoughts but I'd rather err on the side of caution and make them private unless they're useful now.

Comment thread src/unix/mod.rs Outdated
Comment on lines +284 to +287
#[cfg(not(target_os = "solaris"))]
pub icmp6_filt: [u32; 8],
#[cfg(target_os = "solaris")]
pub __icmp6_filt: [u32; 8],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This struct should be opaque, can you make the fields private?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The macros ICMP6_FILTER_SET(PASS|BLOCK)(ALL)? need to be defined for this type. Is the best way to handle this to make the fields pub (crate) and implement those macros as toplevel Rust functions?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like you may have started work here, but that seems reasonable to me.

Comment thread src/unix/mod.rs
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think enabling these in the unix module is too high level; do we know anything about AIX, fuchsia, redox, etc?

Instead, could you put these into the linux_like and bsd modules? That will mean some duplication, but that's probably fine because it will simplify some of the repetitive padding config.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What would be ideal here is to instead put these in src/new/common/bsd/{icmp6.rs,ip6.rs} and src/new/common/linux_like/{icmp6.rs,ip6.rs}, to match the header structure. The reexport them in src/new/{bionic_libc,musl,glibc,openbsd,freebsd,...}/{icmp6.rs,ip6.rs}, similar to what is done with unistd, and update src/new/mod.rs.

I won't require that because this has already been waiting a while, but eventually everything will move to that new structure so anything to help that is appreciated.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'm not sure about AIX, but Fuchsia does support icmp6_filter and RedoxOS (relibc) does not, at least for now.

I can try refactoring the code into those two files, but a lot of the differences with respect to alignment doesn't have a clean linux/bsd divide with android's implementation being more similar to that of the BSDs.
We might want to come up with a solution to the problem I remarked on here before I add definitions of these structs, because any solution will possibly change the public API for these structs anyways.

Also, I'm fine with a more major structural change to properly model the addition.
I have some more additions from RFC 3542 (the follow-on to 2292) which I plan to make a PR for after this is accepted. It just happens that the feature I was personally missing from libc was specified in the first Advanced IPv6 Sockets API RFC.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's okay to omit Fuchsia and others that aren't covered in CI for now. If a need comes up then usually one of their target maintainers does the addition, which also means they can run tests.

Could you split to BSD and Linux-like, then add a cfg(not(target_os = "android")) to the Linux version? I think that would still be cleaner.

Also, I'm fine with a more major structural change to properly model the addition. I have some more additions from RFC 3542 (the follow-on to 2292) which I plan to make a PR for after this is accepted. It just happens that the feature I was personally missing from libc was specified in the first Advanced IPv6 Sockets API RFC.

If you have more followups here then using the new structure might be nice, it's certainly more organized than the status quo. Up to you.

Comment thread src/unix/mod.rs
Comment on lines +240 to +250
#[cfg_attr(
any(
target_os = "android",
target_os = "freebsd",
target_os = "openbsd",
target_os = "dragonfly",
target_os = "macos"
),
repr(packed)
)]
#[cfg_attr(any(target_os = "linux", target_os = "emscripten"), repr(align(4)))]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could you add links to the PR description to the headers for these other platforms that have the specific alignment requirements? (Looks like only glibc/musl/freebsd are there)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Do you mean link to this PR, or directly link to the glibc/freebsd headers in the comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just in the PR description, and at least for the tier 2 targets (Android, emscripten, MacOS). I'm just looking for something to compare the aligned/packed/etc config against.

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 1, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

This allows the icmp6_filter struct's fields
to become private.
@Skyb0rg007
Copy link
Copy Markdown
Author

After adding the ICMP_FILTER_ functions, I realize that the meaning of a set bit is different between Linux and BSD. I’m going to split that code out into a new PR since I think it’s going to be a decent effort to get tests written for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author stable-nominated This PR should be considered for cherry-pick to libc's stable release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants