History

icmp: support rfc 4884

Add setsockopt SOL_IP/IP_RECVERR_4884 to return the offset to an extension struct if present. ICMP messages may include an extension structure after the original datagram. RFC 4884 standardized this behavior. It stores the offset in words to the extension header in u8 icmphdr.un.reserved[1]. The field is valid only for ICMP types destination unreachable, time exceeded and parameter problem, if length is at least 128 bytes and entire packet does not exceed 576 bytes. Return the offset to the start of the extension struct when reading an ICMP error from the error queue, if it matches the above constraints. Do not return the raw u8 field. Return the offset from the start of the user buffer, in bytes. The kernel does not return the network and transport headers, so subtract those. Also validate the headers. Return the offset regardless of validation, as an invalid extension must still not be misinterpreted as part of the original datagram. Note that !invalid does not imply valid. If the extension version does not match, no validation can take place, for instance. For backward compatibility, make this optional, set by setsockopt SOL_IP/IP_RECVERR_RFC4884. For API example and feature test, see github.com/wdebruij/kerneltools/blob/master/tests/recv_icmp_v2.c For forward compatibility, reserve only setsockopt value 1, leaving other bits for additional icmp extensions. Changes v1->v2: - convert word offset to byte offset from start of user buffer - return in ee_data as u8 may be insufficient - define extension struct and object header structs - return len only if constraints met - if returning len, also validate

Willem de Bruijn committed 6 years ago

Commit eba75c51 parent 930bc4c7 files · +124 −1Browse files

Showing the changes to include/uapi/linux (3 of 7 files). Show all

Unified · Split

3 files
  1. include/uapi/linux/errqueue.h +13 −1
  2. include/uapi/linux/icmp.h +22 −0
  3. include/uapi/linux/in.h +1 −0
include/uapi/linux/errqueue.h+13−1
@@ -5,6 +5,13 @@ · 4 unmodified lines
5#include <linux/types.h>5#include <linux/types.h>
6#include <linux/time_types.h>6#include <linux/time_types.h>
7 7
8/* RFC 4884: return offset to extension struct + validation */
9struct sock_ee_data_rfc4884 {
10 __u16 len;
11 __u8 flags;
12 __u8 reserved;
13};
14
8struct sock_extended_err {15struct sock_extended_err {
9 __u32 ee_errno; 16 __u32 ee_errno;
10 __u8 ee_origin;17 __u8 ee_origin;
@@ -12,7 +19,10 @@ struct sock_extended_err { · 1 unmodified line
12 __u8 ee_code;19 __u8 ee_code;
13 __u8 ee_pad;20 __u8 ee_pad;
14 __u32 ee_info;21 __u32 ee_info;
15 __u32 ee_data;22 union {
23 __u32 ee_data;
24 struct sock_ee_data_rfc4884 ee_rfc4884;
25 };
16};26};
17 27
18#define SO_EE_ORIGIN_NONE 028#define SO_EE_ORIGIN_NONE 0
@@ -31,6 +41,8 @@ struct sock_extended_err { · 12 unmodified lines
31#define SO_EE_CODE_TXTIME_INVALID_PARAM 141#define SO_EE_CODE_TXTIME_INVALID_PARAM 1
32#define SO_EE_CODE_TXTIME_MISSED 242#define SO_EE_CODE_TXTIME_MISSED 2
33 43
44#define SO_EE_RFC4884_FLAG_INVALID 1
45
34/**46/**
35 * struct scm_timestamping - timestamps exposed through cmsg47 * struct scm_timestamping - timestamps exposed through cmsg
36 *48 *
include/uapi/linux/icmp.h+22−0
@@ -19,6 +19,7 @@ · 18 unmodified lines
19#define _UAPI_LINUX_ICMP_H19#define _UAPI_LINUX_ICMP_H
20 20
21#include <linux/types.h>21#include <linux/types.h>
22#include <asm/byteorder.h>
22 23
23#define ICMP_ECHOREPLY 0 /* Echo Reply */24#define ICMP_ECHOREPLY 0 /* Echo Reply */
24#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */25#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */
@@ -95,5 +96,26 @@ struct icmp_filter { · 70 unmodified lines
95 __u32 data;96 __u32 data;
96};97};
97 98
99/* RFC 4884 extension struct: one per message */
100struct icmp_ext_hdr {
101#if defined(__LITTLE_ENDIAN_BITFIELD)
102 __u8 reserved1:4,
103 version:4;
104#elif defined(__BIG_ENDIAN_BITFIELD)
105 __u8 version:4,
106 reserved1:4;
107#else
108#error "Please fix <asm/byteorder.h>"
109#endif
110 __u8 reserved2;
111 __sum16 checksum;
112};
113
114/* RFC 4884 extension object header: one for each object */
115struct icmp_extobj_hdr {
116 __be16 length;
117 __u8 class_num;
118 __u8 class_type;
119};
98 120
99#endif /* _UAPI_LINUX_ICMP_H */121#endif /* _UAPI_LINUX_ICMP_H */
include/uapi/linux/in.h+1−0
@@ -123,6 +123,7 @@ struct in_addr { · 122 unmodified lines
123#define IP_CHECKSUM 23123#define IP_CHECKSUM 23
124#define IP_BIND_ADDRESS_NO_PORT 24124#define IP_BIND_ADDRESS_NO_PORT 24
125#define IP_RECVFRAGSIZE 25125#define IP_RECVFRAGSIZE 25
126#define IP_RECVERR_RFC4884 26
126 127
127/* IP_MTU_DISCOVER values */128/* IP_MTU_DISCOVER values */
128#define IP_PMTUDISC_DONT 0 /* Never send DF frames */129#define IP_PMTUDISC_DONT 0 /* Never send DF frames */