diff options
| author | David S. Miller <davem@nuts.ninka.net> | 2002-10-11 02:10:08 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-10-11 02:10:08 -0700 |
| commit | dcddf5b041daf44bd0336574ab5e2f0233ca0709 (patch) | |
| tree | 7d66c0df4121ffbf1298d142d99e0507ea3f71b6 | |
| parent | 3f43be64b1c47e48b029ecffa168762b17c0a3c9 (diff) | |
[IPV4]: Use generic struct flowi as routing key.
37 files changed, 548 insertions, 1144 deletions
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 <net/flow.h> - -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 <linux/config.h> +#include <net/flow.h> 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 <linux/config.h> #include <net/dst.h> #include <net/inetpeer.h> +#include <net/flow.h> #include <linux/in_route.h> #include <linux/rtnetlink.h> #include <linux/route.h> @@ -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 <roque@di.fc.ul.pt> - * - * $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 <linux/config.h> -#include <linux/errno.h> -#include <linux/types.h> -#include <linux/string.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/net.h> -#include <linux/route.h> -#include <linux/netdevice.h> -#include <linux/in6.h> -#include <linux/udp.h> -#include <linux/init.h> - -#include <net/ipv6.h> -#include <net/ip6_route.h> -#include <net/ip6_fw.h> -#include <net/netlink.h> - -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 <linux/sysctl.h> #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); |
