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 33struct guehdr { 34 union { 35 struct { 36#if defined(__LITTLE_ENDIAN_BITFIELD) 37 __u8 hlen:5, 38 control:1, 39 version:2; 40#elif defined (__BIG_ENDIAN_BITFIELD) 41 __u8 version:2, 42 control:1, 43 hlen:5; 44#else 45#error "Please fix <asm/byteorder.h>" 46#endif 47 __u8 proto_ctype; 48 __be16 flags; 49 }; 50 __be32 word; 51 }; 52}; 53 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 63#define GUE_PFLAG_REMCSUM htonl(1U << 31) 64#define GUE_PLEN_REMCSUM 4 65 66#define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM) 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 */ 73static inline size_t guehdr_flags_len(__be16 flags) 74{ 75 return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0); 76} 77 78static 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 */ 87static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen) 88{ 89 __be16 flags = guehdr->flags; 90 size_t len; 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 */ 103 __be32 pflags = *(__be32 *)((void *)&guehdr[1] + 104 len - GUE_LEN_PRIV); 105 106 if (pflags & ~GUE_PFLAGS_ALL) 107 return 1; 108 109 len += guehdr_priv_flags_len(pflags); 110 if (len > optlen) 111 return 1; 112 } 113 114 return 0; 115} 116 117#endif 118