Subject: [PATCH] nethost ipv4: make flow.iff significant in ip_route_output_key and ip_route_output_flow From: Eric W. Biederman Date: 1134314887 -0700 For forwarding purposed iff remains 0. For connections to userspace iff gets set to the interface index of the loopback device. This information is needed for purposes of properly routing to localhost and for purposes of selecting the source address when none is specified. --- drivers/net/bonding/bond_main.c | 1 + include/net/route.h | 2 +- net/atm/clip.c | 4 ++-- net/bridge/br_netfilter.c | 4 ++-- net/dccp/ipv4.c | 3 ++- net/ipv4/af_inet.c | 1 + net/ipv4/arp.c | 17 +++++++++-------- net/ipv4/icmp.c | 8 +++++--- net/ipv4/igmp.c | 15 +++++++++------ net/ipv4/inet_connection_sock.c | 3 ++- net/ipv4/ip_gre.c | 11 ++++++++--- net/ipv4/ip_output.c | 8 +++++--- net/ipv4/ipip.c | 8 ++++++-- net/ipv4/ipmr.c | 10 ++++++---- net/ipv4/ipvs/ip_vs_xmit.c | 3 +++ net/ipv4/netfilter.c | 6 ++++-- net/ipv4/netfilter/ip_nat_rule.c | 2 +- net/ipv4/netfilter/ipt_REJECT.c | 2 ++ net/ipv4/raw.c | 3 ++- net/ipv4/route.c | 24 ++++++------------------ net/ipv4/syncookies.c | 5 +++-- net/ipv4/udp.c | 3 ++- net/ipv6/sit.c | 10 ++++++---- net/sctp/protocol.c | 1 + 24 files changed, 89 insertions(+), 65 deletions(-) bd0b740257f724e58565156b65e7056d60dc90bb diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f264ff1..f77d742 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2744,6 +2744,7 @@ static void bond_arp_send_all(struct bon * can tag the ARP with the proper VLAN tag. */ memset(&fl, 0, sizeof(fl)); + fl.iff = 0; fl.fl4_dst = targets[i]; fl.fl4_tos = RTO_ONLINK; diff --git a/include/net/route.h b/include/net/route.h index 1271713..e826eae 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -115,7 +115,7 @@ extern void ip_rt_redirect(u32 old_gw, extern void ip_rt_advice(struct rtable **rp, int advice); extern void rt_cache_flush(int how); extern int __ip_route_output_key(struct rtable **, const struct flowi *flp); -extern int ip_route_output_key(struct nethost *host, struct rtable **, struct flowi *flp); +extern int ip_route_output_key(struct rtable **, struct flowi *flp); extern int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); extern int ip_route_input(struct sk_buff*, u32 dst, u32 src, u8 tos, struct net_device *devin); extern unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu); diff --git a/net/atm/clip.c b/net/atm/clip.c index 039436e..87263d5 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -520,7 +520,7 @@ static int clip_setentry(struct atm_vcc struct atmarp_entry *entry; int error; struct clip_vcc *clip_vcc; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; + struct flowi fl = { .iif = 0, .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; struct rtable *rt; if (vcc->push != clip_push) { @@ -537,7 +537,7 @@ static int clip_setentry(struct atm_vcc unlink_clip_vcc(clip_vcc); return 0; } - error = ip_route_output_key(NULL, &rt,&fl); + error = ip_route_output_key(&rt,&fl); if (error) return error; neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); ip_rt_put(rt); diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 29e15e4..15790db 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -209,11 +209,11 @@ static int br_nf_pre_routing_finish(stru if (ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev)) { struct rtable *rt; - struct flowi fl = { .nl_u = + struct flowi fl = { .iff = 0, .nl_u = { .ip4_u = { .daddr = iph->daddr, .saddr = 0 , .tos = RT_TOS(iph->tos)} }, .proto = 0}; - if (!ip_route_output_key(NULL, &rt, &fl)) { + if (!ip_route_output_key(&rt, &fl)) { /* - Bridged-and-DNAT'ed traffic doesn't * require ip_forwarding. * - Deal with redirected traffic. */ diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ae088d1..1fcd5ab 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -888,7 +888,8 @@ static struct dst_entry* dccp_v4_route_s struct sk_buff *skb) { struct rtable *rt; - struct flowi fl = { .oif = ((struct rtable *)skb->dst)->rt_iif, + struct flowi fl = { .iif = sk->skhost->loopback_dev.ifindex, + .oif = ((struct rtable *)skb->dst)->rt_iif, .nl_u = { .ip4_u = { .daddr = skb->nh.iph->saddr, .saddr = skb->nh.iph->daddr, diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index bc2f5aa..e577a3f 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1059,6 +1059,7 @@ int inet_sk_rebuild_header(struct sock * daddr = inet->opt->faddr; { struct flowi fl = { + .iif = sk->sk_host->loopback_dev.ifindex, .oif = sk->sk_bound_dev_if, .nl_u = { .ip4_u = { diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 744ea0a..d4cbd03 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -421,15 +421,14 @@ static int arp_ignore(struct in_device * static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) { - struct nethost *host; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip, + struct flowi fl = { .iif = 0, + .nl_u = { .ip4_u = { .daddr = sip, .saddr = tip } } }; struct rtable *rt; int flag = 0; /*unsigned long now; */ - host = inet_host(dev, tip); - if (ip_route_output_key(host, &rt, &fl) < 0) + if (ip_route_output_key(&rt, &fl) < 0) return 1; if (rt->u.dst.dev != dev) { NET_INC_STATS_BH(LINUX_MIB_ARPFILTER); @@ -1001,10 +1000,11 @@ static int arp_req_set(struct arpreq *r, if (r->arp_flags & ATF_PERM) r->arp_flags |= ATF_COM; if (dev == NULL) { - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, + struct flowi fl = { .iif = current->host->loopback_dev.ifindex, + .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; - if ((err = ip_route_output_key(current->host, &rt, &fl)) != 0) + if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); @@ -1107,10 +1107,11 @@ static int arp_req_delete(struct arpreq } if (dev == NULL) { - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, + struct flowi fl = { .iif = current->host->loopback_dev.ifindex, + .nl_u = { .ip4_u = { .daddr = ip, .tos = RTO_ONLINK } } }; struct rtable * rt; - if ((err = ip_route_output_key(current->host, &rt, &fl)) != 0) + if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index f08ca46..8ffcf39 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -401,12 +401,13 @@ static void icmp_reply(struct icmp_bxm * daddr = icmp_param->replyopts.faddr; } { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = skb->dst->dev->ifindex, + .nl_u = { .ip4_u = { .daddr = daddr, .saddr = rt->rt_spec_dst, .tos = RT_TOS(skb->nh.iph->tos) } }, .proto = IPPROTO_ICMP }; - if (ip_route_output_key(rt_dhost(rt), &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) goto out_unlock; } if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, @@ -547,6 +548,7 @@ void icmp_send(struct sk_buff *skb_in, i { struct flowi fl = { + .iif = skb_in->dst->dev->ifindex, .nl_u = { .ip4_u = { .daddr = icmp_param.replyopts.srr ? @@ -564,7 +566,7 @@ void icmp_send(struct sk_buff *skb_in, i } } }; - if (ip_route_output_key(rt_dhost(rt), &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) goto out_unlock; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index d77ba2d..cd8488a 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -282,11 +282,12 @@ static struct sk_buff *igmpv3_newpack(st return NULL; { - struct flowi fl = { .oif = dev->ifindex, + struct flowi fl = { .iif = 0, + .oif = dev->ifindex, .nl_u = { .ip4_u = { .daddr = IGMPV3_ALL_MCR } }, .proto = IPPROTO_IGMP }; - if (ip_route_output_key(NULL, &rt, &fl)) { + if (ip_route_output_key(&rt, &fl)) { kfree_skb(skb); return NULL; } @@ -627,10 +628,11 @@ static int igmp_send_report(struct in_de dst = group; { - struct flowi fl = { .oif = dev->ifindex, + struct flowi fl = { .iif = 0, + .oif = dev->ifindex, .nl_u = { .ip4_u = { .daddr = dst } }, .proto = IPPROTO_IGMP }; - if (ip_route_output_key(NULL, &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) return -1; } if (rt->rt_src == 0) { @@ -1298,7 +1300,8 @@ void ip_mc_destroy_dev(struct in_device static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = 0, + .nl_u = { .ip4_u = { .daddr = imr->imr_multiaddr.s_addr } } }; struct rtable *rt; struct net_device *dev = NULL; @@ -1317,7 +1320,7 @@ static struct in_device * ip_mc_find_dev __dev_put(dev); } - if (!dev && !ip_route_output_key(NULL, &rt, &fl)) { + if (!dev && !ip_route_output_key(&rt, &fl)) { dev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 575f8c8..be02492 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -320,7 +320,8 @@ struct dst_entry* inet_csk_route_req(str struct rtable *rt; const struct inet_request_sock *ireq = inet_rsk(req); struct ip_options *opt = inet_rsk(req)->opt; - struct flowi fl = { .oif = sk->sk_bound_dev_if, + struct flowi fl = { .iif = sk->sk_host->loopback_dev.ifindex, + .oif = sk->sk_bound_dev_if, .nl_u = { .ip4_u = { .daddr = ((opt && opt->srr) ? opt->faddr : diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index c7f2d40..8b92963 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -477,6 +477,7 @@ out: /* Try to guess incoming interface */ memset(&fl, 0, sizeof(fl)); + fl.iif = 0; fl.fl4_dst = eiph->saddr; fl.fl4_tos = RT_TOS(eiph->tos); fl.proto = IPPROTO_GRE; @@ -490,6 +491,7 @@ out: if (rt->rt_flags&RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; + fl.iif = 0; fl.fl4_dst = eiph->daddr; fl.fl4_src = eiph->saddr; fl.fl4_tos = eiph->tos; @@ -742,7 +744,8 @@ static int ipgre_tunnel_xmit(struct sk_b } { - struct flowi fl = { .oif = tunnel->parms.link, + struct flowi fl = { .iif = 0, + .oif = tunnel->parms.link, .nl_u = { .ip4_u = { .daddr = dst, .saddr = tiph->saddr, @@ -1093,7 +1096,8 @@ static int ipgre_open(struct net_device struct ip_tunnel *t = (struct ip_tunnel*)dev->priv; if (MULTICAST(t->parms.iph.daddr)) { - struct flowi fl = { .oif = t->parms.link, + struct flowi fl = { .iif = 0, + .oif = t->parms.link, .nl_u = { .ip4_u = { .daddr = t->parms.iph.daddr, .saddr = t->parms.iph.saddr, @@ -1166,7 +1170,8 @@ static int ipgre_tunnel_init(struct net_ /* Guess output device to choose reasonable mtu and hard_header_len */ if (iph->daddr) { - struct flowi fl = { .oif = tunnel->parms.link, + struct flowi fl = { .iif = 0, + .oif = tunnel->parms.link, .nl_u = { .ip4_u = { .daddr = iph->daddr, .saddr = iph->saddr, diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4e4e9a1..4554185 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -307,7 +307,8 @@ int ip_queue_xmit(struct sk_buff *skb, i daddr = opt->faddr; { - struct flowi fl = { .oif = sk->sk_bound_dev_if, + struct flowi fl = { .iif = sk->sk_host->loopback_dev.ifindex, + .oif = sk->sk_bound_dev_if, .nl_u = { .ip4_u = { .daddr = daddr, .saddr = inet->saddr, @@ -1275,7 +1276,8 @@ void ip_send_reply(struct sock *sk, stru } { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = skb->dst->dev->ifindex, + .nl_u = { .ip4_u = { .daddr = daddr, .saddr = rt->rt_spec_dst, .tos = RT_TOS(skb->nh.iph->tos) } }, @@ -1284,7 +1286,7 @@ void ip_send_reply(struct sock *sk, stru { .sport = skb->h.th->dest, .dport = skb->h.th->source } }, .proto = sk->sk_protocol }; - if (ip_route_output_key(rt_dhost(rt), &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) return; } diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index c05c1df..f5b4490 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -402,6 +402,7 @@ out: /* Try to guess incoming interface */ memset(&fl, 0, sizeof(fl)); + fl.iif = 0; fl.fl4_daddr = eiph->saddr; fl.fl4_tos = RT_TOS(eiph->tos); fl.proto = IPPROTO_IPIP; @@ -415,6 +416,7 @@ out: if (rt->rt_flags&RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; + fl.iif = 0; fl.fl4_daddr = eiph->daddr; fl.fl4_src = eiph->saddr; fl.fl4_tos = eiph->tos; @@ -548,7 +550,8 @@ static int ipip_tunnel_xmit(struct sk_bu } { - struct flowi fl = { .oif = tunnel->parms.link, + struct flowi fl = { .iif = 0, + .oif = tunnel->parms.link, .nl_u = { .ip4_u = { .daddr = dst, .saddr = tiph->saddr, @@ -808,7 +811,8 @@ static int ipip_tunnel_init(struct net_d memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); if (iph->daddr) { - struct flowi fl = { .oif = tunnel->parms.link, + struct flowi fl = { .iif = 0, + .oif = tunnel->parms.link, .nl_u = { .ip4_u = { .daddr = iph->daddr, .saddr = iph->saddr, diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 82ff9d7..070a815 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1156,22 +1156,24 @@ static void ipmr_queue_xmit(struct sk_bu #endif if (vif->flags&VIFF_TUNNEL) { - struct flowi fl = { .oif = vif->link, + struct flowi fl = { .iif = 0, + .oif = vif->link, .nl_u = { .ip4_u = { .daddr = vif->remote, .saddr = vif->local, .tos = RT_TOS(iph->tos) } }, .proto = IPPROTO_IPIP }; - if (ip_route_output_key(NULL, &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) goto out_free; encap = sizeof(struct iphdr); } else { - struct flowi fl = { .oif = vif->link, + struct flowi fl = { .iif = 0, + .oif = vif->link, .nl_u = { .ip4_u = { .daddr = iph->daddr, .tos = RT_TOS(iph->tos) } }, .proto = IPPROTO_IPIP }; - if (ip_route_output_key(NULL, &rt, &fl)) + if (ip_route_output_key(&rt, &fl)) goto out_free; } diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c index 3b87482..9b04694 100644 --- a/net/ipv4/ipvs/ip_vs_xmit.c +++ b/net/ipv4/ipvs/ip_vs_xmit.c @@ -70,6 +70,7 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp if (!(rt = (struct rtable *) __ip_vs_dst_check(dest, rtos, 0))) { struct flowi fl = { + .iif = 0, .oif = 0, .nl_u = { .ip4_u = { @@ -93,6 +94,7 @@ __ip_vs_get_out_rt(struct ip_vs_conn *cp spin_unlock(&dest->dst_lock); } else { struct flowi fl = { + .iif = 0, .oif = 0, .nl_u = { .ip4_u = { @@ -160,6 +162,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, s u8 tos = iph->tos; int mtu; struct flowi fl = { + .iif = 0, .oif = 0, .nl_u = { .ip4_u = { diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index 63440d1..19c46ad 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c @@ -26,6 +26,7 @@ int ip_route_me_harder(struct sk_buff ** * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook. */ if (inet_addr_type(iph->saddr) == RTN_LOCAL) { + fl.iif = 0, fl.nl_u.ip4_u.daddr = iph->daddr; fl.nl_u.ip4_u.saddr = iph->saddr; fl.nl_u.ip4_u.tos = RT_TOS(iph->tos); @@ -34,7 +35,7 @@ int ip_route_me_harder(struct sk_buff ** fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark; #endif fl.proto = iph->protocol; - if (ip_route_output_key(NULL, &rt, &fl) != 0) + if (ip_route_output_key(&rt, &fl) != 0) return -1; /* Drop old route. */ @@ -43,8 +44,9 @@ int ip_route_me_harder(struct sk_buff ** } else { /* non-local src, find valid iif to satisfy * rp-filter when calling ip_route_input. */ + fl.iif = 0, fl.nl_u.ip4_u.daddr = iph->saddr; - if (ip_route_output_key(NULL, &rt, &fl) != 0) + if (ip_route_output_key(&rt, &fl) != 0) return -1; odst = (*pskb)->dst; diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c index cb66b8b..db2a42d 100644 --- a/net/ipv4/netfilter/ip_nat_rule.c +++ b/net/ipv4/netfilter/ip_nat_rule.c @@ -125,7 +125,7 @@ static unsigned int ipt_snat_target(stru static void warn_if_extra_mangle(u32 dstip, u32 srcip) { static int warned = 0; - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dstip } } }; + struct flowi fl = { .iff = 0, .nl_u = { .ip4_u = { .daddr = dstip } } }; struct rtable *rt; if (ip_route_output_key(&rt, &fl) != 0) diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index f057025..7489e96 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -54,6 +54,7 @@ static inline struct rtable *route_rever || (skb->nf_bridge && skb->nf_bridge->mask & BRNF_BRIDGED) #endif ) { + fl.iif = 0; fl.nl_u.ip4_u.daddr = iph->saddr; if (hook == NF_IP_LOCAL_IN) fl.nl_u.ip4_u.saddr = iph->daddr; @@ -64,6 +65,7 @@ static inline struct rtable *route_rever } else { /* non-local src, find valid iif to satisfy * rp-filter when calling ip_route_input. */ + fl.iif = 0; fl.nl_u.ip4_u.daddr = iph->daddr; if (ip_route_output_key(&rt, &fl) != 0) return NULL; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index d0d10ba..3c5eb7a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -475,7 +475,8 @@ static int raw_sendmsg(struct kiocb *ioc } { - struct flowi fl = { .oif = ipc.oif, + struct flowi fl = { .iif = sk->sk_host->loopback_dev.ifindex, + .oif = ipc.oif, .nl_u = { .ip4_u = { .daddr = daddr, .saddr = saddr, diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 604f31e..81dffd1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2673,18 +2673,10 @@ int __ip_route_output_key(struct rtable EXPORT_SYMBOL_GPL(__ip_route_output_key); -static int __ip_route_output_flow(struct nethost *host, struct rtable **rp, - struct flowi *flp, struct sock *sk, int flags) +int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags) { int err; - if (sk) - host = sk->sk_host; - - /* Add the host loopback interface to the flow */ - if (host) - flp->iif = host->loopback_dev.ifindex; - if ((err = __ip_route_output_key(rp, flp)) != 0) return err; @@ -2699,16 +2691,11 @@ static int __ip_route_output_flow(struct return 0; } -int ip_route_output_flow(struct rtable **rp, struct flowi *flp, struct sock *sk, int flags) -{ - return __ip_route_output_flow(NULL, rp, flp, sk, flags); -} - EXPORT_SYMBOL_GPL(ip_route_output_flow); -int ip_route_output_key(struct nethost *host, struct rtable **rp, struct flowi *flp) +int ip_route_output_key(struct rtable **rp, struct flowi *flp) { - return __ip_route_output_flow(host, rp, flp, NULL, 0); + return ip_route_output_flow(rp, flp, NULL, 0); } static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, @@ -2855,14 +2842,15 @@ int inet_rtm_getroute(struct sk_buff *in if (!err && rt->u.dst.error) err = -rt->u.dst.error; } else { - struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst, + struct flowi fl = { .iif = in_skb->sk->sk_host->loopback_dev.ifindex, + .nl_u = { .ip4_u = { .daddr = dst, .saddr = src, .tos = rtm->rtm_tos } } }; int oif = 0; if (rta[RTA_OIF - 1]) memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int)); fl.oif = oif; - err = ip_route_output_key(in_skb->sk->sk_host, &rt, &fl); + err = ip_route_output_key(&rt, &fl); } if (err) goto out_free; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 20d60d4..1107de0 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -249,7 +249,8 @@ struct sock *cookie_v4_check(struct sock * no easy way to do this. */ { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = sk->sk_host->loopback_dev.ifindex, + .nl_u = { .ip4_u = { .daddr = ((opt && opt->srr) ? opt->faddr : ireq->rmt_addr), @@ -259,7 +260,7 @@ struct sock *cookie_v4_check(struct sock .uli_u = { .ports = { .sport = skb->h.th->dest, .dport = skb->h.th->source } } }; - if (ip_route_output_key(sk->sk_host, &rt, &fl)) { + if (ip_route_output_key(&rt, &fl)) { reqsk_free(req); goto out; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7c0b7e1..f4255f3 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -600,7 +600,8 @@ int udp_sendmsg(struct kiocb *iocb, stru rt = (struct rtable*)sk_dst_check(sk, 0); if (rt == NULL) { - struct flowi fl = { .oif = ipc.oif, + struct flowi fl = { .iif = sk->sk_host->loopback_dev.ifindex, + .oif = ipc.oif, .nl_u = { .ip4_u = { .daddr = faddr, .saddr = saddr, diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 39daed3..8aa1e6c 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -474,13 +474,14 @@ static int ipip6_tunnel_xmit(struct sk_b } { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = 0, + .nl_u = { .ip4_u = { .daddr = dst, .saddr = tiph->saddr, .tos = RT_TOS(tos) } }, .oif = tunnel->parms.link, .proto = IPPROTO_IPV6 }; - if (ip_route_output_key(NULL, &rt, &fl)) { + if (ip_route_output_key(&rt, &fl)) { tunnel->stat.tx_carrier_errors++; goto tx_error_icmp; } @@ -742,14 +743,15 @@ static int ipip6_tunnel_init(struct net_ memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); if (iph->daddr) { - struct flowi fl = { .nl_u = { .ip4_u = + struct flowi fl = { .iif = 0, + .nl_u = { .ip4_u = { .daddr = iph->daddr, .saddr = iph->saddr, .tos = RT_TOS(iph->tos) } }, .oif = tunnel->parms.link, .proto = IPPROTO_IPV6 }; struct rtable *rt; - if (!ip_route_output_key(NULL, &rt, &fl)) { + if (!ip_route_output_key(&rt, &fl)) { tdev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 26de4d3..5ed5536 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -448,6 +448,7 @@ static struct dst_entry *sctp_v4_get_dst fl.fl4_dst = daddr->v4.sin_addr.s_addr; fl.proto = IPPROTO_SCTP; if (asoc) { + fl.iif = assoc->base.sk->sk_host->loopback_dev.ifindex; fl.fl4_tos = RT_CONN_FLAGS(asoc->base.sk); fl.oif = asoc->base.sk->sk_bound_dev_if; } -- 1.0.GIT