forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
117 lines
3.2 KiB
117 lines
3.2 KiB
/* 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. |
|
*/ |
|
|
|
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 0; |
|
} |
|
|
|
/* Validate standard and private flags. Returns non-zero (meaning invalid) |
|
* if there is an unknown standard or private flags, or the options length for |
|
* the flags exceeds the options length specific in hlen of the GUE header. |
|
*/ |
|
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 |
|
*/ |
|
__be32 pflags = *(__be32 *)((void *)&guehdr[1] + |
|
len - GUE_LEN_PRIV); |
|
|
|
if (pflags & ~GUE_PFLAGS_ALL) |
|
return 1; |
|
|
|
len += guehdr_priv_flags_len(pflags); |
|
if (len > optlen) |
|
return 1; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
#endif
|
|
|