From 1c72073155386b17a3f29aa44961b45d10d57c03 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 16 May 2012 20:23:17 +0200 Subject: [PATCH] --- yaml --- r: 314696 b: refs/heads/master c: 0354440ba142eb9b6a03d287349350c1f75e5786 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/include/net/ip.h | 5 ++--- trunk/include/net/ip_fib.h | 3 +-- trunk/include/net/route.h | 1 + trunk/net/batman-adv/unicast.c | 29 ++++++++++++++------------ trunk/net/ipv4/fib_frontend.c | 38 +++++++--------------------------- trunk/net/ipv4/icmp.c | 6 ++---- trunk/net/ipv4/ip_options.c | 22 ++++++++++---------- trunk/net/ipv4/ip_output.c | 9 ++++---- trunk/net/ipv4/ip_sockglue.c | 7 +++---- trunk/net/ipv4/route.c | 38 ++++++++++++++++++++++++++-------- trunk/net/ipv4/tcp_ipv4.c | 8 +++---- trunk/net/ipv4/xfrm4_policy.c | 1 + 13 files changed, 82 insertions(+), 87 deletions(-) diff --git a/[refs] b/[refs] index e7f987078b59..7031af9edf5c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 41347dcdd81988b8e60853257b2875285cc17a4e +refs/heads/master: 0354440ba142eb9b6a03d287349350c1f75e5786 diff --git a/trunk/include/net/ip.h b/trunk/include/net/ip.h index ec5cfde85e9a..50841bd6f10e 100644 --- a/trunk/include/net/ip.h +++ b/trunk/include/net/ip.h @@ -158,9 +158,8 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; } -void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, - __be32 saddr, const struct ip_reply_arg *arg, - unsigned int len); +void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + const struct ip_reply_arg *arg, unsigned int len); struct ipv4_config { int log_martians; diff --git a/trunk/include/net/ip_fib.h b/trunk/include/net/ip_fib.h index 9e6c26d4ba4c..4b347c0ca094 100644 --- a/trunk/include/net/ip_fib.h +++ b/trunk/include/net/ip_fib.h @@ -230,10 +230,9 @@ extern struct fib_table *fib_get_table(struct net *net, u32 id); /* Exported by fib_frontend.c */ extern const struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); -extern __be32 fib_compute_spec_dst(struct sk_buff *skb); extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, - u32 *itag); + __be32 *spec_dst, u32 *itag); extern void fib_select_default(struct fib_result *res); /* Exported by fib_semantics.c */ diff --git a/trunk/include/net/route.h b/trunk/include/net/route.h index 211e2665139b..47eb25ac1f7f 100644 --- a/trunk/include/net/route.h +++ b/trunk/include/net/route.h @@ -65,6 +65,7 @@ struct rtable { __be32 rt_gateway; /* Miscellaneous cached information */ + __be32 rt_spec_dst; /* RFC1122 specific destination */ u32 rt_peer_genid; unsigned long _peer; /* long-living peer info */ struct fib_info *fi; /* for client ref to shared metrics */ diff --git a/trunk/net/batman-adv/unicast.c b/trunk/net/batman-adv/unicast.c index d021055ad262..472436a06d89 100644 --- a/trunk/net/batman-adv/unicast.c +++ b/trunk/net/batman-adv/unicast.c @@ -29,9 +29,10 @@ #include "hard-interface.h" -static struct sk_buff *frag_merge_packet(struct list_head *head, - struct frag_packet_list_entry *tfp, - struct sk_buff *skb) +static struct sk_buff * +batadv_frag_merge_packet(struct list_head *head, + struct frag_packet_list_entry *tfp, + struct sk_buff *skb) { struct unicast_frag_packet *up = (struct unicast_frag_packet *)skb->data; @@ -75,7 +76,8 @@ static struct sk_buff *frag_merge_packet(struct list_head *head, return NULL; } -static void frag_create_entry(struct list_head *head, struct sk_buff *skb) +static void batadv_frag_create_entry(struct list_head *head, + struct sk_buff *skb) { struct frag_packet_list_entry *tfp; struct unicast_frag_packet *up = @@ -91,7 +93,7 @@ static void frag_create_entry(struct list_head *head, struct sk_buff *skb) return; } -static int frag_create_buffer(struct list_head *head) +static int batadv_frag_create_buffer(struct list_head *head) { int i; struct frag_packet_list_entry *tfp; @@ -111,8 +113,9 @@ static int frag_create_buffer(struct list_head *head) return 0; } -static struct frag_packet_list_entry *frag_search_packet(struct list_head *head, - const struct unicast_frag_packet *up) +static struct frag_packet_list_entry * +batadv_frag_search_packet(struct list_head *head, + const struct unicast_frag_packet *up) { struct frag_packet_list_entry *tfp; struct unicast_frag_packet *tmp_up = NULL; @@ -188,22 +191,22 @@ int batadv_frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, orig_node->last_frag_packet = jiffies; if (list_empty(&orig_node->frag_list) && - frag_create_buffer(&orig_node->frag_list)) { + batadv_frag_create_buffer(&orig_node->frag_list)) { pr_debug("couldn't create frag buffer\n"); goto out; } - tmp_frag_entry = frag_search_packet(&orig_node->frag_list, - unicast_packet); + tmp_frag_entry = batadv_frag_search_packet(&orig_node->frag_list, + unicast_packet); if (!tmp_frag_entry) { - frag_create_entry(&orig_node->frag_list, skb); + batadv_frag_create_entry(&orig_node->frag_list, skb); ret = NET_RX_SUCCESS; goto out; } - *new_skb = frag_merge_packet(&orig_node->frag_list, tmp_frag_entry, - skb); + *new_skb = batadv_frag_merge_packet(&orig_node->frag_list, + tmp_frag_entry, skb); /* if not, merge failed */ if (*new_skb) ret = NET_RX_SUCCESS; diff --git a/trunk/net/ipv4/fib_frontend.c b/trunk/net/ipv4/fib_frontend.c index 63b11ca54d95..3854411fa37c 100644 --- a/trunk/net/ipv4/fib_frontend.c +++ b/trunk/net/ipv4/fib_frontend.c @@ -180,35 +180,6 @@ unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, } EXPORT_SYMBOL(inet_dev_addr_type); -__be32 fib_compute_spec_dst(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct in_device *in_dev; - struct fib_result res; - struct flowi4 fl4; - struct net *net; - - if (skb->pkt_type != PACKET_BROADCAST && - skb->pkt_type != PACKET_MULTICAST) - return ip_hdr(skb)->daddr; - - in_dev = __in_dev_get_rcu(dev); - BUG_ON(!in_dev); - fl4.flowi4_oif = 0; - fl4.flowi4_iif = 0; - fl4.daddr = ip_hdr(skb)->saddr; - fl4.saddr = ip_hdr(skb)->daddr; - fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); - fl4.flowi4_scope = RT_SCOPE_UNIVERSE; - fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; - - net = dev_net(dev); - if (!fib_lookup(net, &fl4, &res)) - return FIB_RES_PREFSRC(net, res); - else - return inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); -} - /* Given (packet source, input interface) and optional (dst, oif, tos): * - (main) check, that source is valid i.e. not broadcast or our local * address. @@ -218,7 +189,8 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) * called with rcu_read_lock() */ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, - int oif, struct net_device *dev, u32 *itag) + int oif, struct net_device *dev, __be32 *spec_dst, + u32 *itag) { struct in_device *in_dev; struct flowi4 fl4; @@ -257,6 +229,7 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, if (res.type != RTN_LOCAL || !accept_local) goto e_inval; } + *spec_dst = FIB_RES_PREFSRC(net, res); fib_combine_itag(itag, &res); dev_match = false; @@ -285,14 +258,17 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, ret = 0; if (fib_lookup(net, &fl4, &res) == 0) { - if (res.type == RTN_UNICAST) + if (res.type == RTN_UNICAST) { + *spec_dst = FIB_RES_PREFSRC(net, res); ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; + } } return ret; last_resort: if (rpf) goto e_rpf; + *spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); *itag = 0; return 0; diff --git a/trunk/net/ipv4/icmp.c b/trunk/net/ipv4/icmp.c index 4bce5a2830aa..49a74cc79dc8 100644 --- a/trunk/net/ipv4/icmp.c +++ b/trunk/net/ipv4/icmp.c @@ -95,7 +95,6 @@ #include #include #include -#include /* * Build xmit assembly blocks @@ -334,7 +333,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) struct flowi4 fl4; struct sock *sk; struct inet_sock *inet; - __be32 daddr, saddr; + __be32 daddr; if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb)) return; @@ -348,7 +347,6 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) inet->tos = ip_hdr(skb)->tos; daddr = ipc.addr = ip_hdr(skb)->saddr; - saddr = fib_compute_spec_dst(skb); ipc.opt = NULL; ipc.tx_flags = 0; if (icmp_param->replyopts.opt.opt.optlen) { @@ -358,7 +356,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) } memset(&fl4, 0, sizeof(fl4)); fl4.daddr = daddr; - fl4.saddr = saddr; + fl4.saddr = rt->rt_spec_dst; fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_proto = IPPROTO_ICMP; security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); diff --git a/trunk/net/ipv4/ip_options.c b/trunk/net/ipv4/ip_options.c index 766dfe56885a..708b99494e23 100644 --- a/trunk/net/ipv4/ip_options.c +++ b/trunk/net/ipv4/ip_options.c @@ -27,7 +27,6 @@ #include #include #include -#include /* * Write options to IP header, record destination address to @@ -105,7 +104,7 @@ int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb) sptr = skb_network_header(skb); dptr = dopt->__data; - daddr = fib_compute_spec_dst(skb); + daddr = skb_rtable(skb)->rt_spec_dst; if (sopt->rr) { optlen = sptr[sopt->rr+1]; @@ -251,14 +250,15 @@ void ip_options_fragment(struct sk_buff *skb) int ip_options_compile(struct net *net, struct ip_options *opt, struct sk_buff *skb) { - __be32 spec_dst = (__force __be32) 0; - unsigned char *pp_ptr = NULL; - unsigned char *optptr; + int l; unsigned char *iph; - int optlen, l; + unsigned char *optptr; + int optlen; + unsigned char *pp_ptr = NULL; + struct rtable *rt = NULL; if (skb != NULL) { - spec_dst = fib_compute_spec_dst(skb); + rt = skb_rtable(skb); optptr = (unsigned char *)&(ip_hdr(skb)[1]); } else optptr = opt->__data; @@ -330,8 +330,8 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 2; goto error; } - if (skb) { - memcpy(&optptr[optptr[2]-1], &spec_dst, 4); + if (rt) { + memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); opt->is_changed = 1; } optptr[2] += 4; @@ -372,8 +372,8 @@ int ip_options_compile(struct net *net, goto error; } opt->ts = optptr - iph; - if (skb) { - memcpy(&optptr[optptr[2]-1], &spec_dst, 4); + if (rt) { + memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); timeptr = &optptr[optptr[2]+3]; } opt->ts_needaddr = 1; diff --git a/trunk/net/ipv4/ip_output.c b/trunk/net/ipv4/ip_output.c index 2630900e480a..0f3185a662c3 100644 --- a/trunk/net/ipv4/ip_output.c +++ b/trunk/net/ipv4/ip_output.c @@ -1459,14 +1459,13 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, /* * Generic function to send a packet as reply to another packet. - * Used to send TCP resets so far. + * Used to send TCP resets so far. ICMP should use this function too. * * Should run single threaded per socket because it uses the sock * structure to pass arguments. */ -void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, - __be32 saddr, const struct ip_reply_arg *arg, - unsigned int len) +void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, + const struct ip_reply_arg *arg, unsigned int len) { struct inet_sock *inet = inet_sk(sk); struct ip_options_data replyopts; @@ -1492,7 +1491,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, RT_TOS(arg->tos), RT_SCOPE_UNIVERSE, sk->sk_protocol, ip_reply_arg_flowi_flags(arg), - daddr, saddr, + daddr, rt->rt_spec_dst, tcp_hdr(skb)->source, tcp_hdr(skb)->dest); security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); rt = ip_route_output_key(sock_net(sk), &fl4); diff --git a/trunk/net/ipv4/ip_sockglue.c b/trunk/net/ipv4/ip_sockglue.c index de29f46f68b0..0d11f234d615 100644 --- a/trunk/net/ipv4/ip_sockglue.c +++ b/trunk/net/ipv4/ip_sockglue.c @@ -40,7 +40,6 @@ #if IS_ENABLED(CONFIG_IPV6) #include #endif -#include #include #include @@ -1020,8 +1019,8 @@ static int do_ip_setsockopt(struct sock *sk, int level, * @sk: socket * @skb: buffer * - * To support IP_CMSG_PKTINFO option, we store rt_iif and specific - * destination in skb->cb[] before dst drop. + * To support IP_CMSG_PKTINFO option, we store rt_iif and rt_spec_dst + * in skb->cb[] before dst drop. * This way, receiver doesnt make cache line misses to read rtable. */ void ipv4_pktinfo_prepare(struct sk_buff *skb) @@ -1031,7 +1030,7 @@ void ipv4_pktinfo_prepare(struct sk_buff *skb) if (rt) { pktinfo->ipi_ifindex = rt->rt_iif; - pktinfo->ipi_spec_dst.s_addr = fib_compute_spec_dst(skb); + pktinfo->ipi_spec_dst.s_addr = rt->rt_spec_dst; } else { pktinfo->ipi_ifindex = 0; pktinfo->ipi_spec_dst.s_addr = 0; diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 83d56a016625..81533e3a23d1 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -440,7 +440,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) r->rt_key_tos, -1, HHUptod, - 0, &len); + r->rt_spec_dst, &len); seq_printf(seq, "%*s\n", 127 - len, ""); } @@ -1978,6 +1978,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, { unsigned int hash; struct rtable *rth; + __be32 spec_dst; struct in_device *in_dev = __in_dev_get_rcu(dev); u32 itag = 0; int err; @@ -1998,8 +1999,10 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (ipv4_is_zeronet(saddr)) { if (!ipv4_is_local_multicast(daddr)) goto e_inval; + spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); } else { - err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &itag); + err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, + &itag); if (err < 0) goto e_err; } @@ -2026,6 +2029,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, rth->rt_oif = 0; rth->rt_mark = skb->mark; rth->rt_gateway = daddr; + rth->rt_spec_dst= spec_dst; rth->rt_peer_genid = 0; rt_init_peer(rth, dev_net(dev)->ipv4.peers); rth->fi = NULL; @@ -2089,6 +2093,7 @@ static int __mkroute_input(struct sk_buff *skb, int err; struct in_device *out_dev; unsigned int flags = 0; + __be32 spec_dst; u32 itag; /* get a working reference to the output device */ @@ -2100,7 +2105,7 @@ static int __mkroute_input(struct sk_buff *skb, err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), - in_dev->dev, &itag); + in_dev->dev, &spec_dst, &itag); if (err < 0) { ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, saddr); @@ -2152,6 +2157,7 @@ static int __mkroute_input(struct sk_buff *skb, rth->rt_oif = 0; rth->rt_mark = skb->mark; rth->rt_gateway = daddr; + rth->rt_spec_dst= spec_dst; rth->rt_peer_genid = 0; rt_init_peer(rth, &res->table->tb_peers); rth->fi = NULL; @@ -2217,6 +2223,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, u32 itag = 0; struct rtable *rth; unsigned int hash; + __be32 spec_dst; int err = -EINVAL; struct net *net = dev_net(dev); @@ -2274,11 +2281,12 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (res.type == RTN_LOCAL) { err = fib_validate_source(skb, saddr, daddr, tos, net->loopback_dev->ifindex, - dev, &itag); + dev, &spec_dst, &itag); if (err < 0) goto martian_source_keep_err; if (err) flags |= RTCF_DIRECTSRC; + spec_dst = daddr; goto local_input; } @@ -2294,8 +2302,11 @@ out: return err; if (skb->protocol != htons(ETH_P_IP)) goto e_inval; - if (!ipv4_is_zeronet(saddr)) { - err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &itag); + if (ipv4_is_zeronet(saddr)) + spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); + else { + err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, + &itag); if (err < 0) goto martian_source_keep_err; if (err) @@ -2333,6 +2344,7 @@ out: return err; rth->rt_oif = 0; rth->rt_mark = skb->mark; rth->rt_gateway = daddr; + rth->rt_spec_dst= spec_dst; rth->rt_peer_genid = 0; rt_init_peer(rth, net->ipv4.peers); rth->fi = NULL; @@ -2350,6 +2362,7 @@ out: return err; no_route: RT_CACHE_STAT_INC(in_no_route); + spec_dst = inet_select_addr(dev, 0, RT_SCOPE_UNIVERSE); res.type = RTN_UNREACHABLE; if (err == -ESRCH) err = -ENETUNREACH; @@ -2532,6 +2545,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, rth->rt_oif = orig_oif; rth->rt_mark = fl4->flowi4_mark; rth->rt_gateway = fl4->daddr; + rth->rt_spec_dst= fl4->saddr; rth->rt_peer_genid = 0; rt_init_peer(rth, (res->table ? &res->table->tb_peers : @@ -2540,9 +2554,12 @@ static struct rtable *__mkroute_output(const struct fib_result *res, RT_CACHE_STAT_INC(out_slow_tot); - if (flags & RTCF_LOCAL) + if (flags & RTCF_LOCAL) { rth->dst.input = ip_local_deliver; + rth->rt_spec_dst = fl4->daddr; + } if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { + rth->rt_spec_dst = fl4->saddr; if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) { rth->dst.output = ip_mc_output; @@ -2873,6 +2890,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or rt->rt_dst = ort->rt_dst; rt->rt_src = ort->rt_src; rt->rt_gateway = ort->rt_gateway; + rt->rt_spec_dst = ort->rt_spec_dst; rt_transfer_peer(rt, ort); rt->fi = ort->fi; if (rt->fi) @@ -2947,8 +2965,10 @@ static int rt_fill_info(struct net *net, nla_put_u32(skb, RTA_FLOW, rt->dst.tclassid)) goto nla_put_failure; #endif - if (!rt_is_input_route(rt) && - rt->rt_src != rt->rt_key_src) { + if (rt_is_input_route(rt)) { + if (nla_put_be32(skb, RTA_PREFSRC, rt->rt_spec_dst)) + goto nla_put_failure; + } else if (rt->rt_src != rt->rt_key_src) { if (nla_put_be32(skb, RTA_PREFSRC, rt->rt_src)) goto nla_put_failure; } diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index 64568fa21d05..b4ae1c199f3e 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -698,8 +698,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) net = dev_net(skb_dst(skb)->dev); arg.tos = ip_hdr(skb)->tos; - ip_send_unicast_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, + &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); @@ -781,8 +781,8 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, if (oif) arg.bound_dev_if = oif; arg.tos = tos; - ip_send_unicast_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, &arg, arg.iov[0].iov_len); + ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, + &arg, arg.iov[0].iov_len); TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); } diff --git a/trunk/net/ipv4/xfrm4_policy.c b/trunk/net/ipv4/xfrm4_policy.c index 9815ea0bca7f..8855d8268552 100644 --- a/trunk/net/ipv4/xfrm4_policy.c +++ b/trunk/net/ipv4/xfrm4_policy.c @@ -100,6 +100,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, xdst->u.rt.rt_src = rt->rt_src; xdst->u.rt.rt_dst = rt->rt_dst; xdst->u.rt.rt_gateway = rt->rt_gateway; + xdst->u.rt.rt_spec_dst = rt->rt_spec_dst; return 0; }