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