mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 10:49:33 +00:00
![Pedro Ribeiro](/assets/img/avatar_default.png)
Problem observed: In IPv6, in the presence of multiple routers candidates to default gateway in one segment, each sending a different value of preference, the Linux hosts connected to the segment weren't selecting the right one in all the combinations possible of LOW/MEDIUM/HIGH preference. This patch changes two files: include/linux/icmpv6.h Get the "router_pref" bitfield in the right place (as RFC4191 says), named the bit left with this fix as "home_agent" (RFC3775 say that's his function) net/ipv6/ndisc.c Corrects the binary logic behind the updating of the router preference in the flags of the routing table Result: With this two fixes applied, the default route used by the system was to consistent with the rules mentioned in RFC4191 in case of changes in the value of preference in router advertisements Signed-off-by: Pedro Ribeiro <pribeiro@net.ipl.pt> Acked-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
198 lines
4.5 KiB
C
198 lines
4.5 KiB
C
#ifndef _LINUX_ICMPV6_H
|
|
#define _LINUX_ICMPV6_H
|
|
|
|
#include <asm/byteorder.h>
|
|
|
|
struct icmp6hdr {
|
|
|
|
__u8 icmp6_type;
|
|
__u8 icmp6_code;
|
|
__sum16 icmp6_cksum;
|
|
|
|
|
|
union {
|
|
__be32 un_data32[1];
|
|
__be16 un_data16[2];
|
|
__u8 un_data8[4];
|
|
|
|
struct icmpv6_echo {
|
|
__be16 identifier;
|
|
__be16 sequence;
|
|
} u_echo;
|
|
|
|
struct icmpv6_nd_advt {
|
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
|
__u32 reserved:5,
|
|
override:1,
|
|
solicited:1,
|
|
router:1,
|
|
reserved2:24;
|
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
|
__u32 router:1,
|
|
solicited:1,
|
|
override:1,
|
|
reserved:29;
|
|
#else
|
|
#error "Please fix <asm/byteorder.h>"
|
|
#endif
|
|
} u_nd_advt;
|
|
|
|
struct icmpv6_nd_ra {
|
|
__u8 hop_limit;
|
|
#if defined(__LITTLE_ENDIAN_BITFIELD)
|
|
__u8 reserved:3,
|
|
router_pref:2,
|
|
home_agent:1,
|
|
other:1,
|
|
managed:1;
|
|
|
|
#elif defined(__BIG_ENDIAN_BITFIELD)
|
|
__u8 managed:1,
|
|
other:1,
|
|
home_agent:1,
|
|
router_pref:2,
|
|
reserved:3;
|
|
#else
|
|
#error "Please fix <asm/byteorder.h>"
|
|
#endif
|
|
__be16 rt_lifetime;
|
|
} u_nd_ra;
|
|
|
|
} icmp6_dataun;
|
|
|
|
#define icmp6_identifier icmp6_dataun.u_echo.identifier
|
|
#define icmp6_sequence icmp6_dataun.u_echo.sequence
|
|
#define icmp6_pointer icmp6_dataun.un_data32[0]
|
|
#define icmp6_mtu icmp6_dataun.un_data32[0]
|
|
#define icmp6_unused icmp6_dataun.un_data32[0]
|
|
#define icmp6_maxdelay icmp6_dataun.un_data16[0]
|
|
#define icmp6_router icmp6_dataun.u_nd_advt.router
|
|
#define icmp6_solicited icmp6_dataun.u_nd_advt.solicited
|
|
#define icmp6_override icmp6_dataun.u_nd_advt.override
|
|
#define icmp6_ndiscreserved icmp6_dataun.u_nd_advt.reserved
|
|
#define icmp6_hop_limit icmp6_dataun.u_nd_ra.hop_limit
|
|
#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
|
|
#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
|
|
#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
|
|
#define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref
|
|
};
|
|
|
|
#ifdef __KERNEL__
|
|
#include <linux/skbuff.h>
|
|
|
|
static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb)
|
|
{
|
|
return (struct icmp6hdr *)skb_transport_header(skb);
|
|
}
|
|
#endif
|
|
|
|
#define ICMPV6_ROUTER_PREF_LOW 0x3
|
|
#define ICMPV6_ROUTER_PREF_MEDIUM 0x0
|
|
#define ICMPV6_ROUTER_PREF_HIGH 0x1
|
|
#define ICMPV6_ROUTER_PREF_INVALID 0x2
|
|
|
|
#define ICMPV6_DEST_UNREACH 1
|
|
#define ICMPV6_PKT_TOOBIG 2
|
|
#define ICMPV6_TIME_EXCEED 3
|
|
#define ICMPV6_PARAMPROB 4
|
|
|
|
#define ICMPV6_INFOMSG_MASK 0x80
|
|
|
|
#define ICMPV6_ECHO_REQUEST 128
|
|
#define ICMPV6_ECHO_REPLY 129
|
|
#define ICMPV6_MGM_QUERY 130
|
|
#define ICMPV6_MGM_REPORT 131
|
|
#define ICMPV6_MGM_REDUCTION 132
|
|
|
|
#define ICMPV6_NI_QUERY 139
|
|
#define ICMPV6_NI_REPLY 140
|
|
|
|
#define ICMPV6_MLD2_REPORT 143
|
|
|
|
#define ICMPV6_DHAAD_REQUEST 144
|
|
#define ICMPV6_DHAAD_REPLY 145
|
|
#define ICMPV6_MOBILE_PREFIX_SOL 146
|
|
#define ICMPV6_MOBILE_PREFIX_ADV 147
|
|
|
|
/*
|
|
* Codes for Destination Unreachable
|
|
*/
|
|
#define ICMPV6_NOROUTE 0
|
|
#define ICMPV6_ADM_PROHIBITED 1
|
|
#define ICMPV6_NOT_NEIGHBOUR 2
|
|
#define ICMPV6_ADDR_UNREACH 3
|
|
#define ICMPV6_PORT_UNREACH 4
|
|
|
|
/*
|
|
* Codes for Time Exceeded
|
|
*/
|
|
#define ICMPV6_EXC_HOPLIMIT 0
|
|
#define ICMPV6_EXC_FRAGTIME 1
|
|
|
|
/*
|
|
* Codes for Parameter Problem
|
|
*/
|
|
#define ICMPV6_HDR_FIELD 0
|
|
#define ICMPV6_UNK_NEXTHDR 1
|
|
#define ICMPV6_UNK_OPTION 2
|
|
|
|
/*
|
|
* constants for (set|get)sockopt
|
|
*/
|
|
|
|
#define ICMPV6_FILTER 1
|
|
|
|
/*
|
|
* ICMPV6 filter
|
|
*/
|
|
|
|
#define ICMPV6_FILTER_BLOCK 1
|
|
#define ICMPV6_FILTER_PASS 2
|
|
#define ICMPV6_FILTER_BLOCKOTHERS 3
|
|
#define ICMPV6_FILTER_PASSONLY 4
|
|
|
|
struct icmp6_filter {
|
|
__u32 data[8];
|
|
};
|
|
|
|
/*
|
|
* Definitions for MLDv2
|
|
*/
|
|
#define MLD2_MODE_IS_INCLUDE 1
|
|
#define MLD2_MODE_IS_EXCLUDE 2
|
|
#define MLD2_CHANGE_TO_INCLUDE 3
|
|
#define MLD2_CHANGE_TO_EXCLUDE 4
|
|
#define MLD2_ALLOW_NEW_SOURCES 5
|
|
#define MLD2_BLOCK_OLD_SOURCES 6
|
|
|
|
#define MLD2_ALL_MCR_INIT { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x16 } } }
|
|
|
|
#ifdef __KERNEL__
|
|
|
|
#include <linux/netdevice.h>
|
|
#include <linux/skbuff.h>
|
|
|
|
|
|
extern void icmpv6_send(struct sk_buff *skb,
|
|
int type, int code,
|
|
__u32 info,
|
|
struct net_device *dev);
|
|
|
|
extern int icmpv6_init(void);
|
|
extern int icmpv6_err_convert(int type, int code,
|
|
int *err);
|
|
extern void icmpv6_cleanup(void);
|
|
extern void icmpv6_param_prob(struct sk_buff *skb,
|
|
int code, int pos);
|
|
|
|
struct flowi;
|
|
struct in6_addr;
|
|
extern void icmpv6_flow_init(struct sock *sk,
|
|
struct flowi *fl,
|
|
u8 type,
|
|
const struct in6_addr *saddr,
|
|
const struct in6_addr *daddr,
|
|
int oif);
|
|
#endif
|
|
|
|
#endif
|