Something went wrong. Try again.
(I'm so sorry!) Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132/* SPDX-License-Identifier: GPL-2.0 */#ifndef __NET_GUE_H#define __NET_GUE_H
/* Definitions for the GUE header, standard and private flags, lengths * of optional fields are below. * * Diagram of GUE header: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Ver|C| Hlen | Proto/ctype | Standard flags |P| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * ~ Fields (optional) ~ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Private flags (optional, P bit is set) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * ~ Private fields (optional) ~ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * C bit indicates control message when set, data message when unset. * For a control message, proto/ctype is interpreted as a type of * control message. For data messages, proto/ctype is the IP protocol * of the next header. * * P bit indicates private flags field is present. The private flags * may refer to options placed after this field. */
#include <asm/byteorder.h>#include <linux/types.h>
struct guehdr { union { struct {#if defined(__LITTLE_ENDIAN_BITFIELD) __u8 hlen:5, control:1, version:2;#elif defined (__BIG_ENDIAN_BITFIELD) __u8 version:2, control:1, hlen:5;#else#error "Please fix <asm/byteorder.h>"#endif __u8 proto_ctype; __be16 flags; }; __be32 word; };};
/* Standard flags in GUE header */
#define GUE_FLAG_PRIV htons(1<<0) /* Private flags are in options */#define GUE_LEN_PRIV 4
#define GUE_FLAGS_ALL (GUE_FLAG_PRIV)
/* Private flags in the private option extension */
#define GUE_PFLAG_REMCSUM htonl(1U << 31)#define GUE_PLEN_REMCSUM 4
#define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM)
/* Functions to compute options length corresponding to flags. * If we ever have a lot of flags this can be potentially be * converted to a more optimized algorithm (table lookup * for instance). */static inline size_t guehdr_flags_len(__be16 flags){ return ((flags & GUE_FLAG_PRIV) ? GUE_LEN_PRIV : 0);}
static inline size_t guehdr_priv_flags_len(__be32 flags){ return (flags & GUE_PFLAG_REMCSUM) ? GUE_PLEN_REMCSUM : 0;}
/* Validate standard and private flags. Returns non-zero (meaning invalid) * if there is an unknown standard or private flags, if the options length for * the flags exceeds the options length specified in hlen of the GUE header, or * if a private option contains invalid data. */static inline int validate_gue_flags(struct guehdr *guehdr, size_t optlen){ __be16 flags = guehdr->flags; size_t len;
if (flags & ~GUE_FLAGS_ALL) return 1;
len = guehdr_flags_len(flags); if (len > optlen) return 1;
if (flags & GUE_FLAG_PRIV) { /* Private flags are last four bytes accounted in * guehdr_flags_len */ void *data = (void *)&guehdr[1] + len; __be32 pflags = *(__be32 *)(data - GUE_LEN_PRIV);
if (pflags & ~GUE_PFLAGS_ALL) return 1;
len += guehdr_priv_flags_len(pflags); if (len > optlen) return 1;
if (pflags & GUE_PFLAG_REMCSUM) { __be16 *pd = data;
/* The field offset pd[1] must not be less * than the start pd[0]. */ if (ntohs(pd[1]) < ntohs(pd[0])) return 1; } }
return 0;}
#endif