Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
dcddf5b0
Commit
dcddf5b0
authored
Oct 11, 2002
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV4]: Use generic struct flowi as routing key.
parent
3f43be64
Changes
37
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
548 additions
and
1144 deletions
+548
-1144
include/net/flow.h
include/net/flow.h
+12
-58
include/net/ip6_fib.h
include/net/ip6_fib.h
+0
-8
include/net/ip6_fw.h
include/net/ip6_fw.h
+0
-54
include/net/ip_fib.h
include/net/ip_fib.h
+12
-11
include/net/route.h
include/net/route.h
+12
-29
net/atm/clip.c
net/atm/clip.c
+2
-1
net/core/netfilter.c
net/core/netfilter.c
+10
-8
net/ipv4/arp.c
net/ipv4/arp.c
+9
-3
net/ipv4/fib_frontend.c
net/ipv4/fib_frontend.c
+12
-19
net/ipv4/fib_hash.c
net/ipv4/fib_hash.c
+6
-6
net/ipv4/fib_rules.c
net/ipv4/fib_rules.c
+10
-10
net/ipv4/fib_semantics.c
net/ipv4/fib_semantics.c
+15
-14
net/ipv4/icmp.c
net/ipv4/icmp.c
+22
-10
net/ipv4/igmp.c
net/ipv4/igmp.c
+10
-4
net/ipv4/ip_gre.c
net/ipv4/ip_gre.c
+32
-10
net/ipv4/ip_nat_dumb.c
net/ipv4/ip_nat_dumb.c
+9
-11
net/ipv4/ip_output.c
net/ipv4/ip_output.c
+22
-10
net/ipv4/ipip.c
net/ipv4/ipip.c
+25
-6
net/ipv4/ipmr.c
net/ipv4/ipmr.c
+12
-3
net/ipv4/netfilter/ip_fw_compat_masq.c
net/ipv4/netfilter/ip_fw_compat_masq.c
+2
-1
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_core.c
+2
-1
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/ipt_MASQUERADE.c
+13
-10
net/ipv4/netfilter/ipt_MIRROR.c
net/ipv4/netfilter/ipt_MIRROR.c
+4
-3
net/ipv4/netfilter/ipt_REJECT.c
net/ipv4/netfilter/ipt_REJECT.c
+21
-9
net/ipv4/raw.c
net/ipv4/raw.c
+8
-2
net/ipv4/route.c
net/ipv4/route.c
+164
-162
net/ipv4/syncookies.c
net/ipv4/syncookies.c
+11
-8
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_ipv4.c
+18
-7
net/ipv4/udp.c
net/ipv4/udp.c
+6
-1
net/ipv6/Config.in
net/ipv6/Config.in
+0
-3
net/ipv6/Makefile
net/ipv6/Makefile
+0
-1
net/ipv6/ip6_fib.c
net/ipv6/ip6_fib.c
+0
-1
net/ipv6/ip6_fw.c
net/ipv6/ip6_fw.c
+0
-390
net/ipv6/route.c
net/ipv6/route.c
+46
-255
net/ipv6/sit.c
net/ipv6/sit.c
+16
-4
net/sched/cls_route.c
net/sched/cls_route.c
+1
-1
net/sctp/protocol.c
net/sctp/protocol.c
+4
-10
No files found.
include/net/flow.h
View file @
dcddf5b0
/*
*
*
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
include/net/ip6_fib.h
View file @
dcddf5b0
...
...
@@ -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
;
};
...
...
include/net/ip6_fw.h
deleted
100644 → 0
View file @
3f43be64
#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
include/net/ip_fib.h
View file @
dcddf5b0
...
...
@@ -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
);
...
...
include/net/route.h
View file @
dcddf5b0
...
...
@@ -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
);
...
...
net/atm/clip.c
View file @
dcddf5b0
...
...
@@ -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
);
...
...
net/core/netfilter.c
View file @
dcddf5b0
...
...
@@ -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
->
s
addr
,
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
->
d
addr
,
.
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
,
...
...
net/ipv4/arp.c
View file @
dcddf5b0
...
...
@@ -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
);
...
...
net/ipv4/fib_frontend.c
View file @
dcddf5b0
...
...
@@ -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 @@ struct net_device * ip_dev_find(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
;
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
;
...
...
net/ipv4/fib_hash.c
View file @
dcddf5b0
...
...
@@ -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
;
...
...
net/ipv4/fib_rules.c
View file @
dcddf5b0
...
...
@@ -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
);
}
}
...
...
net/ipv4/fib_semantics.c
View file @
dcddf5b0
...
...
@@ -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
;
{
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
(
key
.
scope
<
RT_SCOPE_LINK
)
key
.
scope
=
RT_SCOPE_LINK
;
if
((
err
=
fib_lookup
(
&
key
,
&
res
))
!=
0
)
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 @@ fib_create_info(const struct rtmsg *r, struct kern_rta *rta,
}
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
;
...
...
net/ipv4/icmp.c
View file @
dcddf5b0
...
...
@@ -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
))
{
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
))
{
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
;
}
...
...
net/ipv4/igmp.c
View file @
dcddf5b0
...
...
@@ -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
))
{
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
);
}
...
...
net/ipv4/ip_gre.c
View file @
dcddf5b0
...
...
@@ -412,6 +412,7 @@ void ipgre_err(struct sk_buff *skb, u32 info)
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 @@ void ipgre_err(struct sk_buff *skb, u32 info)
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 @@ void ipgre_err(struct sk_buff *skb, u32 info)
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,10 +756,17 @@ 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
))
{
{
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
;
if
(
tdev
==
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
);
}
...
...
net/ipv4/ip_nat_dumb.c
View file @
dcddf5b0
...
...
@@ -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
)
...
...
net/ipv4/ip_output.c
View file @
dcddf5b0
...
...
@@ -372,14 +372,20 @@ int ip_queue_xmit(struct sk_buff *skb)
if
(
opt
&&
opt
->
srr
)
daddr
=
opt
->
faddr
;
{
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
(
&
rt
,
daddr
,
inet
->
saddr
,
RT_CONN_FLAGS
(
sk
),
sk
->
bound_dev_if
))
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
))
{
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.
...
...
net/ipv4/ipip.c
View file @
dcddf5b0
...
...
@@ -355,6 +355,7 @@ void ipip_err(struct sk_buff *skb, u32 info)
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 @@ void ipip_err(struct sk_buff *skb, u32 info)
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 @@ void ipip_err(struct sk_buff *skb, u32 info)
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,10 +567,17 @@ 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
))
{
{
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
;
if
(
tdev
==
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
);
}
...
...
net/ipv4/ipmr.c
View file @
dcddf5b0
...
...
@@ -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...
...
...
net/ipv4/netfilter/ip_fw_compat_masq.c
View file @
dcddf5b0
...
...
@@ -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
;
}
...
...
net/ipv4/netfilter/ip_nat_core.c
View file @
dcddf5b0
...
...
@@ -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
;
...
...
net/ipv4/netfilter/ipt_MASQUERADE.c
View file @
dcddf5b0
...
...
@@ -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,18 +83,22 @@ 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
)
{
}
},
.
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
;
DEBUGP
(
"newsrc = %u.%u.%u.%u
\n
"
,
NIPQUAD
(
newsrc
));
...
...
net/ipv4/netfilter/ipt_MIRROR.c
View file @
dcddf5b0
...
...
@@ -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
;
}
...
...
net/ipv4/netfilter/ipt_REJECT.c
View file @
dcddf5b0
...
...
@@ -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
);
{
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
(
&
rt
,
nskb
->
nh
.
iph
->
daddr
,
local
?
nskb
->
nh
.
iph
->
saddr
:
0
,
RT_TOS
(
nskb
->
nh
.
iph
->
tos
)
|
RTO_CONN
,
0
)
!=
0
)
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
))
{
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
);
...
...
net/ipv4/raw.c
View file @
dcddf5b0
...
...
@@ -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
;
...
...
net/ipv4/route.c
View file @
dcddf5b0
...
...
@@ -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 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
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 @@ static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
/* 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 @@ static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
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 @@ out: return err;
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
(
old
key
->
src
)
{
if
(
old
flp
->
fl4_
src
)
{
err
=
-
EINVAL
;
if
(
MULTICAST
(
old
key
->
src
)
||
BADCLASS
(
old
key
->
src
)
||
ZERONET
(
old
key
->
src
))
if
(
MULTICAST
(
old
flp
->
fl4_
src
)
||
BADCLASS
(
old
flp
->
fl4_
src
)
||
ZERONET
(
old
flp
->
fl4_
src
))
goto
out
;
/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
dev_out
=
ip_dev_find
(
old
key
->
src
);
dev_out
=
ip_dev_find
(
old
flp
->
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
(
old
key
->
oif
==
0
&&
(
MULTICAST
(
old
key
->
dst
)
||
oldkey
->
dst
==
0xFFFFFFFF
))
{
if
(
old
flp
->
oif
==
0
&&
(
MULTICAST
(
old
flp
->
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
(
old
key
->
oif
)
{
dev_out
=
dev_get_by_index
(
old
key
->
oif
);
if
(
old
flp
->
oif
)
{
dev_out
=
dev_get_by_index
(
old
flp
->
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
(
old
key
->
dst
)
||
oldkey
->
dst
==
0xFFFFFFFF
)
{
if
(
!
key
.
src
)
key
.
src
=
inet_select_addr
(
dev_out
,
0
,
if
(
LOCAL_MCAST
(
old
flp
->
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
(
old
key
->
dst
))
key
.
src
=
inet_select_addr
(
dev_out
,
0
,
key
.
scope
);
else
if
(
!
old
key
->
dst
)
key
.
src
=
inet_select_addr
(
dev_out
,
0
,
if
(
!
fl
.
fl4_
src
)
{
if
(
MULTICAST
(
old
flp
->
fl4_
dst
))
fl
.
fl4_
src
=
inet_select_addr
(
dev_out
,
0
,
fl
.
fl4_
scope
);
else
if
(
!
old
flp
->
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
(
old
key
->
oif
)
{
if
(
old
flp
->
oif
)
{
/* Apparently, routing tables are wrong. Assume,
that the destination is on link.
...
...
@@ -1832,8 +1831,8 @@ 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
,
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 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
flags
|=
RTCF_MULTICAST
|
RTCF_LOCAL
;
read_lock
(
&
inetdev_lock
);
if
(
!
__in_dev_get
(
dev_out
)
||
!
ip_check_mc
(
__in_dev_get
(
dev_out
),
old
key
->
dst
))
!
ip_check_mc
(
__in_dev_get
(
dev_out
),
old
flp
->
fl4_
dst
))
flags
&=
~
RTCF_LOCAL
;
read_unlock
(
&
inetdev_lock
);
/* If multicast route do not exist use
...
...
@@ -1923,25 +1922,24 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
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
=
old
key
->
oif
?
:
dev_out
->
ifindex
;
rth
->
rt_iif
=
old
flp
->
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 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
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 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
struct
in_device
*
in_dev
=
in_dev_get
(
dev_out
);
if
(
in_dev
)
{
if
(
IN_DEV_MFORWARD
(
in_dev
)
&&
!
LOCAL_MCAST
(
old
key
->
dst
))
{
!
LOCAL_MCAST
(
old
flp
->
fl4_
dst
))
{
rth
->
u
.
dst
.
input
=
ip_mr_input
;
rth
->
u
.
dst
.
output
=
ip_mc_output
;
}
...
...
@@ -1976,7 +1974,7 @@ int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
rth
->
rt_flags
=
flags
;
hash
=
rt_hash_code
(
old
key
->
dst
,
oldkey
->
src
^
(
oldkey
->
oif
<<
5
),
tos
);
hash
=
rt_hash_code
(
old
flp
->
fl4_dst
,
oldflp
->
fl4_src
^
(
oldflp
->
oif
<<
5
),
tos
);
err
=
rt_intern_hash
(
hash
,
rth
,
rp
);
done:
if
(
free_res
)
...
...
@@ -1993,23 +1991,23 @@ out: return err;
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
);
...
...
net/ipv4/syncookies.c
View file @
dcddf5b0
...
...
@@ -171,15 +171,18 @@ 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
))
{
{
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. */
req
->
window_clamp
=
rt
->
u
.
dst
.
window
;
...
...
net/ipv4/tcp_ipv4.c
View file @
dcddf5b0
...
...
@@ -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
:
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
((
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
))
{
.
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
);
...
...
net/ipv4/udp.c
View file @
dcddf5b0
...
...
@@ -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
;
...
...
net/ipv6/Config.in
View file @
dcddf5b0
...
...
@@ -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
net/ipv6/Makefile
View file @
dcddf5b0
...
...
@@ -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
net/ipv6/ip6_fib.c
View file @
dcddf5b0
...
...
@@ -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
))
...
...
net/ipv6/ip6_fw.c
deleted
100644 → 0
View file @
3f43be64
/*
* 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
net/ipv6/route.c
View file @
dcddf5b0
...
...
@@ -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,32 +404,15 @@ void ip6_route_input(struct sk_buff *skb)
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
,
0
);
BACKTRACK
();
if
(
ip6_rt_policy
==
0
)
{
if
(
!
rt
->
rt6i_nexthop
&&
!
(
rt
->
rt6i_flags
&
RTF_NONEXTHOP
))
{
read_unlock_bh
(
&
rt6_lock
);
...
...
@@ -490,13 +427,6 @@ void ip6_route_input(struct sk_buff *skb)
goto
relookup
;
}
dst_clone
(
&
rt
->
u
.
dst
);
}
else
{
#ifdef CONFIG_RT6_POLICY
rt
=
rt6_flow_lookup_in
(
rt
,
skb
);
#else
/* NEVER REACHED */
#endif
}
out:
read_unlock_bh
(
&
rt6_lock
);
...
...
@@ -525,27 +455,11 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
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
}
if
(
rt
->
rt6i_flags
&
RTF_DEFAULT
)
{
if
(
rt
->
rt6i_metric
>=
IP6_RT_PRIO_ADDRCONF
)
rt
=
rt6_best_dflt
(
rt
,
fl
->
oif
);
...
...
@@ -554,7 +468,6 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
BACKTRACK
();
}
if
(
ip6_rt_policy
==
0
)
{
if
(
!
rt
->
rt6i_nexthop
&&
!
(
rt
->
rt6i_flags
&
RTF_NONEXTHOP
))
{
read_unlock_bh
(
&
rt6_lock
);
...
...
@@ -570,13 +483,6 @@ struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl)
goto
relookup
;
}
dst_clone
(
&
rt
->
u
.
dst
);
}
else
{
#ifdef CONFIG_RT6_POLICY
rt
=
rt6_flow_lookup_out
(
rt
,
sk
,
fl
);
#else
/* NEVER REACHED */
#endif
}
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
)
&&
...
...
net/ipv6/sit.c
View file @
dcddf5b0
...
...
@@ -502,10 +502,17 @@ 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
))
{
{
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
++
;
goto
tx_error_icmp
;
...
...
@@ -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
);
}
...
...
net/sched/cls_route.c
View file @
dcddf5b0
...
...
@@ -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
&&
...
...
net/sctp/protocol.c
View file @
dcddf5b0
...
...
@@ -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
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment