Commit dcddf5b0 authored by David S. Miller's avatar David S. Miller

[IPV4]: Use generic struct flowi as routing key.

parent 3f43be64
/* /*
* *
* Flow based forwarding rules (usage: firewalling, etc) * Generic internet FLOW.
* *
*/ */
...@@ -8,12 +8,16 @@ ...@@ -8,12 +8,16 @@
#define _NET_FLOW_H #define _NET_FLOW_H
struct flowi { struct flowi {
int proto; /* {TCP, UDP, ICMP} */ int oif;
int iif;
union { union {
struct { struct {
__u32 daddr; __u32 daddr;
__u32 saddr; __u32 saddr;
__u32 fwmark;
__u8 tos;
__u8 scope;
} ip4_u; } ip4_u;
struct { struct {
...@@ -27,9 +31,12 @@ struct flowi { ...@@ -27,9 +31,12 @@ struct flowi {
#define fl6_flowlabel nl_u.ip6_u.flowlabel #define fl6_flowlabel nl_u.ip6_u.flowlabel
#define fl4_dst nl_u.ip4_u.daddr #define fl4_dst nl_u.ip4_u.daddr
#define fl4_src nl_u.ip4_u.saddr #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 { union {
struct { struct {
__u16 sport; __u16 sport;
...@@ -41,61 +48,8 @@ struct flowi { ...@@ -41,61 +48,8 @@ struct flowi {
__u8 code; __u8 code;
} icmpt; } icmpt;
unsigned long data; __u32 spi;
} uli_u; } 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 #endif
...@@ -70,14 +70,6 @@ struct rt6_info ...@@ -70,14 +70,6 @@ struct rt6_info
u8 rt6i_hoplimit; u8 rt6i_hoplimit;
atomic_t rt6i_ref; 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_dst;
struct rt6key rt6i_src; struct rt6key rt6i_src;
}; };
......
#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
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#define _NET_IP_FIB_H #define _NET_IP_FIB_H
#include <linux/config.h> #include <linux/config.h>
#include <net/flow.h>
struct kern_rta struct kern_rta
{ {
...@@ -117,7 +118,7 @@ struct fib_table ...@@ -117,7 +118,7 @@ struct fib_table
{ {
unsigned char tb_id; unsigned char tb_id;
unsigned tb_stamp; 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, int (*tb_insert)(struct fib_table *table, struct rtmsg *r,
struct kern_rta *rta, struct nlmsghdr *n, struct kern_rta *rta, struct nlmsghdr *n,
struct netlink_skb_parms *req); struct netlink_skb_parms *req);
...@@ -130,7 +131,7 @@ struct fib_table ...@@ -130,7 +131,7 @@ struct fib_table
int (*tb_get_info)(struct fib_table *table, char *buf, int (*tb_get_info)(struct fib_table *table, char *buf,
int first, int count); int first, int count);
void (*tb_select_default)(struct fib_table *table, 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]; unsigned char tb_data[0];
}; };
...@@ -152,18 +153,18 @@ static inline struct fib_table *fib_new_table(int id) ...@@ -152,18 +153,18 @@ static inline struct fib_table *fib_new_table(int id)
return fib_get_table(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) && if (local_table->tb_lookup(local_table, flp, res) &&
main_table->tb_lookup(main_table, key, res)) main_table->tb_lookup(main_table, flp, res))
return -ENETUNREACH; return -ENETUNREACH;
return 0; 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) 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 */ #else /* CONFIG_IP_MULTIPLE_TABLES */
...@@ -171,7 +172,7 @@ static inline void fib_select_default(const struct rt_key *key, struct fib_resul ...@@ -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]) #define main_table (fib_tables[RT_TABLE_MAIN])
extern struct fib_table * fib_tables[RT_TABLE_MAX+1]; 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 struct fib_table *__fib_new_table(int id);
extern void fib_rule_put(struct fib_rule *r); extern void fib_rule_put(struct fib_rule *r);
...@@ -191,7 +192,7 @@ static inline struct fib_table *fib_new_table(int id) ...@@ -191,7 +192,7 @@ static inline struct fib_table *fib_new_table(int id)
return fib_tables[id] ? : __fib_new_table(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 */ #endif /* CONFIG_IP_MULTIPLE_TABLES */
...@@ -204,13 +205,13 @@ extern int inet_rtm_getroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *ar ...@@ -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 inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb);
extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, extern int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
struct net_device *dev, u32 *spec_dst, u32 *itag); 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 */ /* Exported by fib_semantics.c */
extern int ip_fib_check_default(u32 gw, struct net_device *dev); extern int ip_fib_check_default(u32 gw, struct net_device *dev);
extern void fib_release_info(struct fib_info *); extern void fib_release_info(struct fib_info *);
extern int fib_semantic_match(int type, 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, extern struct fib_info *fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
const struct nlmsghdr *, int *err); const struct nlmsghdr *, int *err);
extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi); extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *, struct kern_rta *rta, struct fib_info *fi);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/config.h> #include <linux/config.h>
#include <net/dst.h> #include <net/dst.h>
#include <net/inetpeer.h> #include <net/inetpeer.h>
#include <net/flow.h>
#include <linux/in_route.h> #include <linux/in_route.h>
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <linux/route.h> #include <linux/route.h>
...@@ -45,19 +46,6 @@ ...@@ -45,19 +46,6 @@
#define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sk->localroute) #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 inet_peer;
struct rtable struct rtable
{ {
...@@ -78,7 +66,7 @@ struct rtable ...@@ -78,7 +66,7 @@ struct rtable
__u32 rt_gateway; __u32 rt_gateway;
/* Cache lookup keys */ /* Cache lookup keys */
struct rt_key key; struct flowi fl;
/* Miscellaneous cached information */ /* Miscellaneous cached information */
__u32 rt_spec_dst; /* RFC1122 specific destination */ __u32 rt_spec_dst; /* RFC1122 specific destination */
...@@ -124,7 +112,7 @@ extern void ip_rt_redirect(u32 old_gw, u32 dst, u32 new_gw, ...@@ -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); u32 src, u8 tos, struct net_device *dev);
extern void ip_rt_advice(struct rtable **rp, int advice); extern void ip_rt_advice(struct rtable **rp, int advice);
extern void rt_cache_flush(int how); 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 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 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); 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); ...@@ -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 void ip_rt_get_source(u8 *src, struct rtable *rt);
extern int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb); 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) static inline void ip_rt_put(struct rtable * rt)
{ {
if (rt) if (rt)
...@@ -163,15 +141,20 @@ static inline char rt_tos2priority(u8 tos) ...@@ -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) 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; int err;
err = ip_route_output(rp, dst, src, tos, oif); err = ip_route_output_key(rp, &fl);
if (err || (dst && src)) if (err || (dst && src))
return err; return err;
dst = (*rp)->rt_dst; fl.fl4_dst = (*rp)->rt_dst;
src = (*rp)->rt_src; fl.fl4_src = (*rp)->rt_src;
ip_rt_put(*rp); ip_rt_put(*rp);
*rp = NULL; *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); extern void rt_bind_peer(struct rtable *rt, int create);
......
...@@ -509,6 +509,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip) ...@@ -509,6 +509,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip)
struct atmarp_entry *entry; struct atmarp_entry *entry;
int error; int error;
struct clip_vcc *clip_vcc; struct clip_vcc *clip_vcc;
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip, .tos = 1 } } };
struct rtable *rt; struct rtable *rt;
if (vcc->push != clip_push) { if (vcc->push != clip_push) {
...@@ -525,7 +526,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip) ...@@ -525,7 +526,7 @@ int clip_setentry(struct atm_vcc *vcc,u32 ip)
unlink_clip_vcc(clip_vcc); unlink_clip_vcc(clip_vcc);
return 0; return 0;
} }
error = ip_route_output(&rt,ip,0,1,0); error = ip_route_output_key(&rt,&fl);
if (error) return error; if (error) return error;
neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1); neigh = __neigh_lookup(&clip_tbl,&ip,rt->u.dst.dev,1);
ip_rt_put(rt); ip_rt_put(rt);
......
...@@ -563,13 +563,15 @@ int ip_route_me_harder(struct sk_buff **pskb) ...@@ -563,13 +563,15 @@ int ip_route_me_harder(struct sk_buff **pskb)
{ {
struct iphdr *iph = (*pskb)->nh.iph; struct iphdr *iph = (*pskb)->nh.iph;
struct rtable *rt; struct rtable *rt;
struct rt_key key = { dst:iph->daddr, struct flowi fl = { .nl_u = { .ip4_u =
src:iph->saddr, { .daddr = iph->daddr,
oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, .saddr = iph->saddr,
tos:RT_TOS(iph->tos)|RTO_CONN, .tos = RT_TOS(iph->tos)|RTO_CONN,
#ifdef CONFIG_IP_ROUTE_FWMARK #ifdef CONFIG_IP_ROUTE_FWMARK
fwmark:(*pskb)->nfmark .fwmark = (*pskb)->nfmark
#endif #endif
} },
.oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
}; };
struct net_device *dev_src = NULL; struct net_device *dev_src = NULL;
int err; int err;
...@@ -578,10 +580,10 @@ int ip_route_me_harder(struct sk_buff **pskb) ...@@ -578,10 +580,10 @@ int ip_route_me_harder(struct sk_buff **pskb)
0 or a local address; however some non-standard hacks like 0 or a local address; however some non-standard hacks like
ipt_REJECT.c:send_reset() can cause packets with foreign ipt_REJECT.c:send_reset() can cause packets with foreign
saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */ saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
if(key.src && !(dev_src = ip_dev_find(key.src))) if(fl.fl4_src && !(dev_src = ip_dev_find(fl.fl4_src)))
key.src = 0; 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", 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), NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0, (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
......
...@@ -347,11 +347,13 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) ...@@ -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) 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; struct rtable *rt;
int flag = 0; int flag = 0;
/*unsigned long now; */ /*unsigned long now; */
if (ip_route_output(&rt, sip, tip, 0, 0) < 0) if (ip_route_output_key(&rt, &fl) < 0)
return 1; return 1;
if (rt->u.dst.dev != dev) { if (rt->u.dst.dev != dev) {
NET_INC_STATS_BH(ArpFilter); NET_INC_STATS_BH(ArpFilter);
...@@ -890,8 +892,10 @@ int arp_req_set(struct arpreq *r, struct net_device * dev) ...@@ -890,8 +892,10 @@ int arp_req_set(struct arpreq *r, struct net_device * dev)
if (r->arp_flags & ATF_PERM) if (r->arp_flags & ATF_PERM)
r->arp_flags |= ATF_COM; r->arp_flags |= ATF_COM;
if (dev == NULL) { if (dev == NULL) {
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
.tos = RTO_ONLINK } } };
struct rtable * rt; 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; return err;
dev = rt->u.dst.dev; dev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
...@@ -974,8 +978,10 @@ int arp_req_delete(struct arpreq *r, struct net_device * dev) ...@@ -974,8 +978,10 @@ int arp_req_delete(struct arpreq *r, struct net_device * dev)
} }
if (dev == NULL) { if (dev == NULL) {
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = ip,
.tos = RTO_ONLINK } } };
struct rtable * rt; 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; return err;
dev = rt->u.dst.dev; dev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
......
...@@ -144,17 +144,15 @@ fib_get_procinfo(char *buffer, char **start, off_t offset, int length) ...@@ -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 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 fib_result res;
struct net_device *dev = NULL; struct net_device *dev = NULL;
memset(&key, 0, sizeof(key));
key.dst = addr;
#ifdef CONFIG_IP_MULTIPLE_TABLES #ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL; res.r = NULL;
#endif #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; return NULL;
} }
if (res.type != RTN_LOCAL) if (res.type != RTN_LOCAL)
...@@ -170,7 +168,7 @@ struct net_device * ip_dev_find(u32 addr) ...@@ -170,7 +168,7 @@ struct net_device * ip_dev_find(u32 addr)
unsigned inet_addr_type(u32 addr) unsigned inet_addr_type(u32 addr)
{ {
struct rt_key key; struct flowi fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
struct fib_result res; struct fib_result res;
unsigned ret = RTN_BROADCAST; unsigned ret = RTN_BROADCAST;
...@@ -179,15 +177,13 @@ unsigned inet_addr_type(u32 addr) ...@@ -179,15 +177,13 @@ unsigned inet_addr_type(u32 addr)
if (MULTICAST(addr)) if (MULTICAST(addr))
return RTN_MULTICAST; return RTN_MULTICAST;
memset(&key, 0, sizeof(key));
key.dst = addr;
#ifdef CONFIG_IP_MULTIPLE_TABLES #ifdef CONFIG_IP_MULTIPLE_TABLES
res.r = NULL; res.r = NULL;
#endif #endif
if (local_table) { if (local_table) {
ret = RTN_UNICAST; 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; ret = res.type;
fib_res_put(&res); fib_res_put(&res);
} }
...@@ -207,18 +203,15 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, ...@@ -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 net_device *dev, u32 *spec_dst, u32 *itag)
{ {
struct in_device *in_dev; 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; struct fib_result res;
int no_addr, rpf; int no_addr, rpf;
int ret; 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; no_addr = rpf = 0;
read_lock(&inetdev_lock); read_lock(&inetdev_lock);
in_dev = __in_dev_get(dev); in_dev = __in_dev_get(dev);
...@@ -231,7 +224,7 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, ...@@ -231,7 +224,7 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
if (in_dev == NULL) if (in_dev == NULL)
goto e_inval; goto e_inval;
if (fib_lookup(&key, &res)) if (fib_lookup(&fl, &res))
goto last_resort; goto last_resort;
if (res.type != RTN_UNICAST) if (res.type != RTN_UNICAST)
goto e_inval_res; goto e_inval_res;
...@@ -252,10 +245,10 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif, ...@@ -252,10 +245,10 @@ int fib_validate_source(u32 src, u32 dst, u8 tos, int oif,
goto last_resort; goto last_resort;
if (rpf) if (rpf)
goto e_inval; goto e_inval;
key.oif = dev->ifindex; fl.oif = dev->ifindex;
ret = 0; ret = 0;
if (fib_lookup(&key, &res) == 0) { if (fib_lookup(&fl, &res) == 0) {
if (res.type == RTN_UNICAST) { if (res.type == RTN_UNICAST) {
*spec_dst = FIB_RES_PREFSRC(res); *spec_dst = FIB_RES_PREFSRC(res);
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST; ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
......
...@@ -266,7 +266,7 @@ fn_new_zone(struct fn_hash *table, int z) ...@@ -266,7 +266,7 @@ fn_new_zone(struct fn_hash *table, int z)
} }
static int 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; int err;
struct fn_zone *fz; struct fn_zone *fz;
...@@ -275,7 +275,7 @@ fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result ...@@ -275,7 +275,7 @@ fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result
read_lock(&fib_hash_lock); read_lock(&fib_hash_lock);
for (fz = t->fn_zone_list; fz; fz = fz->fz_next) { for (fz = t->fn_zone_list; fz; fz = fz->fz_next) {
struct fib_node *f; 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) { for (f = fz_chain(k, fz); f; f = f->fn_next) {
if (!fn_key_eq(k, f->fn_key)) { 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 ...@@ -285,17 +285,17 @@ fn_hash_lookup(struct fib_table *tb, const struct rt_key *key, struct fib_result
continue; continue;
} }
#ifdef CONFIG_IP_ROUTE_TOS #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; continue;
#endif #endif
f->fn_state |= FN_S_ACCESSED; f->fn_state |= FN_S_ACCESSED;
if (f->fn_state&FN_S_ZOMBIE) if (f->fn_state&FN_S_ZOMBIE)
continue; continue;
if (f->fn_scope < key->scope) if (f->fn_scope < flp->fl4_scope)
continue; 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) { if (err == 0) {
res->type = f->fn_type; res->type = f->fn_type;
res->scope = f->fn_scope; res->scope = f->fn_scope;
...@@ -338,7 +338,7 @@ static int fib_detect_death(struct fib_info *fi, int order, ...@@ -338,7 +338,7 @@ static int fib_detect_death(struct fib_info *fi, int order,
} }
static void 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; int order, last_idx;
struct fib_node *f; struct fib_node *f;
......
...@@ -307,28 +307,28 @@ static void fib_rules_attach(struct net_device *dev) ...@@ -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; int err;
struct fib_rule *r, *policy; struct fib_rule *r, *policy;
struct fib_table *tb; struct fib_table *tb;
u32 daddr = key->dst; u32 daddr = flp->fl4_dst;
u32 saddr = key->src; u32 saddr = flp->fl4_src;
FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", 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); read_lock(&fib_rules_lock);
for (r = fib_rules; r; r=r->r_next) { for (r = fib_rules; r; r=r->r_next) {
if (((saddr^r->r_src) & r->r_srcmask) || if (((saddr^r->r_src) & r->r_srcmask) ||
((daddr^r->r_dst) & r->r_dstmask) || ((daddr^r->r_dst) & r->r_dstmask) ||
#ifdef CONFIG_IP_ROUTE_TOS #ifdef CONFIG_IP_ROUTE_TOS
(r->r_tos && r->r_tos != key->tos) || (r->r_tos && r->r_tos != flp->fl4_tos) ||
#endif #endif
#ifdef CONFIG_IP_ROUTE_FWMARK #ifdef CONFIG_IP_ROUTE_FWMARK
(r->r_fwmark && r->r_fwmark != key->fwmark) || (r->r_fwmark && r->r_fwmark != flp->fl4_fwmark) ||
#endif #endif
(r->r_ifindex && r->r_ifindex != key->iif)) (r->r_ifindex && r->r_ifindex != flp->iif))
continue; continue;
FRprintk("tb %d r %d ", r->r_table, r->r_action); 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); ...@@ -351,7 +351,7 @@ FRprintk("tb %d r %d ", r->r_table, r->r_action);
if ((tb = fib_get_table(r->r_table)) == NULL) if ((tb = fib_get_table(r->r_table)) == NULL)
continue; continue;
err = tb->tb_lookup(tb, key, res); err = tb->tb_lookup(tb, flp, res);
if (err == 0) { if (err == 0) {
res->r = policy; res->r = policy;
if (policy) if (policy)
...@@ -369,13 +369,13 @@ FRprintk("FAILURE\n"); ...@@ -369,13 +369,13 @@ FRprintk("FAILURE\n");
return -ENETUNREACH; 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 && if (res->r && res->r->r_action == RTN_UNICAST &&
FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) {
struct fib_table *tb; struct fib_table *tb;
if ((tb = fib_get_table(res->r->r_table)) != NULL) if ((tb = fib_get_table(res->r->r_table)) != NULL)
tb->tb_select_default(tb, key, res); tb->tb_select_default(tb, flp, res);
} }
} }
......
...@@ -349,7 +349,6 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n ...@@ -349,7 +349,6 @@ static int fib_check_nh(const struct rtmsg *r, struct fib_info *fi, struct fib_n
int err; int err;
if (nh->nh_gw) { if (nh->nh_gw) {
struct rt_key key;
struct fib_result res; struct fib_result res;
#ifdef CONFIG_IP_ROUTE_PERVASIVE #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 ...@@ -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; nh->nh_scope = RT_SCOPE_LINK;
return 0; return 0;
} }
memset(&key, 0, sizeof(key)); {
key.dst = nh->nh_gw; struct flowi fl = { .nl_u = { .ip4_u =
key.oif = nh->nh_oif; { .daddr = nh->nh_gw,
key.scope = r->rtm_scope + 1; .scope = r->rtm_scope + 1 } },
.oif = nh->nh_oif };
/* It is not necessary, but requires a bit of thinking */
if (key.scope < RT_SCOPE_LINK) /* It is not necessary, but requires a bit of thinking */
key.scope = RT_SCOPE_LINK; if (fl.fl4_scope < RT_SCOPE_LINK)
if ((err = fib_lookup(&key, &res)) != 0) fl.fl4_scope = RT_SCOPE_LINK;
return err; if ((err = fib_lookup(&fl, &res)) != 0)
return err;
}
err = -EINVAL; err = -EINVAL;
if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
goto out; goto out;
...@@ -578,7 +579,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta, ...@@ -578,7 +579,7 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
} }
int 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; 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 ...@@ -603,7 +604,7 @@ fib_semantic_match(int type, struct fib_info *fi, const struct rt_key *key, stru
for_nexthops(fi) { for_nexthops(fi) {
if (nh->nh_flags&RTNH_F_DEAD) if (nh->nh_flags&RTNH_F_DEAD)
continue; continue;
if (!key->oif || key->oif == nh->nh_oif) if (!flp->oif || flp->oif == nh->nh_oif)
break; break;
} }
#ifdef CONFIG_IP_ROUTE_MULTIPATH #ifdef CONFIG_IP_ROUTE_MULTIPATH
...@@ -949,7 +950,7 @@ int fib_sync_up(struct net_device *dev) ...@@ -949,7 +950,7 @@ int fib_sync_up(struct net_device *dev)
fair weighted route distribution. 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; struct fib_info *fi = res->fi;
int w; int w;
......
...@@ -418,9 +418,14 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) ...@@ -418,9 +418,14 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
if (ipc.opt->srr) if (ipc.opt->srr)
daddr = icmp_param->replyopts.faddr; daddr = icmp_param->replyopts.faddr;
} }
if (ip_route_output(&rt, daddr, rt->rt_spec_dst, {
RT_TOS(skb->nh.iph->tos), 0)) struct flowi fl = { .nl_u = { .ip4_u =
goto out_unlock; { .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, if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
icmp_param->data.icmph.code)) { icmp_param->data.icmph.code)) {
ip_build_xmit(sk, icmp_glue_bits, icmp_param, 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) ...@@ -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. * Restore original addresses if packet has been translated.
*/ */
if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) { if (rt->rt_flags & RTCF_NAT && IPCB(skb_in)->flags & IPSKB_TRANSLATED) {
iph->daddr = rt->key.dst; iph->daddr = rt->fl.fl4_dst;
iph->saddr = rt->key.src; iph->saddr = rt->fl.fl4_src;
} }
#endif #endif
...@@ -539,9 +544,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) ...@@ -539,9 +544,13 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
IPTOS_PREC_INTERNETCONTROL) : IPTOS_PREC_INTERNETCONTROL) :
iph->tos; 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)) if (ip_options_echo(&icmp_param.replyopts, skb_in))
goto ende; goto ende;
...@@ -563,9 +572,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info) ...@@ -563,9 +572,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
ipc.addr = iph->saddr; ipc.addr = iph->saddr;
ipc.opt = &icmp_param.replyopts; ipc.opt = &icmp_param.replyopts;
if (icmp_param.replyopts.srr) { 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); ip_rt_put(rt);
if (ip_route_output(&rt, icmp_param.replyopts.faddr, if (ip_route_output_key(&rt, &fl))
saddr, RT_TOS(tos), 0))
goto out_unlock; goto out_unlock;
} }
......
...@@ -207,8 +207,12 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ...@@ -207,8 +207,12 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type)
if (type == IGMP_HOST_LEAVE_MESSAGE) if (type == IGMP_HOST_LEAVE_MESSAGE)
dst = IGMP_ALL_ROUTER; 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) { if (rt->rt_src == 0) {
ip_rt_put(rt); ip_rt_put(rt);
return -1; return -1;
...@@ -374,7 +378,7 @@ int igmp_rcv(struct sk_buff *skb) ...@@ -374,7 +378,7 @@ int igmp_rcv(struct sk_buff *skb)
case IGMP_HOST_MEMBERSHIP_REPORT: case IGMP_HOST_MEMBERSHIP_REPORT:
case IGMP_HOST_NEW_MEMBERSHIP_REPORT: case IGMP_HOST_NEW_MEMBERSHIP_REPORT:
/* Is it our report looped back? */ /* Is it our report looped back? */
if (((struct rtable*)skb->dst)->key.iif == 0) if (((struct rtable*)skb->dst)->fl.iif == 0)
break; break;
igmp_heard_report(in_dev, ih->group); igmp_heard_report(in_dev, ih->group);
break; break;
...@@ -608,6 +612,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev) ...@@ -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) 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 rtable *rt;
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct in_device *idev = NULL; struct in_device *idev = NULL;
...@@ -619,7 +625,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr) ...@@ -619,7 +625,7 @@ static struct in_device * ip_mc_find_dev(struct ip_mreqn *imr)
__dev_put(dev); __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; dev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
} }
......
...@@ -412,6 +412,7 @@ void ipgre_err(struct sk_buff *skb, u32 info) ...@@ -412,6 +412,7 @@ void ipgre_err(struct sk_buff *skb, u32 info)
u16 flags; u16 flags;
int grehlen = (iph->ihl<<2) + 4; int grehlen = (iph->ihl<<2) + 4;
struct sk_buff *skb2; struct sk_buff *skb2;
struct flowi fl;
struct rtable *rt; struct rtable *rt;
if (p[1] != htons(ETH_P_IP)) if (p[1] != htons(ETH_P_IP))
...@@ -488,7 +489,10 @@ void ipgre_err(struct sk_buff *skb, u32 info) ...@@ -488,7 +489,10 @@ void ipgre_err(struct sk_buff *skb, u32 info)
skb2->nh.raw = skb2->data; skb2->nh.raw = skb2->data;
/* Try to guess incoming interface */ /* 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); kfree_skb(skb2);
return; return;
} }
...@@ -498,7 +502,10 @@ void ipgre_err(struct sk_buff *skb, u32 info) ...@@ -498,7 +502,10 @@ void ipgre_err(struct sk_buff *skb, u32 info)
if (rt->rt_flags&RTCF_LOCAL) { if (rt->rt_flags&RTCF_LOCAL) {
ip_rt_put(rt); ip_rt_put(rt);
rt = NULL; 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) { rt->u.dst.dev->type != ARPHRD_IPGRE) {
ip_rt_put(rt); ip_rt_put(rt);
kfree_skb(skb2); kfree_skb(skb2);
...@@ -619,7 +626,7 @@ int ipgre_rcv(struct sk_buff *skb) ...@@ -619,7 +626,7 @@ int ipgre_rcv(struct sk_buff *skb)
#ifdef CONFIG_NET_IPGRE_BROADCAST #ifdef CONFIG_NET_IPGRE_BROADCAST
if (MULTICAST(iph->daddr)) { if (MULTICAST(iph->daddr)) {
/* Looped back packet, drop it! */ /* Looped back packet, drop it! */
if (((struct rtable*)skb->dst)->key.iif == 0) if (((struct rtable*)skb->dst)->fl.iif == 0)
goto drop; goto drop;
tunnel->stat.multicast++; tunnel->stat.multicast++;
skb->pkt_type = PACKET_BROADCAST; skb->pkt_type = PACKET_BROADCAST;
...@@ -749,9 +756,16 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -749,9 +756,16 @@ static int ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
tos &= ~1; tos &= ~1;
} }
if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { {
tunnel->stat.tx_carrier_errors++; struct flowi fl = { .nl_u = { .ip4_u =
goto tx_error; { .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; tdev = rt->u.dst.dev;
...@@ -1104,10 +1118,13 @@ static int ipgre_open(struct net_device *dev) ...@@ -1104,10 +1118,13 @@ static int ipgre_open(struct net_device *dev)
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if (MULTICAST(t->parms.iph.daddr)) { 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; struct rtable *rt;
if (ip_route_output(&rt, t->parms.iph.daddr, if (ip_route_output_key(&rt, &fl)) {
t->parms.iph.saddr, RT_TOS(t->parms.iph.tos),
t->parms.link)) {
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
...@@ -1177,8 +1194,13 @@ static int ipgre_tunnel_init(struct net_device *dev) ...@@ -1177,8 +1194,13 @@ static int ipgre_tunnel_init(struct net_device *dev)
/* Guess output device to choose reasonable mtu and hard_header_len */ /* Guess output device to choose reasonable mtu and hard_header_len */
if (iph->daddr) { 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; 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; tdev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
} }
......
...@@ -117,23 +117,21 @@ ip_do_nat(struct sk_buff *skb) ...@@ -117,23 +117,21 @@ ip_do_nat(struct sk_buff *skb)
if (rt->rt_flags&RTCF_SNAT) { if (rt->rt_flags&RTCF_SNAT) {
if (ciph->daddr != osaddr) { if (ciph->daddr != osaddr) {
struct fib_result res; struct fib_result res;
struct rt_key key;
unsigned flags = 0; unsigned flags = 0;
struct flowi fl = { .nl_u =
key.src = ciph->daddr; { .ip4_u =
key.dst = ciph->saddr; { .daddr = ciph->saddr,
key.iif = skb->dev->ifindex; .saddr = ciph->daddr,
key.oif = 0;
#ifdef CONFIG_IP_ROUTE_TOS #ifdef CONFIG_IP_ROUTE_TOS
key.tos = RT_TOS(ciph->tos); .tos = RT_TOS(ciph->tos)
#endif
#ifdef CONFIG_IP_ROUTE_FWMARK
key.fwmark = 0;
#endif #endif
} },
.iif = skb->dev->ifindex };
/* Use fib_lookup() until we get our own /* Use fib_lookup() until we get our own
* hash table of NATed hosts -- Rani * hash table of NATed hosts -- Rani
*/ */
if (fib_lookup(&key, &res) == 0) { if (fib_lookup(&fl, &res) == 0) {
if (res.r) { if (res.r) {
ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags); ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
if (ciph->daddr != idaddr) if (ciph->daddr != idaddr)
......
...@@ -372,14 +372,20 @@ int ip_queue_xmit(struct sk_buff *skb) ...@@ -372,14 +372,20 @@ int ip_queue_xmit(struct sk_buff *skb)
if(opt && opt->srr) if(opt && opt->srr)
daddr = opt->faddr; daddr = opt->faddr;
/* If this fails, retransmit mechanism of transport layer will {
* keep trying until route appears or the connection times itself struct flowi fl = { .nl_u = { .ip4_u =
* out. { .daddr = daddr,
*/ .saddr = inet->saddr,
if (ip_route_output(&rt, daddr, inet->saddr, .tos = RT_CONN_FLAGS(sk) } },
RT_CONN_FLAGS(sk), .oif = sk->bound_dev_if };
sk->bound_dev_if))
goto no_route; /* 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); __sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(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 ...@@ -991,8 +997,14 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
daddr = replyopts.opt.faddr; 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. /* And let IP do all the hard work.
......
...@@ -355,6 +355,7 @@ void ipip_err(struct sk_buff *skb, u32 info) ...@@ -355,6 +355,7 @@ void ipip_err(struct sk_buff *skb, u32 info)
int rel_code = 0; int rel_code = 0;
int rel_info = 0; int rel_info = 0;
struct sk_buff *skb2; struct sk_buff *skb2;
struct flowi fl;
struct rtable *rt; struct rtable *rt;
if (len < hlen + sizeof(struct iphdr)) if (len < hlen + sizeof(struct iphdr))
...@@ -417,7 +418,10 @@ void ipip_err(struct sk_buff *skb, u32 info) ...@@ -417,7 +418,10 @@ void ipip_err(struct sk_buff *skb, u32 info)
skb2->nh.raw = skb2->data; skb2->nh.raw = skb2->data;
/* Try to guess incoming interface */ /* 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); kfree_skb(skb2);
return; return;
} }
...@@ -427,7 +431,10 @@ void ipip_err(struct sk_buff *skb, u32 info) ...@@ -427,7 +431,10 @@ void ipip_err(struct sk_buff *skb, u32 info)
if (rt->rt_flags&RTCF_LOCAL) { if (rt->rt_flags&RTCF_LOCAL) {
ip_rt_put(rt); ip_rt_put(rt);
rt = NULL; 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) { rt->u.dst.dev->type != ARPHRD_IPGRE) {
ip_rt_put(rt); ip_rt_put(rt);
kfree_skb(skb2); kfree_skb(skb2);
...@@ -560,9 +567,16 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -560,9 +567,16 @@ static int ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
goto tx_error_icmp; goto tx_error_icmp;
} }
if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { {
tunnel->stat.tx_carrier_errors++; struct flowi fl = { .nl_u = { .ip4_u =
goto tx_error_icmp; { .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; tdev = rt->u.dst.dev;
...@@ -822,8 +836,13 @@ static int ipip_tunnel_init(struct net_device *dev) ...@@ -822,8 +836,13 @@ static int ipip_tunnel_init(struct net_device *dev)
ipip_tunnel_init_gen(dev); ipip_tunnel_init_gen(dev);
if (iph->daddr) { 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; 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; tdev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
} }
......
...@@ -1146,11 +1146,20 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, ...@@ -1146,11 +1146,20 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c,
#endif #endif
if (vif->flags&VIFF_TUNNEL) { 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; return;
encap = sizeof(struct iphdr); encap = sizeof(struct iphdr);
} else { } 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; return;
} }
...@@ -1244,7 +1253,7 @@ int ip_mr_forward(struct sk_buff *skb, struct mfc_cache *cache, int local) ...@@ -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) { if (vif_table[vif].dev != skb->dev) {
int true_vifi; 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. /* It is our own packet, looped back.
Very complicated situation... Very complicated situation...
......
...@@ -68,12 +68,13 @@ do_masquerade(struct sk_buff **pskb, const struct net_device *dev) ...@@ -68,12 +68,13 @@ do_masquerade(struct sk_buff **pskb, const struct net_device *dev)
/* Setup the masquerade, if not already */ /* Setup the masquerade, if not already */
if (!info->initialized) { if (!info->initialized) {
u_int32_t newsrc; u_int32_t newsrc;
struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->daddr } } };
struct rtable *rt; struct rtable *rt;
struct ip_nat_multi_range range; struct ip_nat_multi_range range;
/* Pass 0 instead of saddr, since it's going to be changed /* Pass 0 instead of saddr, since it's going to be changed
anyway. */ 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"); DEBUGP("ipnat_rule_masquerade: Can't reroute.\n");
return NF_DROP; return NF_DROP;
} }
......
...@@ -209,10 +209,11 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple, ...@@ -209,10 +209,11 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
static int static int
do_extra_mangle(u_int32_t var_ip, u_int32_t *other_ipp) 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; struct rtable *rt;
/* FIXME: IPTOS_TOS(iph->tos) --RR */ /* 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", DEBUGP("do_extra_mangle: Can't get route to %u.%u.%u.%u\n",
NIPQUAD(var_ip)); NIPQUAD(var_ip));
return 0; return 0;
......
...@@ -69,7 +69,6 @@ masquerade_target(struct sk_buff **pskb, ...@@ -69,7 +69,6 @@ masquerade_target(struct sk_buff **pskb,
struct ip_nat_multi_range newrange; struct ip_nat_multi_range newrange;
u_int32_t newsrc; u_int32_t newsrc;
struct rtable *rt; struct rtable *rt;
struct rt_key key;
IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING); IP_NF_ASSERT(hooknum == NF_IP_POST_ROUTING);
...@@ -84,17 +83,21 @@ masquerade_target(struct sk_buff **pskb, ...@@ -84,17 +83,21 @@ masquerade_target(struct sk_buff **pskb,
mr = targinfo; mr = targinfo;
key.dst = (*pskb)->nh.iph->daddr; {
key.src = 0; /* Unknown: that's what we're trying to establish */ struct flowi fl = { .nl_u = { .ip4_u =
key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN; { .daddr = (*pskb)->nh.iph->daddr,
key.oif = out->ifindex; .tos = (RT_TOS((*pskb)->nh.iph->tos) |
RTO_CONN),
#ifdef CONFIG_IP_ROUTE_FWMARK #ifdef CONFIG_IP_ROUTE_FWMARK
key.fwmark = (*pskb)->nfmark; .fwmark = (*pskb)->nfmark
#endif #endif
if (ip_route_output_key(&rt, &key) != 0) { } },
/* Shouldn't happen */ .oif = out->ifindex };
printk("MASQUERADE: No route: Rusty's brain broke!\n"); if (ip_route_output_key(&rt, &fl) != 0) {
return NF_DROP; /* Shouldn't happen */
printk("MASQUERADE: No route: Rusty's brain broke!\n");
return NF_DROP;
}
} }
newsrc = rt->rt_src; newsrc = rt->rt_src;
......
...@@ -44,12 +44,13 @@ struct in_device; ...@@ -44,12 +44,13 @@ struct in_device;
static int route_mirror(struct sk_buff *skb) static int route_mirror(struct sk_buff *skb)
{ {
struct iphdr *iph = skb->nh.iph; 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; struct rtable *rt;
/* Backwards */ /* Backwards */
if (ip_route_output(&rt, iph->saddr, iph->daddr, if (ip_route_output_key(&rt, &fl)) {
RT_TOS(iph->tos) | RTO_CONN,
0)) {
return 0; return 0;
} }
......
...@@ -130,12 +130,19 @@ static void send_reset(struct sk_buff *oldskb, int local) ...@@ -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->check = ip_fast_csum((unsigned char *)nskb->nh.iph,
nskb->nh.iph->ihl); nskb->nh.iph->ihl);
/* Routing: if not headed for us, route won't like source */ {
if (ip_route_output(&rt, nskb->nh.iph->daddr, struct flowi fl = { .nl_u = { .ip4_u =
local ? nskb->nh.iph->saddr : 0, { .daddr = nskb->nh.iph->daddr,
RT_TOS(nskb->nh.iph->tos) | RTO_CONN, .saddr = (local ?
0) != 0) nskb->nh.iph->saddr :
goto free_nskb; 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); dst_release(nskb->dst);
nskb->dst = &rt->u.dst; nskb->dst = &rt->u.dst;
...@@ -207,9 +214,14 @@ static void send_unreach(struct sk_buff *skb_in, int code) ...@@ -207,9 +214,14 @@ static void send_unreach(struct sk_buff *skb_in, int code)
tos = (iph->tos & IPTOS_TOS_MASK) | IPTOS_PREC_INTERNETCONTROL; 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. */ /* RFC says return as much as we can without exceeding 576 bytes. */
length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr); length = skb_in->len + sizeof(struct iphdr) + sizeof(struct icmphdr);
......
...@@ -402,8 +402,14 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len) ...@@ -402,8 +402,14 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, int len)
rfh.saddr = inet->mc_addr; 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) if (err)
goto done; goto done;
......
This diff is collapsed.
...@@ -171,14 +171,17 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, ...@@ -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 * hasn't changed since we received the original syn, but I see
* no easy way to do this. * no easy way to do this.
*/ */
if (ip_route_output(&rt, {
opt && struct flowi fl = { .nl_u = { .ip4_u =
opt->srr ? opt->faddr : req->af.v4_req.rmt_addr, { .daddr = ((opt && opt->srr) ?
req->af.v4_req.loc_addr, opt->faddr :
RT_CONN_FLAGS(sk), req->af.v4_req.rmt_addr),
0)) { .saddr = req->af.v4_req.loc_addr,
tcp_openreq_free(req); .tos = RT_CONN_FLAGS(sk) } } };
goto out; if (ip_route_output_key(&rt, &fl)) {
tcp_openreq_free(req);
goto out;
}
} }
/* Try to redo what tcp_v4_send_synack did. */ /* Try to redo what tcp_v4_send_synack did. */
......
...@@ -1266,11 +1266,15 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk, ...@@ -1266,11 +1266,15 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk,
{ {
struct rtable *rt; struct rtable *rt;
struct ip_options *opt = req->af.v4_req.opt; struct ip_options *opt = req->af.v4_req.opt;
struct flowi fl = { .nl_u = { .ip4_u =
if (ip_route_output(&rt, ((opt && opt->srr) ? opt->faddr : { .daddr = ((opt && opt->srr) ?
req->af.v4_req.rmt_addr), opt->faddr :
req->af.v4_req.loc_addr, req->af.v4_req.rmt_addr),
RT_CONN_FLAGS(sk), sk->bound_dev_if)) { .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); IP_INC_STATS_BH(IpOutNoRoutes);
return NULL; return NULL;
} }
...@@ -1909,8 +1913,15 @@ int tcp_v4_rebuild_header(struct sock *sk) ...@@ -1909,8 +1913,15 @@ int tcp_v4_rebuild_header(struct sock *sk)
if (inet->opt && inet->opt->srr) if (inet->opt && inet->opt->srr)
daddr = inet->opt->faddr; 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) { if (!err) {
__sk_dst_set(sk, &rt->u.dst); __sk_dst_set(sk, &rt->u.dst);
tcp_v4_setup_caps(sk, &rt->u.dst); tcp_v4_setup_caps(sk, &rt->u.dst);
......
...@@ -528,7 +528,12 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len) ...@@ -528,7 +528,12 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, int len)
rt = (struct rtable*)sk_dst_check(sk, 0); rt = (struct rtable*)sk_dst_check(sk, 0);
if (rt == NULL) { 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) if (err)
goto out; goto out;
......
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
# IPv6 configuration # IPv6 configuration
# #
#bool ' IPv6: flow policy support' CONFIG_RT6_POLICY
#bool ' IPv6: firewall support' CONFIG_IPV6_FIREWALL
if [ "$CONFIG_NETFILTER" != "n" ]; then if [ "$CONFIG_NETFILTER" != "n" ]; then
source net/ipv6/netfilter/Config.in source net/ipv6/netfilter/Config.in
fi fi
...@@ -12,7 +12,6 @@ ipv6-objs := af_inet6.o ip6_output.o ip6_input.o addrconf.o sit.o \ ...@@ -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 \ exthdrs.o sysctl_net_ipv6.o datagram.o proc.o \
ip6_flowlabel.o ipv6_syms.o ip6_flowlabel.o ipv6_syms.o
#obj-$(CONFIG_IPV6_FIREWALL) += ip6_fw.o
obj-$(CONFIG_NETFILTER) += netfilter/ obj-$(CONFIG_NETFILTER) += netfilter/
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
...@@ -452,7 +452,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt) ...@@ -452,7 +452,6 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt)
*/ */
if ((iter->rt6i_dev == rt->rt6i_dev) && if ((iter->rt6i_dev == rt->rt6i_dev) &&
(iter->rt6i_flowr == rt->rt6i_flowr) &&
(ipv6_addr_cmp(&iter->rt6i_gateway, (ipv6_addr_cmp(&iter->rt6i_gateway,
&rt->rt6i_gateway) == 0)) { &rt->rt6i_gateway) == 0)) {
if (!(iter->rt6i_flags&RTF_EXPIRES)) if (!(iter->rt6i_flags&RTF_EXPIRES))
......
/*
* 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
...@@ -56,8 +56,6 @@ ...@@ -56,8 +56,6 @@
#include <linux/sysctl.h> #include <linux/sysctl.h>
#endif #endif
#undef CONFIG_RT6_POLICY
/* Set to 3 to get tracing. */ /* Set to 3 to get tracing. */
#define RT6_DEBUG 2 #define RT6_DEBUG 2
...@@ -103,16 +101,22 @@ static struct dst_ops ip6_dst_ops = { ...@@ -103,16 +101,22 @@ static struct dst_ops ip6_dst_ops = {
}; };
struct rt6_info ip6_null_entry = { struct rt6_info ip6_null_entry = {
{{NULL, ATOMIC_INIT(1), 1, &loopback_dev, .u = {
-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, .dst = {
-ENETUNREACH, NULL, NULL, .__refcnt = ATOMIC_INIT(1),
ip6_pkt_discard, ip6_pkt_discard, .__use = 1,
#ifdef CONFIG_NET_CLS_ROUTE .dev = &loopback_dev,
0, .obsolete = -1,
#endif .error = -ENETUNREACH,
&ip6_dst_ops}}, .input = ip6_pkt_discard,
NULL, {{{0}}}, RTF_REJECT|RTF_NONEXTHOP, ~0U, .output = ip6_pkt_discard,
255, ATOMIC_INIT(1), {NULL}, {{{{0}}}, 0}, {{{{0}}}, 0} .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 = { struct fib6_node ip6_routing_table = {
...@@ -121,24 +125,6 @@ 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 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 */ /* Protects all the ip6 fib */
rwlock_t rt6_lock = RW_LOCK_UNLOCKED; 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, ...@@ -386,38 +372,6 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
return &ip6_null_entry; 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() \ #define BACKTRACK() \
if (rt == &ip6_null_entry && strict) { \ if (rt == &ip6_null_entry && strict) { \
while ((fn = fn->parent) != NULL) { \ while ((fn = fn->parent) != NULL) { \
...@@ -450,53 +404,29 @@ void ip6_route_input(struct sk_buff *skb) ...@@ -450,53 +404,29 @@ void ip6_route_input(struct sk_buff *skb)
rt = fn->leaf; rt = fn->leaf;
if ((rt->rt6i_flags & RTF_CACHE)) { if ((rt->rt6i_flags & RTF_CACHE)) {
if (ip6_rt_policy == 0) { rt = rt6_device_match(rt, skb->dev->ifindex, strict);
rt = rt6_device_match(rt, skb->dev->ifindex, strict); BACKTRACK();
BACKTRACK(); dst_clone(&rt->u.dst);
dst_clone(&rt->u.dst); goto out;
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, 0); rt = rt6_device_match(rt, skb->dev->ifindex, 0);
BACKTRACK(); BACKTRACK();
if (ip6_rt_policy == 0) { if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { read_unlock_bh(&rt6_lock);
read_unlock_bh(&rt6_lock);
rt = rt6_cow(rt, &skb->nh.ipv6h->daddr, rt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
&skb->nh.ipv6h->saddr); &skb->nh.ipv6h->saddr);
if (rt->u.dst.error != -EEXIST || --attempts <= 0) if (rt->u.dst.error != -EEXIST || --attempts <= 0)
goto out2; goto out2;
/* Race condition! In the gap, when rt6_lock was /* Race condition! In the gap, when rt6_lock was
released someone could insert this route. Relookup. released someone could insert this route. Relookup.
*/ */
goto relookup; goto relookup;
}
dst_clone(&rt->u.dst);
} else {
#ifdef CONFIG_RT6_POLICY
rt = rt6_flow_lookup_in(rt, skb);
#else
/* NEVER REACHED */
#endif
} }
dst_clone(&rt->u.dst);
out: out:
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
...@@ -525,26 +455,10 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) ...@@ -525,26 +455,10 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
rt = fn->leaf; rt = fn->leaf;
if ((rt->rt6i_flags & RTF_CACHE)) { if ((rt->rt6i_flags & RTF_CACHE)) {
if (ip6_rt_policy == 0) { rt = rt6_device_match(rt, fl->oif, strict);
rt = rt6_device_match(rt, fl->oif, strict); BACKTRACK();
BACKTRACK(); dst_clone(&rt->u.dst);
dst_clone(&rt->u.dst); goto out;
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
} }
if (rt->rt6i_flags & RTF_DEFAULT) { if (rt->rt6i_flags & RTF_DEFAULT) {
if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF) if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF)
...@@ -554,29 +468,21 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) ...@@ -554,29 +468,21 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
BACKTRACK(); BACKTRACK();
} }
if (ip6_rt_policy == 0) { if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { read_unlock_bh(&rt6_lock);
read_unlock_bh(&rt6_lock);
rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr,
fl->nl_u.ip6_u.saddr); fl->nl_u.ip6_u.saddr);
if (rt->u.dst.error != -EEXIST || --attempts <= 0) if (rt->u.dst.error != -EEXIST || --attempts <= 0)
goto out2; goto out2;
/* Race condition! In the gap, when rt6_lock was /* Race condition! In the gap, when rt6_lock was
released someone could insert this route. Relookup. released someone could insert this route. Relookup.
*/ */
goto 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
} }
dst_clone(&rt->u.dst);
out: out:
read_unlock_bh(&rt6_lock); read_unlock_bh(&rt6_lock);
...@@ -1304,121 +1210,6 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev) ...@@ -1304,121 +1210,6 @@ int ip6_rt_addr_del(struct in6_addr *addr, struct net_device *dev)
return err; 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) static int fib6_ifdown(struct rt6_info *rt, void *arg)
{ {
if (((void*)rt->rt6i_dev == arg || arg == NULL) && if (((void*)rt->rt6i_dev == arg || arg == NULL) &&
......
...@@ -502,9 +502,16 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -502,9 +502,16 @@ static int ipip6_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
dst = addr6->s6_addr32[3]; dst = addr6->s6_addr32[3];
} }
if (ip_route_output(&rt, dst, tiph->saddr, RT_TOS(tos), tunnel->parms.link)) { {
tunnel->stat.tx_carrier_errors++; struct flowi fl = { .nl_u = { .ip4_u =
goto tx_error_icmp; { .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) { if (rt->rt_type != RTN_UNICAST) {
tunnel->stat.tx_carrier_errors++; tunnel->stat.tx_carrier_errors++;
...@@ -777,8 +784,13 @@ static int ipip6_tunnel_init(struct net_device *dev) ...@@ -777,8 +784,13 @@ static int ipip6_tunnel_init(struct net_device *dev)
ipip6_tunnel_init_gen(dev); ipip6_tunnel_init_gen(dev);
if (iph->daddr) { 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; 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; tdev = rt->u.dst.dev;
ip_rt_put(rt); ip_rt_put(rt);
} }
......
...@@ -154,7 +154,7 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp, ...@@ -154,7 +154,7 @@ static int route4_classify(struct sk_buff *skb, struct tcf_proto *tp,
if (head == NULL) if (head == NULL)
goto old_method; goto old_method;
iif = ((struct rtable*)dst)->key.iif; iif = ((struct rtable*)dst)->fl.iif;
h = route4_fastmap_hash(id, iif); h = route4_fastmap_hash(id, iif);
if (id == head->fastmap[h].id && if (id == head->fastmap[h].id &&
......
...@@ -260,16 +260,10 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address) ...@@ -260,16 +260,10 @@ int sctp_v4_get_dst_mtu(const sockaddr_storage_t *address)
{ {
int dst_mtu = SCTP_DEFAULT_MAXSEGMENT; int dst_mtu = SCTP_DEFAULT_MAXSEGMENT;
struct rtable *rt; struct rtable *rt;
struct rt_key key = { struct flowi fl = { .nl_u = { .ip4_u =
.dst = address->v4.sin_addr.s_addr, { .daddr = address->v4.sin_addr.s_addr } } };
.src = 0,
.iif = 0, if (ip_route_output_key(&rt, &fl)) {
.oif = 0,
.tos = 0,
.scope = 0
};
if (ip_route_output_key(&rt, &key)) {
SCTP_DEBUG_PRINTK("sctp_v4_get_dst_mtu:ip_route_output_key" SCTP_DEBUG_PRINTK("sctp_v4_get_dst_mtu:ip_route_output_key"
" failed, returning %d as dst_mtu\n", " failed, returning %d as dst_mtu\n",
dst_mtu); dst_mtu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment