Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
37dd0247 TH |
2 | #ifndef __NET_GUE_H |
3 | #define __NET_GUE_H | |
4 | ||
5024c33a TH |
5 | /* Definitions for the GUE header, standard and private flags, lengths |
6 | * of optional fields are below. | |
7 | * | |
8 | * Diagram of GUE header: | |
9 | * | |
10 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
11 | * |Ver|C| Hlen | Proto/ctype | Standard flags |P| | |
12 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
13 | * | | | |
14 | * ~ Fields (optional) ~ | |
15 | * | | | |
16 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
17 | * | Private flags (optional, P bit is set) | | |
18 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
19 | * | | | |
20 | * ~ Private fields (optional) ~ | |
21 | * | | | |
22 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
23 | * | |
26ac10be | 24 | * C bit indicates control message when set, data message when unset. |
5024c33a TH |
25 | * For a control message, proto/ctype is interpreted as a type of |
26 | * control message. For data messages, proto/ctype is the IP protocol | |
27 | * of the next header. | |
28 | * | |
29 | * P bit indicates private flags field is present. The private flags | |
30 | * may refer to options placed after this field. | |
31 | */ | |
32 | ||
37dd0247 TH |
33 | struct guehdr { |
34 | union { | |
35 | struct { | |
36 | #if defined(__LITTLE_ENDIAN_BITFIELD) | |
5024c33a TH |
37 | __u8 hlen:5, |
38 | control:1, | |
39 | version:2; | |
37dd0247 | 40 | #elif defined (__BIG_ENDIAN_BITFIELD) |
5024c33a TH |
41 | __u8 version:2, |
42 | control:1, | |
43 | hlen:5; | |
37dd0247 TH |
44 | #else |
45 | #error "Please fix <asm/byteorder.h>" | |
46 | #endif | |
20080971 XL |
47 | __u8 proto_ctype; |
48 | __be16 flags; | |
37dd0247 | 49 | }; |
20080971 | 50 | __be32 word; |
37dd0247 TH |
51 | }; |
52 | }; | |
53 | ||
5024c33a TH |
54 | /* Standard flags in GUE header */ |
55 | ||
56 | #define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */ | |
57 | #define GUE_LEN_PRIV 4 | |
58 | ||
59 | #define GUE_FLAGS_ALL (GUE_FLAG_PRIV) | |
60 | ||
61 | /* Private flags in the private option extension */ | |
62 | ||
88405680 | 63 | #define GUE_PFLAG_REMCSUM htonl(1U << 31) |
c1aa8347 TH |
64 | #define GUE_PLEN_REMCSUM 4 |
65 | ||
66 | #define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM) | |
5024c33a TH |
67 | |
68 | /* Functions to compute options length corresponding to flags. | |
69 | * If we ever have a lot of flags this can be potentially be | |
70 | * converted to a more optimized algorithm (table lookup | |
71 | * for instance). | |
72 | */ | |
73 | static inline size_t guehdr_flags_len(__be16 flags) | |
74 | { | |
75 | return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0); | |
76 | } | |
77 | ||
78 | static inline size_t guehdr_priv_flags_len(__be32 flags) | |
79 | { | |
80 | return 0; | |
81 | } | |
82 | ||
83 | /* Validate standard and private flags. Returns non-zero (meaning invalid) | |
84 | * if there is an unknown standard or private flags, or the options length for | |
85 | * the flags exceeds the options length specific in hlen of the GUE header. | |
86 | */ | |
20080971 | 87 | static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen) |
5024c33a | 88 | { |
20080971 | 89 | __be16 flags = guehdr->flags; |
5024c33a | 90 | size_t len; |
5024c33a TH |
91 | |
92 | if (flags & ~GUE_FLAGS_ALL) | |
93 | return 1; | |
94 | ||
95 | len = guehdr_flags_len(flags); | |
96 | if (len > optlen) | |
97 | return 1; | |
98 | ||
99 | if (flags & GUE_FLAG_PRIV) { | |
100 | /* Private flags are last four bytes accounted in | |
101 | * guehdr_flags_len | |
102 | */ | |
20080971 XL |
103 | __be32 pflags = *(__be32 *)((void *)&guehdr[1] + |
104 | len - GUE_LEN_PRIV); | |
5024c33a | 105 | |
20080971 | 106 | if (pflags & ~GUE_PFLAGS_ALL) |
5024c33a TH |
107 | return 1; |
108 | ||
20080971 | 109 | len += guehdr_priv_flags_len(pflags); |
5024c33a TH |
110 | if (len > optlen) |
111 | return 1; | |
112 | } | |
113 | ||
114 | return 0; | |
115 | } | |
116 | ||
37dd0247 | 117 | #endif |