ICMP6(4)
π icmp6 β Internet Control Message Protocol for IPv6 π
okay bestie, so this is the icmp6(4) page from section 4 of the Kernel Interfaces Manual, and it's literally the whole vibe guide to ICMPv6 β the error-and-control-message protocol for IPv6. no cap, it's giving "networking's group chat for complaints and announcements" energy. let's get into it π«Ά
β¨ SYNOPSIS β¨
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
int
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
πΈ DESCRIPTION πΈ
ICMPv6 is the error and control message protocol used by IPv6 and the whole IPv6 protocol family (peep ip6(4) and inet6(4) for the lore). you can slide into it through a "raw socket" if you're doing network monitoring and diagnostic functions. it's the main character of diagnostics, periodt. π
the proto parameter you pass to the socket(2) call to create an ICMPv6 socket? you can get it from getprotobyname(3). ICMPv6 sockets are connectionless, and they're normally used with sendto(2) and recvfrom(2) calls β though the connect(2) call can also be used to lock in the destination for future packets. and if you do that? then read(2) or recv(2), plus write(2) or send(2) system calls, are totally allowed too. choose your own adventure bestie β¨
outgoing packets automatically get an IPv6 header prepended to them (based on the destination address). incoming packets on the socket arrive with the IPv6 header and any extension headers already removed. so clean, so efficient, we love her π
π¦ Types π¦
ICMPv6 messages get sorted by the type and code fields hanging out in the ICMPv6 header. the abbreviations for the types and codes can be used in rules in pf.conf(5) β iykyk. here are the types that are defined:
1βunreachβ Destination unreachable2βtoobigβ Packet too big3βtimexβ Time exceeded4βparamprobβ Invalid IPv6 header128βechoreqβ Echo service request129βechorepβ Echo service reply130βgroupqryβ Group membership query130βlistqryβ Multicast listener query131βgrouprepβ Group membership report131βlistenrepβ Multicast listener report132βgrouptermβ Group membership termination132βlistendoneβ Multicast listener done133βroutersolβ Router solicitation134βrouteradvβ Router advertisement135βneighbrsolβ Neighbor solicitation136βneighbradvβ Neighbor advertisement137βredirβ Shorter route exists138βroutrrenumβ Route renumbering139βfqdnreqβ FQDN query139βniqryβ Node information query139βwrureqβ Who-are-you request140βfqdnrepβ FQDN reply140βnirepβ Node information reply140βwrurepβ Who-are-you reply200βmtracerespβ mtrace response201βmtraceβ mtrace messages
and here are the codes that are defined (with their type, obvi):
0βnoroute-unrβ typeunreachβ No route to destination1βadmin-unrβ typeunreachβ Administratively prohibited2βbeyond-unrβ typeunreachβ Beyond scope of source address2βnotnbr-unrβ typeunreachβ Not a neighbor (obsolete)3βaddr-unrβ typeunreachβ Address unreachable4βport-unrβ typeunreachβ Port unreachable0βtransitβ typetimexβ Time exceeded in transit1βreassembβ typetimexβ Time exceeded in reassembly0βbadheadβ typeparamprobβ Erroneous header field1βnxthdrβ typeparamprobβ Unrecognized next header2β (no abbrev, she's mysterious) β typeredirβ Unrecognized option0βredironlinkβ typeredirβ Redirection to on-link node1βredirrouterβ typeredirβ Redirection to better router
π Headers π
all ICMPv6 messages get prefixed with an ICMPv6 header. this header matches the icmp6_hdr structure and it looks exactly like this, bestie:
struct icmp6_hdr {
uint8_t icmp6_type; /* type field */
uint8_t icmp6_code; /* code field */
uint16_t icmp6_cksum; /* checksum field */
union {
uint32_t icmp6_un_data32[1]; /* type-specific */
uint16_t icmp6_un_data16[2]; /* type-specific */
uint8_t icmp6_un_data8[4]; /* type-specific */
} icmp6_dataun;
} __packed;
#define icmp6_data32 icmp6_dataun.icmp6_un_data32
#define icmp6_data16 icmp6_dataun.icmp6_un_data16
#define icmp6_data8 icmp6_dataun.icmp6_un_data8
#define icmp6_pptr icmp6_data32[0] /* parameter prob */
#define icmp6_mtu icmp6_data32[0] /* packet too big */
#define icmp6_id icmp6_data16[0] /* echo request/reply */
#define icmp6_seq icmp6_data16[1] /* echo request/reply */
#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership*/
so icmp6_type describes the type of the message, and the suitable values are defined in β¨netinet/icmp6.hβ©. icmp6_code describes the sub-type of the message and it depends on icmp6_type (they're a package deal, fr). icmp6_cksum holds the checksum for the message and it gets filled in by the kernel on outgoing messages β the kernel does that for you, no need to stress π. the other fields are used for type-specific purposes.
π Filters π
because ICMPv6 has so much extra functionality compared to ICMPv4, a larger number of messages may potentially be received on an ICMPv6 socket. so input filters are the move β they restrict input to a subset of the incoming ICMPv6 messages so that only the interesting ones get returned by the recv(2) family of calls to an application. vibe check: only the messages you asked for make it through.
the icmp6_filter structure can be used to refine the input message set according to the ICMPv6 type. by default, all message types are allowed on newly created raw ICMPv6 sockets. these macros are available to refine the input set:
void ICMP6_FILTER_SETPASSALL(struct icmp6_filter *filterp)β allow all incoming messages.filterpis modified to allow all message types.void ICMP6_FILTER_SETBLOCKALL(struct icmp6_filter *filterp)β ignore all incoming messages.filterpis modified to ignore all message types.void ICMP6_FILTER_SETPASS(int type, struct icmp6_filter *filterp)β allow ICMPv6 messages with the given type.filterpis modified to allow such messages.void ICMP6_FILTER_SETBLOCK(int type, struct icmp6_filter *filterp)β ignore ICMPv6 messages with the given type.filterpis modified to ignore such messages.int ICMP6_FILTER_WILLPASS(int type, const struct icmp6_filter *filterp)β determine if the given filter will allow an ICMPv6 message of the given type.int ICMP6_FILTER_WILLBLOCK(int type, const struct icmp6_filter *filterp)β determine if the given filter will ignore an ICMPv6 message of the given type.
the getsockopt(2) and setsockopt(2) calls may be used to obtain and install the filter on ICMPv6 sockets β at option level IPPROTO_ICMPV6 and name ICMP6_FILTER, with a pointer to the icmp6_filter structure as the option value. that's the whole recipe, slay. β¨
π SEE ALSO π
W. Stevens and M. Thomas, Advanced Sockets API for IPv6, RFC 2292, February 1998.
A. Conta and S. Deering, Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification, RFC 2463, December 1998.
okay that's the whole page bestie, you ate it π
this one came from Debian, dated November 7, 2012, and it lives in the manual as ICMP6(4). go forth and diagnose, you iconic network gremlin π¦π
π¦ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 Β· BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 1986, 1991, 1993 The Regents of the University of California. All rights reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms