summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/flow.h70
-rw-r--r--include/net/ip6_fib.h8
-rw-r--r--include/net/ip6_fw.h54
-rw-r--r--include/net/ip_fib.h23
-rw-r--r--include/net/route.h41
-rw-r--r--net/atm/clip.c3
-rw-r--r--net/core/netfilter.c18
-rw-r--r--net/ipv4/arp.c12
-rw-r--r--net/ipv4/fib_frontend.c31
-rw-r--r--net/ipv4/fib_hash.c12
-rw-r--r--net/ipv4/fib_rules.c20
-rw-r--r--net/ipv4/fib_semantics.c29
-rw-r--r--net/ipv4/icmp.c32
-rw-r--r--net/ipv4/igmp.c14
-rw-r--r--net/ipv4/ip_gre.c42
-rw-r--r--net/ipv4/ip_nat_dumb.c20
-rw-r--r--net/ipv4/ip_output.c32
-rw-r--r--net/ipv4/ipip.c31
-rw-r--r--net/ipv4/ipmr.c15
-rw-r--r--net/ipv4/netfilter/ip_fw_compat_masq.c3
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c3
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c23
-rw-r--r--net/ipv4/netfilter/ipt_MIRROR.c7
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c30
-rw-r--r--net/ipv4/raw.c10
-rw-r--r--net/ipv4/route.c326
-rw-r--r--net/ipv4/syncookies.c19
-rw-r--r--net/ipv4/tcp_ipv4.c25
-rw-r--r--net/ipv4/udp.c7
-rw-r--r--net/ipv6/Config.in3
-rw-r--r--net/ipv6/Makefile1
-rw-r--r--net/ipv6/ip6_fib.c1
-rw-r--r--net/ipv6/ip6_fw.c390
-rw-r--r--net/ipv6/route.c301
-rw-r--r--net/ipv6/sit.c20
-rw-r--r--net/sched/cls_route.c2
-rw-r--r--net/sctp/protocol.c14
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);