Warning: This file is not a C or C++ file. It does not have highlighting.
1 | /* SPDX-License-Identifier: GPL-2.0 */ |
---|---|
2 | #ifndef __NET_GUE_H |
3 | #define __NET_GUE_H |
4 | |
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 | * |
24 | * C bit indicates control message when set, data message when unset. |
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 | |
33 | #include <asm/byteorder.h> |
34 | #include <linux/types.h> |
35 | |
36 | struct guehdr { |
37 | union { |
38 | struct { |
39 | #if defined(__LITTLE_ENDIAN_BITFIELD) |
40 | __u8 hlen:5, |
41 | control:1, |
42 | version:2; |
43 | #elif defined (__BIG_ENDIAN_BITFIELD) |
44 | __u8 version:2, |
45 | control:1, |
46 | hlen:5; |
47 | #else |
48 | #error "Please fix <asm/byteorder.h>" |
49 | #endif |
50 | __u8 proto_ctype; |
51 | __be16 flags; |
52 | }; |
53 | __be32 word; |
54 | }; |
55 | }; |
56 | |
57 | /* Standard flags in GUE header */ |
58 | |
59 | #define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */ |
60 | #define GUE_LEN_PRIV 4 |
61 | |
62 | #define GUE_FLAGS_ALL (GUE_FLAG_PRIV) |
63 | |
64 | /* Private flags in the private option extension */ |
65 | |
66 | #define GUE_PFLAG_REMCSUM htonl(1U << 31) |
67 | #define GUE_PLEN_REMCSUM 4 |
68 | |
69 | #define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM) |
70 | |
71 | /* Functions to compute options length corresponding to flags. |
72 | * If we ever have a lot of flags this can be potentially be |
73 | * converted to a more optimized algorithm (table lookup |
74 | * for instance). |
75 | */ |
76 | static inline size_t guehdr_flags_len(__be16 flags) |
77 | { |
78 | return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0); |
79 | } |
80 | |
81 | static inline size_t guehdr_priv_flags_len(__be32 flags) |
82 | { |
83 | return 0; |
84 | } |
85 | |
86 | /* Validate standard and private flags. Returns non-zero (meaning invalid) |
87 | * if there is an unknown standard or private flags, or the options length for |
88 | * the flags exceeds the options length specific in hlen of the GUE header. |
89 | */ |
90 | static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen) |
91 | { |
92 | __be16 flags = guehdr->flags; |
93 | size_t len; |
94 | |
95 | if (flags & ~GUE_FLAGS_ALL) |
96 | return 1; |
97 | |
98 | len = guehdr_flags_len(flags); |
99 | if (len > optlen) |
100 | return 1; |
101 | |
102 | if (flags & GUE_FLAG_PRIV) { |
103 | /* Private flags are last four bytes accounted in |
104 | * guehdr_flags_len |
105 | */ |
106 | __be32 pflags = *(__be32 *)((void *)&guehdr[1] + |
107 | len - GUE_LEN_PRIV); |
108 | |
109 | if (pflags & ~GUE_PFLAGS_ALL) |
110 | return 1; |
111 | |
112 | len += guehdr_priv_flags_len(pflags); |
113 | if (len > optlen) |
114 | return 1; |
115 | } |
116 | |
117 | return 0; |
118 | } |
119 | |
120 | #endif |
121 |
Warning: This file is not a C or C++ file. It does not have highlighting.