2014-10-04 02:48:09 +04:00
# ifndef __NET_GUE_H
# define __NET_GUE_H
2014-11-04 20:06:53 +03:00
/* 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 contol 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 .
*/
2014-10-04 02:48:09 +04:00
struct guehdr {
union {
struct {
# if defined(__LITTLE_ENDIAN_BITFIELD)
2014-11-04 20:06:53 +03:00
__u8 hlen : 5 ,
control : 1 ,
version : 2 ;
2014-10-04 02:48:09 +04:00
# elif defined (__BIG_ENDIAN_BITFIELD)
2014-11-04 20:06:53 +03:00
__u8 version : 2 ,
control : 1 ,
hlen : 5 ;
2014-10-04 02:48:09 +04:00
# else
# error "Please fix <asm / byteorder.h>"
# endif
2014-11-04 20:06:53 +03:00
__u8 proto_ctype ;
2014-10-04 02:48:09 +04:00
__u16 flags ;
} ;
__u32 word ;
} ;
} ;
2014-11-04 20:06:53 +03:00
/* 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 */
2014-11-04 20:06:55 +03:00
# define GUE_PFLAG_REMCSUM htonl(1 << 31)
# define GUE_PLEN_REMCSUM 4
# define GUE_PFLAGS_ALL (GUE_PFLAG_REMCSUM)
2014-11-04 20:06:53 +03:00
/* 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 )
{
size_t len ;
__be32 flags = guehdr - > flags ;
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
*/
flags = * ( __be32 * ) ( ( void * ) & guehdr [ 1 ] + len - GUE_LEN_PRIV ) ;
if ( flags & ~ GUE_PFLAGS_ALL )
return 1 ;
len + = guehdr_priv_flags_len ( flags ) ;
if ( len > optlen )
return 1 ;
}
return 0 ;
}
2014-10-04 02:48:09 +04:00
# endif