| .. | .. |
|---|
| 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, |
|---|