Commit 97be95af authored by David S. Miller's avatar David S. Miller

[IPV4]: Provide full proto/ports in flowi route lookups.

parent 01770cd0
......@@ -139,12 +139,16 @@ static inline char rt_tos2priority(u8 tos)
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}
static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif)
static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif, u8 protocol, u16 sport, u16 dport)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst,
struct flowi fl = { .oif = oif,
.nl_u = { .ip4_u = { .daddr = dst,
.saddr = src,
.tos = tos } },
.oif = oif };
.proto = protocol,
.uli_u = { .ports =
{ .sport = sport,
.dport = dport } } };
int err;
err = ip_route_output_key(rp, &fl);
......@@ -157,6 +161,21 @@ static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos
return ip_route_output_key(rp, &fl);
}
static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport)
{
if (sport != (*rp)->fl.uli_u.ports.sport ||
dport != (*rp)->fl.uli_u.ports.dport) {
struct flowi fl;
memcpy(&fl, &(*rp)->fl, sizeof(fl));
fl.uli_u.ports.sport = sport;
fl.uli_u.ports.dport = dport;
*rp = NULL;
return ip_route_output_key(rp, &fl);
}
return 0;
}
extern void rt_bind_peer(struct rtable *rt, int create);
static inline struct inet_peer *rt_get_peer(struct rtable *rt)
......
......@@ -428,7 +428,8 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = rt->rt_spec_dst,
.tos = RT_TOS(skb->nh.iph->tos) } } };
.tos = RT_TOS(skb->nh.iph->tos) } },
.proto = IPPROTO_ICMP };
if (ip_route_output_key(&rt, &fl))
goto out_unlock;
}
......@@ -550,7 +551,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
.saddr = saddr,
.tos = RT_TOS(tos) } } };
.tos = RT_TOS(tos) } },
.proto = IPPROTO_ICMP };
if (ip_route_output_key(&rt, &fl))
goto out_unlock;
}
......@@ -577,7 +579,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = icmp_param.replyopts.faddr,
.saddr = saddr,
.tos = RT_TOS(tos) } } };
.tos = RT_TOS(tos) } },
.proto = IPPROTO_ICMP };
ip_rt_put(rt);
if (ip_route_output_key(&rt, &fl))
goto out_unlock;
......
......@@ -208,8 +208,9 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
dst = IGMP_ALL_ROUTER;
{
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst } },
.oif = dev->ifindex };
struct flowi fl = { .oif = dev->ifindex,
.nl_u = { .ip4_u = { .daddr = dst } },
.proto = IPPROTO_IGMP };
if (ip_route_output_key(&rt, &fl))
return -1;
}
......
......@@ -492,6 +492,7 @@ void ipgre_err(struct sk_buff *skb, u32 info)
memset(&fl, 0, sizeof(fl));
fl.fl4_dst = eiph->saddr;
fl.fl4_tos = RT_TOS(eiph->tos);
fl.proto = IPPROTO_GRE;
if (ip_route_output_key(&rt, &fl)) {
kfree_skb(skb2);
return;
......@@ -757,11 +758,12 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
{
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = tunnel->parms.link,
.nl_u = { .ip4_u =
{ .daddr = dst,
.saddr = tiph->saddr,
.tos = RT_TOS(tos) } },
.oif = tunnel->parms.link };
.proto = IPPROTO_GRE };
if (ip_route_output_key(&rt, &fl)) {
tunnel->stat.tx_carrier_errors++;
goto tx_error;
......@@ -1118,11 +1120,12 @@ static int ipgre_open(struct net_device *dev)
MOD_INC_USE_COUNT;
if (MULTICAST(t->parms.iph.daddr)) {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = t->parms.link,
.nl_u = { .ip4_u =
{ .daddr = t->parms.iph.daddr,
.saddr = t->parms.iph.saddr,
.tos = RT_TOS(t->parms.iph.tos) } },
.oif = t->parms.link };
.proto = IPPROTO_GRE };
struct rtable *rt;
if (ip_route_output_key(&rt, &fl)) {
MOD_DEC_USE_COUNT;
......@@ -1194,11 +1197,12 @@ static int ipgre_tunnel_init(struct net_device *dev)
/* Guess output device to choose reasonable mtu and hard_header_len */
if (iph->daddr) {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = tunnel->parms.link,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr,
.tos = RT_TOS(iph->tos) } },
.oif = tunnel->parms.link };
.proto = IPPROTO_GRE };
struct rtable *rt;
if (!ip_route_output_key(&rt, &fl)) {
tdev = rt->u.dst.dev;
......
......@@ -118,15 +118,17 @@ ip_do_nat(struct sk_buff *skb)
if (ciph->daddr != osaddr) {
struct fib_result res;
unsigned flags = 0;
struct flowi fl = { .nl_u =
{ .ip4_u =
{ .daddr = ciph->saddr,
.saddr = ciph->daddr,
struct flowi fl = {
.iif = skb->dev->ifindex,
.nl_u =
{ .ip4_u =
{ .daddr = ciph->saddr,
.saddr = ciph->daddr,
#ifdef CONFIG_IP_ROUTE_TOS
.tos = RT_TOS(ciph->tos)
.tos = RT_TOS(ciph->tos)
#endif
} },
.iif = skb->dev->ifindex };
} },
.proto = ciph->protocol };
/* Use fib_lookup() until we get our own
* hash table of NATed hosts -- Rani
......
......@@ -306,15 +306,19 @@ int ip_queue_xmit(struct sk_buff *skb)
daddr = opt->faddr;
{
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = sk->bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = inet->saddr,
.tos = RT_CONN_FLAGS(sk) } },
.oif = sk->bound_dev_if };
.proto = sk->protocol,
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = inet->dport } } };
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times itself
* out.
* keep trying until route appears or the connection times
* itself out.
*/
if (ip_route_output_key(&rt, &fl))
goto no_route;
......@@ -1206,7 +1210,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = rt->rt_spec_dst,
.tos = RT_TOS(skb->nh.iph->tos) } } };
.tos = RT_TOS(skb->nh.iph->tos) } },
.proto = sk->protocol };
if (ip_route_output_key(&rt, &fl))
return;
}
......
......@@ -421,6 +421,7 @@ void ipip_err(struct sk_buff *skb, u32 info)
memset(&fl, 0, sizeof(fl));
fl.fl4_daddr = eiph->saddr;
fl.fl4_tos = RT_TOS(eiph->tos);
fl.proto = IPPROTO_IPIP;
if (ip_route_output_key(&rt, &key)) {
kfree_skb(skb2);
return;
......@@ -568,11 +569,12 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
}
{
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = tunnel->parms.link,
.nl_u = { .ip4_u =
{ .daddr = dst,
.saddr = tiph->saddr,
.tos = RT_TOS(tos) } },
.oif = tunnel->parms.link };
.proto = IPPROTO_IPIP };
if (ip_route_output_key(&rt, &fl)) {
tunnel->stat.tx_carrier_errors++;
goto tx_error_icmp;
......@@ -836,11 +838,12 @@ static int ipip_tunnel_init(struct net_device *dev)
ipip_tunnel_init_gen(dev);
if (iph->daddr) {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = tunnel->parms.link,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.saddr = iph->saddr,
.tos = RT_TOS(iph->tos) } },
.oif = tunnel->parms.link };
.proto = IPPROTO_IPIP };
struct rtable *rt;
if (!ip_route_output_key(&rt, &fl)) {
tdev = rt->u.dst.dev;
......
......@@ -1146,19 +1146,21 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
#endif
if (vif->flags&VIFF_TUNNEL) {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = vif->link,
.nl_u = { .ip4_u =
{ .daddr = vif->remote,
.saddr = vif->local,
.tos = RT_TOS(iph->tos) } },
.oif = vif->link };
.proto = IPPROTO_IPIP };
if (ip_route_output_key(&rt, &fl))
return;
encap = sizeof(struct iphdr);
} else {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = vif->link,
.nl_u = { .ip4_u =
{ .daddr = iph->daddr,
.tos = RT_TOS(iph->tos) } },
.oif = vif->link };
.proto = IPPROTO_IPIP };
if (ip_route_output_key(&rt, &fl))
return;
}
......
......@@ -420,11 +420,12 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
{
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = ipc.oif,
.nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = saddr,
.tos = tos } },
.oif = ipc.oif };
.proto = IPPROTO_RAW };
err = ip_route_output_key(&rt, &fl);
}
if (err)
......
......@@ -177,7 +177,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
opt->faddr :
req->af.v4_req.rmt_addr),
.saddr = req->af.v4_req.loc_addr,
.tos = RT_CONN_FLAGS(sk) } } };
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = skb->h.th->dest,
.dport = skb->h.th->source } } };
if (ip_route_output_key(&rt, &fl)) {
tcp_openreq_free(req);
goto out;
......
......@@ -770,7 +770,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
tmp = ip_route_connect(&rt, nexthop, inet->saddr,
RT_CONN_FLAGS(sk), sk->bound_dev_if);
RT_CONN_FLAGS(sk), sk->bound_dev_if,
IPPROTO_TCP,
inet->sport, usin->sin_port);
if (tmp < 0)
return tmp;
......@@ -779,10 +781,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return -ENETUNREACH;
}
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
tp->ext_header_len += rt->u.dst.header_len;
if (!inet->opt || !inet->opt->srr)
daddr = rt->rt_dst;
......@@ -831,6 +829,19 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (err)
goto failure;
err = ip_route_newports(&rt, inet->sport, inet->dport);
if (err)
goto failure;
/* OK, now commit destination to socket. */
__sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst);
/* DAVEM REDPEN: This used to sit above forced ext_header_len = 0
* above, it was real bug. Is this one correct?
*/
tp->ext_header_len += rt->u.dst.header_len;
if (!tp->write_seq)
tp->write_seq = secure_tcp_sequence_number(inet->saddr,
inet->daddr,
......@@ -846,8 +857,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
return 0;
failure:
/* This unhashes the socket and releases the local port, if necessary. */
tcp_set_state(sk, TCP_CLOSE);
__sk_dst_reset(sk);
ip_rt_put(rt);
sk->route_caps = 0;
inet->dport = 0;
return err;
......@@ -1265,13 +1277,17 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk,
{
struct rtable *rt;
struct ip_options *opt = req->af.v4_req.opt;
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = sk->bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = ((opt && opt->srr) ?
opt->faddr :
req->af.v4_req.rmt_addr),
.saddr = req->af.v4_req.loc_addr,
.tos = RT_CONN_FLAGS(sk) } },
.oif = sk->bound_dev_if };
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = inet_sk(sk)->sport,
.dport = req->rmt_port } } };
if (ip_route_output_key(&rt, &fl)) {
IP_INC_STATS_BH(IpOutNoRoutes);
......@@ -1864,7 +1880,9 @@ static int tcp_v4_reselect_saddr(struct sock *sk)
/* Query new route. */
err = ip_route_connect(&rt, daddr, 0,
RT_TOS(inet->tos) | sk->localroute,
sk->bound_dev_if);
sk->bound_dev_if,
IPPROTO_TCP,
inet->sport, inet->dport);
if (err)
return err;
......@@ -1914,11 +1932,15 @@ int tcp_v4_rebuild_header(struct sock *sk)
daddr = inet->opt->faddr;
{
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = sk->bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = daddr,
.saddr = inet->saddr,
.tos = RT_CONN_FLAGS(sk) } },
.oif = sk->bound_dev_if };
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = inet->dport } } };
err = ip_route_output_key(&rt, &fl);
}
......
......@@ -586,11 +586,15 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
rt = (struct rtable*)sk_dst_check(sk, 0);
if (rt == NULL) {
struct flowi fl = { .nl_u = { .ip4_u =
struct flowi fl = { .oif = ipc.oif,
.nl_u = { .ip4_u =
{ .daddr = faddr,
.saddr = saddr,
.tos = tos } },
.oif = ipc.oif };
.proto = IPPROTO_UDP,
.uli_u = { .ports =
{ .sport = inet->sport,
.dport = dport } } };
err = ip_route_output_key(&rt, &fl);
if (err)
goto out;
......@@ -872,7 +876,9 @@ int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
saddr = inet->mc_addr;
}
err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
RT_CONN_FLAGS(sk), oif);
RT_CONN_FLAGS(sk), oif,
IPPROTO_UDP,
inet->sport, usin->sin_port);
if (err)
return err;
if ((rt->rt_flags&RTCF_BROADCAST) && !sk->broadcast) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment