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
f05cd468
Commit
f05cd468
authored
Mar 23, 2003
by
Mitsuru Kanda
Committed by
David S. Miller
Mar 23, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[IPV6]: Process all extension headers via ipproto->handler.
parent
4228d368
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
158 additions
and
196 deletions
+158
-196
include/net/ipv6.h
include/net/ipv6.h
+0
-4
include/net/protocol.h
include/net/protocol.h
+1
-1
include/net/transp_v6.h
include/net/transp_v6.h
+8
-0
include/net/xfrm.h
include/net/xfrm.h
+1
-1
net/ipv6/af_inet6.c
net/ipv6/af_inet6.c
+7
-0
net/ipv6/exthdrs.c
net/ipv6/exthdrs.c
+93
-127
net/ipv6/icmp.c
net/ipv6/icmp.c
+3
-2
net/ipv6/ip6_input.c
net/ipv6/ip6_input.c
+8
-31
net/ipv6/reassembly.c
net/ipv6/reassembly.c
+29
-7
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+2
-1
net/ipv6/udp.c
net/ipv6/udp.c
+2
-1
net/ipv6/xfrm6_input.c
net/ipv6/xfrm6_input.c
+4
-21
No files found.
include/net/ipv6.h
View file @
f05cd468
...
@@ -203,12 +203,8 @@ extern int ip6_ra_control(struct sock *sk, int sel,
...
@@ -203,12 +203,8 @@ extern int ip6_ra_control(struct sock *sk, int sel,
extern
int
ip6_call_ra_chain
(
struct
sk_buff
*
skb
,
int
sel
);
extern
int
ip6_call_ra_chain
(
struct
sk_buff
*
skb
,
int
sel
);
extern
int
ipv6_reassembly
(
struct
sk_buff
**
skb
,
int
);
extern
int
ipv6_parse_hopopts
(
struct
sk_buff
*
skb
,
int
);
extern
int
ipv6_parse_hopopts
(
struct
sk_buff
*
skb
,
int
);
extern
int
ipv6_parse_exthdrs
(
struct
sk_buff
**
skb
,
int
);
extern
struct
ipv6_txoptions
*
ipv6_dup_options
(
struct
sock
*
sk
,
struct
ipv6_txoptions
*
opt
);
extern
struct
ipv6_txoptions
*
ipv6_dup_options
(
struct
sock
*
sk
,
struct
ipv6_txoptions
*
opt
);
extern
int
ip6_frag_nqueues
;
extern
int
ip6_frag_nqueues
;
...
...
include/net/protocol.h
View file @
f05cd468
...
@@ -44,7 +44,7 @@ struct inet_protocol
...
@@ -44,7 +44,7 @@ struct inet_protocol
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct
inet6_protocol
struct
inet6_protocol
{
{
int
(
*
handler
)(
struct
sk_buff
*
skb
);
int
(
*
handler
)(
struct
sk_buff
*
*
skbp
);
void
(
*
err_handler
)(
struct
sk_buff
*
skb
,
void
(
*
err_handler
)(
struct
sk_buff
*
skb
,
struct
inet6_skb_parm
*
opt
,
struct
inet6_skb_parm
*
opt
,
...
...
include/net/transp_v6.h
View file @
f05cd468
...
@@ -15,6 +15,14 @@ extern struct proto tcpv6_prot;
...
@@ -15,6 +15,14 @@ extern struct proto tcpv6_prot;
struct
flowi
;
struct
flowi
;
/* extention headers */
extern
void
ipv6_hopopts_init
(
void
);
extern
void
ipv6_rthdr_init
(
void
);
extern
void
ipv6_frag_init
(
void
);
extern
void
ipv6_nodata_init
(
void
);
extern
void
ipv6_destopt_init
(
void
);
/* transport protocols */
extern
void
rawv6_init
(
void
);
extern
void
rawv6_init
(
void
);
extern
void
udpv6_init
(
void
);
extern
void
udpv6_init
(
void
);
extern
void
tcpv6_init
(
void
);
extern
void
tcpv6_init
(
void
);
...
...
include/net/xfrm.h
View file @
f05cd468
...
@@ -730,7 +730,7 @@ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
...
@@ -730,7 +730,7 @@ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
extern
void
xfrm_replay_advance
(
struct
xfrm_state
*
x
,
u32
seq
);
extern
void
xfrm_replay_advance
(
struct
xfrm_state
*
x
,
u32
seq
);
extern
int
xfrm_check_selectors
(
struct
xfrm_state
**
x
,
int
n
,
struct
flowi
*
fl
);
extern
int
xfrm_check_selectors
(
struct
xfrm_state
**
x
,
int
n
,
struct
flowi
*
fl
);
extern
int
xfrm4_rcv
(
struct
sk_buff
*
skb
);
extern
int
xfrm4_rcv
(
struct
sk_buff
*
skb
);
extern
int
xfrm6_rcv
(
struct
sk_buff
*
skb
);
extern
int
xfrm6_rcv
(
struct
sk_buff
*
*
p
skb
);
extern
int
xfrm6_clear_mutable_options
(
struct
sk_buff
*
skb
,
u16
*
nh_offset
,
int
dir
);
extern
int
xfrm6_clear_mutable_options
(
struct
sk_buff
*
skb
,
u16
*
nh_offset
,
int
dir
);
extern
int
xfrm_user_policy
(
struct
sock
*
sk
,
int
optname
,
u8
*
optval
,
int
optlen
);
extern
int
xfrm_user_policy
(
struct
sock
*
sk
,
int
optname
,
u8
*
optval
,
int
optlen
);
...
...
net/ipv6/af_inet6.c
View file @
f05cd468
...
@@ -799,6 +799,13 @@ static int __init inet6_init(void)
...
@@ -799,6 +799,13 @@ static int __init inet6_init(void)
addrconf_init
();
addrconf_init
();
sit_init
();
sit_init
();
/* Init v6 extention headers. */
ipv6_hopopts_init
();
ipv6_rthdr_init
();
ipv6_frag_init
();
ipv6_nodata_init
();
ipv6_destopt_init
();
/* Init v6 transport protocols. */
/* Init v6 transport protocols. */
udpv6_init
();
udpv6_init
();
tcpv6_init
();
tcpv6_init
();
...
...
net/ipv6/exthdrs.c
View file @
f05cd468
...
@@ -18,6 +18,9 @@
...
@@ -18,6 +18,9 @@
/* Changes:
/* Changes:
* yoshfuji : ensure not to overrun while parsing
* yoshfuji : ensure not to overrun while parsing
* tlv options.
* tlv options.
* Mitsuru KANDA @USAGI : Remove ipv6_parse_exthdrs().
* : Register inbound extention header
* : handlers as inet6_protocol{}.
*/
*/
#include <linux/errno.h>
#include <linux/errno.h>
...
@@ -43,20 +46,6 @@
...
@@ -43,20 +46,6 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>
/*
* Parsing inbound headers.
*
* Parsing function "func" returns offset wrt skb->nh of the place,
* where next nexthdr value is stored or NULL, if parsing
* failed. It should also update skb->h tp point at the next header.
*/
struct
hdrtype_proc
{
int
type
;
int
(
*
func
)
(
struct
sk_buff
**
,
int
offset
);
};
/*
/*
* Parsing tlv encoded headers.
* Parsing tlv encoded headers.
*
*
...
@@ -164,49 +153,77 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
...
@@ -164,49 +153,77 @@ static struct tlvtype_proc tlvprocdestopt_lst[] = {
{
-
1
,
NULL
}
{
-
1
,
NULL
}
};
};
static
int
ipv6_dest
_opt
(
struct
sk_buff
**
skb_ptr
,
int
nhoff
)
static
int
ipv6_dest
opt_rcv
(
struct
sk_buff
**
skbp
)
{
{
struct
sk_buff
*
skb
=*
skb_ptr
;
struct
sk_buff
*
skb
=
*
skbp
;
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
u8
nexthdr
=
0
;
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
8
)
||
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
8
)
||
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
}
nexthdr
=
((
struct
ipv6_destopt_hdr
*
)
skb
->
h
.
raw
)
->
nexthdr
;
opt
->
dst1
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
opt
->
dst1
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
if
(
ip6_parse_tlv
(
tlvprocdestopt_lst
,
skb
))
{
if
(
ip6_parse_tlv
(
tlvprocdestopt_lst
,
skb
))
{
skb
->
h
.
raw
+=
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
);
skb
->
h
.
raw
+=
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
);
return
opt
->
dst1
;
return
-
nexthdr
;
}
}
return
0
;
}
return
-
1
;
static
struct
inet6_protocol
destopt_protocol
=
{
.
handler
=
ipv6_destopt_rcv
,
};
void
__init
ipv6_destopt_init
(
void
)
{
if
(
inet6_add_protocol
(
&
destopt_protocol
,
IPPROTO_DSTOPTS
)
<
0
)
printk
(
KERN_ERR
"ipv6_destopt_init: Could not register protocol
\n
"
);
}
}
/********************************
/********************************
NONE header. No data in packet.
NONE header. No data in packet.
********************************/
********************************/
static
int
ipv6_nodata
(
struct
sk_buff
**
skb_ptr
,
int
nhoff
)
static
int
ipv6_nodata
_rcv
(
struct
sk_buff
**
skbp
)
{
{
kfree_skb
(
*
skb_ptr
);
struct
sk_buff
*
skb
=
*
skbp
;
return
-
1
;
kfree_skb
(
skb
);
return
0
;
}
static
struct
inet6_protocol
nodata_protocol
=
{
.
handler
=
ipv6_nodata_rcv
,
};
void
__init
ipv6_nodata_init
(
void
)
{
if
(
inet6_add_protocol
(
&
nodata_protocol
,
IPPROTO_NONE
)
<
0
)
printk
(
KERN_ERR
"ipv6_nodata_init: Could not register protocol
\n
"
);
}
}
/********************************
/********************************
Routing header.
Routing header.
********************************/
********************************/
static
int
ipv6_r
outing_header
(
struct
sk_buff
**
skb_ptr
,
int
nhoff
)
static
int
ipv6_r
thdr_rcv
(
struct
sk_buff
**
skbp
)
{
{
struct
sk_buff
*
skb
=
*
skb
_ptr
;
struct
sk_buff
*
skb
=
*
skb
p
;
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
struct
in6_addr
*
addr
;
struct
in6_addr
*
addr
;
struct
in6_addr
daddr
;
struct
in6_addr
daddr
;
int
addr_type
;
int
addr_type
;
int
n
,
i
;
int
n
,
i
;
u8
nexthdr
=
0
;
struct
ipv6_rt_hdr
*
hdr
;
struct
ipv6_rt_hdr
*
hdr
;
struct
rt0_hdr
*
rthdr
;
struct
rt0_hdr
*
rthdr
;
...
@@ -215,15 +232,16 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
...
@@ -215,15 +232,16 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
IP6_INC_STATS_BH
(
Ip6InHdrErrors
);
IP6_INC_STATS_BH
(
Ip6InHdrErrors
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
}
hdr
=
(
struct
ipv6_rt_hdr
*
)
skb
->
h
.
raw
;
hdr
=
(
struct
ipv6_rt_hdr
*
)
skb
->
h
.
raw
;
nexthdr
=
hdr
->
nexthdr
;
if
((
ipv6_addr_type
(
&
skb
->
nh
.
ipv6h
->
daddr
)
&
IPV6_ADDR_MULTICAST
)
||
if
((
ipv6_addr_type
(
&
skb
->
nh
.
ipv6h
->
daddr
)
&
IPV6_ADDR_MULTICAST
)
||
skb
->
pkt_type
!=
PACKET_HOST
)
{
skb
->
pkt_type
!=
PACKET_HOST
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
}
looped_back:
looped_back:
...
@@ -232,24 +250,24 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
...
@@ -232,24 +250,24 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
skb
->
h
.
raw
+=
(
hdr
->
hdrlen
+
1
)
<<
3
;
skb
->
h
.
raw
+=
(
hdr
->
hdrlen
+
1
)
<<
3
;
opt
->
dst0
=
opt
->
dst1
;
opt
->
dst0
=
opt
->
dst1
;
opt
->
dst1
=
0
;
opt
->
dst1
=
0
;
return
(
&
hdr
->
nexthdr
)
-
skb
->
nh
.
raw
;
return
-
nexthdr
;
}
}
if
(
hdr
->
type
!=
IPV6_SRCRT_TYPE_0
||
(
hdr
->
hdrlen
&
0x01
))
{
if
(
hdr
->
type
!=
IPV6_SRCRT_TYPE_0
||
(
hdr
->
hdrlen
&
0x01
))
{
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
hdr
->
type
!=
IPV6_SRCRT_TYPE_0
?
2
:
1
);
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
hdr
->
type
!=
IPV6_SRCRT_TYPE_0
?
2
:
1
);
return
-
1
;
return
0
;
}
}
/*
/*
* This is the routing header forwarding algorithm from
* This is the routing header forwarding algorithm from
* RFC
1883, page 17
.
* RFC
2460, page 16
.
*/
*/
n
=
hdr
->
hdrlen
>>
1
;
n
=
hdr
->
hdrlen
>>
1
;
if
(
hdr
->
segments_left
>
n
)
{
if
(
hdr
->
segments_left
>
n
)
{
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
(
&
hdr
->
segments_left
)
-
skb
->
nh
.
raw
);
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
(
&
hdr
->
segments_left
)
-
skb
->
nh
.
raw
);
return
-
1
;
return
0
;
}
}
/* We are about to mangle packet header. Be careful!
/* We are about to mangle packet header. Be careful!
...
@@ -259,8 +277,8 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
...
@@ -259,8 +277,8 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
struct
sk_buff
*
skb2
=
skb_copy
(
skb
,
GFP_ATOMIC
);
struct
sk_buff
*
skb2
=
skb_copy
(
skb
,
GFP_ATOMIC
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
if
(
skb2
==
NULL
)
if
(
skb2
==
NULL
)
return
-
1
;
return
0
;
*
skb
_ptr
=
skb
=
skb2
;
*
skb
p
=
skb
=
skb2
;
opt
=
(
struct
inet6_skb_parm
*
)
skb2
->
cb
;
opt
=
(
struct
inet6_skb_parm
*
)
skb2
->
cb
;
hdr
=
(
struct
ipv6_rt_hdr
*
)
skb2
->
h
.
raw
;
hdr
=
(
struct
ipv6_rt_hdr
*
)
skb2
->
h
.
raw
;
}
}
...
@@ -278,7 +296,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
...
@@ -278,7 +296,7 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
if
(
addr_type
&
IPV6_ADDR_MULTICAST
)
{
if
(
addr_type
&
IPV6_ADDR_MULTICAST
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
}
ipv6_addr_copy
(
&
daddr
,
addr
);
ipv6_addr_copy
(
&
daddr
,
addr
);
...
@@ -289,23 +307,34 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
...
@@ -289,23 +307,34 @@ static int ipv6_routing_header(struct sk_buff **skb_ptr, int nhoff)
ip6_route_input
(
skb
);
ip6_route_input
(
skb
);
if
(
skb
->
dst
->
error
)
{
if
(
skb
->
dst
->
error
)
{
dst_input
(
skb
);
dst_input
(
skb
);
return
-
1
;
return
0
;
}
}
if
(
skb
->
dst
->
dev
->
flags
&
IFF_LOOPBACK
)
{
if
(
skb
->
dst
->
dev
->
flags
&
IFF_LOOPBACK
)
{
if
(
skb
->
nh
.
ipv6h
->
hop_limit
<=
1
)
{
if
(
skb
->
nh
.
ipv6h
->
hop_limit
<=
1
)
{
icmpv6_send
(
skb
,
ICMPV6_TIME_EXCEED
,
ICMPV6_EXC_HOPLIMIT
,
icmpv6_send
(
skb
,
ICMPV6_TIME_EXCEED
,
ICMPV6_EXC_HOPLIMIT
,
0
,
skb
->
dev
);
0
,
skb
->
dev
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
}
skb
->
nh
.
ipv6h
->
hop_limit
--
;
skb
->
nh
.
ipv6h
->
hop_limit
--
;
goto
looped_back
;
goto
looped_back
;
}
}
dst_input
(
skb
);
dst_input
(
skb
);
return
-
1
;
return
0
;
}
}
static
struct
inet6_protocol
rthdr_protocol
=
{
.
handler
=
ipv6_rthdr_rcv
,
};
void
__init
ipv6_rthdr_init
(
void
)
{
if
(
inet6_add_protocol
(
&
rthdr_protocol
,
IPPROTO_ROUTING
)
<
0
)
printk
(
KERN_ERR
"ipv6_rthdr_init: Could not register protocol
\n
"
);
};
/*
/*
This function inverts received rthdr.
This function inverts received rthdr.
NOTE: specs allow to make it automatically only if
NOTE: specs allow to make it automatically only if
...
@@ -371,97 +400,6 @@ ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
...
@@ -371,97 +400,6 @@ ipv6_invert_rthdr(struct sock *sk, struct ipv6_rt_hdr *hdr)
return
opt
;
return
opt
;
}
}
/********************************
AUTH header.
********************************/
/*
rfc1826 said, that if a host does not implement AUTH header
it MAY ignore it. We use this hole 8)
Actually, now we can implement OSPFv6 without kernel IPsec.
Authentication for poors may be done in user space with the same success.
Yes, it means, that we allow application to send/receive
raw authentication header. Apparently, we suppose, that it knows
what it does and calculates authentication data correctly.
Certainly, it is possible only for udp and raw sockets, but not for tcp.
AUTH header has 4byte granular length, which kills all the idea
behind AUTOMATIC 64bit alignment of IPv6. Now we will lose
cpu ticks, checking that sender did not something stupid
and opt->hdrlen is even. Shit! --ANK (980730)
*/
static
int
ipv6_auth_hdr
(
struct
sk_buff
**
skb_ptr
,
int
nhoff
)
{
struct
sk_buff
*
skb
=*
skb_ptr
;
struct
inet6_skb_parm
*
opt
=
(
struct
inet6_skb_parm
*
)
skb
->
cb
;
int
len
;
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
8
))
goto
fail
;
/*
* RFC2402 2.2 Payload Length
* The 8-bit field specifies the length of AH in 32-bit words
* (4-byte units), minus "2".
* -- Noriaki Takamiya @USAGI Project
*/
len
=
(
skb
->
h
.
raw
[
1
]
+
2
)
<<
2
;
if
(
len
&
7
)
goto
fail
;
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
len
))
goto
fail
;
opt
->
auth
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
skb
->
h
.
raw
+=
len
;
return
opt
->
auth
;
fail:
kfree_skb
(
skb
);
return
-
1
;
}
/* This list MUST NOT contain entry for NEXTHDR_HOP.
It is parsed immediately after packet received
and if it occurs somewhere in another place we must
generate error.
*/
static
struct
hdrtype_proc
hdrproc_lst
[]
=
{
{
NEXTHDR_FRAGMENT
,
ipv6_reassembly
},
{
NEXTHDR_ROUTING
,
ipv6_routing_header
},
{
NEXTHDR_DEST
,
ipv6_dest_opt
},
{
NEXTHDR_NONE
,
ipv6_nodata
},
{
NEXTHDR_AUTH
,
ipv6_auth_hdr
},
/*
{NEXTHDR_ESP, ipv6_esp_hdr},
*/
{
-
1
,
NULL
}
};
int
ipv6_parse_exthdrs
(
struct
sk_buff
**
skb_in
,
int
nhoff
)
{
struct
hdrtype_proc
*
hdrt
;
u8
nexthdr
=
(
*
skb_in
)
->
nh
.
raw
[
nhoff
];
restart:
for
(
hdrt
=
hdrproc_lst
;
hdrt
->
type
>=
0
;
hdrt
++
)
{
if
(
hdrt
->
type
==
nexthdr
)
{
if
((
nhoff
=
hdrt
->
func
(
skb_in
,
nhoff
))
>=
0
)
{
nexthdr
=
(
*
skb_in
)
->
nh
.
raw
[
nhoff
];
goto
restart
;
}
return
-
1
;
}
}
return
nhoff
;
}
/**********************************
/**********************************
Hop-by-hop options.
Hop-by-hop options.
**********************************/
**********************************/
...
@@ -532,6 +470,34 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
...
@@ -532,6 +470,34 @@ int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff)
return
-
1
;
return
-
1
;
}
}
/* This is fake. We have already parsed hopopts in ipv6_rcv(). -mk */
static
int
ipv6_hopopts_rcv
(
struct
sk_buff
**
skbp
)
{
struct
sk_buff
*
skb
=
*
skbp
;
u8
nexthdr
=
0
;
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
8
)
||
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
kfree_skb
(
skb
);
return
0
;
}
nexthdr
=
((
struct
ipv6_hopopt_hdr
*
)
skb
->
h
.
raw
)
->
nexthdr
;
skb
->
h
.
raw
+=
(
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
;
return
-
nexthdr
;
}
static
struct
inet6_protocol
hopopts_protocol
=
{
.
handler
=
ipv6_hopopts_rcv
,
};
void
__init
ipv6_hopopts_init
(
void
)
{
if
(
inet6_add_protocol
(
&
hopopts_protocol
,
IPPROTO_HOPOPTS
)
<
0
)
printk
(
KERN_ERR
"ipv6_hopopts_init: Could not register protocol
\n
"
);
}
/*
/*
* Creating outbound headers.
* Creating outbound headers.
*
*
...
...
net/ipv6/icmp.c
View file @
f05cd468
...
@@ -74,7 +74,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
...
@@ -74,7 +74,7 @@ DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
static
struct
socket
*
__icmpv6_socket
[
NR_CPUS
];
static
struct
socket
*
__icmpv6_socket
[
NR_CPUS
];
#define icmpv6_socket __icmpv6_socket[smp_processor_id()]
#define icmpv6_socket __icmpv6_socket[smp_processor_id()]
static
int
icmpv6_rcv
(
struct
sk_buff
*
skb
);
static
int
icmpv6_rcv
(
struct
sk_buff
*
*
p
skb
);
static
struct
inet6_protocol
icmpv6_protocol
=
{
static
struct
inet6_protocol
icmpv6_protocol
=
{
.
handler
=
icmpv6_rcv
,
.
handler
=
icmpv6_rcv
,
...
@@ -459,8 +459,9 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
...
@@ -459,8 +459,9 @@ static void icmpv6_notify(struct sk_buff *skb, int type, int code, u32 info)
* Handle icmp messages
* Handle icmp messages
*/
*/
static
int
icmpv6_rcv
(
struct
sk_buff
*
skb
)
static
int
icmpv6_rcv
(
struct
sk_buff
*
*
p
skb
)
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
in6_addr
*
saddr
,
*
daddr
;
struct
in6_addr
*
saddr
,
*
daddr
;
struct
ipv6hdr
*
orig_hdr
;
struct
ipv6hdr
*
orig_hdr
;
...
...
net/ipv6/ip6_input.c
View file @
f05cd468
...
@@ -15,6 +15,10 @@
...
@@ -15,6 +15,10 @@
* as published by the Free Software Foundation; either version
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* 2 of the License, or (at your option) any later version.
*/
*/
/* Changes
*
* Mitsuru KANDA @USAGI : Remove ipv6_parse_exthdrs().
*/
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/types.h>
...
@@ -126,39 +130,11 @@ static inline int ip6_input_finish(struct sk_buff *skb)
...
@@ -126,39 +130,11 @@ static inline int ip6_input_finish(struct sk_buff *skb)
struct
ipv6hdr
*
hdr
=
skb
->
nh
.
ipv6h
;
struct
ipv6hdr
*
hdr
=
skb
->
nh
.
ipv6h
;
struct
inet6_protocol
*
ipprot
;
struct
inet6_protocol
*
ipprot
;
struct
sock
*
raw_sk
;
struct
sock
*
raw_sk
;
int
nhoff
;
int
nexthdr
=
hdr
->
nexthdr
;
int
nexthdr
;
u8
hash
;
u8
hash
;
skb
->
h
.
raw
=
skb
->
nh
.
raw
+
sizeof
(
struct
ipv6hdr
);
skb
->
h
.
raw
=
skb
->
nh
.
raw
+
sizeof
(
struct
ipv6hdr
);
/*
* Parse extension headers
*/
nexthdr
=
hdr
->
nexthdr
;
nhoff
=
offsetof
(
struct
ipv6hdr
,
nexthdr
);
/* Skip hop-by-hop options, they are already parsed. */
if
(
nexthdr
==
NEXTHDR_HOP
)
{
nhoff
=
sizeof
(
struct
ipv6hdr
);
nexthdr
=
skb
->
h
.
raw
[
0
];
skb
->
h
.
raw
+=
(
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
;
}
/* This check is sort of optimization.
It would be stupid to detect for optional headers,
which are missing with probability of 200%
*/
if
(
nexthdr
!=
IPPROTO_TCP
&&
nexthdr
!=
IPPROTO_UDP
&&
nexthdr
!=
NEXTHDR_AUTH
&&
nexthdr
!=
NEXTHDR_ESP
)
{
nhoff
=
ipv6_parse_exthdrs
(
&
skb
,
nhoff
);
if
(
nhoff
<
0
)
return
0
;
nexthdr
=
skb
->
nh
.
raw
[
nhoff
];
hdr
=
skb
->
nh
.
ipv6h
;
}
if
(
!
pskb_pull
(
skb
,
skb
->
h
.
raw
-
skb
->
data
))
if
(
!
pskb_pull
(
skb
,
skb
->
h
.
raw
-
skb
->
data
))
goto
discard
;
goto
discard
;
...
@@ -173,7 +149,7 @@ static inline int ip6_input_finish(struct sk_buff *skb)
...
@@ -173,7 +149,7 @@ static inline int ip6_input_finish(struct sk_buff *skb)
hash
=
nexthdr
&
(
MAX_INET_PROTOS
-
1
);
hash
=
nexthdr
&
(
MAX_INET_PROTOS
-
1
);
if
((
ipprot
=
inet6_protos
[
hash
])
!=
NULL
)
{
if
((
ipprot
=
inet6_protos
[
hash
])
!=
NULL
)
{
int
ret
=
ipprot
->
handler
(
skb
);
int
ret
=
ipprot
->
handler
(
&
skb
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
nexthdr
=
-
ret
;
nexthdr
=
-
ret
;
goto
resubmit
;
goto
resubmit
;
...
@@ -182,7 +158,8 @@ static inline int ip6_input_finish(struct sk_buff *skb)
...
@@ -182,7 +158,8 @@ static inline int ip6_input_finish(struct sk_buff *skb)
}
else
{
}
else
{
if
(
!
raw_sk
)
{
if
(
!
raw_sk
)
{
IP6_INC_STATS_BH
(
Ip6InUnknownProtos
);
IP6_INC_STATS_BH
(
Ip6InUnknownProtos
);
icmpv6_param_prob
(
skb
,
ICMPV6_UNK_NEXTHDR
,
nhoff
);
icmpv6_param_prob
(
skb
,
ICMPV6_UNK_NEXTHDR
,
offsetof
(
struct
ipv6hdr
,
nexthdr
));
}
else
{
}
else
{
IP6_INC_STATS_BH
(
Ip6InDelivers
);
IP6_INC_STATS_BH
(
Ip6InDelivers
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
...
...
net/ipv6/reassembly.c
View file @
f05cd468
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
* Horst von Brand Add missing #include <linux/string.h>
* Horst von Brand Add missing #include <linux/string.h>
* Alexey Kuznetsov SMP races, threading, cleanup.
* Alexey Kuznetsov SMP races, threading, cleanup.
* Patrick McHardy LRU queue of frag heads for evictor.
* Patrick McHardy LRU queue of frag heads for evictor.
* Mitsuru KANDA @USAGI Register inet6_protocol{}.
*/
*/
#include <linux/config.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/errno.h>
...
@@ -525,6 +526,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
...
@@ -525,6 +526,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
int
remove_fraghdr
=
0
;
int
remove_fraghdr
=
0
;
int
payload_len
;
int
payload_len
;
int
nhoff
;
int
nhoff
;
u8
nexthdr
=
0
;
fq_kill
(
fq
);
fq_kill
(
fq
);
...
@@ -535,6 +537,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
...
@@ -535,6 +537,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
payload_len
=
(
head
->
data
-
head
->
nh
.
raw
)
-
sizeof
(
struct
ipv6hdr
)
+
fq
->
len
;
payload_len
=
(
head
->
data
-
head
->
nh
.
raw
)
-
sizeof
(
struct
ipv6hdr
)
+
fq
->
len
;
nhoff
=
head
->
h
.
raw
-
head
->
nh
.
raw
;
nhoff
=
head
->
h
.
raw
-
head
->
nh
.
raw
;
nexthdr
=
((
struct
frag_hdr
*
)
head
->
h
.
raw
)
->
nexthdr
;
if
(
payload_len
>
65535
)
{
if
(
payload_len
>
65535
)
{
payload_len
-=
8
;
payload_len
-=
8
;
if
(
payload_len
>
65535
)
if
(
payload_len
>
65535
)
...
@@ -609,9 +613,12 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
...
@@ -609,9 +613,12 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
if
(
head
->
ip_summed
==
CHECKSUM_HW
)
if
(
head
->
ip_summed
==
CHECKSUM_HW
)
head
->
csum
=
csum_partial
(
head
->
nh
.
raw
,
head
->
h
.
raw
-
head
->
nh
.
raw
,
head
->
csum
);
head
->
csum
=
csum_partial
(
head
->
nh
.
raw
,
head
->
h
.
raw
-
head
->
nh
.
raw
,
head
->
csum
);
if
(
!
pskb_pull
(
head
,
head
->
h
.
raw
-
head
->
data
))
goto
out_fail
;
IP6_INC_STATS_BH
(
Ip6ReasmOKs
);
IP6_INC_STATS_BH
(
Ip6ReasmOKs
);
fq
->
fragments
=
NULL
;
fq
->
fragments
=
NULL
;
return
n
hoff
;
return
n
exthdr
;
out_oversize:
out_oversize:
if
(
net_ratelimit
())
if
(
net_ratelimit
())
...
@@ -622,16 +629,18 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
...
@@ -622,16 +629,18 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff **skb_in,
printk
(
KERN_DEBUG
"ip6_frag_reasm: no memory for reassembly
\n
"
);
printk
(
KERN_DEBUG
"ip6_frag_reasm: no memory for reassembly
\n
"
);
out_fail:
out_fail:
IP6_INC_STATS_BH
(
Ip6ReasmFails
);
IP6_INC_STATS_BH
(
Ip6ReasmFails
);
return
-
1
;
return
0
;
}
}
int
ipv6_reassembly
(
struct
sk_buff
**
skbp
,
int
nhoff
)
static
int
ipv6_frag_rcv
(
struct
sk_buff
**
skbp
)
{
{
struct
sk_buff
*
skb
=
*
skbp
;
struct
sk_buff
*
skb
=
*
skbp
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
frag_hdr
*
fhdr
;
struct
frag_hdr
*
fhdr
;
struct
frag_queue
*
fq
;
struct
frag_queue
*
fq
;
struct
ipv6hdr
*
hdr
;
struct
ipv6hdr
*
hdr
;
int
nhoff
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
u8
nexthdr
=
0
;
hdr
=
skb
->
nh
.
ipv6h
;
hdr
=
skb
->
nh
.
ipv6h
;
...
@@ -640,15 +649,16 @@ int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
...
@@ -640,15 +649,16 @@ int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
/* Jumbo payload inhibits frag. header */
/* Jumbo payload inhibits frag. header */
if
(
hdr
->
payload_len
==
0
)
{
if
(
hdr
->
payload_len
==
0
)
{
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
skb
->
h
.
raw
-
skb
->
nh
.
raw
);
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
skb
->
h
.
raw
-
skb
->
nh
.
raw
);
return
-
1
;
goto
discard
;
}
}
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
sizeof
(
struct
frag_hdr
)))
{
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
sizeof
(
struct
frag_hdr
)))
{
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
skb
->
h
.
raw
-
skb
->
nh
.
raw
);
icmpv6_param_prob
(
skb
,
ICMPV6_HDR_FIELD
,
skb
->
h
.
raw
-
skb
->
nh
.
raw
);
return
-
1
;
goto
discard
;
}
}
hdr
=
skb
->
nh
.
ipv6h
;
hdr
=
skb
->
nh
.
ipv6h
;
fhdr
=
(
struct
frag_hdr
*
)
skb
->
h
.
raw
;
fhdr
=
(
struct
frag_hdr
*
)
skb
->
h
.
raw
;
nexthdr
=
fhdr
->
nexthdr
;
if
(
!
(
fhdr
->
frag_off
&
htons
(
0xFFF9
)))
{
if
(
!
(
fhdr
->
frag_off
&
htons
(
0xFFF9
)))
{
/* It is not a fragmented frame */
/* It is not a fragmented frame */
...
@@ -674,10 +684,22 @@ int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
...
@@ -674,10 +684,22 @@ int ipv6_reassembly(struct sk_buff **skbp, int nhoff)
spin_unlock
(
&
fq
->
lock
);
spin_unlock
(
&
fq
->
lock
);
fq_put
(
fq
);
fq_put
(
fq
);
return
ret
;
return
-
ret
;
}
}
discard:
IP6_INC_STATS_BH
(
Ip6ReasmFails
);
IP6_INC_STATS_BH
(
Ip6ReasmFails
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
-
1
;
return
0
;
}
static
struct
inet6_protocol
frag_protocol
=
{
.
handler
=
ipv6_frag_rcv
,
};
void
__init
ipv6_frag_init
(
void
)
{
if
(
inet6_add_protocol
(
&
frag_protocol
,
IPPROTO_FRAGMENT
)
<
0
)
printk
(
KERN_ERR
"ipv6_frag_init: Could not register protocol
\n
"
);
}
}
net/ipv6/tcp_ipv6.c
View file @
f05cd468
...
@@ -1591,8 +1591,9 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
...
@@ -1591,8 +1591,9 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
return
0
;
return
0
;
}
}
static
int
tcp_v6_rcv
(
struct
sk_buff
*
skb
)
static
int
tcp_v6_rcv
(
struct
sk_buff
*
*
p
skb
)
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
tcphdr
*
th
;
struct
tcphdr
*
th
;
struct
sock
*
sk
;
struct
sock
*
sk
;
int
ret
;
int
ret
;
...
...
net/ipv6/udp.c
View file @
f05cd468
...
@@ -641,8 +641,9 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
...
@@ -641,8 +641,9 @@ static void udpv6_mcast_deliver(struct udphdr *uh,
read_unlock
(
&
udp_hash_lock
);
read_unlock
(
&
udp_hash_lock
);
}
}
static
int
udpv6_rcv
(
struct
sk_buff
*
skb
)
static
int
udpv6_rcv
(
struct
sk_buff
*
*
p
skb
)
{
{
struct
sk_buff
*
skb
=
*
pskb
;
struct
sock
*
sk
;
struct
sock
*
sk
;
struct
udphdr
*
uh
;
struct
udphdr
*
uh
;
struct
net_device
*
dev
=
skb
->
dev
;
struct
net_device
*
dev
=
skb
->
dev
;
...
...
net/ipv6/xfrm6_input.c
View file @
f05cd468
...
@@ -123,8 +123,9 @@ int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
...
@@ -123,8 +123,9 @@ int xfrm6_clear_mutable_options(struct sk_buff *skb, u16 *nh_offset, int dir)
return
nexthdr
;
return
nexthdr
;
}
}
int
xfrm6_rcv
(
struct
sk_buff
*
skb
)
int
xfrm6_rcv
(
struct
sk_buff
*
*
p
skb
)
{
{
struct
sk_buff
*
skb
=
*
pskb
;
int
err
;
int
err
;
u32
spi
,
seq
;
u32
spi
,
seq
;
struct
xfrm_state
*
xfrm_vec
[
XFRM_MAX_DEPTH
];
struct
xfrm_state
*
xfrm_vec
[
XFRM_MAX_DEPTH
];
...
@@ -137,12 +138,8 @@ int xfrm6_rcv(struct sk_buff *skb)
...
@@ -137,12 +138,8 @@ int xfrm6_rcv(struct sk_buff *skb)
u16
nh_offset
=
0
;
u16
nh_offset
=
0
;
u8
nexthdr
=
0
;
u8
nexthdr
=
0
;
if
(
hdr
->
nexthdr
==
IPPROTO_AH
||
hdr
->
nexthdr
==
IPPROTO_ESP
)
{
nh_offset
=
((
unsigned
char
*
)
&
skb
->
nh
.
ipv6h
->
nexthdr
)
-
skb
->
nh
.
raw
;
nh_offset
=
((
unsigned
char
*
)
&
skb
->
nh
.
ipv6h
->
nexthdr
)
-
skb
->
nh
.
raw
;
hdr_len
=
sizeof
(
struct
ipv6hdr
);
hdr_len
=
sizeof
(
struct
ipv6hdr
);
}
else
{
hdr_len
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
}
tmp_hdr
=
kmalloc
(
hdr_len
,
GFP_ATOMIC
);
tmp_hdr
=
kmalloc
(
hdr_len
,
GFP_ATOMIC
);
if
(
!
tmp_hdr
)
if
(
!
tmp_hdr
)
...
@@ -189,20 +186,6 @@ int xfrm6_rcv(struct sk_buff *skb)
...
@@ -189,20 +186,6 @@ int xfrm6_rcv(struct sk_buff *skb)
xfrm_vec
[
xfrm_nr
++
]
=
x
;
xfrm_vec
[
xfrm_nr
++
]
=
x
;
iph
=
skb
->
nh
.
ipv6h
;
/* ??? */
if
(
nexthdr
==
NEXTHDR_DEST
)
{
if
(
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
8
)
||
!
pskb_may_pull
(
skb
,
(
skb
->
h
.
raw
-
skb
->
data
)
+
((
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
)))
{
err
=
-
EINVAL
;
goto
drop
;
}
nexthdr
=
skb
->
h
.
raw
[
0
];
nh_offset
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
skb_pull
(
skb
,
(
skb
->
h
.
raw
[
1
]
+
1
)
<<
3
);
skb
->
h
.
raw
=
skb
->
data
;
}
if
(
x
->
props
.
mode
)
{
/* XXX */
if
(
x
->
props
.
mode
)
{
/* XXX */
if
(
iph
->
nexthdr
!=
IPPROTO_IPV6
)
if
(
iph
->
nexthdr
!=
IPPROTO_IPV6
)
goto
drop
;
goto
drop
;
...
...
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