.. | .. |
---|
16 | 16 | reserved_h:3; |
---|
17 | 17 | #endif |
---|
18 | 18 | __be32 lifetime; |
---|
19 | | - __u8 prefix[0]; /* 0,8 or 16 */ |
---|
| 19 | + __u8 prefix[]; /* 0,8 or 16 */ |
---|
20 | 20 | }; |
---|
21 | 21 | |
---|
22 | 22 | #include <net/addrconf.h> |
---|
.. | .. |
---|
27 | 27 | #include <linux/ip.h> |
---|
28 | 28 | #include <linux/ipv6.h> |
---|
29 | 29 | #include <linux/route.h> |
---|
| 30 | +#include <net/nexthop.h> |
---|
30 | 31 | |
---|
31 | 32 | #define RT6_LOOKUP_F_IFACE 0x00000001 |
---|
32 | 33 | #define RT6_LOOKUP_F_REACHABLE 0x00000002 |
---|
.. | .. |
---|
35 | 36 | #define RT6_LOOKUP_F_SRCPREF_PUBLIC 0x00000010 |
---|
36 | 37 | #define RT6_LOOKUP_F_SRCPREF_COA 0x00000020 |
---|
37 | 38 | #define RT6_LOOKUP_F_IGNORE_LINKSTATE 0x00000040 |
---|
| 39 | +#define RT6_LOOKUP_F_DST_NOREF 0x00000080 |
---|
38 | 40 | |
---|
39 | 41 | /* We do not (yet ?) support IPv6 jumbograms (RFC 2675) |
---|
40 | 42 | * Unlike IPv4, hdr->seg_len doesn't include the IPv6 header |
---|
.. | .. |
---|
66 | 68 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); |
---|
67 | 69 | } |
---|
68 | 70 | |
---|
| 71 | +/* fib entries using a nexthop object can not be coalesced into |
---|
| 72 | + * a multipath route |
---|
| 73 | + */ |
---|
69 | 74 | static inline bool rt6_qualify_for_ecmp(const struct fib6_info *f6i) |
---|
70 | 75 | { |
---|
71 | | - return (f6i->fib6_flags & (RTF_GATEWAY|RTF_ADDRCONF|RTF_DYNAMIC)) == |
---|
72 | | - RTF_GATEWAY; |
---|
| 76 | + /* the RTF_ADDRCONF flag filters out RA's */ |
---|
| 77 | + return !(f6i->fib6_flags & RTF_ADDRCONF) && !f6i->nh && |
---|
| 78 | + f6i->fib6_nh->fib_nh_gw_family; |
---|
73 | 79 | } |
---|
74 | 80 | |
---|
75 | 81 | void ip6_route_input(struct sk_buff *skb); |
---|
.. | .. |
---|
77 | 83 | struct net_device *dev, |
---|
78 | 84 | struct flowi6 *fl6, |
---|
79 | 85 | const struct sk_buff *skb, int flags); |
---|
| 86 | + |
---|
| 87 | +struct dst_entry *ip6_route_output_flags_noref(struct net *net, |
---|
| 88 | + const struct sock *sk, |
---|
| 89 | + struct flowi6 *fl6, int flags); |
---|
80 | 90 | |
---|
81 | 91 | struct dst_entry *ip6_route_output_flags(struct net *net, const struct sock *sk, |
---|
82 | 92 | struct flowi6 *fl6, int flags); |
---|
.. | .. |
---|
86 | 96 | struct flowi6 *fl6) |
---|
87 | 97 | { |
---|
88 | 98 | return ip6_route_output_flags(net, sk, fl6, 0); |
---|
| 99 | +} |
---|
| 100 | + |
---|
| 101 | +/* Only conditionally release dst if flags indicates |
---|
| 102 | + * !RT6_LOOKUP_F_DST_NOREF or dst is in uncached_list. |
---|
| 103 | + */ |
---|
| 104 | +static inline void ip6_rt_put_flags(struct rt6_info *rt, int flags) |
---|
| 105 | +{ |
---|
| 106 | + if (!(flags & RT6_LOOKUP_F_DST_NOREF) || |
---|
| 107 | + !list_empty(&rt->rt6i_uncached)) |
---|
| 108 | + ip6_rt_put(rt); |
---|
89 | 109 | } |
---|
90 | 110 | |
---|
91 | 111 | struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6, |
---|
.. | .. |
---|
98 | 118 | int ip6_route_init(void); |
---|
99 | 119 | void ip6_route_cleanup(void); |
---|
100 | 120 | |
---|
101 | | -int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg); |
---|
| 121 | +int ipv6_route_ioctl(struct net *net, unsigned int cmd, |
---|
| 122 | + struct in6_rtmsg *rtmsg); |
---|
102 | 123 | |
---|
103 | 124 | int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags, |
---|
104 | 125 | struct netlink_ext_ack *extack); |
---|
105 | 126 | int ip6_ins_rt(struct net *net, struct fib6_info *f6i); |
---|
106 | | -int ip6_del_rt(struct net *net, struct fib6_info *f6i); |
---|
| 127 | +int ip6_del_rt(struct net *net, struct fib6_info *f6i, bool skip_notify); |
---|
107 | 128 | |
---|
108 | 129 | void rt6_flush_exceptions(struct fib6_info *f6i); |
---|
109 | 130 | void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args, |
---|
.. | .. |
---|
165 | 186 | void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); |
---|
166 | 187 | void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark, |
---|
167 | 188 | kuid_t uid); |
---|
168 | | -void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, |
---|
169 | | - u32 mark); |
---|
| 189 | +void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif); |
---|
170 | 190 | void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); |
---|
171 | 191 | |
---|
172 | 192 | struct netlink_callback; |
---|
.. | .. |
---|
175 | 195 | struct sk_buff *skb; |
---|
176 | 196 | struct netlink_callback *cb; |
---|
177 | 197 | struct net *net; |
---|
| 198 | + struct fib_dump_filter filter; |
---|
178 | 199 | }; |
---|
179 | 200 | |
---|
180 | | -int rt6_dump_route(struct fib6_info *f6i, void *p_arg); |
---|
| 201 | +int rt6_dump_route(struct fib6_info *f6i, void *p_arg, unsigned int skip); |
---|
181 | 202 | void rt6_mtu_change(struct net_device *dev, unsigned int mtu); |
---|
182 | 203 | void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); |
---|
183 | 204 | void rt6_clean_tohost(struct net *net, struct in6_addr *gateway); |
---|
184 | | -void rt6_sync_up(struct net_device *dev, unsigned int nh_flags); |
---|
| 205 | +void rt6_sync_up(struct net_device *dev, unsigned char nh_flags); |
---|
185 | 206 | void rt6_disable_ip(struct net_device *dev, unsigned long event); |
---|
186 | 207 | void rt6_sync_down_dev(struct net_device *dev, unsigned long event); |
---|
187 | 208 | void rt6_multipath_rebalance(struct fib6_info *f6i); |
---|
.. | .. |
---|
269 | 290 | inet6_sk(sk)->pmtudisc == IPV6_PMTUDISC_OMIT; |
---|
270 | 291 | } |
---|
271 | 292 | |
---|
272 | | -static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt, |
---|
273 | | - struct in6_addr *daddr) |
---|
| 293 | +static inline const struct in6_addr *rt6_nexthop(const struct rt6_info *rt, |
---|
| 294 | + const struct in6_addr *daddr) |
---|
274 | 295 | { |
---|
275 | 296 | if (rt->rt6i_flags & RTF_GATEWAY) |
---|
276 | 297 | return &rt->rt6i_gateway; |
---|
.. | .. |
---|
282 | 303 | |
---|
283 | 304 | static inline bool rt6_duplicate_nexthop(struct fib6_info *a, struct fib6_info *b) |
---|
284 | 305 | { |
---|
285 | | - return a->fib6_nh.nh_dev == b->fib6_nh.nh_dev && |
---|
286 | | - ipv6_addr_equal(&a->fib6_nh.nh_gw, &b->fib6_nh.nh_gw) && |
---|
287 | | - !lwtunnel_cmp_encap(a->fib6_nh.nh_lwtstate, b->fib6_nh.nh_lwtstate); |
---|
| 306 | + struct fib6_nh *nha, *nhb; |
---|
| 307 | + |
---|
| 308 | + if (a->nh || b->nh) |
---|
| 309 | + return nexthop_cmp(a->nh, b->nh); |
---|
| 310 | + |
---|
| 311 | + nha = a->fib6_nh; |
---|
| 312 | + nhb = b->fib6_nh; |
---|
| 313 | + return nha->fib_nh_dev == nhb->fib_nh_dev && |
---|
| 314 | + ipv6_addr_equal(&nha->fib_nh_gw6, &nhb->fib_nh_gw6) && |
---|
| 315 | + !lwtunnel_cmp_encap(nha->fib_nh_lws, nhb->fib_nh_lws); |
---|
288 | 316 | } |
---|
289 | 317 | |
---|
290 | 318 | static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) |
---|
.. | .. |
---|
309 | 337 | return mtu - lwtunnel_headroom(dst->lwtstate, mtu); |
---|
310 | 338 | } |
---|
311 | 339 | |
---|
312 | | -u32 ip6_mtu_from_fib6(struct fib6_info *f6i, struct in6_addr *daddr, |
---|
313 | | - struct in6_addr *saddr); |
---|
| 340 | +u32 ip6_mtu_from_fib6(const struct fib6_result *res, |
---|
| 341 | + const struct in6_addr *daddr, |
---|
| 342 | + const struct in6_addr *saddr); |
---|
314 | 343 | |
---|
315 | 344 | struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw, |
---|
316 | 345 | struct net_device *dev, struct sk_buff *skb, |
---|