From 074d9880da564d09159d50649e870ac4dacf6d4f Mon Sep 17 00:00:00 2001 From: Pasi Sarolahti Date: Wed, 9 Oct 2002 02:04:19 -0700 Subject: [TCP]: Add F-RTO support. Motivation for this modification is that especially on some wireless network technologies there are delay spikes that trigger RTO even though no packets are lost. F-RTO sender continues by sending new data after RTO retransmission in order to avoid unnecessary retransmissions in that case. If the sender sees any duplicate acks after the RTO retransmission, it reverts to traditional slow start retransmissions. If new acks arrive after forward transmissions, they very likely indicate that the RTO was indeed spurious and the sender can continue sending new data (because only one segment was retransmitted). --- include/linux/sysctl.h | 3 ++- include/linux/tcp.h | 3 +++ include/net/tcp.h | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index 9fd7d5c05605..0fb31130009d 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -301,7 +301,8 @@ enum NET_IPV4_NONLOCAL_BIND=88, NET_IPV4_ICMP_RATELIMIT=89, NET_IPV4_ICMP_RATEMASK=90, - NET_TCP_TW_REUSE=91 + NET_TCP_TW_REUSE=91, + NET_TCP_FRTO=92 }; enum { diff --git a/include/linux/tcp.h b/include/linux/tcp.h index ce34341d6a2c..91b66d7ab004 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -366,6 +366,9 @@ struct tcp_opt { unsigned int keepalive_intvl; /* time interval between keep alive probes */ int linger2; + int frto_counter; /* Number of new acks after RTO */ + __u32 frto_highmark; /* snd_nxt when RTO occurred */ + unsigned long last_synq_overflow; }; diff --git a/include/net/tcp.h b/include/net/tcp.h index 0a58d80e7794..f5aa33e5b15e 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -472,6 +472,7 @@ extern int sysctl_tcp_rmem[3]; extern int sysctl_tcp_app_win; extern int sysctl_tcp_adv_win_scale; extern int sysctl_tcp_tw_reuse; +extern int sysctl_tcp_frto; extern atomic_t tcp_memory_allocated; extern atomic_t tcp_sockets_allocated; @@ -1855,4 +1856,17 @@ static inline void tcp_v4_setup_caps(struct sock *sk, struct dst_entry *dst) #define TCP_CHECK_TIMER(sk) do { } while (0) +static inline int tcp_use_frto(const struct sock *sk) +{ + const struct tcp_opt *tp = tcp_sk(sk); + + /* F-RTO must be activated in sysctl and there must be some + * unsent new data, and the advertised window should allow + * sending it. + */ + return (sysctl_tcp_frto && tp->send_head && + !after(TCP_SKB_CB(tp->send_head)->end_seq, + tp->snd_una + tp->snd_wnd)); +} + #endif /* _TCP_H */ -- cgit v1.2.3 From dcddf5b041daf44bd0336574ab5e2f0233ca0709 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 11 Oct 2002 02:10:08 -0700 Subject: [IPV4]: Use generic struct flowi as routing key. --- include/net/flow.h | 70 +----- include/net/ip6_fib.h | 8 - include/net/ip6_fw.h | 54 ----- include/net/ip_fib.h | 23 +- include/net/route.h | 41 +--- net/atm/clip.c | 3 +- net/core/netfilter.c | 18 +- net/ipv4/arp.c | 12 +- net/ipv4/fib_frontend.c | 31 +-- net/ipv4/fib_hash.c | 12 +- net/ipv4/fib_rules.c | 20 +- net/ipv4/fib_semantics.c | 29 +-- net/ipv4/icmp.c | 32 ++- net/ipv4/igmp.c | 14 +- net/ipv4/ip_gre.c | 42 +++- net/ipv4/ip_nat_dumb.c | 20 +- net/ipv4/ip_output.c | 32 ++- net/ipv4/ipip.c | 31 ++- net/ipv4/ipmr.c | 15 +- net/ipv4/netfilter/ip_fw_compat_masq.c | 3 +- net/ipv4/netfilter/ip_nat_core.c | 3 +- net/ipv4/netfilter/ipt_MASQUERADE.c | 23 +- net/ipv4/netfilter/ipt_MIRROR.c | 7 +- net/ipv4/netfilter/ipt_REJECT.c | 30 ++- net/ipv4/raw.c | 10 +- net/ipv4/route.c | 326 +++++++++++++-------------- net/ipv4/syncookies.c | 19 +- net/ipv4/tcp_ipv4.c | 25 ++- net/ipv4/udp.c | 7 +- net/ipv6/Config.in | 3 - net/ipv6/Makefile | 1 - net/ipv6/ip6_fib.c | 1 - net/ipv6/ip6_fw.c | 390 --------------------------------- net/ipv6/route.c | 301 ++++--------------------- net/ipv6/sit.c | 20 +- net/sched/cls_route.c | 2 +- net/sctp/protocol.c | 14 +- 37 files changed, 548 insertions(+), 1144 deletions(-) delete mode 100644 include/net/ip6_fw.h delete mode 100644 net/ipv6/ip6_fw.c (limited to 'include') diff --git a/include/net/flow.h b/include/net/flow.h index e1ce1b2aea31..58fbf0e8314a 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -1,6 +1,6 @@ /* * - * Flow based forwarding rules (usage: firewalling, etc) + * Generic internet FLOW. * */ @@ -8,12 +8,16 @@ #define _NET_FLOW_H struct flowi { - int proto; /* {TCP, UDP, ICMP} */ + int oif; + int iif; union { struct { __u32 daddr; __u32 saddr; + __u32 fwmark; + __u8 tos; + __u8 scope; } ip4_u; struct { @@ -27,9 +31,12 @@ struct flowi { #define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl4_dst nl_u.ip4_u.daddr #define fl4_src nl_u.ip4_u.saddr +#define fl4_fwmark nl_u.ip4_u.fwmark +#define fl4_tos nl_u.ip4_u.tos +#define fl4_scope nl_u.ip4_u.scope - int oif; - + __u8 proto; + __u8 flags; union { struct { __u16 sport; @@ -41,61 +48,8 @@ struct flowi { __u8 code; } icmpt; - unsigned long data; + __u32 spi; } uli_u; }; -#define FLOWR_NODECISION 0 /* rule not appliable to flow */ -#define FLOWR_SELECT 1 /* flow must follow this rule */ -#define FLOWR_CLEAR 2 /* priority level clears flow */ -#define FLOWR_ERROR 3 - -struct fl_acc_args { - int type; - - -#define FL_ARG_FORWARD 1 -#define FL_ARG_ORIGIN 2 - - union { - struct sk_buff *skb; - struct { - struct sock *sk; - struct flowi *flow; - } fl_o; - } fl_u; -}; - - -struct pkt_filter { - atomic_t refcnt; - unsigned int offset; - __u32 value; - __u32 mask; - struct pkt_filter *next; -}; - -#define FLR_INPUT 1 -#define FLR_OUTPUT 2 - -struct flow_filter { - int type; - union { - struct pkt_filter *filter; - struct sock *sk; - } u; -}; - -struct flow_rule { - struct flow_rule_ops *ops; - unsigned char private[0]; -}; - -struct flow_rule_ops { - int (*accept)(struct rt6_info *rt, - struct rt6_info *rule, - struct fl_acc_args *args, - struct rt6_info **nrt); -}; - #endif diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index f8d382f4e7d8..4fb406133dbb 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -70,14 +70,6 @@ struct rt6_info u8 rt6i_hoplimit; atomic_t rt6i_ref; - union { - struct flow_rule *rt6iu_flowr; - struct flow_filter *rt6iu_filter; - } flow_u; - -#define rt6i_flowr flow_u.rt6iu_flowr -#define rt6i_filter flow_u.rt6iu_filter - struct rt6key rt6i_dst; struct rt6key rt6i_src; }; diff --git a/include/net/ip6_fw.h b/include/net/ip6_fw.h deleted file mode 100644 index 7866273d3d56..000000000000 --- a/include/net/ip6_fw.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __NET_IP6_FW_H -#define __NET_IP6_FW_H - -#define IP6_FW_LISTHEAD 0x1000 -#define IP6_FW_ACCEPT 0x0001 -#define IP6_FW_REJECT 0x0002 - -#define IP6_FW_DEBUG 2 - -#define IP6_FW_MSG_ADD 1 -#define IP6_FW_MSG_DEL 2 -#define IP6_FW_MSG_REPORT 3 - - -/* - * Fast "hack" user interface - */ -struct ip6_fw_msg { - struct in6_addr dst; - struct in6_addr src; - int dst_len; - int src_len; - int action; - int policy; - int proto; - union { - struct { - __u16 sport; - __u16 dport; - } transp; - - unsigned long data; - - int icmp_type; - } u; - - int msg_len; -}; - -#ifdef __KERNEL__ - -#include - -struct ip6_fw_rule { - struct flow_rule flowr; - struct ip6_fw_rule *next; - struct ip6_fw_rule *prev; - struct flowi info; - unsigned long policy; -}; - -#endif - -#endif diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 3b84c5bff809..236641e5bc51 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -17,6 +17,7 @@ #define _NET_IP_FIB_H #include +#include struct kern_rta { @@ -117,7 +118,7 @@ struct fib_table { unsigned char tb_id; unsigned tb_stamp; - int (*tb_lookup)(struct fib_table *tb, const struct rt_key *key, struct fib_result *res); + int (*tb_lookup)(struct fib_table *tb, const struct flowi *flp, struct fib_result *res); int (*tb_insert)(struct fib_table *table, struct rtmsg *r, struct kern_rta *rta, struct nlmsghdr *n, struct netlink_skb_parms *req); @@ -130,7 +131,7 @@ struct fib_table int (*tb_get_info)(struct fib_table *table, char *buf, int first, int count); void (*tb_select_default)(struct fib_table *table, - const struct rt_key *key, struct fib_result *res); + const struct flowi *flp, struct fib_result *res); unsigned char tb_data[0]; }; @@ -152,18 +153,18 @@ static inline struct fib_table *fib_new_table(int id) return fib_get_table(id); } -static inline int fib_lookup(const struct rt_key *key, struct fib_result *res) +static inline int fib_lookup(const struct flowi *flp, struct fib_result *res) { - if (local_table->tb_lookup(local_table, key, res) && - main_table->tb_lookup(main_table, key, res)) + if (local_table->tb_lookup(local_table, flp, res) && + main_table->tb_lookup(main_table, flp, res)) return -ENETUNREACH; return 0; } -static inline void fib_select_default(const struct rt_key *key, struct fib_result *res) +static inline void fib_select_default(const struct flowi *flp, struct fib_result *res) { if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) - main_table->tb_select_default(main_table, key, res); + main_table->tb_select_default(main_table, flp, res); } #else /* CONFIG_IP_MULTIPLE_TABLES */ @@ -171,7 +172,7 @@ static inline void fib_select_default(const struct rt_key *key, struct fib_resul #define main_table (fib_tables[RT_TABLE_MAIN]) extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; -extern int fib_lookup(const struct rt_key *key, struct fib_result *res); +extern int fib_lookup(const struct flowi *flp, struct fib_result *res); extern struct fib_table *__fib_new_table(int id); extern void fib_rule_put(struct fib_rule *r); @@ -191,7 +192,7 @@ static inline struct fib_table *fib_new_table(int id) return fib_tables[id] ? : __fib_new_table(id); } -extern void fib_select_default(const struct rt_key *key, struct fib_result *res); +extern void fib_select_default(const struct flowi *flp, struct fib_result *res); #endif /* CONFIG_IP_MULTIPLE_TABLES */ @@ -204,13 +205,13 @@ extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *ar extern int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb); extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, struct net_device *dev, u32 *spec_dst, u32 *itag); -extern void fib_select_multipath(const struct rt_key *key, struct fib_result *res); +extern void fib_select_multipath(const struct flowi *flp, struct fib_result *res); /* Exported by fib_semantics.c */ extern int ip_fib_check_default(u32 gw, struct net_device *dev); extern void fib_release_info(struct fib_info *); extern int fib_semantic_match(int type, struct fib_info *, - const struct rt_key *, struct fib_result*); + const struct flowi *, struct fib_result*); extern struct fib_info *fib_create_info(const struct rtmsg *r, struct kern_rta *rta, const struct nlmsghdr *, int *err); extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi); diff --git a/include/net/route.h b/include/net/route.h index 7ddc79e4d07e..621b0c44b250 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -45,19 +46,6 @@ #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sk->localroute) -struct rt_key -{ - __u32 dst; - __u32 src; - int iif; - int oif; -#ifdef CONFIG_IP_ROUTE_FWMARK - __u32 fwmark; -#endif - __u8 tos; - __u8 scope; -}; - struct inet_peer; struct rtable { @@ -78,7 +66,7 @@ struct rtable __u32 rt_gateway; /* Cache lookup keys */ - struct rt_key key; + struct flowi fl; /* Miscellaneous cached information */ __u32 rt_spec_dst; /* RFC1122 specific destination */ @@ -124,7 +112,7 @@ extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw, u32 src, u8 tos, struct net_device *dev); 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 rt_key *key); +extern int ip_route_output_key(struct rtable **, const struct flowi *flp); 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); extern void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu); @@ -136,16 +124,6 @@ extern int ip_rt_ioctl(unsigned int cmd, void *arg); extern void ip_rt_get_source(u8 *src, struct rtable *rt); extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); -/* Deprecated: use ip_route_output_key directly */ -static inline int ip_route_output(struct rtable **rp, - u32 daddr, u32 saddr, u32 tos, int oif) -{ - struct rt_key key = { dst:daddr, src:saddr, oif:oif, tos:tos }; - - return ip_route_output_key(rp, &key); -} - - static inline void ip_rt_put(struct rtable * rt) { if (rt) @@ -163,15 +141,20 @@ static inline char rt_tos2priority(u8 tos) static inline int ip_route_connect(struct rtable **rp, u32 dst, u32 src, u32 tos, int oif) { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst, + .saddr = src, + .tos = tos } }, + .oif = oif }; + int err; - err = ip_route_output(rp, dst, src, tos, oif); + err = ip_route_output_key(rp, &fl); if (err || (dst && src)) return err; - dst = (*rp)->rt_dst; - src = (*rp)->rt_src; + fl.fl4_dst = (*rp)->rt_dst; + fl.fl4_src = (*rp)->rt_src; ip_rt_put(*rp); *rp = NULL; - return ip_route_output(rp, dst, src, tos, oif); + return ip_route_output_key(rp, &fl); } extern void rt_bind_peer(struct rtable *rt, int create); diff --git a/net/atm/clip.c b/net/atm/clip.c index 96013cb4c0e5..87bf9d4b28ac 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -509,6 +509,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip) struct atmarp_entry *entry; int error; struct clip_vcc *clip_vcc; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } }; struct rtable *rt; if (vcc->push != clip_push) { @@ -525,7 +526,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip) unlink_clip_vcc(clip_vcc); return 0; } - error = ip_route_output(&rt,ip,0,1,0); + 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/core/netfilter.c b/net/core/netfilter.c index 816c063896d9..4af99cda49bf 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -563,13 +563,15 @@ int ip_route_me_harder(struct sk_buff **pskb) { struct iphdr *iph = (*pskb)->nh.iph; struct rtable *rt; - struct rt_key key = { dst:iph->daddr, - src:iph->saddr, - oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, - tos:RT_TOS(iph->tos)|RTO_CONN, + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->daddr, + .saddr = iph->saddr, + .tos = RT_TOS(iph->tos)|RTO_CONN, #ifdef CONFIG_IP_ROUTE_FWMARK - fwmark:(*pskb)->nfmark + .fwmark = (*pskb)->nfmark #endif + } }, + .oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, }; struct net_device *dev_src = NULL; int err; @@ -578,10 +580,10 @@ int ip_route_me_harder(struct sk_buff **pskb) 0 or a local address; however some non-standard hacks like ipt_REJECT.c:send_reset() can cause packets with foreign saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */ - if(key.src && !(dev_src = ip_dev_find(key.src))) - key.src = 0; + if(fl.fl4_src && !(dev_src = ip_dev_find(fl.fl4_src))) + fl.fl4_src = 0; - if ((err=ip_route_output_key(&rt, &key)) != 0) { + if ((err=ip_route_output_key(&rt, &fl)) != 0) { printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n", NIPQUAD(iph->daddr), NIPQUAD(iph->saddr), (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index a24265d561e5..083b0904c68c 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -347,11 +347,13 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev) { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = sip, + .saddr = tip } } }; struct rtable *rt; int flag = 0; /*unsigned long now; */ - if (ip_route_output(&rt, sip, tip, 0, 0) < 0) + if (ip_route_output_key(&rt, &fl) < 0) return 1; if (rt->u.dst.dev != dev) { NET_INC_STATS_BH(ArpFilter); @@ -890,8 +892,10 @@ int arp_req_set(struct arpreq *r, struct net_device * dev) if (r->arp_flags & ATF_PERM) r->arp_flags |= ATF_COM; if (dev == NULL) { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, + .tos = RTO_ONLINK } } }; struct rtable * rt; - if ((err = ip_route_output(&rt, ip, 0, RTO_ONLINK, 0)) != 0) + if ((err = ip_route_output_key(&rt, &fl)) != 0) return err; dev = rt->u.dst.dev; ip_rt_put(rt); @@ -974,8 +978,10 @@ int arp_req_delete(struct arpreq *r, struct net_device * dev) } if (dev == NULL) { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, + .tos = RTO_ONLINK } } }; struct rtable * rt; - if ((err = ip_route_output(&rt, ip, 0, RTO_ONLINK, 0)) != 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/fib_frontend.c b/net/ipv4/fib_frontend.c index c101889f0226..74905d6696f2 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -144,17 +144,15 @@ fib_get_procinfo(char *buffer, char **start, off_t offset, int length) struct net_device * ip_dev_find(u32 addr) { - struct rt_key key; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; struct fib_result res; struct net_device *dev = NULL; - memset(&key, 0, sizeof(key)); - key.dst = addr; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif - if (!local_table || local_table->tb_lookup(local_table, &key, &res)) { + if (!local_table || local_table->tb_lookup(local_table, &fl, &res)) { return NULL; } if (res.type != RTN_LOCAL) @@ -170,7 +168,7 @@ out: unsigned inet_addr_type(u32 addr) { - struct rt_key key; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } }; struct fib_result res; unsigned ret = RTN_BROADCAST; @@ -179,15 +177,13 @@ unsigned inet_addr_type(u32 addr) if (MULTICAST(addr)) return RTN_MULTICAST; - memset(&key, 0, sizeof(key)); - key.dst = addr; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif if (local_table) { ret = RTN_UNICAST; - if (local_table->tb_lookup(local_table, &key, &res) == 0) { + if (local_table->tb_lookup(local_table, &fl, &res) == 0) { ret = res.type; fib_res_put(&res); } @@ -207,18 +203,15 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, struct net_device *dev, u32 *spec_dst, u32 *itag) { struct in_device *in_dev; - struct rt_key key; + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = src, + .saddr = dst, + .tos = tos } }, + .iif = oif }; struct fib_result res; int no_addr, rpf; int ret; - key.dst = src; - key.src = dst; - key.tos = tos; - key.oif = 0; - key.iif = oif; - key.scope = RT_SCOPE_UNIVERSE; - no_addr = rpf = 0; read_lock(&inetdev_lock); in_dev = __in_dev_get(dev); @@ -231,7 +224,7 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, if (in_dev == NULL) goto e_inval; - if (fib_lookup(&key, &res)) + if (fib_lookup(&fl, &res)) goto last_resort; if (res.type != RTN_UNICAST) goto e_inval_res; @@ -252,10 +245,10 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, goto last_resort; if (rpf) goto e_inval; - key.oif = dev->ifindex; + fl.oif = dev->ifindex; ret = 0; - if (fib_lookup(&key, &res) == 0) { + if (fib_lookup(&fl, &res) == 0) { if (res.type == RTN_UNICAST) { *spec_dst = FIB_RES_PREFSRC(res); ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c index b16d479e817e..8b4ed3701998 100644 --- a/net/ipv4/fib_hash.c +++ b/net/ipv4/fib_hash.c @@ -266,7 +266,7 @@ fn_new_zone(struct fn_hash *table, int z) } static int -fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result *res) +fn_hash_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) { int err; struct fn_zone *fz; @@ -275,7 +275,7 @@ fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result read_lock(&fib_hash_lock); for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { struct fib_node *f; - fn_key_t k = fz_key(key->dst, fz); + fn_key_t k = fz_key(flp->fl4_dst, fz); for (f = fz_chain(k, fz); f; f = f->fn_next) { if (!fn_key_eq(k, f->fn_key)) { @@ -285,17 +285,17 @@ fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result continue; } #ifdef CONFIG_IP_ROUTE_TOS - if (f->fn_tos && f->fn_tos != key->tos) + if (f->fn_tos && f->fn_tos != flp->fl4_tos) continue; #endif f->fn_state |= FN_S_ACCESSED; if (f->fn_state&FN_S_ZOMBIE) continue; - if (f->fn_scope < key->scope) + if (f->fn_scope < flp->fl4_scope) continue; - err = fib_semantic_match(f->fn_type, FIB_INFO(f), key, res); + err = fib_semantic_match(f->fn_type, FIB_INFO(f), flp, res); if (err == 0) { res->type = f->fn_type; res->scope = f->fn_scope; @@ -338,7 +338,7 @@ static int fib_detect_death(struct fib_info *fi, int order, } static void -fn_hash_select_default(struct fib_table *tb, const struct rt_key *key, struct fib_result *res) +fn_hash_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res) { int order, last_idx; struct fib_node *f; diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 8ae6cbeee71e..c271e5965779 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -307,28 +307,28 @@ static void fib_rules_attach(struct net_device *dev) } } -int fib_lookup(const struct rt_key *key, struct fib_result *res) +int fib_lookup(const struct flowi *flp, struct fib_result *res) { int err; struct fib_rule *r, *policy; struct fib_table *tb; - u32 daddr = key->dst; - u32 saddr = key->src; + u32 daddr = flp->fl4_dst; + u32 saddr = flp->fl4_src; FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", - NIPQUAD(key->dst), NIPQUAD(key->src)); + NIPQUAD(flp->fl4_dst), NIPQUAD(flp->fl4_src)); read_lock(&fib_rules_lock); for (r = fib_rules; r; r=r->r_next) { if (((saddr^r->r_src) & r->r_srcmask) || ((daddr^r->r_dst) & r->r_dstmask) || #ifdef CONFIG_IP_ROUTE_TOS - (r->r_tos && r->r_tos != key->tos) || + (r->r_tos && r->r_tos != flp->fl4_tos) || #endif #ifdef CONFIG_IP_ROUTE_FWMARK - (r->r_fwmark && r->r_fwmark != key->fwmark) || + (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) || #endif - (r->r_ifindex && r->r_ifindex != key->iif)) + (r->r_ifindex && r->r_ifindex != flp->iif)) continue; FRprintk("tb %d r %d ", r->r_table, r->r_action); @@ -351,7 +351,7 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action); if ((tb = fib_get_table(r->r_table)) == NULL) continue; - err = tb->tb_lookup(tb, key, res); + err = tb->tb_lookup(tb, flp, res); if (err == 0) { res->r = policy; if (policy) @@ -369,13 +369,13 @@ FRprintk("FAILURE\n"); return -ENETUNREACH; } -void fib_select_default(const struct rt_key *key, struct fib_result *res) +void fib_select_default(const struct flowi *flp, struct fib_result *res) { if (res->r && res->r->r_action == RTN_UNICAST && FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { struct fib_table *tb; if ((tb = fib_get_table(res->r->r_table)) != NULL) - tb->tb_select_default(tb, key, res); + tb->tb_select_default(tb, flp, res); } } diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index 071b4af2b05b..4e2674a5ad79 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -349,7 +349,6 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n int err; if (nh->nh_gw) { - struct rt_key key; struct fib_result res; #ifdef CONFIG_IP_ROUTE_PERVASIVE @@ -372,16 +371,18 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n nh->nh_scope = RT_SCOPE_LINK; return 0; } - memset(&key, 0, sizeof(key)); - key.dst = nh->nh_gw; - key.oif = nh->nh_oif; - key.scope = r->rtm_scope + 1; - - /* It is not necessary, but requires a bit of thinking */ - if (key.scope < RT_SCOPE_LINK) - key.scope = RT_SCOPE_LINK; - if ((err = fib_lookup(&key, &res)) != 0) - return err; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = nh->nh_gw, + .scope = r->rtm_scope + 1 } }, + .oif = nh->nh_oif }; + + /* It is not necessary, but requires a bit of thinking */ + if (fl.fl4_scope < RT_SCOPE_LINK) + fl.fl4_scope = RT_SCOPE_LINK; + if ((err = fib_lookup(&fl, &res)) != 0) + return err; + } err = -EINVAL; if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) goto out; @@ -578,7 +579,7 @@ failure: } int -fib_semantic_match(int type, struct fib_info *fi, const struct rt_key *key, struct fib_result *res) +fib_semantic_match(int type, struct fib_info *fi, const struct flowi *flp, struct fib_result *res) { int err = fib_props[type].error; @@ -603,7 +604,7 @@ fib_semantic_match(int type, struct fib_info *fi, const struct rt_key *key, stru for_nexthops(fi) { if (nh->nh_flags&RTNH_F_DEAD) continue; - if (!key->oif || key->oif == nh->nh_oif) + if (!flp->oif || flp->oif == nh->nh_oif) break; } #ifdef CONFIG_IP_ROUTE_MULTIPATH @@ -949,7 +950,7 @@ int fib_sync_up(struct net_device *dev) fair weighted route distribution. */ -void fib_select_multipath(const struct rt_key *key, struct fib_result *res) +void fib_select_multipath(const struct flowi *flp, struct fib_result *res) { struct fib_info *fi = res->fi; int w; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index ebbb05b5243d..0407a4babb3a 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -418,9 +418,14 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) if (ipc.opt->srr) daddr = icmp_param->replyopts.faddr; } - if (ip_route_output(&rt, daddr, rt->rt_spec_dst, - RT_TOS(skb->nh.iph->tos), 0)) - goto out_unlock; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = rt->rt_spec_dst, + .tos = RT_TOS(skb->nh.iph->tos) } } }; + if (ip_route_output_key(&rt, &fl)) + goto out_unlock; + } if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, icmp_param->data.icmph.code)) { ip_build_xmit(sk, icmp_glue_bits, icmp_param, @@ -526,8 +531,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) * Restore original addresses if packet has been translated. */ if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) { - iph->daddr = rt->key.dst; - iph->saddr = rt->key.src; + iph->daddr = rt->fl.fl4_dst; + iph->saddr = rt->fl.fl4_src; } #endif @@ -539,9 +544,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) IPTOS_PREC_INTERNETCONTROL) : iph->tos; - if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0)) - goto out_unlock; - + { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr, + .saddr = saddr, + .tos = RT_TOS(tos) } } }; + if (ip_route_output_key(&rt, &fl)) + goto out_unlock; + } if (ip_options_echo(&icmp_param.replyopts, skb_in)) goto ende; @@ -563,9 +572,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) ipc.addr = iph->saddr; ipc.opt = &icmp_param.replyopts; if (icmp_param.replyopts.srr) { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = icmp_param.replyopts.faddr, + .saddr = saddr, + .tos = RT_TOS(tos) } } }; ip_rt_put(rt); - if (ip_route_output(&rt, icmp_param.replyopts.faddr, - saddr, RT_TOS(tos), 0)) + if (ip_route_output_key(&rt, &fl)) goto out_unlock; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c887839e79ea..661e65974e39 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -207,8 +207,12 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) if (type == IGMP_HOST_LEAVE_MESSAGE) dst = IGMP_ALL_ROUTER; - if (ip_route_output(&rt, dst, 0, 0, dev->ifindex)) - return -1; + { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = dst } }, + .oif = dev->ifindex }; + if (ip_route_output_key(&rt, &fl)) + return -1; + } if (rt->rt_src == 0) { ip_rt_put(rt); return -1; @@ -374,7 +378,7 @@ int igmp_rcv(struct sk_buff *skb) case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_NEW_MEMBERSHIP_REPORT: /* Is it our report looped back? */ - if (((struct rtable*)skb->dst)->key.iif == 0) + if (((struct rtable*)skb->dst)->fl.iif == 0) break; igmp_heard_report(in_dev, ih->group); break; @@ -608,6 +612,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev) static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = imr->imr_address.s_addr } } }; struct rtable *rt; struct net_device *dev = NULL; struct in_device *idev = NULL; @@ -619,7 +625,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) __dev_put(dev); } - if (!dev && !ip_route_output(&rt, imr->imr_multiaddr.s_addr, 0, 0, 0)) { + if (!dev && !ip_route_output_key(&rt, &fl)) { dev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index ed0525d342bd..f120e87b4cc3 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -412,6 +412,7 @@ out: u16 flags; int grehlen = (iph->ihl<<2) + 4; struct sk_buff *skb2; + struct flowi fl; struct rtable *rt; if (p[1] != htons(ETH_P_IP)) @@ -488,7 +489,10 @@ out: skb2->nh.raw = skb2->data; /* Try to guess incoming interface */ - if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) { + memset(&fl, 0, sizeof(fl)); + fl.fl4_dst = eiph->saddr; + fl.fl4_tos = RT_TOS(eiph->tos); + if (ip_route_output_key(&rt, &fl)) { kfree_skb(skb2); return; } @@ -498,7 +502,10 @@ out: if (rt->rt_flags&RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; - if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) || + fl.fl4_dst = eiph->daddr; + fl.fl4_src = eiph->saddr; + fl.fl4_tos = eiph->tos; + if (ip_route_output_key(&rt, &fl) || rt->u.dst.dev->type != ARPHRD_IPGRE) { ip_rt_put(rt); kfree_skb(skb2); @@ -619,7 +626,7 @@ int ipgre_rcv(struct sk_buff *skb) #ifdef CONFIG_NET_IPGRE_BROADCAST if (MULTICAST(iph->daddr)) { /* Looped back packet, drop it! */ - if (((struct rtable*)skb->dst)->key.iif == 0) + if (((struct rtable*)skb->dst)->fl.iif == 0) goto drop; tunnel->stat.multicast++; skb->pkt_type = PACKET_BROADCAST; @@ -749,9 +756,16 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) tos &= ~1; } - if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { - tunnel->stat.tx_carrier_errors++; - goto tx_error; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = dst, + .saddr = tiph->saddr, + .tos = RT_TOS(tos) } }, + .oif = tunnel->parms.link }; + if (ip_route_output_key(&rt, &fl)) { + tunnel->stat.tx_carrier_errors++; + goto tx_error; + } } tdev = rt->u.dst.dev; @@ -1104,10 +1118,13 @@ 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 = + { .daddr = t->parms.iph.daddr, + .saddr = t->parms.iph.saddr, + .tos = RT_TOS(t->parms.iph.tos) } }, + .oif = t->parms.link }; struct rtable *rt; - if (ip_route_output(&rt, t->parms.iph.daddr, - t->parms.iph.saddr, RT_TOS(t->parms.iph.tos), - t->parms.link)) { + if (ip_route_output_key(&rt, &fl)) { MOD_DEC_USE_COUNT; return -EADDRNOTAVAIL; } @@ -1177,8 +1194,13 @@ 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 = + { .daddr = iph->daddr, + .saddr = iph->saddr, + .tos = RT_TOS(iph->tos) } }, + .oif = tunnel->parms.link }; struct rtable *rt; - if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) { + if (!ip_route_output_key(&rt, &fl)) { tdev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/ipv4/ip_nat_dumb.c b/net/ipv4/ip_nat_dumb.c index 449c4f44102e..58d1d3f4b8c9 100644 --- a/net/ipv4/ip_nat_dumb.c +++ b/net/ipv4/ip_nat_dumb.c @@ -117,23 +117,21 @@ ip_do_nat(struct sk_buff *skb) if (rt->rt_flags&RTCF_SNAT) { if (ciph->daddr != osaddr) { struct fib_result res; - struct rt_key key; unsigned flags = 0; - - key.src = ciph->daddr; - key.dst = ciph->saddr; - key.iif = skb->dev->ifindex; - key.oif = 0; + struct flowi fl = { .nl_u = + { .ip4_u = + { .daddr = ciph->saddr, + .saddr = ciph->daddr, #ifdef CONFIG_IP_ROUTE_TOS - key.tos = RT_TOS(ciph->tos); -#endif -#ifdef CONFIG_IP_ROUTE_FWMARK - key.fwmark = 0; + .tos = RT_TOS(ciph->tos) #endif + } }, + .iif = skb->dev->ifindex }; + /* Use fib_lookup() until we get our own * hash table of NATed hosts -- Rani */ - if (fib_lookup(&key, &res) == 0) { + if (fib_lookup(&fl, &res) == 0) { if (res.r) { ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags); if (ciph->daddr != idaddr) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 082c29da4047..efbe98cf67b0 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -372,14 +372,20 @@ int ip_queue_xmit(struct sk_buff *skb) if(opt && opt->srr) daddr = opt->faddr; - /* If this fails, retransmit mechanism of transport layer will - * keep trying until route appears or the connection times itself - * out. - */ - if (ip_route_output(&rt, daddr, inet->saddr, - RT_CONN_FLAGS(sk), - sk->bound_dev_if)) - goto no_route; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = inet->saddr, + .tos = RT_CONN_FLAGS(sk) } }, + .oif = sk->bound_dev_if }; + + /* If this fails, retransmit mechanism of transport layer will + * keep trying until route appears or the connection times itself + * out. + */ + if (ip_route_output_key(&rt, &fl)) + goto no_route; + } __sk_dst_set(sk, &rt->u.dst); tcp_v4_setup_caps(sk, &rt->u.dst); } @@ -991,8 +997,14 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar daddr = replyopts.opt.faddr; } - if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0)) - return; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = rt->rt_spec_dst, + .tos = RT_TOS(skb->nh.iph->tos) } } }; + if (ip_route_output_key(&rt, &fl)) + return; + } /* And let IP do all the hard work. diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 83c96cb9db73..1e6ed55c935a 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -355,6 +355,7 @@ out: int rel_code = 0; int rel_info = 0; struct sk_buff *skb2; + struct flowi fl; struct rtable *rt; if (len < hlen + sizeof(struct iphdr)) @@ -417,7 +418,10 @@ out: skb2->nh.raw = skb2->data; /* Try to guess incoming interface */ - if (ip_route_output(&rt, eiph->saddr, 0, RT_TOS(eiph->tos), 0)) { + memset(&fl, 0, sizeof(fl)); + fl.fl4_daddr = eiph->saddr; + fl.fl4_tos = RT_TOS(eiph->tos); + if (ip_route_output_key(&rt, &key)) { kfree_skb(skb2); return; } @@ -427,7 +431,10 @@ out: if (rt->rt_flags&RTCF_LOCAL) { ip_rt_put(rt); rt = NULL; - if (ip_route_output(&rt, eiph->daddr, eiph->saddr, eiph->tos, 0) || + fl.fl4_daddr = eiph->daddr; + fl.fl4_src = eiph->saddr; + fl.fl4_tos = eiph->tos; + if (ip_route_output_key(&rt, &fl) || rt->u.dst.dev->type != ARPHRD_IPGRE) { ip_rt_put(rt); kfree_skb(skb2); @@ -560,9 +567,16 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) goto tx_error_icmp; } - if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { - tunnel->stat.tx_carrier_errors++; - goto tx_error_icmp; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = dst, + .saddr = tiph->saddr, + .tos = RT_TOS(tos) } }, + .oif = tunnel->parms.link }; + if (ip_route_output_key(&rt, &fl)) { + tunnel->stat.tx_carrier_errors++; + goto tx_error_icmp; + } } tdev = rt->u.dst.dev; @@ -822,8 +836,13 @@ static int ipip_tunnel_init(struct net_device *dev) ipip_tunnel_init_gen(dev); if (iph->daddr) { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->daddr, + .saddr = iph->saddr, + .tos = RT_TOS(iph->tos) } }, + .oif = tunnel->parms.link }; struct rtable *rt; - if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) { + if (!ip_route_output_key(&rt, &fl)) { tdev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index c3db6285f1d4..a5450b23ef8a 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1146,11 +1146,20 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, #endif if (vif->flags&VIFF_TUNNEL) { - if (ip_route_output(&rt, vif->remote, vif->local, RT_TOS(iph->tos), vif->link)) + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = vif->remote, + .saddr = vif->local, + .tos = RT_TOS(iph->tos) } }, + .oif = vif->link }; + if (ip_route_output_key(&rt, &fl)) return; encap = sizeof(struct iphdr); } else { - if (ip_route_output(&rt, iph->daddr, 0, RT_TOS(iph->tos), vif->link)) + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->daddr, + .tos = RT_TOS(iph->tos) } }, + .oif = vif->link }; + if (ip_route_output_key(&rt, &fl)) return; } @@ -1244,7 +1253,7 @@ int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local) if (vif_table[vif].dev != skb->dev) { int true_vifi; - if (((struct rtable*)skb->dst)->key.iif == 0) { + if (((struct rtable*)skb->dst)->fl.iif == 0) { /* It is our own packet, looped back. Very complicated situation... diff --git a/net/ipv4/netfilter/ip_fw_compat_masq.c b/net/ipv4/netfilter/ip_fw_compat_masq.c index 708dff11745b..f522eab4038b 100644 --- a/net/ipv4/netfilter/ip_fw_compat_masq.c +++ b/net/ipv4/netfilter/ip_fw_compat_masq.c @@ -68,12 +68,13 @@ do_masquerade(struct sk_buff **pskb, const struct net_device *dev) /* Setup the masquerade, if not already */ if (!info->initialized) { u_int32_t newsrc; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->daddr } } }; struct rtable *rt; struct ip_nat_multi_range range; /* Pass 0 instead of saddr, since it's going to be changed anyway. */ - if (ip_route_output(&rt, iph->daddr, 0, 0, 0) != 0) { + if (ip_route_output_key(&rt, &fl) != 0) { DEBUGP("ipnat_rule_masquerade: Can't reroute.\n"); return NF_DROP; } diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c index 5c72c54e02b2..38a8e37ffd9a 100644 --- a/net/ipv4/netfilter/ip_nat_core.c +++ b/net/ipv4/netfilter/ip_nat_core.c @@ -209,10 +209,11 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, static int do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp) { + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = var_ip } } }; struct rtable *rt; /* FIXME: IPTOS_TOS(iph->tos) --RR */ - if (ip_route_output(&rt, var_ip, 0, 0, 0) != 0) { + if (ip_route_output_key(&rt, &fl) != 0) { DEBUGP("do_extra_mangle: Can't get route to %u.%u.%u.%u\n", NIPQUAD(var_ip)); return 0; diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 82515c49a8f2..fcbc2341447e 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c @@ -69,7 +69,6 @@ masquerade_target(struct sk_buff **pskb, struct ip_nat_multi_range newrange; u_int32_t newsrc; struct rtable *rt; - struct rt_key key; IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); @@ -84,17 +83,21 @@ masquerade_target(struct sk_buff **pskb, mr = targinfo; - key.dst = (*pskb)->nh.iph->daddr; - key.src = 0; /* Unknown: that's what we're trying to establish */ - key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN; - key.oif = out->ifindex; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = (*pskb)->nh.iph->daddr, + .tos = (RT_TOS((*pskb)->nh.iph->tos) | + RTO_CONN), #ifdef CONFIG_IP_ROUTE_FWMARK - key.fwmark = (*pskb)->nfmark; + .fwmark = (*pskb)->nfmark #endif - if (ip_route_output_key(&rt, &key) != 0) { - /* Shouldn't happen */ - printk("MASQUERADE: No route: Rusty's brain broke!\n"); - return NF_DROP; + } }, + .oif = out->ifindex }; + if (ip_route_output_key(&rt, &fl) != 0) { + /* Shouldn't happen */ + printk("MASQUERADE: No route: Rusty's brain broke!\n"); + return NF_DROP; + } } newsrc = rt->rt_src; diff --git a/net/ipv4/netfilter/ipt_MIRROR.c b/net/ipv4/netfilter/ipt_MIRROR.c index 2fd35b69924f..ba003e5a0dd1 100644 --- a/net/ipv4/netfilter/ipt_MIRROR.c +++ b/net/ipv4/netfilter/ipt_MIRROR.c @@ -44,12 +44,13 @@ struct in_device; static int route_mirror(struct sk_buff *skb) { struct iphdr *iph = skb->nh.iph; + struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr, + .saddr = iph->daddr, + .tos = RT_TOS(iph->tos) | RTO_CONN } } }; struct rtable *rt; /* Backwards */ - if (ip_route_output(&rt, iph->saddr, iph->daddr, - RT_TOS(iph->tos) | RTO_CONN, - 0)) { + if (ip_route_output_key(&rt, &fl)) { return 0; } diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 31adecb393ac..8a444327ae9b 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -130,12 +130,19 @@ static void send_reset(struct sk_buff *oldskb, int local) nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, nskb->nh.iph->ihl); - /* Routing: if not headed for us, route won't like source */ - if (ip_route_output(&rt, nskb->nh.iph->daddr, - local ? nskb->nh.iph->saddr : 0, - RT_TOS(nskb->nh.iph->tos) | RTO_CONN, - 0) != 0) - goto free_nskb; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = nskb->nh.iph->daddr, + .saddr = (local ? + nskb->nh.iph->saddr : + 0), + .tos = (RT_TOS(nskb->nh.iph->tos) | + RTO_CONN) } } }; + + /* Routing: if not headed for us, route won't like source */ + if (ip_route_output_key(&rt, &fl)) + goto free_nskb; + } dst_release(nskb->dst); nskb->dst = &rt->u.dst; @@ -207,9 +214,14 @@ static void send_unreach(struct sk_buff *skb_in, int code) tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL; - if (ip_route_output(&rt, iph->saddr, saddr, RT_TOS(tos), 0)) - return; - + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->saddr, + .saddr = saddr, + .tos = RT_TOS(tos) } } }; + if (ip_route_output_key(&rt, &fl)) + return; + } /* RFC says return as much as we can without exceeding 576 bytes. */ length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 05fe5ed5e64c..26aa9a576e99 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -402,8 +402,14 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len) rfh.saddr = inet->mc_addr; } - err = ip_route_output(&rt, daddr, rfh.saddr, tos, ipc.oif); - + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = rfh.saddr, + .tos = tos } }, + .oif = ipc.oif }; + err = ip_route_output_key(&rt, &fl); + } if (err) goto done; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 692053a355e2..4b3b1aba12e5 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -251,7 +251,7 @@ static int rt_cache_get_info(char *buffer, char **start, off_t offset, (int)r->u.dst.advmss + 40, r->u.dst.window, (int)((r->u.dst.rtt >> 3) + r->u.dst.rttvar), - r->key.tos, + r->fl.fl4_tos, r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1, @@ -332,7 +332,7 @@ static __inline__ int rt_fast_clean(struct rtable *rth) /* Kill broadcast/multicast entries very aggresively, if they collide in hash table with more useful entries */ return (rth->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) && - rth->key.iif && rth->u.rt_next; + rth->fl.iif && rth->u.rt_next; } static __inline__ int rt_valuable(struct rtable *rth) @@ -621,7 +621,7 @@ restart: write_lock_bh(&rt_hash_table[hash].lock); while ((rth = *rthp) != NULL) { - if (memcmp(&rth->key, &rt->key, sizeof(rt->key)) == 0) { + if (memcmp(&rth->fl, &rt->fl, sizeof(rt->fl)) == 0) { /* Put it first */ *rthp = rth->u.rt_next; rth->u.rt_next = rt_hash_table[hash].chain; @@ -643,7 +643,7 @@ restart: /* Try to bind route to arp only if it is output route or unicast forwarding path. */ - if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) { + if (rt->rt_type == RTN_UNICAST || rt->fl.iif == 0) { int err = arp_bind_neighbour(&rt->u.dst); if (err) { write_unlock_bh(&rt_hash_table[hash].lock); @@ -806,11 +806,11 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, while ((rth = *rthp) != NULL) { struct rtable *rt; - if (rth->key.dst != daddr || - rth->key.src != skeys[i] || - rth->key.tos != tos || - rth->key.oif != ikeys[k] || - rth->key.iif != 0) { + if (rth->fl.fl4_dst != daddr || + rth->fl.fl4_src != skeys[i] || + rth->fl.fl4_tos != tos || + rth->fl.oif != ikeys[k] || + rth->fl.iif != 0) { rthp = &rth->u.rt_next; continue; } @@ -901,14 +901,14 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) ret = NULL; } else if ((rt->rt_flags & RTCF_REDIRECTED) || rt->u.dst.expires) { - unsigned hash = rt_hash_code(rt->key.dst, - rt->key.src ^ - (rt->key.oif << 5), - rt->key.tos); + unsigned hash = rt_hash_code(rt->fl.fl4_dst, + rt->fl.fl4_src ^ + (rt->fl.oif << 5), + rt->fl.fl4_tos); #if RT_CACHE_DEBUG >= 1 printk(KERN_DEBUG "ip_rt_advice: redirect to " "%u.%u.%u.%u/%02x dropped\n", - NIPQUAD(rt->rt_dst), rt->key.tos); + NIPQUAD(rt->rt_dst), rt->fl.fl4_tos); #endif rt_del(hash, rt); ret = NULL; @@ -1052,12 +1052,12 @@ unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu) read_lock(&rt_hash_table[hash].lock); for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) { - if (rth->key.dst == daddr && - rth->key.src == skeys[i] && + if (rth->fl.fl4_dst == daddr && + rth->fl.fl4_src == skeys[i] && rth->rt_dst == daddr && rth->rt_src == iph->saddr && - rth->key.tos == tos && - rth->key.iif == 0 && + rth->fl.fl4_tos == tos && + rth->fl.iif == 0 && !(rth->u.dst.mxlock & (1 << RTAX_MTU))) { unsigned short mtu = new_mtu; @@ -1162,9 +1162,9 @@ void ip_rt_get_source(u8 *addr, struct rtable *rt) u32 src; struct fib_result res; - if (rt->key.iif == 0) + if (rt->fl.iif == 0) src = rt->rt_src; - else if (fib_lookup(&rt->key, &res) == 0) { + else if (fib_lookup(&rt->fl, &res) == 0) { #ifdef CONFIG_IP_ROUTE_NAT if (res.type == RTN_NAT) src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, @@ -1263,13 +1263,13 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr, atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; - rth->key.dst = daddr; + rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; - rth->key.tos = tos; + rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark = skb->nfmark; + rth->fl.fl4_fwmark= skb->nfmark; #endif - rth->key.src = saddr; + rth->fl.fl4_src = saddr; rth->rt_src = saddr; #ifdef CONFIG_IP_ROUTE_NAT rth->rt_dst_map = daddr; @@ -1279,10 +1279,10 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr, rth->u.dst.tclassid = itag; #endif rth->rt_iif = - rth->key.iif = dev->ifindex; + rth->fl.iif = dev->ifindex; rth->u.dst.dev = &loopback_dev; dev_hold(rth->u.dst.dev); - rth->key.oif = 0; + rth->fl.oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->rt_type = RTN_MULTICAST; @@ -1324,10 +1324,19 @@ e_inval: int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, u8 tos, struct net_device *dev) { - struct rt_key key; struct fib_result res; struct in_device *in_dev = in_dev_get(dev); struct in_device *out_dev = NULL; + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = saddr, + .tos = tos, + .scope = RT_SCOPE_UNIVERSE, +#ifdef CONFIG_IP_ROUTE_FWMARK + .fwmark = skb->nfmark +#endif + } }, + .iif = dev->ifindex }; unsigned flags = 0; u32 itag = 0; struct rtable * rth; @@ -1341,17 +1350,7 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, if (!in_dev) goto out; - key.dst = daddr; - key.src = saddr; - key.tos = tos; -#ifdef CONFIG_IP_ROUTE_FWMARK - key.fwmark = skb->nfmark; -#endif - key.iif = dev->ifindex; - key.oif = 0; - key.scope = RT_SCOPE_UNIVERSE; - - hash = rt_hash_code(daddr, saddr ^ (key.iif << 5), tos); + hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos); /* Check for the most weird martians, which can be not detected by fib_lookup. @@ -1375,7 +1374,7 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, /* * Now we are ready to route packet. */ - if ((err = fib_lookup(&key, &res)) != 0) { + if ((err = fib_lookup(&fl, &res)) != 0) { if (!IN_DEV_FORWARD(in_dev)) goto e_inval; goto no_route; @@ -1395,17 +1394,17 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, src_map = fib_rules_policy(saddr, &res, &flags); if (res.type == RTN_NAT) { - key.dst = fib_rules_map_destination(daddr, &res); + fl.fl4_dst = fib_rules_map_destination(daddr, &res); fib_res_put(&res); free_res = 0; - if (fib_lookup(&key, &res)) + if (fib_lookup(&fl, &res)) goto e_inval; free_res = 1; if (res.type != RTN_UNICAST) goto e_inval; flags |= RTCF_DNAT; } - key.src = src_map; + fl.fl4_src = src_map; } #endif @@ -1431,8 +1430,8 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, goto martian_destination; #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (res.fi->fib_nhs > 1 && key.oif == 0) - fib_select_multipath(&key, &res); + if (res.fi->fib_nhs > 1 && fl.oif == 0) + fib_select_multipath(&fl, &res); #endif out_dev = in_dev_get(FIB_RES_DEV(res)); if (out_dev == NULL) { @@ -1469,26 +1468,26 @@ int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr, atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; - rth->key.dst = daddr; + rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; - rth->key.tos = tos; + rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark = skb->nfmark; + rth->fl.fl4_fwmark= skb->nfmark; #endif - rth->key.src = saddr; + rth->fl.fl4_src = saddr; rth->rt_src = saddr; rth->rt_gateway = daddr; #ifdef CONFIG_IP_ROUTE_NAT - rth->rt_src_map = key.src; - rth->rt_dst_map = key.dst; + rth->rt_src_map = fl.fl4_src; + rth->rt_dst_map = fl.fl4_dst; if (flags&RTCF_DNAT) - rth->rt_gateway = key.dst; + rth->rt_gateway = fl.fl4_dst; #endif rth->rt_iif = - rth->key.iif = dev->ifindex; + rth->fl.iif = dev->ifindex; rth->u.dst.dev = out_dev->dev; dev_hold(rth->u.dst.dev); - rth->key.oif = 0; + rth->fl.oif = 0; rth->rt_spec_dst= spec_dst; rth->u.dst.input = ip_forward; @@ -1546,26 +1545,25 @@ local_input: atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; - rth->key.dst = daddr; + rth->fl.fl4_dst = daddr; rth->rt_dst = daddr; - rth->key.tos = tos; + rth->fl.fl4_tos = tos; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark = skb->nfmark; + rth->fl.fl4_fwmark= skb->nfmark; #endif - rth->key.src = saddr; + rth->fl.fl4_src = saddr; rth->rt_src = saddr; #ifdef CONFIG_IP_ROUTE_NAT - rth->rt_dst_map = key.dst; - rth->rt_src_map = key.src; + rth->rt_dst_map = fl.fl4_dst; + rth->rt_src_map = fl.fl4_src; #endif #ifdef CONFIG_NET_CLS_ROUTE rth->u.dst.tclassid = itag; #endif rth->rt_iif = - rth->key.iif = dev->ifindex; + rth->fl.iif = dev->ifindex; rth->u.dst.dev = &loopback_dev; dev_hold(rth->u.dst.dev); - rth->key.oif = 0; rth->rt_gateway = daddr; rth->rt_spec_dst= spec_dst; rth->u.dst.input= ip_local_deliver; @@ -1643,14 +1641,14 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, read_lock(&rt_hash_table[hash].lock); for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) { - if (rth->key.dst == daddr && - rth->key.src == saddr && - rth->key.iif == iif && - rth->key.oif == 0 && + if (rth->fl.fl4_dst == daddr && + rth->fl.fl4_src == saddr && + rth->fl.iif == iif && + rth->fl.oif == 0 && #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark == skb->nfmark && + rth->fl.fl4_fwmark == skb->nfmark && #endif - rth->key.tos == tos) { + rth->fl.fl4_tos == tos) { rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); rth->u.dst.__use++; @@ -1699,9 +1697,22 @@ int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr, * Major route resolver routine. */ -int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) +int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) { - struct rt_key key; + u32 tos = oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK); + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = oldflp->fl4_dst, + .saddr = oldflp->fl4_src, + .tos = tos & IPTOS_RT_MASK, + .scope = ((tos & RTO_ONLINK) ? + RT_SCOPE_LINK : + RT_SCOPE_UNIVERSE), +#ifdef CONFIG_IP_ROUTE_FWMARK + .fwmark = oldflp->fl4_fwmark +#endif + } }, + .iif = loopback_dev.ifindex, + .oif = oldflp->oif }; struct fib_result res; unsigned flags = 0; struct rtable *rth; @@ -1709,33 +1720,21 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) unsigned hash; int free_res = 0; int err; - u32 tos; - - tos = oldkey->tos & (IPTOS_RT_MASK | RTO_ONLINK); - key.dst = oldkey->dst; - key.src = oldkey->src; - key.tos = tos & IPTOS_RT_MASK; - key.iif = loopback_dev.ifindex; - key.oif = oldkey->oif; -#ifdef CONFIG_IP_ROUTE_FWMARK - key.fwmark = oldkey->fwmark; -#endif - key.scope = (tos & RTO_ONLINK) ? RT_SCOPE_LINK : - RT_SCOPE_UNIVERSE; + res.fi = NULL; #ifdef CONFIG_IP_MULTIPLE_TABLES res.r = NULL; #endif - if (oldkey->src) { + if (oldflp->fl4_src) { err = -EINVAL; - if (MULTICAST(oldkey->src) || - BADCLASS(oldkey->src) || - ZERONET(oldkey->src)) + if (MULTICAST(oldflp->fl4_src) || + BADCLASS(oldflp->fl4_src) || + ZERONET(oldflp->fl4_src)) goto out; /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - dev_out = ip_dev_find(oldkey->src); + dev_out = ip_dev_find(oldflp->fl4_src); if (dev_out == NULL) goto out; @@ -1747,8 +1746,8 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) of another iface. --ANK */ - if (oldkey->oif == 0 - && (MULTICAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF)) { + if (oldflp->oif == 0 + && (MULTICAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF)) { /* Special hack: user can direct multicasts and limited broadcast via necessary interface without fiddling with IP_MULTICAST_IF or IP_PKTINFO. @@ -1764,15 +1763,15 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) Luckily, this hack is good workaround. */ - key.oif = dev_out->ifindex; + fl.oif = dev_out->ifindex; goto make_route; } if (dev_out) dev_put(dev_out); dev_out = NULL; } - if (oldkey->oif) { - dev_out = dev_get_by_index(oldkey->oif); + if (oldflp->oif) { + dev_out = dev_get_by_index(oldflp->oif); err = -ENODEV; if (dev_out == NULL) goto out; @@ -1781,39 +1780,39 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) goto out; /* Wrong error code */ } - if (LOCAL_MCAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF) { - if (!key.src) - key.src = inet_select_addr(dev_out, 0, - RT_SCOPE_LINK); + if (LOCAL_MCAST(oldflp->fl4_dst) || oldflp->fl4_dst == 0xFFFFFFFF) { + if (!fl.fl4_src) + fl.fl4_src = inet_select_addr(dev_out, 0, + RT_SCOPE_LINK); goto make_route; } - if (!key.src) { - if (MULTICAST(oldkey->dst)) - key.src = inet_select_addr(dev_out, 0, - key.scope); - else if (!oldkey->dst) - key.src = inet_select_addr(dev_out, 0, - RT_SCOPE_HOST); + if (!fl.fl4_src) { + if (MULTICAST(oldflp->fl4_dst)) + fl.fl4_src = inet_select_addr(dev_out, 0, + fl.fl4_scope); + else if (!oldflp->fl4_dst) + fl.fl4_src = inet_select_addr(dev_out, 0, + RT_SCOPE_HOST); } } - if (!key.dst) { - key.dst = key.src; - if (!key.dst) - key.dst = key.src = htonl(INADDR_LOOPBACK); + if (!fl.fl4_dst) { + fl.fl4_dst = fl.fl4_src; + if (!fl.fl4_dst) + fl.fl4_dst = fl.fl4_src = htonl(INADDR_LOOPBACK); if (dev_out) dev_put(dev_out); dev_out = &loopback_dev; dev_hold(dev_out); - key.oif = loopback_dev.ifindex; + fl.oif = loopback_dev.ifindex; res.type = RTN_LOCAL; flags |= RTCF_LOCAL; goto make_route; } - if (fib_lookup(&key, &res)) { + if (fib_lookup(&fl, &res)) { res.fi = NULL; - if (oldkey->oif) { + if (oldflp->oif) { /* Apparently, routing tables are wrong. Assume, that the destination is on link. @@ -1832,9 +1831,9 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) likely IPv6, but we do not. */ - if (key.src == 0) - key.src = inet_select_addr(dev_out, 0, - RT_SCOPE_LINK); + if (fl.fl4_src == 0) + fl.fl4_src = inet_select_addr(dev_out, 0, + RT_SCOPE_LINK); res.type = RTN_UNICAST; goto make_route; } @@ -1849,13 +1848,13 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) goto e_inval; if (res.type == RTN_LOCAL) { - if (!key.src) - key.src = key.dst; + if (!fl.fl4_src) + fl.fl4_src = fl.fl4_dst; if (dev_out) dev_put(dev_out); dev_out = &loopback_dev; dev_hold(dev_out); - key.oif = dev_out->ifindex; + fl.oif = dev_out->ifindex; if (res.fi) fib_info_put(res.fi); res.fi = NULL; @@ -1864,31 +1863,31 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey) } #ifdef CONFIG_IP_ROUTE_MULTIPATH - if (res.fi->fib_nhs > 1 && key.oif == 0) - fib_select_multipath(&key, &res); + if (res.fi->fib_nhs > 1 && fl.oif == 0) + fib_select_multipath(&fl, &res); else #endif - if (!res.prefixlen && res.type == RTN_UNICAST && !key.oif) - fib_select_default(&key, &res); + if (!res.prefixlen && res.type == RTN_UNICAST && !fl.oif) + fib_select_default(&fl, &res); - if (!key.src) - key.src = FIB_RES_PREFSRC(res); + if (!fl.fl4_src) + fl.fl4_src = FIB_RES_PREFSRC(res); if (dev_out) dev_put(dev_out); dev_out = FIB_RES_DEV(res); dev_hold(dev_out); - key.oif = dev_out->ifindex; + fl.oif = dev_out->ifindex; make_route: - if (LOOPBACK(key.src) && !(dev_out->flags&IFF_LOOPBACK)) + if (LOOPBACK(fl.fl4_src) && !(dev_out->flags&IFF_LOOPBACK)) goto e_inval; - if (key.dst == 0xFFFFFFFF) + if (fl.fl4_dst == 0xFFFFFFFF) res.type = RTN_BROADCAST; - else if (MULTICAST(key.dst)) + else if (MULTICAST(fl.fl4_dst)) res.type = RTN_MULTICAST; - else if (BADCLASS(key.dst) || ZERONET(key.dst)) + else if (BADCLASS(fl.fl4_dst) || ZERONET(fl.fl4_dst)) goto e_inval; if (dev_out->flags & IFF_LOOPBACK) @@ -1904,7 +1903,7 @@ make_route: flags |= RTCF_MULTICAST|RTCF_LOCAL; read_lock(&inetdev_lock); if (!__in_dev_get(dev_out) || - !ip_check_mc(__in_dev_get(dev_out), oldkey->dst)) + !ip_check_mc(__in_dev_get(dev_out), oldflp->fl4_dst)) flags &= ~RTCF_LOCAL; read_unlock(&inetdev_lock); /* If multicast route do not exist use @@ -1923,25 +1922,24 @@ make_route: atomic_set(&rth->u.dst.__refcnt, 1); rth->u.dst.flags= DST_HOST; - rth->key.dst = oldkey->dst; - rth->key.tos = tos; - rth->key.src = oldkey->src; - rth->key.iif = 0; - rth->key.oif = oldkey->oif; + rth->fl.fl4_dst = oldflp->fl4_dst; + rth->fl.fl4_tos = tos; + rth->fl.fl4_src = oldflp->fl4_src; + rth->fl.oif = oldflp->oif; #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark = oldkey->fwmark; + rth->fl.fl4_fwmark= oldflp->fl4_fwmark; #endif - rth->rt_dst = key.dst; - rth->rt_src = key.src; + rth->rt_dst = fl.fl4_dst; + rth->rt_src = fl.fl4_src; #ifdef CONFIG_IP_ROUTE_NAT - rth->rt_dst_map = key.dst; - rth->rt_src_map = key.src; + rth->rt_dst_map = fl.fl4_dst; + rth->rt_src_map = fl.fl4_src; #endif - rth->rt_iif = oldkey->oif ? : dev_out->ifindex; + rth->rt_iif = oldflp->oif ? : dev_out->ifindex; rth->u.dst.dev = dev_out; dev_hold(dev_out); - rth->rt_gateway = key.dst; - rth->rt_spec_dst= key.src; + rth->rt_gateway = fl.fl4_dst; + rth->rt_spec_dst= fl.fl4_src; rth->u.dst.output=ip_output; @@ -1949,10 +1947,10 @@ make_route: if (flags & RTCF_LOCAL) { rth->u.dst.input = ip_local_deliver; - rth->rt_spec_dst = key.dst; + rth->rt_spec_dst = fl.fl4_dst; } if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) { - rth->rt_spec_dst = key.src; + rth->rt_spec_dst = fl.fl4_src; if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) { rth->u.dst.output = ip_mc_output; rt_cache_stat[smp_processor_id()].out_slow_mc++; @@ -1962,7 +1960,7 @@ make_route: struct in_device *in_dev = in_dev_get(dev_out); if (in_dev) { if (IN_DEV_MFORWARD(in_dev) && - !LOCAL_MCAST(oldkey->dst)) { + !LOCAL_MCAST(oldflp->fl4_dst)) { rth->u.dst.input = ip_mr_input; rth->u.dst.output = ip_mc_output; } @@ -1976,7 +1974,7 @@ make_route: rth->rt_flags = flags; - hash = rt_hash_code(oldkey->dst, oldkey->src ^ (oldkey->oif << 5), tos); + hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos); err = rt_intern_hash(hash, rth, rp); done: if (free_res) @@ -1993,23 +1991,23 @@ e_nobufs: goto done; } -int ip_route_output_key(struct rtable **rp, const struct rt_key *key) +int ip_route_output_key(struct rtable **rp, const struct flowi *flp) { unsigned hash; struct rtable *rth; - hash = rt_hash_code(key->dst, key->src ^ (key->oif << 5), key->tos); + hash = rt_hash_code(flp->fl4_dst, flp->fl4_src ^ (flp->oif << 5), flp->fl4_tos); read_lock_bh(&rt_hash_table[hash].lock); for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) { - if (rth->key.dst == key->dst && - rth->key.src == key->src && - rth->key.iif == 0 && - rth->key.oif == key->oif && + if (rth->fl.fl4_dst == flp->fl4_dst && + rth->fl.fl4_src == flp->fl4_src && + rth->fl.iif == 0 && + rth->fl.oif == flp->oif && #ifdef CONFIG_IP_ROUTE_FWMARK - rth->key.fwmark == key->fwmark && + rth->fl.fl4_fwmark == flp->fl4_fwmark && #endif - !((rth->key.tos ^ key->tos) & + !((rth->fl.fl4_tos ^ flp->fl4_tos) & (IPTOS_RT_MASK | RTO_ONLINK))) { rth->u.dst.lastuse = jiffies; dst_hold(&rth->u.dst); @@ -2022,7 +2020,7 @@ int ip_route_output_key(struct rtable **rp, const struct rt_key *key) } read_unlock_bh(&rt_hash_table[hash].lock); - return ip_route_output_slow(rp, key); + return ip_route_output_slow(rp, flp); } static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, @@ -2042,7 +2040,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, r->rtm_family = AF_INET; r->rtm_dst_len = 32; r->rtm_src_len = 0; - r->rtm_tos = rt->key.tos; + r->rtm_tos = rt->fl.fl4_tos; r->rtm_table = RT_TABLE_MAIN; r->rtm_type = rt->rt_type; r->rtm_scope = RT_SCOPE_UNIVERSE; @@ -2051,9 +2049,9 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, if (rt->rt_flags & RTCF_NOTIFY) r->rtm_flags |= RTM_F_NOTIFY; RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst); - if (rt->key.src) { + if (rt->fl.fl4_src) { r->rtm_src_len = 32; - RTA_PUT(skb, RTA_SRC, 4, &rt->key.src); + RTA_PUT(skb, RTA_SRC, 4, &rt->fl.fl4_src); } if (rt->u.dst.dev) RTA_PUT(skb, RTA_OIF, sizeof(int), &rt->u.dst.dev->ifindex); @@ -2061,9 +2059,9 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, if (rt->u.dst.tclassid) RTA_PUT(skb, RTA_FLOW, 4, &rt->u.dst.tclassid); #endif - if (rt->key.iif) + if (rt->fl.iif) RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_spec_dst); - else if (rt->rt_src != rt->key.src) + else if (rt->rt_src != rt->fl.fl4_src) RTA_PUT(skb, RTA_PREFSRC, 4, &rt->rt_src); if (rt->rt_dst != rt->rt_gateway) RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway); @@ -2089,7 +2087,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, eptr = (struct rtattr*)skb->tail; #endif RTA_PUT(skb, RTA_CACHEINFO, sizeof(ci), &ci); - if (rt->key.iif) { + if (rt->fl.iif) { #ifdef CONFIG_IP_MROUTE u32 dst = rt->rt_dst; @@ -2109,7 +2107,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, } } else #endif - RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->key.iif); + RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->fl.iif); } nlh->nlmsg_len = skb->tail - b; @@ -2163,10 +2161,14 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) if (!err && rt->u.dst.error) err = -rt->u.dst.error; } else { + struct flowi fl = { .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)); - err = ip_route_output(&rt, dst, src, rtm->rtm_tos, oif); + fl.oif = oif; + err = ip_route_output_key(&rt, &fl); } if (err) { kfree_skb(skb); diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 4061c648dd19..b6de66f262af 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -171,14 +171,17 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, * hasn't changed since we received the original syn, but I see * no easy way to do this. */ - if (ip_route_output(&rt, - opt && - opt->srr ? opt->faddr : req->af.v4_req.rmt_addr, - req->af.v4_req.loc_addr, - RT_CONN_FLAGS(sk), - 0)) { - tcp_openreq_free(req); - goto out; + { + struct flowi fl = { .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) } } }; + if (ip_route_output_key(&rt, &fl)) { + tcp_openreq_free(req); + goto out; + } } /* Try to redo what tcp_v4_send_synack did. */ diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 754d615c1aa5..1caae171c1a6 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1266,11 +1266,15 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk, { struct rtable *rt; struct ip_options *opt = req->af.v4_req.opt; - - if (ip_route_output(&rt, ((opt && opt->srr) ? opt->faddr : - req->af.v4_req.rmt_addr), - req->af.v4_req.loc_addr, - RT_CONN_FLAGS(sk), sk->bound_dev_if)) { + struct flowi fl = { .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 }; + + if (ip_route_output_key(&rt, &fl)) { IP_INC_STATS_BH(IpOutNoRoutes); return NULL; } @@ -1909,8 +1913,15 @@ int tcp_v4_rebuild_header(struct sock *sk) if (inet->opt && inet->opt->srr) daddr = inet->opt->faddr; - err = ip_route_output(&rt, daddr, inet->saddr, - RT_CONN_FLAGS(sk), sk->bound_dev_if); + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = inet->saddr, + .tos = RT_CONN_FLAGS(sk) } }, + .oif = sk->bound_dev_if }; + + err = ip_route_output_key(&rt, &fl); + } if (!err) { __sk_dst_set(sk, &rt->u.dst); tcp_v4_setup_caps(sk, &rt->u.dst); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 04fbbc04f53b..86fee60ce043 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -528,7 +528,12 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len) rt = (struct rtable*)sk_dst_check(sk, 0); if (rt == NULL) { - err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif); + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = daddr, + .saddr = ufh.saddr, + .tos = tos } }, + .oif = ipc.oif }; + err = ip_route_output_key(&rt, &fl); if (err) goto out; diff --git a/net/ipv6/Config.in b/net/ipv6/Config.in index da940bb54629..1a58a98faeeb 100644 --- a/net/ipv6/Config.in +++ b/net/ipv6/Config.in @@ -2,9 +2,6 @@ # IPv6 configuration # -#bool ' IPv6: flow policy support' CONFIG_RT6_POLICY -#bool ' IPv6: firewall support' CONFIG_IPV6_FIREWALL - if [ "$CONFIG_NETFILTER" != "n" ]; then source net/ipv6/netfilter/Config.in fi diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 31f8950011b8..bb23f068cd4a 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -12,7 +12,6 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \ ip6_flowlabel.o ipv6_syms.o -#obj-$(CONFIG_IPV6_FIREWALL) += ip6_fw.o obj-$(CONFIG_NETFILTER) += netfilter/ include $(TOPDIR)/Rules.make diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 5c9d8b0e6f04..3781e05a9cae 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -452,7 +452,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt) */ if ((iter->rt6i_dev == rt->rt6i_dev) && - (iter->rt6i_flowr == rt->rt6i_flowr) && (ipv6_addr_cmp(&iter->rt6i_gateway, &rt->rt6i_gateway) == 0)) { if (!(iter->rt6i_flags&RTF_EXPIRES)) diff --git a/net/ipv6/ip6_fw.c b/net/ipv6/ip6_fw.c deleted file mode 100644 index aa1234efcb31..000000000000 --- a/net/ipv6/ip6_fw.c +++ /dev/null @@ -1,390 +0,0 @@ -/* - * IPv6 Firewall - * Linux INET6 implementation - * - * Authors: - * Pedro Roque - * - * $Id: ip6_fw.c,v 1.16 2001/10/31 08:17:58 davem Exp $ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static unsigned long ip6_fw_rule_cnt; -static struct ip6_fw_rule ip6_fw_rule_list = { - {0}, - NULL, NULL, - {0}, - IP6_FW_REJECT -}; - -static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args); - -struct flow_rule_ops ip6_fw_ops = { - ip6_fw_accept -}; - - -static struct rt6_info ip6_fw_null_entry = { - {{NULL, 0, 0, NULL, - 0, 0, 0, 0, 0, 0, 0, 0, -ENETUNREACH, NULL, NULL, - ip6_pkt_discard, ip6_pkt_discard, NULL}}, - NULL, {{{0}}}, 256, RTF_REJECT|RTF_NONEXTHOP, ~0UL, - 0, &ip6_fw_rule_list, {{{{0}}}, 128}, {{{{0}}}, 128} -}; - -static struct fib6_node ip6_fw_fib = { - NULL, NULL, NULL, NULL, - &ip6_fw_null_entry, - 0, RTN_ROOT|RTN_TL_ROOT, 0 -}; - -rwlock_t ip6_fw_lock = RW_LOCK_UNLOCKED; - - -static void ip6_rule_add(struct ip6_fw_rule *rl) -{ - struct ip6_fw_rule *next; - - write_lock_bh(&ip6_fw_lock); - ip6_fw_rule_cnt++; - next = &ip6_fw_rule_list; - rl->next = next; - rl->prev = next->prev; - rl->prev->next = rl; - next->prev = rl; - write_unlock_bh(&ip6_fw_lock); -} - -static void ip6_rule_del(struct ip6_fw_rule *rl) -{ - struct ip6_fw_rule *next, *prev; - - write_lock_bh(&ip6_fw_lock); - ip6_fw_rule_cnt--; - next = rl->next; - prev = rl->prev; - next->prev = prev; - prev->next = next; - write_unlock_bh(&ip6_fw_lock); -} - -static __inline__ struct ip6_fw_rule * ip6_fwrule_alloc(void) -{ - struct ip6_fw_rule *rl; - - rl = kmalloc(sizeof(struct ip6_fw_rule), GFP_ATOMIC); - if (rl) - { - memset(rl, 0, sizeof(struct ip6_fw_rule)); - rl->flowr.ops = &ip6_fw_ops; - } - return rl; -} - -static __inline__ void ip6_fwrule_free(struct ip6_fw_rule * rl) -{ - kfree(rl); -} - -static __inline__ int port_match(int rl_port, int fl_port) -{ - int res = 0; - if (rl_port == 0 || (rl_port == fl_port)) - res = 1; - return res; -} - -static int ip6_fw_accept_trans(struct ip6_fw_rule *rl, - struct fl_acc_args *args) -{ - int res = FLOWR_NODECISION; - int proto = 0; - int sport = 0; - int dport = 0; - - switch (args->type) { - case FL_ARG_FORWARD: - { - struct sk_buff *skb = args->fl_u.skb; - struct ipv6hdr *hdr = skb->nh.ipv6h; - int len; - - len = skb->len - sizeof(struct ipv6hdr); - - proto = hdr->nexthdr; - - switch (proto) { - case IPPROTO_TCP: - { - struct tcphdr *th; - - if (len < sizeof(struct tcphdr)) { - res = FLOWR_ERROR; - goto out; - } - th = (struct tcphdr *)(hdr + 1); - sport = th->source; - dport = th->dest; - break; - } - case IPPROTO_UDP: - { - struct udphdr *uh; - - if (len < sizeof(struct udphdr)) { - res = FLOWR_ERROR; - goto out; - } - uh = (struct udphdr *)(hdr + 1); - sport = uh->source; - dport = uh->dest; - break; - } - default: - goto out; - }; - break; - } - - case FL_ARG_ORIGIN: - { - proto = args->fl_u.fl_o.flow->proto; - - if (proto == IPPROTO_ICMPV6) { - goto out; - } else { - sport = args->fl_u.fl_o.flow->uli_u.ports.sport; - dport = args->fl_u.fl_o.flow->uli_u.ports.dport; - } - break; - } - - if (proto == rl->info.proto && - port_match(args->fl_u.fl_o.flow->uli_u.ports.sport, sport) && - port_match(args->fl_u.fl_o.flow->uli_u.ports.dport, dport)) { - if (rl->policy & IP6_FW_REJECT) - res = FLOWR_SELECT; - else - res = FLOWR_CLEAR; - } - - default: -#if IP6_FW_DEBUG >= 1 - printk(KERN_DEBUG "ip6_fw_accept: unknown arg type\n"); -#endif - goto out; - }; - -out: - return res; -} - -static int ip6_fw_accept(struct dst_entry *dst, struct fl_acc_args *args) -{ - struct rt6_info *rt; - struct ip6_fw_rule *rl; - int proto; - int res = FLOWR_NODECISION; - - rt = (struct rt6_info *) dst; - rl = (struct ip6_fw_rule *) rt->rt6i_flowr; - - proto = rl->info.proto; - - switch (proto) { - case 0: - if (rl->policy & IP6_FW_REJECT) - res = FLOWR_SELECT; - else - res = FLOWR_CLEAR; - break; - case IPPROTO_TCP: - case IPPROTO_UDP: - res = ip6_fw_accept_trans(rl, args); - break; - case IPPROTO_ICMPV6: - }; - - return res; -} - -static struct dst_entry * ip6_fw_dup(struct dst_entry *frule, - struct dst_entry *rt, - struct fl_acc_args *args) -{ - struct ip6_fw_rule *rl; - struct rt6_info *nrt; - struct rt6_info *frt; - - frt = (struct rt6_info *) frule; - - rl = (struct ip6_fw_rule *) frt->rt6i_flowr; - - nrt = ip6_rt_copy((struct rt6_info *) rt); - - if (nrt) { - nrt->u.dst.input = frule->input; - nrt->u.dst.output = frule->output; - - nrt->rt6i_flowr = flow_clone(frt->rt6i_flowr); - - nrt->rt6i_flags |= RTF_CACHE; - nrt->rt6i_tstamp = jiffies; - } - - return (struct dst_entry *) nrt; -} - -int ip6_fw_reject(struct sk_buff *skb) -{ -#if IP6_FW_DEBUG >= 1 - printk(KERN_DEBUG "packet rejected: \n"); -#endif - - icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, - skb->dev); - /* - * send it via netlink, as (rule, skb) - */ - - kfree_skb(skb); - return 0; -} - -int ip6_fw_discard(struct sk_buff *skb) -{ - printk(KERN_DEBUG "ip6_fw: BUG fw_reject called\n"); - kfree_skb(skb); - return 0; -} - -int ip6_fw_msg_add(struct ip6_fw_msg *msg) -{ - struct in6_rtmsg rtmsg; - struct ip6_fw_rule *rl; - struct rt6_info *rt; - int err; - - ipv6_addr_copy(&rtmsg.rtmsg_dst, &msg->dst); - ipv6_addr_copy(&rtmsg.rtmsg_src, &msg->src); - rtmsg.rtmsg_dst_len = msg->dst_len; - rtmsg.rtmsg_src_len = msg->src_len; - rtmsg.rtmsg_metric = IP6_RT_PRIO_FW; - - rl = ip6_fwrule_alloc(); - - if (rl == NULL) - return -ENOMEM; - - rl->policy = msg->policy; - rl->info.proto = msg->proto; - rl->info.uli_u.data = msg->u.data; - - rtmsg.rtmsg_flags = RTF_NONEXTHOP|RTF_POLICY; - err = ip6_route_add(&rtmsg); - - if (err) { - ip6_fwrule_free(rl); - return err; - } - - /* The rest will not work for now. --ABK (989725) */ - -#ifndef notdef - ip6_fwrule_free(rl); - return -EPERM; -#else - rt->u.dst.error = -EPERM; - - if (msg->policy == IP6_FW_ACCEPT) { - /* - * Accept rules are never selected - * (i.e. packets use normal forwarding) - */ - rt->u.dst.input = ip6_fw_discard; - rt->u.dst.output = ip6_fw_discard; - } else { - rt->u.dst.input = ip6_fw_reject; - rt->u.dst.output = ip6_fw_reject; - } - - ip6_rule_add(rl); - - rt->rt6i_flowr = flow_clone((struct flow_rule *)rl); - - return 0; -#endif -} - -static int ip6_fw_msgrcv(int unit, struct sk_buff *skb) -{ - int count = 0; - - while (skb->len) { - struct ip6_fw_msg *msg; - - if (skb->len < sizeof(struct ip6_fw_msg)) { - count = -EINVAL; - break; - } - - msg = (struct ip6_fw_msg *) skb->data; - skb_pull(skb, sizeof(struct ip6_fw_msg)); - count += sizeof(struct ip6_fw_msg); - - switch (msg->action) { - case IP6_FW_MSG_ADD: - ip6_fw_msg_add(msg); - break; - case IP6_FW_MSG_DEL: - break; - default: - return -EINVAL; - }; - } - - return count; -} - -static void ip6_fw_destroy(struct flow_rule *rl) -{ - ip6_fwrule_free((struct ip6_fw_rule *)rl); -} - -#ifdef MODULE -#define ip6_fw_init module_init -#endif - -void __init ip6_fw_init(void) -{ - netlink_attach(NETLINK_IP6_FW, ip6_fw_msgrcv); -} - -#ifdef MODULE -void cleanup_module(void) -{ - netlink_detach(NETLINK_IP6_FW); -} -#endif diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 65059ed0784f..68136d37eb51 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -56,8 +56,6 @@ #include #endif -#undef CONFIG_RT6_POLICY - /* Set to 3 to get tracing. */ #define RT6_DEBUG 2 @@ -103,16 +101,22 @@ static struct dst_ops ip6_dst_ops = { }; struct rt6_info ip6_null_entry = { - {{NULL, ATOMIC_INIT(1), 1, &loopback_dev, - -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -ENETUNREACH, NULL, NULL, - ip6_pkt_discard, ip6_pkt_discard, -#ifdef CONFIG_NET_CLS_ROUTE - 0, -#endif - &ip6_dst_ops}}, - NULL, {{{0}}}, RTF_REJECT|RTF_NONEXTHOP, ~0U, - 255, ATOMIC_INIT(1), {NULL}, {{{{0}}}, 0}, {{{{0}}}, 0} + .u = { + .dst = { + .__refcnt = ATOMIC_INIT(1), + .__use = 1, + .dev = &loopback_dev, + .obsolete = -1, + .error = -ENETUNREACH, + .input = ip6_pkt_discard, + .output = ip6_pkt_discard, + .ops = &ip6_dst_ops + } + }, + .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), + .rt6i_metric = ~(u32) 0, + .rt6i_hoplimit = 255, + .rt6i_ref = ATOMIC_INIT(1), }; struct fib6_node ip6_routing_table = { @@ -121,24 +125,6 @@ struct fib6_node ip6_routing_table = { 0, RTN_ROOT|RTN_TL_ROOT|RTN_RTINFO, 0 }; -#ifdef CONFIG_RT6_POLICY -int ip6_rt_policy = 0; - -struct pol_chain *rt6_pol_list = NULL; - - -static int rt6_flow_match_in(struct rt6_info *rt, struct sk_buff *skb); -static int rt6_flow_match_out(struct rt6_info *rt, struct sock *sk); - -static struct rt6_info *rt6_flow_lookup(struct rt6_info *rt, - struct in6_addr *daddr, - struct in6_addr *saddr, - struct fl_acc_args *args); - -#else -#define ip6_rt_policy (0) -#endif - /* Protects all the ip6 fib */ rwlock_t rt6_lock = RW_LOCK_UNLOCKED; @@ -386,38 +372,6 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr, return &ip6_null_entry; } -#ifdef CONFIG_RT6_POLICY -static __inline__ struct rt6_info *rt6_flow_lookup_in(struct rt6_info *rt, - struct sk_buff *skb) -{ - struct in6_addr *daddr, *saddr; - struct fl_acc_args arg; - - arg.type = FL_ARG_FORWARD; - arg.fl_u.skb = skb; - - saddr = &skb->nh.ipv6h->saddr; - daddr = &skb->nh.ipv6h->daddr; - - return rt6_flow_lookup(rt, daddr, saddr, &arg); -} - -static __inline__ struct rt6_info *rt6_flow_lookup_out(struct rt6_info *rt, - struct sock *sk, - struct flowi *fl) -{ - struct fl_acc_args arg; - - arg.type = FL_ARG_ORIGIN; - arg.fl_u.fl_o.sk = sk; - arg.fl_u.fl_o.flow = fl; - - return rt6_flow_lookup(rt, fl->nl_u.ip6_u.daddr, fl->nl_u.ip6_u.saddr, - &arg); -} - -#endif - #define BACKTRACK() \ if (rt == &ip6_null_entry && strict) { \ while ((fn = fn->parent) != NULL) { \ @@ -450,53 +404,29 @@ restart: rt = fn->leaf; if ((rt->rt6i_flags & RTF_CACHE)) { - if (ip6_rt_policy == 0) { - rt = rt6_device_match(rt, skb->dev->ifindex, strict); - BACKTRACK(); - dst_clone(&rt->u.dst); - goto out; - } - -#ifdef CONFIG_RT6_POLICY - if ((rt->rt6i_flags & RTF_FLOW)) { - struct rt6_info *sprt; - - for (sprt = rt; sprt; sprt = sprt->u.next) { - if (rt6_flow_match_in(sprt, skb)) { - rt = sprt; - dst_clone(&rt->u.dst); - goto out; - } - } - } -#endif + rt = rt6_device_match(rt, skb->dev->ifindex, strict); + BACKTRACK(); + dst_clone(&rt->u.dst); + goto out; } rt = rt6_device_match(rt, skb->dev->ifindex, 0); BACKTRACK(); - if (ip6_rt_policy == 0) { - if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - read_unlock_bh(&rt6_lock); + if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { + read_unlock_bh(&rt6_lock); - rt = rt6_cow(rt, &skb->nh.ipv6h->daddr, - &skb->nh.ipv6h->saddr); + rt = rt6_cow(rt, &skb->nh.ipv6h->daddr, + &skb->nh.ipv6h->saddr); - if (rt->u.dst.error != -EEXIST || --attempts <= 0) - goto out2; - /* Race condition! In the gap, when rt6_lock was - released someone could insert this route. Relookup. - */ - goto relookup; - } - dst_clone(&rt->u.dst); - } else { -#ifdef CONFIG_RT6_POLICY - rt = rt6_flow_lookup_in(rt, skb); -#else - /* NEVER REACHED */ -#endif + if (rt->u.dst.error != -EEXIST || --attempts <= 0) + goto out2; + /* Race condition! In the gap, when rt6_lock was + released someone could insert this route. Relookup. + */ + goto relookup; } + dst_clone(&rt->u.dst); out: read_unlock_bh(&rt6_lock); @@ -525,26 +455,10 @@ restart: rt = fn->leaf; if ((rt->rt6i_flags & RTF_CACHE)) { - if (ip6_rt_policy == 0) { - rt = rt6_device_match(rt, fl->oif, strict); - BACKTRACK(); - dst_clone(&rt->u.dst); - goto out; - } - -#ifdef CONFIG_RT6_POLICY - if ((rt->rt6i_flags & RTF_FLOW)) { - struct rt6_info *sprt; - - for (sprt = rt; sprt; sprt = sprt->u.next) { - if (rt6_flow_match_out(sprt, sk)) { - rt = sprt; - dst_clone(&rt->u.dst); - goto out; - } - } - } -#endif + rt = rt6_device_match(rt, fl->oif, strict); + BACKTRACK(); + dst_clone(&rt->u.dst); + goto out; } if (rt->rt6i_flags & RTF_DEFAULT) { if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF) @@ -554,29 +468,21 @@ restart: BACKTRACK(); } - if (ip6_rt_policy == 0) { - if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { - read_unlock_bh(&rt6_lock); + if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { + read_unlock_bh(&rt6_lock); - rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, - fl->nl_u.ip6_u.saddr); + rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, + fl->nl_u.ip6_u.saddr); - if (rt->u.dst.error != -EEXIST || --attempts <= 0) - goto out2; + if (rt->u.dst.error != -EEXIST || --attempts <= 0) + goto out2; - /* Race condition! In the gap, when rt6_lock was - released someone could insert this route. Relookup. - */ - goto relookup; - } - dst_clone(&rt->u.dst); - } else { -#ifdef CONFIG_RT6_POLICY - rt = rt6_flow_lookup_out(rt, sk, fl); -#else - /* NEVER REACHED */ -#endif + /* Race condition! In the gap, when rt6_lock was + released someone could insert this route. Relookup. + */ + goto relookup; } + dst_clone(&rt->u.dst); out: read_unlock_bh(&rt6_lock); @@ -1304,121 +1210,6 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev) return err; } -#ifdef CONFIG_RT6_POLICY - -static int rt6_flow_match_in(struct rt6_info *rt, struct sk_buff *skb) -{ - struct flow_filter *frule; - struct pkt_filter *filter; - int res = 1; - - if ((frule = rt->rt6i_filter) == NULL) - goto out; - - if (frule->type != FLR_INPUT) { - res = 0; - goto out; - } - - for (filter = frule->u.filter; filter; filter = filter->next) { - __u32 *word; - - word = (__u32 *) skb->h.raw; - word += filter->offset; - - if ((*word ^ filter->value) & filter->mask) { - res = 0; - break; - } - } - -out: - return res; -} - -static int rt6_flow_match_out(struct rt6_info *rt, struct sock *sk) -{ - struct flow_filter *frule; - int res = 1; - - if ((frule = rt->rt6i_filter) == NULL) - goto out; - - if (frule->type != FLR_INPUT) { - res = 0; - goto out; - } - - if (frule->u.sk != sk) - res = 0; -out: - return res; -} - -static struct rt6_info *rt6_flow_lookup(struct rt6_info *rt, - struct in6_addr *daddr, - struct in6_addr *saddr, - struct fl_acc_args *args) -{ - struct flow_rule *frule; - struct rt6_info *nrt = NULL; - struct pol_chain *pol; - - for (pol = rt6_pol_list; pol; pol = pol->next) { - struct fib6_node *fn; - struct rt6_info *sprt; - - fn = fib6_lookup(pol->rules, daddr, saddr); - - do { - for (sprt = fn->leaf; sprt; sprt=sprt->u.next) { - int res; - - frule = sprt->rt6i_flowr; -#if RT6_DEBUG >= 2 - if (frule == NULL) { - printk(KERN_DEBUG "NULL flowr\n"); - goto error; - } -#endif - res = frule->ops->accept(rt, sprt, args, &nrt); - - switch (res) { - case FLOWR_SELECT: - goto found; - case FLOWR_CLEAR: - goto next_policy; - case FLOWR_NODECISION: - break; - default: - goto error; - }; - } - - fn = fn->parent; - - } while ((fn->fn_flags & RTN_TL_ROOT) == 0); - - next_policy: - } - -error: - dst_clone(&ip6_null_entry.u.dst); - return &ip6_null_entry; - -found: - if (nrt == NULL) - goto error; - - nrt->rt6i_flags |= RTF_CACHE; - dst_clone(&nrt->u.dst); - err = rt6_ins(nrt); - if (err) - nrt->u.dst.error = err; - return nrt; -} -#endif - static int fib6_ifdown(struct rt6_info *rt, void *arg) { if (((void*)rt->rt6i_dev == arg || arg == NULL) && diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 29d9d5bcc3df..ccfd558c1031 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -502,9 +502,16 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) dst = addr6->s6_addr32[3]; } - if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { - tunnel->stat.tx_carrier_errors++; - goto tx_error_icmp; + { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = dst, + .saddr = tiph->saddr, + .tos = RT_TOS(tos) } }, + .oif = tunnel->parms.link }; + if (ip_route_output_key(&rt, &fl)) { + tunnel->stat.tx_carrier_errors++; + goto tx_error_icmp; + } } if (rt->rt_type != RTN_UNICAST) { tunnel->stat.tx_carrier_errors++; @@ -777,8 +784,13 @@ static int ipip6_tunnel_init(struct net_device *dev) ipip6_tunnel_init_gen(dev); if (iph->daddr) { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = iph->daddr, + .saddr = iph->saddr, + .tos = RT_TOS(iph->tos) } }, + .oif = tunnel->parms.link }; struct rtable *rt; - if (!ip_route_output(&rt, iph->daddr, iph->saddr, RT_TOS(iph->tos), tunnel->parms.link)) { + if (!ip_route_output_key(&rt, &fl)) { tdev = rt->u.dst.dev; ip_rt_put(rt); } diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index f25e4be5a8fc..6227b8124c30 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c @@ -154,7 +154,7 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, if (head == NULL) goto old_method; - iif = ((struct rtable*)dst)->key.iif; + iif = ((struct rtable*)dst)->fl.iif; h = route4_fastmap_hash(id, iif); if (id == head->fastmap[h].id && diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 13f0752d00ad..12ff99ea0f89 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -260,16 +260,10 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address) { int dst_mtu = SCTP_DEFAULT_MAXSEGMENT; struct rtable *rt; - struct rt_key key = { - .dst = address->v4.sin_addr.s_addr, - .src = 0, - .iif = 0, - .oif = 0, - .tos = 0, - .scope = 0 - }; - - if (ip_route_output_key(&rt, &key)) { + struct flowi fl = { .nl_u = { .ip4_u = + { .daddr = address->v4.sin_addr.s_addr } } }; + + if (ip_route_output_key(&rt, &fl)) { SCTP_DEBUG_PRINTK("sctp_v4_get_dst_mtu:ip_route_output_key" " failed, returning %d as dst_mtu\n", dst_mtu); -- cgit v1.2.3