net: forward-port FreeBSD IPv6 stack with SLAAC and DHCPv6 autoconfiguration - #1442
net: forward-port FreeBSD IPv6 stack with SLAAC and DHCPv6 autoconfiguration#1442gburd wants to merge 38 commits into
Conversation
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-2-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-3-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-4-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-5-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-6-git-send-email-charles.myers@spirent.com>
classifier changed to object pointer instead of embedded in struct ifnet to reduce compile dependencies. There was also issue with including ip6.h in this file, but that could probably be fixed with struct ip6_hdr forward delcaration and including in6.h instead. Signed-off-by: Charles Myers <charles.myers@spirent.com> Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Message-Id: <1533610192-4019-7-git-send-email-charles.myers@spirent.com>
lltable_foreach(), lltable_foreach_lle() added to support NETLINK sockets Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-8-git-send-email-charles.myers@spirent.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-9-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-10-git-send-email-charles.myers@spirent.com>
Use AF_INET instead of AF_UNIX Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-11-git-send-email-charles.myers@spirent.com>
…socket libc code is from musl library with minor change to prevent partial reads if faster than sender. Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-12-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-13-git-send-email-charles.myers@spirent.com>
…ESTAMP l_size_t in linux.h was not correct size for 64-bit long Signed-off-by: Charles Myers <charles.myers@spirent.com> Message-Id: <1533610192-4019-14-git-send-email-charles.myers@spirent.com>
…ESTAMP Signed-off-by: Charles Myers <charles.myers@spirent.com> Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Message-Id: <1533610192-4019-16-git-send-email-charles.myers@spirent.com>
Signed-off-by: Charles Myers <charles.myers@spirent.com> Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com> Message-Id: <1533610192-4019-17-git-send-email-charles.myers@spirent.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
# Conflicts: # modules/tests/Makefile
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
# Conflicts: # modules/tests/Makefile
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
# Conflicts: # Makefile # modules/tests/Makefile
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
|
Follow-up (deliberately not in this PR): IPv6 inherits OSv's high-value fast paths — net channels ( Net effect: IPv6 is correct but computes checksums in software and doesn't get large-segment TSO, so high-throughput v6 sends/receives use more CPU than v4. This is a self-contained, driver-local performance follow-up (extend the TX/RX offload switch to |
Merge the upstream ipv6 branch (FreeBSD 9 netinet6 import + OSv glue) and add boot-time IPv6 autoconfiguration: - netinet6 stack (ip6, icmp6, nd6, in6_*, udp6, raw_ip6, mld6) behind conf-INET6 - OSv net-channel fast path, LRO, RCU classifier extended for IPv6/TCP - Linux socket-option compat for 43 IPV6_* options; getifaddrs/netlink v6 - SLAAC: kernel Router Solicitation (nd6_rs_output) + accept-RA per-interface flag fix so a unikernel (no rtsold) autoconfigures from Router Advertisements - DHCPv6 client (RFC 8415 stateful: SOLICIT/ADVERTISE/REQUEST/REPLY, DUID-LLT, IA_NA) triggered when the RA sets the Managed (M) flag, e.g. AWS VPC - loader picks SLAAC vs DHCPv6 from RA flags; --ipv6 for IPv6-only boot - all IPv6 code compile-gated (conf-INET6, conf_networking_dhcp6) - tests: tst-tcp-v6-smoke, tst-ipv6-internet, tst-ifaddr-dump
…r and DHCPv6 client Security hardening for the two network-reachable memory-safety issues in the new IPv6/DHCPv6 code (found in audit): 1. classify_ipv6_tcp() OOB read (core/net_channel.cc). ip6_lasthdr_nofrag only guarantees the base IPv6 header + extension headers fit; it did NOT guarantee a full TCP header is present and contiguous, yet the code then dereferenced tcp_hdr (th_flags at +13, ports at +0..3) on the lock-free RX fast path. A crafted IPv6/TCP frame (short, or with extension headers pushing the L4 offset toward the end, or split across a mergeable-buffer mbuf chain via GRO/jumbo) could read out of bounds in the driver softirq. Require nxt_off + sizeof(tcphdr) <= mh_len before touching the TCP header; otherwise fall through to the slow path (tcp_input), which pulls up. 2. DHCPv6 parse() OOB read across an mbuf chain (bsd/porting/dhcp6.cc). The option walk bounded off against pkthdr.len (whole chain) while reading via mtod (first mbuf only); udp6_input makes only the UDP header contiguous. A malicious on-link DHCPv6 server (DHCPv6 is unauthenticated; the client is auto-started on a Managed-flag RA) sending a >4 KiB reply on a jumbo/GRO link becomes an mbuf chain and the walk reads past the first mbuf. Clamp blen to the contiguous first-mbuf length (a well-formed reply is far smaller than one RX buffer). 3. DHCPv6 unbounded state growth (DoS). process_packet() parsed every packet even when BOUND, and parse() appended to _dns/_server_duid, so an on-link attacker who observed our SOLICIT xid could spray REPLYs and grow those without bound. Ignore packets outside SOLICITING/REQUESTING, and reset the per-reply learned state only after the xid matches (so a spoofed packet cannot wipe good state and repeated replies do not accumulate). Verified: IPv6 loopback + dual-stack TCP smoke still passes.
This branch predated the merges of the tgkill/rt_sigtimedwait (osv_sigtimedwait) and pthread_mutex_timedlock work; its diff vs master had begun to revert them (and delete tst-signal-fills.cc). Restore libc/signal.cc, libc/pthread.cc, linux.cc and tst-signal-fills.cc to master and re-add tst-signal-fills.so to the test list, so this branch touches only the IPv6 forward-port.
ad0615e to
b06d3df
Compare
|
Heads-up before merging: this branch was last synced against an older master (via a merge commit), so although GitHub reports it mergeable, its tree predates several tests that have since landed (tst-iovcnt-guard, tst-splice, tst-fs-syscalls, tst-membarrier, tst-mremap) and it still edits the |
This forward-ports the FreeBSD IPv6 stack to current OSv and adds the boot-time
autoconfiguration a unikernel needs (SLAAC and a DHCPv6 client), so an
IPv6-only or dual-stack application works out of the box. All IPv6 code is
compile-time gated so IPv6-less builds stay small.
What this does
netinet6sources (ip6, icmp6,nd6, in6_*, udp6, raw_ip6, mld6, frag6, dest6, route6, scope6) adapted for
OSv. 45 new files under
bsd/sys/netinet6/, plus the shared eth/tcp/udp codetaught about IPv6.
connection lookup are extended to IPv6/TCP so v6 gets the same in-kernel fast
path as v4 (mirrors the existing IPv4 optimizations).
IPV6_*socket options translated in theLinux compat layer (V6ONLY, PKTINFO, HOPLIMIT, TCLASS, MULTICAST_*,
JOIN/LEAVE_GROUP, etc.), plus
getifaddrs()/if_nameindex()over a NETLINKsocket and AAAA-aware
getaddrinfo.rtsold, so the kernel now sends its own RouterSolicitation (
nd6_rs_output) at interface bring-up and processes the RouterAdvertisement to form a global address. Also fixes an ordering bug where
ND6_IFF_ACCEPT_RTADVwas never set on interfaces that attached before theaccept-RA flag was enabled at boot.
(
bsd/porting/dhcp6.cc): SOLICIT/ADVERTISE/REQUEST/REPLY with DUID-LLT andIA_NA, plus Rapid Commit (two-message SOLICIT/REPLY). The loader chooses SLAAC
vs DHCPv6 from the RA flags: an Autonomous-prefix RA (radvd, QEMU SLIRP) uses
SLAAC, a Managed-flag RA (many enterprise/cloud networks) uses DHCPv6. Works
with standard servers (isc-dhcp, kea, dnsmasq).
--ipv6selects the IPv6-only boot path (skips theblocking DHCPv4 wait); static
--ip/--defaultgw/--nameserveralreadyaccept v6 addresses.
Compile-time gating
Everything is behind
conf-INET6(the FreeBSDINET6macro) and, for theDHCPv6 client,
conf_networking_dhcp6. Aconf-INET6=0build compiles andlinks with no IPv6 code and no dangling references (verified), saving ~2.7 MB.
The default remains
conf-INET6=1.Testing
tst-tcp-v6-smoke(new, no boost): IPv6 + IPv4 loopback TCP echo, concurrentdual-stack, and the socket-option/multicast/getaddrinfo API surface. Passes.
tst-ifaddr-dump(new): dumps interface addresses to observe SLAAC/DHCPv6.tst-ipv6-internet(new, manual): DNS AAAA + IPv6 TCP + HTTP to a real host.tst-tcp-v6,tst-pktinfo,tst-socket-timestampbuild and run.Validated on KVM/QEMU (SLIRP
ipv6=on→ SLAAC) and on a bare-metal host:server (SOLICIT with Rapid Commit → REPLY → address bound), confirming the
client is standards-compliant and not tied to any specific network.
Notes for review
OSv adaptation → net-channel → Linux compat → getifaddrs/netlink → tests) so
authorship is intact, with the SLAAC + DHCPv6 work as the final commit. Happy
to squash if preferred.
bsd/porting/(notcore/) because it needs theBSD-internal netinet6 headers, which cannot coexist with the musl/glibc
in6_addrthatboost::asiopulls in; the DNS setter is reached through asmall C-linkage shim in
libc/network/__dns.cc.