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
nexedi
linux
Commits
62105cb5
Commit
62105cb5
authored
Jun 03, 2004
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge nuts.davemloft.net:/disk1/BK/network-2.6
into nuts.davemloft.net:/disk1/BK/net-2.6
parents
79c6b7d3
b5da32d5
Changes
26
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
285 additions
and
242 deletions
+285
-242
include/linux/netdevice.h
include/linux/netdevice.h
+1
-1
include/net/dst.h
include/net/dst.h
+2
-2
include/net/ip.h
include/net/ip.h
+2
-2
include/net/ip6_route.h
include/net/ip6_route.h
+1
-1
include/net/ipv6.h
include/net/ipv6.h
+2
-2
include/net/xfrm.h
include/net/xfrm.h
+1
-1
net/bridge/br_netfilter.c
net/bridge/br_netfilter.c
+1
-1
net/core/dev.c
net/core/dev.c
+33
-16
net/core/dst.c
net/core/dst.c
+11
-11
net/core/netfilter.c
net/core/netfilter.c
+0
-8
net/decnet/dn_route.c
net/decnet/dn_route.c
+8
-2
net/ipv4/ah4.c
net/ipv4/ah4.c
+19
-18
net/ipv4/esp4.c
net/ipv4/esp4.c
+29
-29
net/ipv4/ip_output.c
net/ipv4/ip_output.c
+5
-2
net/ipv4/ipcomp.c
net/ipv4/ipcomp.c
+23
-22
net/ipv4/netfilter/ip_fw_compat.c
net/ipv4/netfilter/ip_fw_compat.c
+2
-1
net/ipv4/netfilter/ip_nat_standalone.c
net/ipv4/netfilter/ip_nat_standalone.c
+2
-1
net/ipv4/netfilter/ipt_ECN.c
net/ipv4/netfilter/ipt_ECN.c
+9
-5
net/ipv4/netfilter/ipt_TCPMSS.c
net/ipv4/netfilter/ipt_TCPMSS.c
+3
-2
net/ipv4/route.c
net/ipv4/route.c
+3
-1
net/ipv4/xfrm4_tunnel.c
net/ipv4/xfrm4_tunnel.c
+2
-1
net/ipv6/ah6.c
net/ipv6/ah6.c
+43
-42
net/ipv6/esp6.c
net/ipv6/esp6.c
+29
-29
net/ipv6/ip6_output.c
net/ipv6/ip6_output.c
+17
-12
net/ipv6/ipcomp6.c
net/ipv6/ipcomp6.c
+28
-27
net/ipv6/route.c
net/ipv6/route.c
+9
-3
No files found.
include/linux/netdevice.h
View file @
62105cb5
...
...
@@ -943,7 +943,7 @@ extern int weight_p;
extern
unsigned
long
netdev_fc_xoff
;
extern
atomic_t
netdev_dropping
;
extern
int
netdev_set_master
(
struct
net_device
*
dev
,
struct
net_device
*
master
);
extern
struct
sk_buff
*
skb_checksum_help
(
struct
sk_buff
*
skb
);
extern
int
skb_checksum_help
(
struct
sk_buff
**
pskb
,
int
inward
);
#ifdef CONFIG_NET_FASTROUTE
extern
int
netdev_fastroute
;
extern
int
netdev_fastroute_obstacles
;
...
...
include/net/dst.h
View file @
62105cb5
...
...
@@ -67,7 +67,7 @@ struct dst_entry
struct
xfrm_state
*
xfrm
;
int
(
*
input
)(
struct
sk_buff
*
);
int
(
*
output
)(
struct
sk_buff
*
);
int
(
*
output
)(
struct
sk_buff
*
*
);
#ifdef CONFIG_NET_CLS_ROUTE
__u32
tclassid
;
...
...
@@ -219,7 +219,7 @@ static inline int dst_output(struct sk_buff *skb)
int
err
;
for
(;;)
{
err
=
skb
->
dst
->
output
(
skb
);
err
=
skb
->
dst
->
output
(
&
skb
);
if
(
likely
(
err
==
0
))
return
err
;
...
...
include/net/ip.h
View file @
62105cb5
...
...
@@ -92,8 +92,8 @@ extern int ip_rcv(struct sk_buff *skb, struct net_device *dev,
struct
packet_type
*
pt
);
extern
int
ip_local_deliver
(
struct
sk_buff
*
skb
);
extern
int
ip_mr_input
(
struct
sk_buff
*
skb
);
extern
int
ip_output
(
struct
sk_buff
*
skb
);
extern
int
ip_mc_output
(
struct
sk_buff
*
skb
);
extern
int
ip_output
(
struct
sk_buff
*
*
p
skb
);
extern
int
ip_mc_output
(
struct
sk_buff
*
*
p
skb
);
extern
int
ip_fragment
(
struct
sk_buff
*
skb
,
int
(
*
out
)(
struct
sk_buff
*
));
extern
int
ip_do_nat
(
struct
sk_buff
*
skb
);
extern
void
ip_send_check
(
struct
iphdr
*
ip
);
...
...
include/net/ip6_route.h
View file @
62105cb5
...
...
@@ -65,7 +65,7 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
extern
struct
dst_entry
*
ndisc_dst_alloc
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
,
struct
in6_addr
*
addr
,
int
(
*
output
)(
struct
sk_buff
*
));
int
(
*
output
)(
struct
sk_buff
*
*
));
extern
int
ndisc_dst_gc
(
int
*
more
);
extern
void
fib6_force_start_gc
(
void
);
...
...
include/net/ipv6.h
View file @
62105cb5
...
...
@@ -355,8 +355,8 @@ extern int ip6_dst_lookup(struct sock *sk,
* skb processing functions
*/
extern
int
ip6_output
(
struct
sk_buff
*
skb
);
extern
int
ip6_output2
(
struct
sk_buff
*
skb
);
extern
int
ip6_output
(
struct
sk_buff
*
*
p
skb
);
extern
int
ip6_output2
(
struct
sk_buff
*
*
p
skb
);
extern
int
ip6_forward
(
struct
sk_buff
*
skb
);
extern
int
ip6_input
(
struct
sk_buff
*
skb
);
extern
int
ip6_mc_input
(
struct
sk_buff
*
skb
);
...
...
include/net/xfrm.h
View file @
62105cb5
...
...
@@ -216,7 +216,7 @@ struct xfrm_type
void
(
*
destructor
)(
struct
xfrm_state
*
);
int
(
*
input
)(
struct
xfrm_state
*
,
struct
xfrm_decap_state
*
,
struct
sk_buff
*
skb
);
int
(
*
post_input
)(
struct
xfrm_state
*
,
struct
xfrm_decap_state
*
,
struct
sk_buff
*
skb
);
int
(
*
output
)(
struct
sk_buff
*
skb
);
int
(
*
output
)(
struct
sk_buff
*
*
p
skb
);
/* Estimate maximal size of result of transformation of a dgram */
u32
(
*
get_max_size
)(
struct
xfrm_state
*
,
int
size
);
};
...
...
net/bridge/br_netfilter.c
View file @
62105cb5
...
...
@@ -165,7 +165,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
skb_pull
(
skb
,
VLAN_HLEN
);
skb
->
nh
.
raw
+=
VLAN_HLEN
;
}
skb
->
dst
->
output
(
skb
);
skb
->
dst
->
output
(
&
skb
);
return
0
;
}
...
...
net/core/dev.c
View file @
62105cb5
...
...
@@ -1180,28 +1180,46 @@ void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
rcu_read_unlock
();
}
/*
Calculate csum in the case, when packet is misrouted.
* I
f it failed by some reason, ignore and send skb with wrong
* c
hecksum
.
/*
* I
nvalidate hardware checksum when packet is to be mangled, and
* c
omplete checksum manually on outgoing path
.
*/
struct
sk_buff
*
skb_checksum_help
(
struct
sk_buff
*
skb
)
int
skb_checksum_help
(
struct
sk_buff
**
pskb
,
int
inward
)
{
unsigned
int
csum
;
int
offset
=
skb
->
h
.
raw
-
skb
->
data
;
int
ret
=
0
,
offset
=
(
*
pskb
)
->
h
.
raw
-
(
*
pskb
)
->
data
;
if
(
inward
)
{
(
*
pskb
)
->
ip_summed
=
CHECKSUM_NONE
;
goto
out
;
}
if
(
offset
>
(
int
)
skb
->
len
)
if
(
skb_shared
(
*
pskb
)
||
skb_cloned
(
*
pskb
))
{
struct
sk_buff
*
newskb
=
skb_copy
(
*
pskb
,
GFP_ATOMIC
);
if
(
!
newskb
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
if
((
*
pskb
)
->
sk
)
skb_set_owner_w
(
newskb
,
(
*
pskb
)
->
sk
);
kfree_skb
(
*
pskb
);
*
pskb
=
newskb
;
}
if
(
offset
>
(
int
)(
*
pskb
)
->
len
)
BUG
();
csum
=
skb_checksum
(
skb
,
offset
,
skb
->
len
-
offset
,
0
);
csum
=
skb_checksum
(
*
pskb
,
offset
,
(
*
pskb
)
->
len
-
offset
,
0
);
offset
=
skb
->
tail
-
skb
->
h
.
raw
;
offset
=
(
*
pskb
)
->
tail
-
(
*
pskb
)
->
h
.
raw
;
if
(
offset
<=
0
)
BUG
();
if
(
skb
->
csum
+
2
>
offset
)
if
(
(
*
pskb
)
->
csum
+
2
>
offset
)
BUG
();
*
(
u16
*
)(
skb
->
h
.
raw
+
skb
->
csum
)
=
csum_fold
(
csum
);
skb
->
ip_summed
=
CHECKSUM_NONE
;
return
skb
;
*
(
u16
*
)((
*
pskb
)
->
h
.
raw
+
(
*
pskb
)
->
csum
)
=
csum_fold
(
csum
);
(
*
pskb
)
->
ip_summed
=
CHECKSUM_NONE
;
out:
return
ret
;
}
#ifdef CONFIG_HIGHMEM
...
...
@@ -1326,10 +1344,9 @@ int dev_queue_xmit(struct sk_buff *skb)
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
(
!
(
dev
->
features
&
(
NETIF_F_HW_CSUM
|
NETIF_F_NO_CSUM
))
&&
(
!
(
dev
->
features
&
NETIF_F_IP_CSUM
)
||
skb
->
protocol
!=
htons
(
ETH_P_IP
))))
{
if
((
skb
=
skb_checksum_help
(
skb
))
==
NULL
)
goto
out
;
}
skb
->
protocol
!=
htons
(
ETH_P_IP
))))
if
(
skb_checksum_help
(
&
skb
,
0
))
goto
out_kfree_skb
;
/* Grab device queue */
spin_lock_bh
(
&
dev
->
queue_lock
);
...
...
net/core/dst.c
View file @
62105cb5
...
...
@@ -100,15 +100,15 @@ static void dst_run_gc(unsigned long dummy)
spin_unlock
(
&
dst_lock
);
}
static
int
dst_discard
(
struct
sk_buff
*
skb
)
static
int
dst_discard
_in
(
struct
sk_buff
*
skb
)
{
kfree_skb
(
skb
);
return
0
;
}
static
int
dst_
blackhole
(
struct
sk_buff
*
skb
)
static
int
dst_
discard_out
(
struct
sk_buff
**
p
skb
)
{
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
return
0
;
}
...
...
@@ -128,8 +128,8 @@ void * dst_alloc(struct dst_ops * ops)
dst
->
ops
=
ops
;
dst
->
lastuse
=
jiffies
;
dst
->
path
=
dst
;
dst
->
input
=
dst_discard
;
dst
->
output
=
dst_
blackhole
;
dst
->
input
=
dst_discard
_in
;
dst
->
output
=
dst_
discard_out
;
#if RT_CACHE_DEBUG >= 2
atomic_inc
(
&
dst_total
);
#endif
...
...
@@ -143,8 +143,8 @@ static void ___dst_free(struct dst_entry * dst)
protocol module is unloaded.
*/
if
(
dst
->
dev
==
NULL
||
!
(
dst
->
dev
->
flags
&
IFF_UP
))
{
dst
->
input
=
dst_discard
;
dst
->
output
=
dst_
blackhole
;
dst
->
input
=
dst_discard
_in
;
dst
->
output
=
dst_
discard_out
;
}
dst
->
obsolete
=
2
;
}
...
...
@@ -228,19 +228,19 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
_race_ _condition_.
*/
if
(
event
!=
NETDEV_DOWN
&&
dst
->
output
==
dst_
blackhole
)
{
dst
->
output
==
dst_
discard_out
)
{
dst
->
dev
=
&
loopback_dev
;
dev_put
(
dev
);
dev_hold
(
&
loopback_dev
);
dst
->
output
=
dst_discard
;
dst
->
output
=
dst_discard
_out
;
if
(
dst
->
neighbour
&&
dst
->
neighbour
->
dev
==
dev
)
{
dst
->
neighbour
->
dev
=
&
loopback_dev
;
dev_put
(
dev
);
dev_hold
(
&
loopback_dev
);
}
}
else
{
dst
->
input
=
dst_discard
;
dst
->
output
=
dst_
blackhole
;
dst
->
input
=
dst_discard
_in
;
dst
->
output
=
dst_
discard_out
;
}
}
}
...
...
net/core/netfilter.c
View file @
62105cb5
...
...
@@ -504,14 +504,6 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
unsigned
int
verdict
;
int
ret
=
0
;
if
(
skb
->
ip_summed
==
CHECKSUM_HW
)
{
if
(
outdev
==
NULL
)
{
skb
->
ip_summed
=
CHECKSUM_NONE
;
}
else
{
skb_checksum_help
(
skb
);
}
}
/* We may already have this, but read-locks nest anyway */
rcu_read_lock
();
...
...
net/decnet/dn_route.c
View file @
62105cb5
...
...
@@ -684,8 +684,9 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
return
NET_RX_DROP
;
}
static
int
dn_output
(
struct
sk_buff
*
skb
)
static
int
dn_output
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dn_route
*
rt
=
(
struct
dn_route
*
)
dst
;
struct
net_device
*
dev
=
dst
->
dev
;
...
...
@@ -796,6 +797,11 @@ static int dn_rt_bug(struct sk_buff *skb)
return
NET_RX_BAD
;
}
static
int
dn_rt_bug_out
(
struct
sk_buff
**
pskb
)
{
return
dn_rt_bug
(
*
pskb
);
}
static
int
dn_rt_set_next_hop
(
struct
dn_route
*
rt
,
struct
dn_fib_res
*
res
)
{
struct
dn_fib_info
*
fi
=
res
->
fi
;
...
...
@@ -1387,7 +1393,7 @@ static int dn_route_input_slow(struct sk_buff *skb)
rt
->
u
.
dst
.
neighbour
=
neigh
;
rt
->
u
.
dst
.
dev
=
out_dev
;
rt
->
u
.
dst
.
lastuse
=
jiffies
;
rt
->
u
.
dst
.
output
=
dn_rt_bug
;
rt
->
u
.
dst
.
output
=
dn_rt_bug
_out
;
switch
(
res
.
type
)
{
case
RTN_UNICAST
:
rt
->
u
.
dst
.
input
=
dn_forward
;
...
...
net/ipv4/ah4.c
View file @
62105cb5
...
...
@@ -54,10 +54,10 @@ static int ip_clear_mutable_options(struct iphdr *iph, u32 *daddr)
return
0
;
}
static
int
ah_output
(
struct
sk_buff
*
skb
)
static
int
ah_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
iphdr
*
iph
,
*
top_iph
;
struct
ip_auth_hdr
*
ah
;
...
...
@@ -67,23 +67,24 @@ static int ah_output(struct sk_buff *skb)
char
buf
[
60
];
}
tmp_iph
;
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET
);
if
(
err
)
goto
error
;
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
if
(
x
->
props
.
mode
)
{
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
top_iph
->
ihl
=
5
;
top_iph
->
version
=
4
;
top_iph
->
tos
=
0
;
top_iph
->
tot_len
=
htons
(
skb
->
len
);
top_iph
->
tot_len
=
htons
(
(
*
pskb
)
->
len
);
top_iph
->
frag_off
=
0
;
if
(
!
(
iph
->
frag_off
&
htons
(
IP_DF
)))
__ip_select_ident
(
top_iph
,
dst
,
0
);
...
...
@@ -95,12 +96,12 @@ static int ah_output(struct sk_buff *skb)
ah
=
(
struct
ip_auth_hdr
*
)(
top_iph
+
1
);
ah
->
nexthdr
=
IPPROTO_IPIP
;
}
else
{
memcpy
(
&
tmp_iph
,
skb
->
data
,
iph
->
ihl
*
4
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
memcpy
(
&
tmp_iph
,
(
*
pskb
)
->
data
,
iph
->
ihl
*
4
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
memcpy
(
top_iph
,
&
tmp_iph
,
iph
->
ihl
*
4
);
iph
=
&
tmp_iph
.
iph
;
top_iph
->
tos
=
0
;
top_iph
->
tot_len
=
htons
(
skb
->
len
);
top_iph
->
tot_len
=
htons
(
(
*
pskb
)
->
len
);
top_iph
->
frag_off
=
0
;
top_iph
->
ttl
=
0
;
top_iph
->
protocol
=
IPPROTO_AH
;
...
...
@@ -120,14 +121,14 @@ static int ah_output(struct sk_buff *skb)
ah
->
reserved
=
0
;
ah
->
spi
=
x
->
id
.
spi
;
ah
->
seq_no
=
htonl
(
++
x
->
replay
.
oseq
);
ahp
->
icv
(
ahp
,
skb
,
ah
->
auth_data
);
ahp
->
icv
(
ahp
,
*
p
skb
,
ah
->
auth_data
);
top_iph
->
tos
=
iph
->
tos
;
top_iph
->
ttl
=
iph
->
ttl
;
if
(
x
->
props
.
mode
)
{
if
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
)
IP_ECN_clear
(
top_iph
);
top_iph
->
frag_off
=
iph
->
frag_off
&~
htons
(
IP_MF
|
IP_OFFSET
);
memset
(
&
(
IPCB
(
skb
)
->
opt
),
0
,
sizeof
(
struct
ip_options
));
memset
(
&
(
IPCB
(
*
p
skb
)
->
opt
),
0
,
sizeof
(
struct
ip_options
));
}
else
{
top_iph
->
frag_off
=
iph
->
frag_off
;
top_iph
->
daddr
=
iph
->
daddr
;
...
...
@@ -136,12 +137,12 @@ static int ah_output(struct sk_buff *skb)
}
ip_send_check
(
top_iph
);
skb
->
nh
.
raw
=
skb
->
data
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -150,7 +151,7 @@ static int ah_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
return
err
;
}
...
...
net/ipv4/esp4.c
View file @
62105cb5
...
...
@@ -20,10 +20,10 @@ struct esp_decap_data {
__u8
proto
;
};
int
esp_output
(
struct
sk_buff
*
skb
)
int
esp_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
iphdr
*
iph
,
*
top_iph
;
struct
ip_esp_hdr
*
esph
;
...
...
@@ -42,28 +42,28 @@ int esp_output(struct sk_buff *skb)
char
buf
[
60
];
}
tmp_iph
;
/* First, if the skb is not checksummed, complete checksum. */
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET
);
if
(
err
)
goto
error
;
err
=
-
ENOMEM
;
/* Strip IP header in transport mode. Save it. */
if
(
!
x
->
props
.
mode
)
{
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
memcpy
(
&
tmp_iph
,
iph
,
iph
->
ihl
*
4
);
__skb_pull
(
skb
,
iph
->
ihl
*
4
);
__skb_pull
(
*
p
skb
,
iph
->
ihl
*
4
);
}
/* Now skb is pure payload to encrypt */
/* Round to block size */
clen
=
skb
->
len
;
clen
=
(
*
pskb
)
->
len
;
esp
=
x
->
data
;
alen
=
esp
->
auth
.
icv_trunc_len
;
...
...
@@ -73,23 +73,23 @@ int esp_output(struct sk_buff *skb)
if
(
esp
->
conf
.
padlen
)
clen
=
(
clen
+
esp
->
conf
.
padlen
-
1
)
&~
(
esp
->
conf
.
padlen
-
1
);
if
((
nfrags
=
skb_cow_data
(
skb
,
clen
-
skb
->
len
+
alen
,
&
trailer
))
<
0
)
if
((
nfrags
=
skb_cow_data
(
*
pskb
,
clen
-
(
*
pskb
)
->
len
+
alen
,
&
trailer
))
<
0
)
goto
error
;
/* Fill padding... */
do
{
int
i
;
for
(
i
=
0
;
i
<
clen
-
skb
->
len
-
2
;
i
++
)
for
(
i
=
0
;
i
<
clen
-
(
*
pskb
)
->
len
-
2
;
i
++
)
*
(
u8
*
)(
trailer
->
tail
+
i
)
=
i
+
1
;
}
while
(
0
);
*
(
u8
*
)(
trailer
->
tail
+
clen
-
skb
->
len
-
2
)
=
(
clen
-
skb
->
len
)
-
2
;
pskb_put
(
skb
,
trailer
,
clen
-
skb
->
len
);
*
(
u8
*
)(
trailer
->
tail
+
clen
-
(
*
pskb
)
->
len
-
2
)
=
(
clen
-
(
*
pskb
)
->
len
)
-
2
;
pskb_put
(
*
pskb
,
trailer
,
clen
-
(
*
pskb
)
->
len
);
encap
=
x
->
encap
;
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
if
(
x
->
props
.
mode
)
{
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
esph
=
(
struct
ip_esp_hdr
*
)(
top_iph
+
1
);
if
(
encap
&&
encap
->
encap_type
)
{
switch
(
encap
->
encap_type
)
{
...
...
@@ -121,7 +121,7 @@ int esp_output(struct sk_buff *skb)
top_iph
->
tos
=
iph
->
tos
;
/* DS disclosed */
if
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
)
IP_ECN_clear
(
top_iph
);
top_iph
->
tot_len
=
htons
(
skb
->
len
+
alen
);
top_iph
->
tot_len
=
htons
(
(
*
pskb
)
->
len
+
alen
);
top_iph
->
frag_off
=
iph
->
frag_off
&
htons
(
IP_DF
);
if
(
!
(
top_iph
->
frag_off
))
ip_select_ident
(
top_iph
,
dst
,
0
);
...
...
@@ -129,10 +129,10 @@ int esp_output(struct sk_buff *skb)
top_iph
->
check
=
0
;
top_iph
->
saddr
=
x
->
props
.
saddr
.
a4
;
top_iph
->
daddr
=
x
->
id
.
daddr
.
a4
;
memset
(
&
(
IPCB
(
skb
)
->
opt
),
0
,
sizeof
(
struct
ip_options
));
memset
(
&
(
IPCB
(
*
p
skb
)
->
opt
),
0
,
sizeof
(
struct
ip_options
));
}
else
{
esph
=
(
struct
ip_esp_hdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
iph
->
ihl
*
4
);
esph
=
(
struct
ip_esp_hdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
*
p
skb
,
iph
->
ihl
*
4
);
memcpy
(
top_iph
,
&
tmp_iph
,
iph
->
ihl
*
4
);
if
(
encap
&&
encap
->
encap_type
)
{
switch
(
encap
->
encap_type
)
{
...
...
@@ -159,7 +159,7 @@ int esp_output(struct sk_buff *skb)
}
else
top_iph
->
protocol
=
IPPROTO_ESP
;
iph
=
&
tmp_iph
.
iph
;
top_iph
->
tot_len
=
htons
(
skb
->
len
+
alen
);
top_iph
->
tot_len
=
htons
(
(
*
pskb
)
->
len
+
alen
);
top_iph
->
check
=
0
;
top_iph
->
frag_off
=
iph
->
frag_off
;
*
(
u8
*
)(
trailer
->
tail
-
1
)
=
iph
->
protocol
;
...
...
@@ -169,7 +169,7 @@ int esp_output(struct sk_buff *skb)
if
(
encap
&&
uh
)
{
uh
->
source
=
encap
->
encap_sport
;
uh
->
dest
=
encap
->
encap_dport
;
uh
->
len
=
htons
(
skb
->
len
+
alen
-
sizeof
(
struct
iphdr
));
uh
->
len
=
htons
(
(
*
pskb
)
->
len
+
alen
-
sizeof
(
struct
iphdr
));
uh
->
check
=
0
;
}
...
...
@@ -188,7 +188,7 @@ int esp_output(struct sk_buff *skb)
if
(
!
sg
)
goto
error
;
}
skb_to_sgvec
(
skb
,
sg
,
esph
->
enc_data
+
esp
->
conf
.
ivlen
-
skb
->
data
,
clen
);
skb_to_sgvec
(
*
pskb
,
sg
,
esph
->
enc_data
+
esp
->
conf
.
ivlen
-
(
*
pskb
)
->
data
,
clen
);
crypto_cipher_encrypt
(
tfm
,
sg
,
sg
,
clen
);
if
(
unlikely
(
sg
!=
sgbuf
))
kfree
(
sg
);
...
...
@@ -200,19 +200,19 @@ int esp_output(struct sk_buff *skb)
}
if
(
esp
->
auth
.
icv_full_len
)
{
esp
->
auth
.
icv
(
esp
,
skb
,
(
u8
*
)
esph
-
skb
->
data
,
esp
->
auth
.
icv
(
esp
,
*
pskb
,
(
u8
*
)
esph
-
(
*
pskb
)
->
data
,
sizeof
(
struct
ip_esp_hdr
)
+
esp
->
conf
.
ivlen
+
clen
,
trailer
->
tail
);
pskb_put
(
skb
,
trailer
,
alen
);
pskb_put
(
*
p
skb
,
trailer
,
alen
);
}
ip_send_check
(
top_iph
);
skb
->
nh
.
raw
=
skb
->
data
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -221,7 +221,7 @@ int esp_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
return
err
;
}
...
...
net/ipv4/ip_output.c
View file @
62105cb5
...
...
@@ -223,8 +223,9 @@ int ip_finish_output(struct sk_buff *skb)
ip_finish_output2
);
}
int
ip_mc_output
(
struct
sk_buff
*
skb
)
int
ip_mc_output
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sock
*
sk
=
skb
->
sk
;
struct
rtable
*
rt
=
(
struct
rtable
*
)
skb
->
dst
;
struct
net_device
*
dev
=
rt
->
u
.
dst
.
dev
;
...
...
@@ -283,8 +284,10 @@ int ip_mc_output(struct sk_buff *skb)
return
ip_finish_output
(
skb
);
}
int
ip_output
(
struct
sk_buff
*
skb
)
int
ip_output
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
IP_INC_STATS
(
OutRequests
);
if
((
skb
->
len
>
dst_pmtu
(
skb
->
dst
)
||
skb_shinfo
(
skb
)
->
frag_list
)
&&
...
...
net/ipv4/ipcomp.c
View file @
62105cb5
...
...
@@ -143,10 +143,10 @@ static void ipcomp_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
skb
->
nh
.
raw
=
skb
->
data
;
}
static
int
ipcomp_output
(
struct
sk_buff
*
skb
)
static
int
ipcomp_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
iphdr
*
iph
,
*
top_iph
;
struct
ip_comp_hdr
*
ipch
;
...
...
@@ -157,25 +157,26 @@ static int ipcomp_output(struct sk_buff *skb)
}
tmp_iph
;
int
hdr_len
=
0
;
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET
);
if
(
err
)
goto
error
;
/* Don't bother compressing */
if
(
!
x
->
props
.
mode
)
{
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
hdr_len
=
iph
->
ihl
*
4
;
}
if
((
skb
->
len
-
hdr_len
)
<
ipcd
->
threshold
)
{
if
((
(
*
pskb
)
->
len
-
hdr_len
)
<
ipcd
->
threshold
)
{
if
(
x
->
props
.
mode
)
{
ipcomp_tunnel_encap
(
x
,
skb
);
iph
=
skb
->
nh
.
iph
;
ipcomp_tunnel_encap
(
x
,
*
p
skb
);
iph
=
(
*
pskb
)
->
nh
.
iph
;
iph
->
protocol
=
IPPROTO_IPIP
;
ip_send_check
(
iph
);
}
...
...
@@ -183,19 +184,19 @@ static int ipcomp_output(struct sk_buff *skb)
}
if
(
x
->
props
.
mode
)
ipcomp_tunnel_encap
(
x
,
skb
);
ipcomp_tunnel_encap
(
x
,
*
p
skb
);
if
((
skb_is_nonlinear
(
skb
)
||
skb_cloned
(
skb
))
&&
skb_linearize
(
skb
,
GFP_ATOMIC
)
!=
0
)
{
if
((
skb_is_nonlinear
(
*
pskb
)
||
skb_cloned
(
*
p
skb
))
&&
skb_linearize
(
*
p
skb
,
GFP_ATOMIC
)
!=
0
)
{
err
=
-
ENOMEM
;
goto
error
;
}
err
=
ipcomp_compress
(
x
,
skb
);
err
=
ipcomp_compress
(
x
,
*
p
skb
);
if
(
err
)
{
if
(
err
==
-
EMSGSIZE
)
{
if
(
x
->
props
.
mode
)
{
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
iph
->
protocol
=
IPPROTO_IPIP
;
ip_send_check
(
iph
);
}
...
...
@@ -205,14 +206,14 @@ static int ipcomp_output(struct sk_buff *skb)
}
/* Install ipcomp header, convert into ipcomp datagram. */
iph
=
skb
->
nh
.
iph
;
iph
=
(
*
pskb
)
->
nh
.
iph
;
memcpy
(
&
tmp_iph
,
iph
,
iph
->
ihl
*
4
);
top_iph
=
(
struct
iphdr
*
)
skb_push
(
skb
,
sizeof
(
struct
ip_comp_hdr
));
top_iph
=
(
struct
iphdr
*
)
skb_push
(
*
p
skb
,
sizeof
(
struct
ip_comp_hdr
));
memcpy
(
top_iph
,
&
tmp_iph
,
iph
->
ihl
*
4
);
iph
=
top_iph
;
if
(
x
->
props
.
mode
&&
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
))
IP_ECN_clear
(
iph
);
iph
->
tot_len
=
htons
(
skb
->
len
);
iph
->
tot_len
=
htons
(
(
*
pskb
)
->
len
);
iph
->
protocol
=
IPPROTO_COMP
;
iph
->
check
=
0
;
ipch
=
(
struct
ip_comp_hdr
*
)((
char
*
)
iph
+
iph
->
ihl
*
4
);
...
...
@@ -220,14 +221,14 @@ static int ipcomp_output(struct sk_buff *skb)
ipch
->
flags
=
0
;
ipch
->
cpi
=
htons
((
u16
)
ntohl
(
x
->
id
.
spi
));
ip_send_check
(
iph
);
skb
->
nh
.
raw
=
skb
->
data
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
out_ok:
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -238,7 +239,7 @@ static int ipcomp_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
goto
out_exit
;
}
...
...
net/ipv4/netfilter/ip_fw_compat.c
View file @
62105cb5
...
...
@@ -69,7 +69,8 @@ fw_in(unsigned int hooknum,
/* Assume worse case: any hook could change packet */
(
*
pskb
)
->
nfcache
|=
NFC_UNKNOWN
|
NFC_ALTERED
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
(
*
pskb
)
->
ip_summed
=
CHECKSUM_NONE
;
if
(
skb_checksum_help
(
pskb
,
(
out
==
NULL
)))
return
NF_DROP
;
switch
(
hooknum
)
{
case
NF_IP_PRE_ROUTING
:
...
...
net/ipv4/netfilter/ip_nat_standalone.c
View file @
62105cb5
...
...
@@ -85,7 +85,8 @@ ip_nat_fn(unsigned int hooknum,
/* If we had a hardware checksum before, it's now invalid */
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
(
*
pskb
)
->
ip_summed
=
CHECKSUM_NONE
;
if
(
skb_checksum_help
(
pskb
,
(
out
==
NULL
)))
return
NF_DROP
;
ct
=
ip_conntrack_get
(
*
pskb
,
&
ctinfo
);
/* Can't track? It's not due to stress, or conntrack would
...
...
net/ipv4/netfilter/ipt_ECN.c
View file @
62105cb5
...
...
@@ -50,7 +50,7 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
/* Return 0 if there was an error. */
static
inline
int
set_ect_tcp
(
struct
sk_buff
**
pskb
,
const
struct
ipt_ECN_info
*
einfo
)
set_ect_tcp
(
struct
sk_buff
**
pskb
,
const
struct
ipt_ECN_info
*
einfo
,
int
inward
)
{
struct
tcphdr
tcph
;
u_int16_t
diffs
[
2
];
...
...
@@ -74,11 +74,15 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
if
(
!
skb_ip_make_writable
(
pskb
,
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
+
sizeof
(
tcph
)))
return
0
;
if
((
*
pskb
)
->
ip_summed
!=
CHECKSUM_HW
)
tcph
.
check
=
csum_fold
(
csum_partial
((
char
*
)
diffs
,
sizeof
(
diffs
),
tcph
.
check
^
0xFFFF
));
memcpy
((
*
pskb
)
->
data
+
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
,
&
tcph
,
sizeof
(
tcph
));
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
if
(
skb_checksum_help
(
pskb
,
inward
))
return
0
;
(
*
pskb
)
->
nfcache
|=
NFC_ALTERED
;
}
return
1
;
...
...
@@ -100,7 +104,7 @@ target(struct sk_buff **pskb,
if
(
einfo
->
operation
&
(
IPT_ECN_OP_SET_ECE
|
IPT_ECN_OP_SET_CWR
)
&&
(
*
pskb
)
->
nh
.
iph
->
protocol
==
IPPROTO_TCP
)
if
(
!
set_ect_tcp
(
pskb
,
einfo
))
if
(
!
set_ect_tcp
(
pskb
,
einfo
,
(
out
==
NULL
)
))
return
NF_DROP
;
return
IPT_CONTINUE
;
...
...
net/ipv4/netfilter/ipt_TCPMSS.c
View file @
62105cb5
...
...
@@ -186,8 +186,9 @@ ipt_tcpmss_target(struct sk_buff **pskb,
newmss
);
retmodified:
/* If we had a hardware checksum before, it's now invalid */
(
*
pskb
)
->
ip_summed
=
CHECKSUM_NONE
;
/* We never hw checksum SYN packets. */
BUG_ON
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
);
(
*
pskb
)
->
nfcache
|=
NFC_UNKNOWN
|
NFC_ALTERED
;
return
IPT_CONTINUE
;
}
...
...
net/ipv4/route.c
View file @
62105cb5
...
...
@@ -1347,8 +1347,10 @@ static void ipv4_link_failure(struct sk_buff *skb)
dst_set_expires
(
&
rt
->
u
.
dst
,
0
);
}
static
int
ip_rt_bug
(
struct
sk_buff
*
skb
)
static
int
ip_rt_bug
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
printk
(
KERN_DEBUG
"ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s
\n
"
,
NIPQUAD
(
skb
->
nh
.
iph
->
saddr
),
NIPQUAD
(
skb
->
nh
.
iph
->
daddr
),
skb
->
dev
?
skb
->
dev
->
name
:
"?"
);
...
...
net/ipv4/xfrm4_tunnel.c
View file @
62105cb5
...
...
@@ -33,8 +33,9 @@ int xfrm4_tunnel_check_size(struct sk_buff *skb)
return
ret
;
}
static
int
ipip_output
(
struct
sk_buff
*
skb
)
static
int
ipip_output
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
iphdr
*
iph
,
*
top_iph
;
...
...
net/ipv6/ah6.c
View file @
62105cb5
...
...
@@ -144,11 +144,11 @@ static int ipv6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int d
return
nexthdr
;
}
int
ah6_output
(
struct
sk_buff
*
skb
)
int
ah6_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
int
hdr_len
=
sizeof
(
struct
ipv6hdr
);
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
ipv6hdr
*
iph
=
NULL
;
struct
ip_auth_hdr
*
ah
;
...
...
@@ -156,54 +156,55 @@ int ah6_output(struct sk_buff *skb)
u16
nh_offset
=
0
;
u8
nexthdr
;
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET6
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET6
);
if
(
err
)
goto
error
;
if
(
x
->
props
.
mode
)
{
iph
=
skb
->
nh
.
ipv6h
;
skb
->
nh
.
ipv6h
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
skb
->
nh
.
ipv6h
->
version
=
6
;
skb
->
nh
.
ipv6h
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
skb
->
nh
.
ipv6h
->
nexthdr
=
IPPROTO_AH
;
ipv6_addr_copy
(
&
skb
->
nh
.
ipv6h
->
saddr
,
iph
=
(
*
pskb
)
->
nh
.
ipv6h
;
(
*
pskb
)
->
nh
.
ipv6h
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
(
*
pskb
)
->
nh
.
ipv6h
->
version
=
6
;
(
*
pskb
)
->
nh
.
ipv6h
->
payload_len
=
htons
((
*
pskb
)
->
len
-
sizeof
(
struct
ipv6hdr
));
(
*
pskb
)
->
nh
.
ipv6h
->
nexthdr
=
IPPROTO_AH
;
ipv6_addr_copy
(
&
(
*
pskb
)
->
nh
.
ipv6h
->
saddr
,
(
struct
in6_addr
*
)
&
x
->
props
.
saddr
);
ipv6_addr_copy
(
&
skb
->
nh
.
ipv6h
->
daddr
,
ipv6_addr_copy
(
&
(
*
pskb
)
->
nh
.
ipv6h
->
daddr
,
(
struct
in6_addr
*
)
&
x
->
id
.
daddr
);
ah
=
(
struct
ip_auth_hdr
*
)(
skb
->
nh
.
ipv6h
+
1
);
ah
=
(
struct
ip_auth_hdr
*
)(
(
*
pskb
)
->
nh
.
ipv6h
+
1
);
ah
->
nexthdr
=
IPPROTO_IPV6
;
}
else
{
hdr_len
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
hdr_len
=
(
*
pskb
)
->
h
.
raw
-
(
*
pskb
)
->
nh
.
raw
;
iph
=
kmalloc
(
hdr_len
,
GFP_ATOMIC
);
if
(
!
iph
)
{
err
=
-
ENOMEM
;
goto
error
;
}
memcpy
(
iph
,
skb
->
data
,
hdr_len
);
skb
->
nh
.
ipv6h
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
memcpy
(
skb
->
nh
.
ipv6h
,
iph
,
hdr_len
);
nexthdr
=
ipv6_clear_mutable_options
(
skb
,
&
nh_offset
,
XFRM_POLICY_OUT
);
memcpy
(
iph
,
(
*
pskb
)
->
data
,
hdr_len
);
(
*
pskb
)
->
nh
.
ipv6h
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
memcpy
(
(
*
pskb
)
->
nh
.
ipv6h
,
iph
,
hdr_len
);
nexthdr
=
ipv6_clear_mutable_options
(
*
p
skb
,
&
nh_offset
,
XFRM_POLICY_OUT
);
if
(
nexthdr
==
0
)
goto
error_free_iph
;
skb
->
nh
.
raw
[
nh_offset
]
=
IPPROTO_AH
;
skb
->
nh
.
ipv6h
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
ah
=
(
struct
ip_auth_hdr
*
)(
skb
->
nh
.
raw
+
hdr_len
);
skb
->
h
.
raw
=
(
unsigned
char
*
)
ah
;
(
*
pskb
)
->
nh
.
raw
[
nh_offset
]
=
IPPROTO_AH
;
(
*
pskb
)
->
nh
.
ipv6h
->
payload_len
=
htons
((
*
pskb
)
->
len
-
sizeof
(
struct
ipv6hdr
));
ah
=
(
struct
ip_auth_hdr
*
)(
(
*
pskb
)
->
nh
.
raw
+
hdr_len
);
(
*
pskb
)
->
h
.
raw
=
(
unsigned
char
*
)
ah
;
ah
->
nexthdr
=
nexthdr
;
}
skb
->
nh
.
ipv6h
->
priority
=
0
;
skb
->
nh
.
ipv6h
->
flow_lbl
[
0
]
=
0
;
skb
->
nh
.
ipv6h
->
flow_lbl
[
1
]
=
0
;
skb
->
nh
.
ipv6h
->
flow_lbl
[
2
]
=
0
;
skb
->
nh
.
ipv6h
->
hop_limit
=
0
;
(
*
pskb
)
->
nh
.
ipv6h
->
priority
=
0
;
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
0
]
=
0
;
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
1
]
=
0
;
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
2
]
=
0
;
(
*
pskb
)
->
nh
.
ipv6h
->
hop_limit
=
0
;
ahp
=
x
->
data
;
ah
->
hdrlen
=
(
XFRM_ALIGN8
(
sizeof
(
struct
ipv6_auth_hdr
)
+
...
...
@@ -212,29 +213,29 @@ int ah6_output(struct sk_buff *skb)
ah
->
reserved
=
0
;
ah
->
spi
=
x
->
id
.
spi
;
ah
->
seq_no
=
htonl
(
++
x
->
replay
.
oseq
);
ahp
->
icv
(
ahp
,
skb
,
ah
->
auth_data
);
ahp
->
icv
(
ahp
,
*
p
skb
,
ah
->
auth_data
);
if
(
x
->
props
.
mode
)
{
skb
->
nh
.
ipv6h
->
hop_limit
=
iph
->
hop_limit
;
skb
->
nh
.
ipv6h
->
priority
=
iph
->
priority
;
skb
->
nh
.
ipv6h
->
flow_lbl
[
0
]
=
iph
->
flow_lbl
[
0
];
skb
->
nh
.
ipv6h
->
flow_lbl
[
1
]
=
iph
->
flow_lbl
[
1
];
skb
->
nh
.
ipv6h
->
flow_lbl
[
2
]
=
iph
->
flow_lbl
[
2
];
(
*
pskb
)
->
nh
.
ipv6h
->
hop_limit
=
iph
->
hop_limit
;
(
*
pskb
)
->
nh
.
ipv6h
->
priority
=
iph
->
priority
;
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
0
]
=
iph
->
flow_lbl
[
0
];
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
1
]
=
iph
->
flow_lbl
[
1
];
(
*
pskb
)
->
nh
.
ipv6h
->
flow_lbl
[
2
]
=
iph
->
flow_lbl
[
2
];
if
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
)
IP6_ECN_clear
(
skb
->
nh
.
ipv6h
);
IP6_ECN_clear
(
(
*
pskb
)
->
nh
.
ipv6h
);
}
else
{
memcpy
(
skb
->
nh
.
ipv6h
,
iph
,
hdr_len
);
skb
->
nh
.
raw
[
nh_offset
]
=
IPPROTO_AH
;
skb
->
nh
.
ipv6h
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
memcpy
(
(
*
pskb
)
->
nh
.
ipv6h
,
iph
,
hdr_len
);
(
*
pskb
)
->
nh
.
raw
[
nh_offset
]
=
IPPROTO_AH
;
(
*
pskb
)
->
nh
.
ipv6h
->
payload_len
=
htons
((
*
pskb
)
->
len
-
sizeof
(
struct
ipv6hdr
));
kfree
(
iph
);
}
skb
->
nh
.
raw
=
skb
->
data
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -244,7 +245,7 @@ int ah6_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
return
err
;
}
...
...
net/ipv6/esp6.c
View file @
62105cb5
...
...
@@ -40,11 +40,11 @@
#define MAX_SG_ONSTACK 4
int
esp6_output
(
struct
sk_buff
*
skb
)
int
esp6_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
int
hdr_len
=
0
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
ipv6hdr
*
iph
=
NULL
,
*
top_iph
;
struct
ipv6_esp_hdr
*
esph
;
...
...
@@ -58,14 +58,14 @@ int esp6_output(struct sk_buff *skb)
u8
*
prevhdr
;
u8
nexthdr
=
0
;
/* First, if the skb is not checksummed, complete checksum. */
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET6
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET6
);
if
(
err
)
goto
error
;
err
=
-
ENOMEM
;
...
...
@@ -73,7 +73,7 @@ int esp6_output(struct sk_buff *skb)
/* Strip IP header in transport mode. Save it. */
if
(
!
x
->
props
.
mode
)
{
hdr_len
=
ip6_find_1stfragopt
(
skb
,
&
prevhdr
);
hdr_len
=
ip6_find_1stfragopt
(
*
p
skb
,
&
prevhdr
);
nexthdr
=
*
prevhdr
;
*
prevhdr
=
IPPROTO_ESP
;
iph
=
kmalloc
(
hdr_len
,
GFP_ATOMIC
);
...
...
@@ -81,14 +81,14 @@ int esp6_output(struct sk_buff *skb)
err
=
-
ENOMEM
;
goto
error
;
}
memcpy
(
iph
,
skb
->
nh
.
raw
,
hdr_len
);
__skb_pull
(
skb
,
hdr_len
);
memcpy
(
iph
,
(
*
pskb
)
->
nh
.
raw
,
hdr_len
);
__skb_pull
(
*
p
skb
,
hdr_len
);
}
/* Now skb is pure payload to encrypt */
/* Round to block size */
clen
=
skb
->
len
;
clen
=
(
*
pskb
)
->
len
;
esp
=
x
->
data
;
alen
=
esp
->
auth
.
icv_trunc_len
;
...
...
@@ -98,7 +98,7 @@ int esp6_output(struct sk_buff *skb)
if
(
esp
->
conf
.
padlen
)
clen
=
(
clen
+
esp
->
conf
.
padlen
-
1
)
&~
(
esp
->
conf
.
padlen
-
1
);
if
((
nfrags
=
skb_cow_data
(
skb
,
clen
-
skb
->
len
+
alen
,
&
trailer
))
<
0
)
{
if
((
nfrags
=
skb_cow_data
(
*
pskb
,
clen
-
(
*
pskb
)
->
len
+
alen
,
&
trailer
))
<
0
)
{
if
(
!
x
->
props
.
mode
&&
iph
)
kfree
(
iph
);
goto
error
;
}
...
...
@@ -106,15 +106,15 @@ int esp6_output(struct sk_buff *skb)
/* Fill padding... */
do
{
int
i
;
for
(
i
=
0
;
i
<
clen
-
skb
->
len
-
2
;
i
++
)
for
(
i
=
0
;
i
<
clen
-
(
*
pskb
)
->
len
-
2
;
i
++
)
*
(
u8
*
)(
trailer
->
tail
+
i
)
=
i
+
1
;
}
while
(
0
);
*
(
u8
*
)(
trailer
->
tail
+
clen
-
skb
->
len
-
2
)
=
(
clen
-
skb
->
len
)
-
2
;
pskb_put
(
skb
,
trailer
,
clen
-
skb
->
len
);
*
(
u8
*
)(
trailer
->
tail
+
clen
-
(
*
pskb
)
->
len
-
2
)
=
(
clen
-
(
*
pskb
)
->
len
)
-
2
;
pskb_put
(
*
pskb
,
trailer
,
clen
-
(
*
pskb
)
->
len
);
if
(
x
->
props
.
mode
)
{
iph
=
skb
->
nh
.
ipv6h
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
iph
=
(
*
pskb
)
->
nh
.
ipv6h
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
esph
=
(
struct
ipv6_esp_hdr
*
)(
top_iph
+
1
);
*
(
u8
*
)(
trailer
->
tail
-
1
)
=
IPPROTO_IPV6
;
top_iph
->
version
=
6
;
...
...
@@ -125,19 +125,19 @@ int esp6_output(struct sk_buff *skb)
if
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
)
IP6_ECN_clear
(
top_iph
);
top_iph
->
nexthdr
=
IPPROTO_ESP
;
top_iph
->
payload_len
=
htons
(
skb
->
len
+
alen
-
sizeof
(
struct
ipv6hdr
));
top_iph
->
payload_len
=
htons
(
(
*
pskb
)
->
len
+
alen
-
sizeof
(
struct
ipv6hdr
));
top_iph
->
hop_limit
=
iph
->
hop_limit
;
ipv6_addr_copy
(
&
top_iph
->
saddr
,
(
struct
in6_addr
*
)
&
x
->
props
.
saddr
);
ipv6_addr_copy
(
&
top_iph
->
daddr
,
(
struct
in6_addr
*
)
&
x
->
id
.
daddr
);
}
else
{
esph
=
(
struct
ipv6_esp_hdr
*
)
skb_push
(
skb
,
x
->
props
.
header_len
);
skb
->
h
.
raw
=
(
unsigned
char
*
)
esph
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
hdr_len
);
esph
=
(
struct
ipv6_esp_hdr
*
)
skb_push
(
*
p
skb
,
x
->
props
.
header_len
);
(
*
pskb
)
->
h
.
raw
=
(
unsigned
char
*
)
esph
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
hdr_len
);
memcpy
(
top_iph
,
iph
,
hdr_len
);
kfree
(
iph
);
top_iph
->
payload_len
=
htons
(
skb
->
len
+
alen
-
sizeof
(
struct
ipv6hdr
));
top_iph
->
payload_len
=
htons
(
(
*
pskb
)
->
len
+
alen
-
sizeof
(
struct
ipv6hdr
));
*
(
u8
*
)(
trailer
->
tail
-
1
)
=
nexthdr
;
}
...
...
@@ -156,7 +156,7 @@ int esp6_output(struct sk_buff *skb)
if
(
!
sg
)
goto
error
;
}
skb_to_sgvec
(
skb
,
sg
,
esph
->
enc_data
+
esp
->
conf
.
ivlen
-
skb
->
data
,
clen
);
skb_to_sgvec
(
*
pskb
,
sg
,
esph
->
enc_data
+
esp
->
conf
.
ivlen
-
(
*
pskb
)
->
data
,
clen
);
crypto_cipher_encrypt
(
tfm
,
sg
,
sg
,
clen
);
if
(
unlikely
(
sg
!=
sgbuf
))
kfree
(
sg
);
...
...
@@ -168,17 +168,17 @@ int esp6_output(struct sk_buff *skb)
}
if
(
esp
->
auth
.
icv_full_len
)
{
esp
->
auth
.
icv
(
esp
,
skb
,
(
u8
*
)
esph
-
skb
->
data
,
esp
->
auth
.
icv
(
esp
,
*
pskb
,
(
u8
*
)
esph
-
(
*
pskb
)
->
data
,
sizeof
(
struct
ipv6_esp_hdr
)
+
esp
->
conf
.
ivlen
+
clen
,
trailer
->
tail
);
pskb_put
(
skb
,
trailer
,
alen
);
pskb_put
(
*
p
skb
,
trailer
,
alen
);
}
skb
->
nh
.
raw
=
skb
->
data
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -187,7 +187,7 @@ int esp6_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
return
err
;
}
...
...
net/ipv6/ip6_output.c
View file @
62105cb5
...
...
@@ -55,7 +55,7 @@
#include <net/icmp.h>
#include <net/xfrm.h>
static
int
ip6_fragment
(
struct
sk_buff
*
skb
,
int
(
*
output
)(
struct
sk_buff
*
));
static
int
ip6_fragment
(
struct
sk_buff
*
*
pskb
,
int
(
*
output
)(
struct
sk_buff
*
*
));
static
__inline__
void
ipv6_select_ident
(
struct
sk_buff
*
skb
,
struct
frag_hdr
*
fhdr
)
{
...
...
@@ -107,8 +107,9 @@ static int ip6_dev_loopback_xmit(struct sk_buff *newskb)
}
int
ip6_output2
(
struct
sk_buff
*
skb
)
int
ip6_output2
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
net_device
*
dev
=
dst
->
dev
;
...
...
@@ -144,12 +145,14 @@ int ip6_output2(struct sk_buff *skb)
return
NF_HOOK
(
PF_INET6
,
NF_IP6_POST_ROUTING
,
skb
,
NULL
,
skb
->
dev
,
ip6_output_finish
);
}
int
ip6_output
(
struct
sk_buff
*
skb
)
int
ip6_output
(
struct
sk_buff
*
*
p
skb
)
{
struct
sk_buff
*
skb
=
*
pskb
;
if
((
skb
->
len
>
dst_pmtu
(
skb
->
dst
)
||
skb_shinfo
(
skb
)
->
frag_list
))
return
ip6_fragment
(
skb
,
ip6_output2
);
return
ip6_fragment
(
p
skb
,
ip6_output2
);
else
return
ip6_output2
(
skb
);
return
ip6_output2
(
p
skb
);
}
#ifdef CONFIG_NETFILTER
...
...
@@ -513,11 +516,11 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
return
offset
;
}
static
int
ip6_fragment
(
struct
sk_buff
*
skb
,
int
(
*
output
)(
struct
sk_buff
*
))
static
int
ip6_fragment
(
struct
sk_buff
*
*
pskb
,
int
(
*
output
)(
struct
sk_buff
*
*
))
{
struct
net_device
*
dev
;
struct
sk_buff
*
frag
,
*
skb
=
*
pskb
;
struct
rt6_info
*
rt
=
(
struct
rt6_info
*
)
skb
->
dst
;
struct
sk_buff
*
frag
;
struct
ipv6hdr
*
tmp_hdr
;
struct
frag_hdr
*
fh
;
unsigned
int
mtu
,
hlen
,
left
,
len
;
...
...
@@ -604,10 +607,12 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
frag
->
nh
.
ipv6h
->
payload_len
=
htons
(
frag
->
len
-
sizeof
(
struct
ipv6hdr
));
ip6_copy_metadata
(
frag
,
skb
);
}
err
=
output
(
skb
);
if
(
err
||
!
frag
)
err
=
output
(
pskb
);
if
(
err
||
!
frag
)
{
if
(
unlikely
(
skb
!=
*
pskb
))
skb
=
*
pskb
;
break
;
}
skb
=
frag
;
frag
=
skb
->
next
;
...
...
@@ -721,7 +726,7 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
IP6_INC_STATS
(
FragCreates
);
err
=
output
(
frag
);
err
=
output
(
&
frag
);
if
(
err
)
goto
fail
;
}
...
...
net/ipv6/ipcomp6.c
View file @
62105cb5
...
...
@@ -118,10 +118,10 @@ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, s
return
err
;
}
static
int
ipcomp6_output
(
struct
sk_buff
*
skb
)
static
int
ipcomp6_output
(
struct
sk_buff
*
*
p
skb
)
{
int
err
;
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
dst_entry
*
dst
=
(
*
pskb
)
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
ipv6hdr
*
tmp_iph
=
NULL
,
*
iph
,
*
top_iph
;
int
hdr_len
=
0
;
...
...
@@ -132,54 +132,55 @@ static int ipcomp6_output(struct sk_buff *skb)
int
plen
,
dlen
;
u8
*
start
,
*
scratch
=
ipcd
->
scratch
;
if
(
skb
->
ip_summed
==
CHECKSUM_HW
&&
skb_checksum_help
(
skb
)
==
NULL
)
{
err
=
-
EINVAL
;
if
((
*
pskb
)
->
ip_summed
==
CHECKSUM_HW
)
{
err
=
skb_checksum_help
(
pskb
,
0
);
if
(
err
)
goto
error_nolock
;
}
spin_lock_bh
(
&
x
->
lock
);
err
=
xfrm_check_output
(
x
,
skb
,
AF_INET6
);
err
=
xfrm_check_output
(
x
,
*
p
skb
,
AF_INET6
);
if
(
err
)
goto
error
;
if
(
x
->
props
.
mode
)
{
hdr_len
=
sizeof
(
struct
ipv6hdr
);
nexthdr
=
IPPROTO_IPV6
;
iph
=
skb
->
nh
.
ipv6h
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
sizeof
(
struct
ipv6hdr
));
iph
=
(
*
pskb
)
->
nh
.
ipv6h
;
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
sizeof
(
struct
ipv6hdr
));
top_iph
->
version
=
6
;
top_iph
->
priority
=
iph
->
priority
;
top_iph
->
flow_lbl
[
0
]
=
iph
->
flow_lbl
[
0
];
top_iph
->
flow_lbl
[
1
]
=
iph
->
flow_lbl
[
1
];
top_iph
->
flow_lbl
[
2
]
=
iph
->
flow_lbl
[
2
];
top_iph
->
nexthdr
=
IPPROTO_IPV6
;
/* initial */
top_iph
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
top_iph
->
payload_len
=
htons
(
(
*
pskb
)
->
len
-
sizeof
(
struct
ipv6hdr
));
top_iph
->
hop_limit
=
iph
->
hop_limit
;
memcpy
(
&
top_iph
->
saddr
,
(
struct
in6_addr
*
)
&
x
->
props
.
saddr
,
sizeof
(
struct
in6_addr
));
memcpy
(
&
top_iph
->
daddr
,
(
struct
in6_addr
*
)
&
x
->
id
.
daddr
,
sizeof
(
struct
in6_addr
));
skb
->
nh
.
raw
=
skb
->
data
;
/* == top_iph */
skb
->
h
.
raw
=
skb
->
nh
.
raw
+
hdr_len
;
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
/* == top_iph */
(
*
pskb
)
->
h
.
raw
=
(
*
pskb
)
->
nh
.
raw
+
hdr_len
;
}
else
{
hdr_len
=
ip6_find_1stfragopt
(
skb
,
&
prevhdr
);
hdr_len
=
ip6_find_1stfragopt
(
*
p
skb
,
&
prevhdr
);
nexthdr
=
*
prevhdr
;
}
/* check whether datagram len is larger than threshold */
if
((
skb
->
len
-
hdr_len
)
<
ipcd
->
threshold
)
{
if
((
(
*
pskb
)
->
len
-
hdr_len
)
<
ipcd
->
threshold
)
{
goto
out_ok
;
}
if
((
skb_is_nonlinear
(
skb
)
||
skb_cloned
(
skb
))
&&
skb_linearize
(
skb
,
GFP_ATOMIC
)
!=
0
)
{
if
((
skb_is_nonlinear
(
*
pskb
)
||
skb_cloned
(
*
p
skb
))
&&
skb_linearize
(
*
p
skb
,
GFP_ATOMIC
)
!=
0
)
{
err
=
-
ENOMEM
;
goto
error
;
}
/* compression */
plen
=
skb
->
len
-
hdr_len
;
plen
=
(
*
pskb
)
->
len
-
hdr_len
;
dlen
=
IPCOMP_SCRATCH_SIZE
;
start
=
skb
->
data
+
hdr_len
;
start
=
(
*
pskb
)
->
data
+
hdr_len
;
err
=
crypto_comp_compress
(
ipcd
->
tfm
,
start
,
plen
,
scratch
,
&
dlen
);
if
(
err
)
{
...
...
@@ -189,7 +190,7 @@ static int ipcomp6_output(struct sk_buff *skb)
goto
out_ok
;
}
memcpy
(
start
,
scratch
,
dlen
);
pskb_trim
(
skb
,
hdr_len
+
dlen
);
pskb_trim
(
*
p
skb
,
hdr_len
+
dlen
);
/* insert ipcomp header and replace datagram */
tmp_iph
=
kmalloc
(
hdr_len
,
GFP_ATOMIC
);
...
...
@@ -197,16 +198,16 @@ static int ipcomp6_output(struct sk_buff *skb)
err
=
-
ENOMEM
;
goto
error
;
}
memcpy
(
tmp_iph
,
skb
->
nh
.
raw
,
hdr_len
);
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
sizeof
(
struct
ipv6_comp_hdr
));
memcpy
(
tmp_iph
,
(
*
pskb
)
->
nh
.
raw
,
hdr_len
);
top_iph
=
(
struct
ipv6hdr
*
)
skb_push
(
*
p
skb
,
sizeof
(
struct
ipv6_comp_hdr
));
memcpy
(
top_iph
,
tmp_iph
,
hdr_len
);
kfree
(
tmp_iph
);
if
(
x
->
props
.
mode
&&
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
))
IP6_ECN_clear
(
top_iph
);
top_iph
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
skb
->
nh
.
raw
=
skb
->
data
;
/* top_iph */
ip6_find_1stfragopt
(
skb
,
&
prevhdr
);
top_iph
->
payload_len
=
htons
(
(
*
pskb
)
->
len
-
sizeof
(
struct
ipv6hdr
));
(
*
pskb
)
->
nh
.
raw
=
(
*
pskb
)
->
data
;
/* top_iph */
ip6_find_1stfragopt
(
*
p
skb
,
&
prevhdr
);
*
prevhdr
=
IPPROTO_COMP
;
ipch
=
(
struct
ipv6_comp_hdr
*
)((
unsigned
char
*
)
top_iph
+
hdr_len
);
...
...
@@ -214,13 +215,13 @@ static int ipcomp6_output(struct sk_buff *skb)
ipch
->
flags
=
0
;
ipch
->
cpi
=
htons
((
u16
)
ntohl
(
x
->
id
.
spi
));
skb
->
h
.
raw
=
(
unsigned
char
*
)
ipch
;
(
*
pskb
)
->
h
.
raw
=
(
unsigned
char
*
)
ipch
;
out_ok:
x
->
curlft
.
bytes
+=
skb
->
len
;
x
->
curlft
.
bytes
+=
(
*
pskb
)
->
len
;
x
->
curlft
.
packets
++
;
spin_unlock_bh
(
&
x
->
lock
);
if
((
skb
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
if
((
(
*
pskb
)
->
dst
=
dst_pop
(
dst
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
error_nolock
;
}
...
...
@@ -231,7 +232,7 @@ static int ipcomp6_output(struct sk_buff *skb)
error:
spin_unlock_bh
(
&
x
->
lock
);
error_nolock:
kfree_skb
(
skb
);
kfree_skb
(
*
p
skb
);
goto
out_exit
;
}
...
...
net/ipv6/route.c
View file @
62105cb5
...
...
@@ -87,6 +87,7 @@ static void ip6_dst_destroy(struct dst_entry *);
static
int
ip6_dst_gc
(
void
);
static
int
ip6_pkt_discard
(
struct
sk_buff
*
skb
);
static
int
ip6_pkt_discard_out
(
struct
sk_buff
**
pskb
);
static
void
ip6_link_failure
(
struct
sk_buff
*
skb
);
static
void
ip6_rt_update_pmtu
(
struct
dst_entry
*
dst
,
u32
mtu
);
...
...
@@ -113,7 +114,7 @@ struct rt6_info ip6_null_entry = {
.
error
=
-
ENETUNREACH
,
.
metrics
=
{
[
RTAX_HOPLIMIT
-
1
]
=
255
,
},
.
input
=
ip6_pkt_discard
,
.
output
=
ip6_pkt_discard
,
.
output
=
ip6_pkt_discard
_out
,
.
ops
=
&
ip6_dst_ops
,
.
path
=
(
struct
dst_entry
*
)
&
ip6_null_entry
,
}
...
...
@@ -576,7 +577,7 @@ static struct dst_entry *ndisc_dst_gc_list;
struct
dst_entry
*
ndisc_dst_alloc
(
struct
net_device
*
dev
,
struct
neighbour
*
neigh
,
struct
in6_addr
*
addr
,
int
(
*
output
)(
struct
sk_buff
*
))
int
(
*
output
)(
struct
sk_buff
*
*
))
{
struct
rt6_info
*
rt
=
ip6_dst_alloc
();
...
...
@@ -778,7 +779,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
dev_put
(
dev
);
dev
=
&
loopback_dev
;
dev_hold
(
dev
);
rt
->
u
.
dst
.
output
=
ip6_pkt_discard
;
rt
->
u
.
dst
.
output
=
ip6_pkt_discard
_out
;
rt
->
u
.
dst
.
input
=
ip6_pkt_discard
;
rt
->
u
.
dst
.
error
=
-
ENETUNREACH
;
rt
->
rt6i_flags
=
RTF_REJECT
|
RTF_NONEXTHOP
;
...
...
@@ -1278,6 +1279,11 @@ int ip6_pkt_discard(struct sk_buff *skb)
return
0
;
}
int
ip6_pkt_discard_out
(
struct
sk_buff
**
pskb
)
{
return
ip6_pkt_discard
(
*
pskb
);
}
/*
* Add address
*/
...
...
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