Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
2e66fc41
K
Kernel
项目概览
openeuler
/
Kernel
12 个月 前同步成功
通知
5
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2e66fc41
编写于
9月 08, 2005
作者:
D
David S. Miller
浏览文件
操作
浏览文件
下载
差异文件
Merge
git://git.skbuff.net/gitroot/yoshfuji/linux-2.6-git-rfc3542
上级
42ca89c1
41a1f8ea
变更
13
隐藏空白更改
内联
并排
Showing
13 changed file
with
525 addition
and
71 deletion
+525
-71
include/linux/in6.h
include/linux/in6.h
+30
-6
include/linux/ipv6.h
include/linux/ipv6.h
+12
-3
include/net/ipv6.h
include/net/ipv6.h
+5
-0
include/net/transp_v6.h
include/net/transp_v6.h
+1
-1
net/ipv6/datagram.c
net/ipv6/datagram.c
+126
-9
net/ipv6/exthdrs.c
net/ipv6/exthdrs.c
+104
-3
net/ipv6/icmp.c
net/ipv6/icmp.c
+12
-3
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_flowlabel.c
+9
-5
net/ipv6/ip6_output.c
net/ipv6/ip6_output.c
+17
-7
net/ipv6/ipv6_sockglue.c
net/ipv6/ipv6_sockglue.c
+174
-12
net/ipv6/raw.c
net/ipv6/raw.c
+12
-5
net/ipv6/tcp_ipv6.c
net/ipv6/tcp_ipv6.c
+10
-11
net/ipv6/udp.c
net/ipv6/udp.c
+13
-6
未找到文件。
include/linux/in6.h
浏览文件 @
2e66fc41
...
...
@@ -148,13 +148,13 @@ struct in6_flowlabel_req
*/
#define IPV6_ADDRFORM 1
#define IPV6_
PKTINFO
2
#define IPV6_
HOPOPTS
3
#define IPV6_
DSTOPTS
4
#define IPV6_RTHDR 5
#define IPV6_
PKTOPTIONS
6
#define IPV6_
2292PKTINFO
2
#define IPV6_
2292HOPOPTS
3
#define IPV6_
2292DSTOPTS
4
#define IPV6_
2292
RTHDR 5
#define IPV6_
2292PKTOPTIONS
6
#define IPV6_CHECKSUM 7
#define IPV6_
HOPLIMIT
8
#define IPV6_
2292HOPLIMIT
8
#define IPV6_NEXTHOP 9
#define IPV6_AUTHHDR 10
/* obsolete */
#define IPV6_FLOWINFO 11
...
...
@@ -198,4 +198,28 @@ struct in6_flowlabel_req
* MCAST_MSFILTER 48
*/
/* RFC3542 advanced socket options (50-67) */
#define IPV6_RECVPKTINFO 50
#define IPV6_PKTINFO 51
#if 0
#define IPV6_RECVPATHMTU 52
#define IPV6_PATHMTU 53
#define IPV6_DONTFRAG 54
#define IPV6_USE_MIN_MTU 55
#endif
#define IPV6_RECVHOPOPTS 56
#define IPV6_HOPOPTS 57
#if 0
#define IPV6_RECVRTHDRDSTOPTS 58 /* Unused, see net/ipv6/datagram.c */
#endif
#define IPV6_RTHDRDSTOPTS 59
#define IPV6_RECVRTHDR 60
#define IPV6_RTHDR 61
#define IPV6_RECVDSTOPTS 62
#define IPV6_DSTOPTS 63
#define IPV6_RECVHOPLIMIT 64
#define IPV6_HOPLIMIT 65
#define IPV6_RECVTCLASS 66
#define IPV6_TCLASS 67
#endif
include/linux/ipv6.h
浏览文件 @
2e66fc41
...
...
@@ -189,6 +189,7 @@ struct inet6_skb_parm {
__u16
dst0
;
__u16
srcrt
;
__u16
dst1
;
__u16
lastopt
;
};
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
...
...
@@ -234,14 +235,20 @@ struct ipv6_pinfo {
/* pktoption flags */
union
{
struct
{
__u8
srcrt
:
2
,
__u16
srcrt
:
2
,
osrcrt:
2
,
rxinfo:
1
,
rxoinfo:
1
,
rxhlim:
1
,
rxohlim:
1
,
hopopts:
1
,
ohopopts:
1
,
dstopts:
1
,
rxflow:
1
;
odstopts:
1
,
rxflow:
1
,
rxtclass:
1
;
}
bits
;
__u
8
all
;
__u
16
all
;
}
rxopt
;
/* sockopt flags */
...
...
@@ -250,6 +257,7 @@ struct ipv6_pinfo {
sndflow:
1
,
pmtudisc:
2
,
ipv6only:
1
;
__u8
tclass
;
__u32
dst_cookie
;
...
...
@@ -263,6 +271,7 @@ struct ipv6_pinfo {
struct
ipv6_txoptions
*
opt
;
struct
rt6_info
*
rt
;
int
hop_limit
;
int
tclass
;
}
cork
;
};
...
...
include/net/ipv6.h
浏览文件 @
2e66fc41
...
...
@@ -233,6 +233,10 @@ extern int ip6_ra_control(struct sock *sk, int sel,
extern
int
ipv6_parse_hopopts
(
struct
sk_buff
*
skb
,
int
);
extern
struct
ipv6_txoptions
*
ipv6_dup_options
(
struct
sock
*
sk
,
struct
ipv6_txoptions
*
opt
);
extern
struct
ipv6_txoptions
*
ipv6_renew_options
(
struct
sock
*
sk
,
struct
ipv6_txoptions
*
opt
,
int
newtype
,
struct
ipv6_opt_hdr
__user
*
newopt
,
int
newoptlen
);
extern
int
ip6_frag_nqueues
;
extern
atomic_t
ip6_frag_mem
;
...
...
@@ -373,6 +377,7 @@ extern int ip6_append_data(struct sock *sk,
int
length
,
int
transhdrlen
,
int
hlimit
,
int
tclass
,
struct
ipv6_txoptions
*
opt
,
struct
flowi
*
fl
,
struct
rt6_info
*
rt
,
...
...
include/net/transp_v6.h
浏览文件 @
2e66fc41
...
...
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct sock *sk,
extern
int
datagram_send_ctl
(
struct
msghdr
*
msg
,
struct
flowi
*
fl
,
struct
ipv6_txoptions
*
opt
,
int
*
hlimit
);
int
*
hlimit
,
int
*
tclass
);
#define LOOPBACK4_IPV6 __constant_htonl(0x7f000006)
...
...
net/ipv6/datagram.c
浏览文件 @
2e66fc41
...
...
@@ -390,32 +390,101 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb)
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_HOPLIMIT
,
sizeof
(
hlim
),
&
hlim
);
}
if
(
np
->
rxopt
.
bits
.
rxtclass
)
{
int
tclass
=
(
ntohl
(
*
(
u32
*
)
skb
->
nh
.
ipv6h
)
>>
20
)
&
0xff
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_TCLASS
,
sizeof
(
tclass
),
&
tclass
);
}
if
(
np
->
rxopt
.
bits
.
rxflow
&&
(
*
(
u32
*
)
skb
->
nh
.
raw
&
IPV6_FLOWINFO_MASK
))
{
u32
flowinfo
=
*
(
u32
*
)
skb
->
nh
.
raw
&
IPV6_FLOWINFO_MASK
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_FLOWINFO
,
sizeof
(
flowinfo
),
&
flowinfo
);
}
/* HbH is allowed only once */
if
(
np
->
rxopt
.
bits
.
hopopts
&&
opt
->
hop
)
{
u8
*
ptr
=
skb
->
nh
.
raw
+
opt
->
hop
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_HOPOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
}
if
(
np
->
rxopt
.
bits
.
dstopts
&&
opt
->
dst0
)
{
if
(
opt
->
lastopt
&&
(
np
->
rxopt
.
bits
.
dstopts
||
np
->
rxopt
.
bits
.
srcrt
))
{
/*
* Silly enough, but we need to reparse in order to
* report extension headers (except for HbH)
* in order.
*
* Also note that IPV6_RECVRTHDRDSTOPTS is NOT
* (and WILL NOT be) defined because
* IPV6_RECVDSTOPTS is more generic. --yoshfuji
*/
unsigned
int
off
=
sizeof
(
struct
ipv6hdr
);
u8
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
while
(
off
<=
opt
->
lastopt
)
{
unsigned
len
;
u8
*
ptr
=
skb
->
nh
.
raw
+
off
;
switch
(
nexthdr
)
{
case
IPPROTO_DSTOPTS
:
nexthdr
=
ptr
[
0
];
len
=
(
ptr
[
1
]
+
1
)
<<
3
;
if
(
np
->
rxopt
.
bits
.
dstopts
)
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_DSTOPTS
,
len
,
ptr
);
break
;
case
IPPROTO_ROUTING
:
nexthdr
=
ptr
[
0
];
len
=
(
ptr
[
1
]
+
1
)
<<
3
;
if
(
np
->
rxopt
.
bits
.
srcrt
)
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_RTHDR
,
len
,
ptr
);
break
;
case
IPPROTO_AH
:
nexthdr
=
ptr
[
0
];
len
=
(
ptr
[
1
]
+
1
)
<<
2
;
break
;
default:
nexthdr
=
ptr
[
0
];
len
=
(
ptr
[
1
]
+
1
)
<<
3
;
break
;
}
off
+=
len
;
}
}
/* socket options in old style */
if
(
np
->
rxopt
.
bits
.
rxoinfo
)
{
struct
in6_pktinfo
src_info
;
src_info
.
ipi6_ifindex
=
opt
->
iif
;
ipv6_addr_copy
(
&
src_info
.
ipi6_addr
,
&
skb
->
nh
.
ipv6h
->
daddr
);
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_2292PKTINFO
,
sizeof
(
src_info
),
&
src_info
);
}
if
(
np
->
rxopt
.
bits
.
rxohlim
)
{
int
hlim
=
skb
->
nh
.
ipv6h
->
hop_limit
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_2292HOPLIMIT
,
sizeof
(
hlim
),
&
hlim
);
}
if
(
np
->
rxopt
.
bits
.
ohopopts
&&
opt
->
hop
)
{
u8
*
ptr
=
skb
->
nh
.
raw
+
opt
->
hop
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_2292HOPOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
}
if
(
np
->
rxopt
.
bits
.
odstopts
&&
opt
->
dst0
)
{
u8
*
ptr
=
skb
->
nh
.
raw
+
opt
->
dst0
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_DSTOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_
2292
DSTOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
}
if
(
np
->
rxopt
.
bits
.
srcrt
&&
opt
->
srcrt
)
{
if
(
np
->
rxopt
.
bits
.
o
srcrt
&&
opt
->
srcrt
)
{
struct
ipv6_rt_hdr
*
rthdr
=
(
struct
ipv6_rt_hdr
*
)(
skb
->
nh
.
raw
+
opt
->
srcrt
);
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_RTHDR
,
(
rthdr
->
hdrlen
+
1
)
<<
3
,
rthdr
);
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_
2292
RTHDR
,
(
rthdr
->
hdrlen
+
1
)
<<
3
,
rthdr
);
}
if
(
np
->
rxopt
.
bits
.
dstopts
&&
opt
->
dst1
)
{
if
(
np
->
rxopt
.
bits
.
o
dstopts
&&
opt
->
dst1
)
{
u8
*
ptr
=
skb
->
nh
.
raw
+
opt
->
dst1
;
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_DSTOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
put_cmsg
(
msg
,
SOL_IPV6
,
IPV6_
2292
DSTOPTS
,
(
ptr
[
1
]
+
1
)
<<
3
,
ptr
);
}
return
0
;
}
int
datagram_send_ctl
(
struct
msghdr
*
msg
,
struct
flowi
*
fl
,
struct
ipv6_txoptions
*
opt
,
int
*
hlimit
)
int
*
hlimit
,
int
*
tclass
)
{
struct
in6_pktinfo
*
src_info
;
struct
cmsghdr
*
cmsg
;
...
...
@@ -438,6 +507,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
switch
(
cmsg
->
cmsg_type
)
{
case
IPV6_PKTINFO
:
case
IPV6_2292PKTINFO
:
if
(
cmsg
->
cmsg_len
<
CMSG_LEN
(
sizeof
(
struct
in6_pktinfo
)))
{
err
=
-
EINVAL
;
goto
exit_f
;
...
...
@@ -492,6 +562,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
fl
->
fl6_flowlabel
=
IPV6_FLOWINFO_MASK
&
*
(
u32
*
)
CMSG_DATA
(
cmsg
);
break
;
case
IPV6_2292HOPOPTS
:
case
IPV6_HOPOPTS
:
if
(
opt
->
hopopt
||
cmsg
->
cmsg_len
<
CMSG_LEN
(
sizeof
(
struct
ipv6_opt_hdr
)))
{
err
=
-
EINVAL
;
...
...
@@ -512,7 +583,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt
->
hopopt
=
hdr
;
break
;
case
IPV6_DSTOPTS
:
case
IPV6_
2292
DSTOPTS
:
if
(
cmsg
->
cmsg_len
<
CMSG_LEN
(
sizeof
(
struct
ipv6_opt_hdr
)))
{
err
=
-
EINVAL
;
goto
exit_f
;
...
...
@@ -536,6 +607,33 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt
->
dst1opt
=
hdr
;
break
;
case
IPV6_DSTOPTS
:
case
IPV6_RTHDRDSTOPTS
:
if
(
cmsg
->
cmsg_len
<
CMSG_LEN
(
sizeof
(
struct
ipv6_opt_hdr
)))
{
err
=
-
EINVAL
;
goto
exit_f
;
}
hdr
=
(
struct
ipv6_opt_hdr
*
)
CMSG_DATA
(
cmsg
);
len
=
((
hdr
->
hdrlen
+
1
)
<<
3
);
if
(
cmsg
->
cmsg_len
<
CMSG_LEN
(
len
))
{
err
=
-
EINVAL
;
goto
exit_f
;
}
if
(
!
capable
(
CAP_NET_RAW
))
{
err
=
-
EPERM
;
goto
exit_f
;
}
if
(
cmsg
->
cmsg_type
==
IPV6_DSTOPTS
)
{
opt
->
opt_flen
+=
len
;
opt
->
dst1opt
=
hdr
;
}
else
{
opt
->
opt_nflen
+=
len
;
opt
->
dst0opt
=
hdr
;
}
break
;
case
IPV6_2292RTHDR
:
case
IPV6_RTHDR
:
if
(
cmsg
->
cmsg_len
<
CMSG_LEN
(
sizeof
(
struct
ipv6_rt_hdr
)))
{
err
=
-
EINVAL
;
...
...
@@ -568,7 +666,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
opt
->
opt_nflen
+=
len
;
opt
->
srcrt
=
rthdr
;
if
(
opt
->
dst1opt
)
{
if
(
cmsg
->
cmsg_type
==
IPV6_2292RTHDR
&&
opt
->
dst1opt
)
{
int
dsthdrlen
=
((
opt
->
dst1opt
->
hdrlen
+
1
)
<<
3
);
opt
->
opt_nflen
+=
dsthdrlen
;
...
...
@@ -579,6 +677,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
break
;
case
IPV6_2292HOPLIMIT
:
case
IPV6_HOPLIMIT
:
if
(
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
err
=
-
EINVAL
;
...
...
@@ -588,6 +687,24 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl,
*
hlimit
=
*
(
int
*
)
CMSG_DATA
(
cmsg
);
break
;
case
IPV6_TCLASS
:
{
int
tc
;
err
=
-
EINVAL
;
if
(
cmsg
->
cmsg_len
!=
CMSG_LEN
(
sizeof
(
int
)))
{
goto
exit_f
;
}
tc
=
*
(
int
*
)
CMSG_DATA
(
cmsg
);
if
(
tc
<
0
||
tc
>
0xff
)
goto
exit_f
;
err
=
0
;
*
tclass
=
tc
;
break
;
}
default:
LIMIT_NETDEBUG
(
KERN_DEBUG
"invalid cmsg type: %d
\n
"
,
cmsg
->
cmsg_type
);
...
...
net/ipv6/exthdrs.c
浏览文件 @
2e66fc41
...
...
@@ -164,6 +164,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
return
-
1
;
}
opt
->
lastopt
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
opt
->
dst1
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
if
(
ip6_parse_tlv
(
tlvprocdestopt_lst
,
skb
))
{
...
...
@@ -243,6 +244,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp)
looped_back:
if
(
hdr
->
segments_left
==
0
)
{
opt
->
lastopt
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
opt
->
srcrt
=
skb
->
h
.
raw
-
skb
->
nh
.
raw
;
skb
->
h
.
raw
+=
(
hdr
->
hdrlen
+
1
)
<<
3
;
opt
->
dst0
=
opt
->
dst1
;
...
...
@@ -538,10 +540,15 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8
*
proto
,
struct
in6_addr
**
daddr
)
{
if
(
opt
->
srcrt
)
if
(
opt
->
srcrt
)
{
ipv6_push_rthdr
(
skb
,
proto
,
opt
->
srcrt
,
daddr
);
if
(
opt
->
dst0opt
)
ipv6_push_exthdr
(
skb
,
proto
,
NEXTHDR_DEST
,
opt
->
dst0opt
);
/*
* IPV6_RTHDRDSTOPTS is ignored
* unless IPV6_RTHDR is set (RFC3542).
*/
if
(
opt
->
dst0opt
)
ipv6_push_exthdr
(
skb
,
proto
,
NEXTHDR_DEST
,
opt
->
dst0opt
);
}
if
(
opt
->
hopopt
)
ipv6_push_exthdr
(
skb
,
proto
,
NEXTHDR_HOP
,
opt
->
hopopt
);
}
...
...
@@ -572,3 +579,97 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt)
}
return
opt2
;
}
static
int
ipv6_renew_option
(
void
*
ohdr
,
struct
ipv6_opt_hdr
__user
*
newopt
,
int
newoptlen
,
int
inherit
,
struct
ipv6_opt_hdr
**
hdr
,
char
**
p
)
{
if
(
inherit
)
{
if
(
ohdr
)
{
memcpy
(
*
p
,
ohdr
,
ipv6_optlen
((
struct
ipv6_opt_hdr
*
)
ohdr
));
*
hdr
=
(
struct
ipv6_opt_hdr
*
)
*
p
;
*
p
+=
CMSG_ALIGN
(
ipv6_optlen
(
*
(
struct
ipv6_opt_hdr
**
)
hdr
));
}
}
else
{
if
(
newopt
)
{
if
(
copy_from_user
(
*
p
,
newopt
,
newoptlen
))
return
-
EFAULT
;
*
hdr
=
(
struct
ipv6_opt_hdr
*
)
*
p
;
if
(
ipv6_optlen
(
*
(
struct
ipv6_opt_hdr
**
)
hdr
)
>
newoptlen
)
return
-
EINVAL
;
*
p
+=
CMSG_ALIGN
(
newoptlen
);
}
}
return
0
;
}
struct
ipv6_txoptions
*
ipv6_renew_options
(
struct
sock
*
sk
,
struct
ipv6_txoptions
*
opt
,
int
newtype
,
struct
ipv6_opt_hdr
__user
*
newopt
,
int
newoptlen
)
{
int
tot_len
=
0
;
char
*
p
;
struct
ipv6_txoptions
*
opt2
;
int
err
;
if
(
newtype
!=
IPV6_HOPOPTS
&&
opt
->
hopopt
)
tot_len
+=
CMSG_ALIGN
(
ipv6_optlen
(
opt
->
hopopt
));
if
(
newtype
!=
IPV6_RTHDRDSTOPTS
&&
opt
->
dst0opt
)
tot_len
+=
CMSG_ALIGN
(
ipv6_optlen
(
opt
->
dst0opt
));
if
(
newtype
!=
IPV6_RTHDR
&&
opt
->
srcrt
)
tot_len
+=
CMSG_ALIGN
(
ipv6_optlen
(
opt
->
srcrt
));
if
(
newtype
!=
IPV6_DSTOPTS
&&
opt
->
dst1opt
)
tot_len
+=
CMSG_ALIGN
(
ipv6_optlen
(
opt
->
dst1opt
));
if
(
newopt
&&
newoptlen
)
tot_len
+=
CMSG_ALIGN
(
newoptlen
);
if
(
!
tot_len
)
return
NULL
;
opt2
=
sock_kmalloc
(
sk
,
tot_len
,
GFP_ATOMIC
);
if
(
!
opt2
)
return
ERR_PTR
(
-
ENOBUFS
);
memset
(
opt2
,
0
,
tot_len
);
opt2
->
tot_len
=
tot_len
;
p
=
(
char
*
)(
opt2
+
1
);
err
=
ipv6_renew_option
(
opt
->
hopopt
,
newopt
,
newoptlen
,
newtype
!=
IPV6_HOPOPTS
,
&
opt2
->
hopopt
,
&
p
);
if
(
err
)
goto
out
;
err
=
ipv6_renew_option
(
opt
->
dst0opt
,
newopt
,
newoptlen
,
newtype
!=
IPV6_RTHDRDSTOPTS
,
&
opt2
->
dst0opt
,
&
p
);
if
(
err
)
goto
out
;
err
=
ipv6_renew_option
(
opt
->
srcrt
,
newopt
,
newoptlen
,
newtype
!=
IPV6_RTHDR
,
(
struct
ipv6_opt_hdr
**
)
opt2
->
srcrt
,
&
p
);
if
(
err
)
goto
out
;
err
=
ipv6_renew_option
(
opt
->
dst1opt
,
newopt
,
newoptlen
,
newtype
!=
IPV6_DSTOPTS
,
&
opt2
->
dst1opt
,
&
p
);
if
(
err
)
goto
out
;
opt2
->
opt_nflen
=
(
opt2
->
hopopt
?
ipv6_optlen
(
opt2
->
hopopt
)
:
0
)
+
(
opt2
->
dst0opt
?
ipv6_optlen
(
opt2
->
dst0opt
)
:
0
)
+
(
opt2
->
srcrt
?
ipv6_optlen
(
opt2
->
srcrt
)
:
0
);
opt2
->
opt_flen
=
(
opt2
->
dst1opt
?
ipv6_optlen
(
opt2
->
dst1opt
)
:
0
);
return
opt2
;
out:
sock_kfree_s
(
sk
,
p
,
tot_len
);
return
ERR_PTR
(
err
);
}
net/ipv6/icmp.c
浏览文件 @
2e66fc41
...
...
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
int
iif
=
0
;
int
addr_type
=
0
;
int
len
;
int
hlimit
;
int
hlimit
,
tclass
;
int
err
=
0
;
if
((
u8
*
)
hdr
<
skb
->
head
||
(
u8
*
)(
hdr
+
1
)
>
skb
->
tail
)
...
...
@@ -385,6 +385,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if
(
hlimit
<
0
)
hlimit
=
ipv6_get_hoplimit
(
dst
->
dev
);
tclass
=
np
->
cork
.
tclass
;
if
(
tclass
<
0
)
tclass
=
0
;
msg
.
skb
=
skb
;
msg
.
offset
=
skb
->
nh
.
raw
-
skb
->
data
;
...
...
@@ -400,7 +404,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
err
=
ip6_append_data
(
sk
,
icmpv6_getfrag
,
&
msg
,
len
+
sizeof
(
struct
icmp6hdr
),
sizeof
(
struct
icmp6hdr
),
hlimit
,
NULL
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
hlimit
,
tclass
,
NULL
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
MSG_DONTWAIT
);
if
(
err
)
{
ip6_flush_pending_frames
(
sk
);
...
...
@@ -434,6 +438,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
struct
dst_entry
*
dst
;
int
err
=
0
;
int
hlimit
;
int
tclass
;
saddr
=
&
skb
->
nh
.
ipv6h
->
daddr
;
...
...
@@ -475,13 +480,17 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if
(
hlimit
<
0
)
hlimit
=
ipv6_get_hoplimit
(
dst
->
dev
);
tclass
=
np
->
cork
.
tclass
;
if
(
tclass
<
0
)
tclass
=
0
;
idev
=
in6_dev_get
(
skb
->
dev
);
msg
.
skb
=
skb
;
msg
.
offset
=
0
;
err
=
ip6_append_data
(
sk
,
icmpv6_getfrag
,
&
msg
,
skb
->
len
+
sizeof
(
struct
icmp6hdr
),
sizeof
(
struct
icmp6hdr
),
hlimit
,
NULL
,
&
fl
,
sizeof
(
struct
icmp6hdr
),
hlimit
,
tclass
,
NULL
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
MSG_DONTWAIT
);
if
(
err
)
{
...
...
net/ipv6/ip6_flowlabel.c
浏览文件 @
2e66fc41
...
...
@@ -225,16 +225,20 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space,
struct
ip6_flowlabel
*
fl
,
struct
ipv6_txoptions
*
fopt
)
{
struct
ipv6_txoptions
*
fl_opt
=
fl
->
opt
;
struct
ipv6_txoptions
*
fl_opt
=
fl
?
fl
->
opt
:
NULL
;
if
(
fopt
==
NULL
||
fopt
->
opt_flen
==
0
)
return
fl_opt
;
if
(
fopt
==
NULL
||
fopt
->
opt_flen
==
0
)
{
if
(
!
fl_opt
||
!
fl_opt
->
dst0opt
||
fl_opt
->
srcrt
)
return
fl_opt
;
}
if
(
fl_opt
!=
NULL
)
{
opt_space
->
hopopt
=
fl_opt
->
hopopt
;
opt_space
->
dst0opt
=
fl_opt
->
dst0opt
;
opt_space
->
dst0opt
=
fl_opt
->
srcrt
?
fl_opt
->
dst0opt
:
NULL
;
opt_space
->
srcrt
=
fl_opt
->
srcrt
;
opt_space
->
opt_nflen
=
fl_opt
->
opt_nflen
;
if
(
fl_opt
->
dst0opt
&&
!
fl_opt
->
srcrt
)
opt_space
->
opt_nflen
-=
ipv6_optlen
(
fl_opt
->
dst0opt
);
}
else
{
if
(
fopt
->
opt_nflen
==
0
)
return
fopt
;
...
...
@@ -310,7 +314,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
msg
.
msg_control
=
(
void
*
)(
fl
->
opt
+
1
);
flowi
.
oif
=
0
;
err
=
datagram_send_ctl
(
&
msg
,
&
flowi
,
fl
->
opt
,
&
junk
);
err
=
datagram_send_ctl
(
&
msg
,
&
flowi
,
fl
->
opt
,
&
junk
,
&
junk
);
if
(
err
)
goto
done
;
err
=
-
EINVAL
;
...
...
net/ipv6/ip6_output.c
浏览文件 @
2e66fc41
...
...
@@ -166,7 +166,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
struct
ipv6hdr
*
hdr
;
u8
proto
=
fl
->
proto
;
int
seg_len
=
skb
->
len
;
int
hlimit
;
int
hlimit
,
tclass
;
u32
mtu
;
if
(
opt
)
{
...
...
@@ -202,7 +202,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
* Fill in the IPv6 header
*/
*
(
u32
*
)
hdr
=
htonl
(
0x60000000
)
|
fl
->
fl6_flowlabel
;
hlimit
=
-
1
;
if
(
np
)
hlimit
=
np
->
hop_limit
;
...
...
@@ -211,6 +210,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
if
(
hlimit
<
0
)
hlimit
=
ipv6_get_hoplimit
(
dst
->
dev
);
tclass
=
-
1
;
if
(
np
)
tclass
=
np
->
tclass
;
if
(
tclass
<
0
)
tclass
=
0
;
*
(
u32
*
)
hdr
=
htonl
(
0x60000000
|
(
tclass
<<
20
))
|
fl
->
fl6_flowlabel
;
hdr
->
payload_len
=
htons
(
seg_len
);
hdr
->
nexthdr
=
proto
;
hdr
->
hop_limit
=
hlimit
;
...
...
@@ -762,10 +769,11 @@ int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
return
err
;
}
int
ip6_append_data
(
struct
sock
*
sk
,
int
getfrag
(
void
*
from
,
char
*
to
,
int
offset
,
int
len
,
int
odd
,
struct
sk_buff
*
skb
),
void
*
from
,
int
length
,
int
transhdrlen
,
int
hlimit
,
struct
ipv6_txoptions
*
opt
,
struct
flowi
*
fl
,
struct
rt6_info
*
rt
,
unsigned
int
flags
)
int
ip6_append_data
(
struct
sock
*
sk
,
int
getfrag
(
void
*
from
,
char
*
to
,
int
offset
,
int
len
,
int
odd
,
struct
sk_buff
*
skb
),
void
*
from
,
int
length
,
int
transhdrlen
,
int
hlimit
,
int
tclass
,
struct
ipv6_txoptions
*
opt
,
struct
flowi
*
fl
,
struct
rt6_info
*
rt
,
unsigned
int
flags
)
{
struct
inet_sock
*
inet
=
inet_sk
(
sk
);
struct
ipv6_pinfo
*
np
=
inet6_sk
(
sk
);
...
...
@@ -803,6 +811,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse
np
->
cork
.
rt
=
rt
;
inet
->
cork
.
fl
=
*
fl
;
np
->
cork
.
hop_limit
=
hlimit
;
np
->
cork
.
tclass
=
tclass
;
inet
->
cork
.
fragsize
=
mtu
=
dst_mtu
(
rt
->
u
.
dst
.
path
);
if
(
dst_allfrag
(
rt
->
u
.
dst
.
path
))
inet
->
cork
.
flags
|=
IPCORK_ALLFRAG
;
...
...
@@ -1084,7 +1093,8 @@ int ip6_push_pending_frames(struct sock *sk)
skb
->
nh
.
ipv6h
=
hdr
=
(
struct
ipv6hdr
*
)
skb_push
(
skb
,
sizeof
(
struct
ipv6hdr
));
*
(
u32
*
)
hdr
=
fl
->
fl6_flowlabel
|
htonl
(
0x60000000
);
*
(
u32
*
)
hdr
=
fl
->
fl6_flowlabel
|
htonl
(
0x60000000
|
((
int
)
np
->
cork
.
tclass
<<
20
));
if
(
skb
->
len
<=
sizeof
(
struct
ipv6hdr
)
+
IPV6_MAXPLEN
)
hdr
->
payload_len
=
htons
(
skb
->
len
-
sizeof
(
struct
ipv6hdr
));
...
...
net/ipv6/ipv6_sockglue.c
浏览文件 @
2e66fc41
...
...
@@ -210,39 +210,139 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
retv
=
0
;
break
;
case
IPV6_PKTINFO
:
case
IPV6_
RECV
PKTINFO
:
np
->
rxopt
.
bits
.
rxinfo
=
valbool
;
retv
=
0
;
break
;
case
IPV6_2292PKTINFO
:
np
->
rxopt
.
bits
.
rxoinfo
=
valbool
;
retv
=
0
;
break
;
case
IPV6_HOPLIMIT
:
case
IPV6_
RECV
HOPLIMIT
:
np
->
rxopt
.
bits
.
rxhlim
=
valbool
;
retv
=
0
;
break
;
case
IPV6_RTHDR
:
case
IPV6_2292HOPLIMIT
:
np
->
rxopt
.
bits
.
rxohlim
=
valbool
;
retv
=
0
;
break
;
case
IPV6_RECVRTHDR
:
if
(
val
<
0
||
val
>
2
)
goto
e_inval
;
np
->
rxopt
.
bits
.
srcrt
=
val
;
retv
=
0
;
break
;
case
IPV6_HOPOPTS
:
case
IPV6_2292RTHDR
:
if
(
val
<
0
||
val
>
2
)
goto
e_inval
;
np
->
rxopt
.
bits
.
osrcrt
=
val
;
retv
=
0
;
break
;
case
IPV6_RECVHOPOPTS
:
np
->
rxopt
.
bits
.
hopopts
=
valbool
;
retv
=
0
;
break
;
case
IPV6_DSTOPTS
:
case
IPV6_2292HOPOPTS
:
np
->
rxopt
.
bits
.
ohopopts
=
valbool
;
retv
=
0
;
break
;
case
IPV6_RECVDSTOPTS
:
np
->
rxopt
.
bits
.
dstopts
=
valbool
;
retv
=
0
;
break
;
case
IPV6_2292DSTOPTS
:
np
->
rxopt
.
bits
.
odstopts
=
valbool
;
retv
=
0
;
break
;
case
IPV6_TCLASS
:
if
(
val
<
0
||
val
>
0xff
)
goto
e_inval
;
np
->
tclass
=
val
;
retv
=
0
;
break
;
case
IPV6_RECVTCLASS
:
np
->
rxopt
.
bits
.
rxtclass
=
valbool
;
retv
=
0
;
break
;
case
IPV6_FLOWINFO
:
np
->
rxopt
.
bits
.
rxflow
=
valbool
;
retv
=
0
;
break
;
case
IPV6_PKTOPTIONS
:
case
IPV6_HOPOPTS
:
case
IPV6_RTHDRDSTOPTS
:
case
IPV6_RTHDR
:
case
IPV6_DSTOPTS
:
{
struct
ipv6_txoptions
*
opt
;
if
(
optlen
==
0
)
optval
=
0
;
/* hop-by-hop / destination options are privileged option */
retv
=
-
EPERM
;
if
(
optname
!=
IPV6_RTHDR
&&
!
capable
(
CAP_NET_RAW
))
break
;
retv
=
-
EINVAL
;
if
(
optlen
&
0x7
||
optlen
>
8
*
255
)
break
;
opt
=
ipv6_renew_options
(
sk
,
np
->
opt
,
optname
,
(
struct
ipv6_opt_hdr
__user
*
)
optval
,
optlen
);
if
(
IS_ERR
(
opt
))
{
retv
=
PTR_ERR
(
opt
);
break
;
}
/* routing header option needs extra check */
if
(
optname
==
IPV6_RTHDR
&&
opt
->
srcrt
)
{
struct
ipv6_rt_hdr
*
rthdr
=
opt
->
srcrt
;
if
(
rthdr
->
type
)
goto
sticky_done
;
if
((
rthdr
->
hdrlen
&
1
)
||
(
rthdr
->
hdrlen
>>
1
)
!=
rthdr
->
segments_left
)
goto
sticky_done
;
}
retv
=
0
;
if
(
sk
->
sk_type
==
SOCK_STREAM
)
{
if
(
opt
)
{
struct
tcp_sock
*
tp
=
tcp_sk
(
sk
);
if
(
!
((
1
<<
sk
->
sk_state
)
&
(
TCPF_LISTEN
|
TCPF_CLOSE
))
&&
inet_sk
(
sk
)
->
daddr
!=
LOOPBACK4_IPV6
)
{
tp
->
ext_header_len
=
opt
->
opt_flen
+
opt
->
opt_nflen
;
tcp_sync_mss
(
sk
,
tp
->
pmtu_cookie
);
}
}
opt
=
xchg
(
&
np
->
opt
,
opt
);
sk_dst_reset
(
sk
);
}
else
{
write_lock
(
&
sk
->
sk_dst_lock
);
opt
=
xchg
(
&
np
->
opt
,
opt
);
write_unlock
(
&
sk
->
sk_dst_lock
);
sk_dst_reset
(
sk
);
}
sticky_done:
if
(
opt
)
sock_kfree_s
(
sk
,
opt
,
opt
->
tot_len
);
break
;
}
case
IPV6_2292PKTOPTIONS
:
{
struct
ipv6_txoptions
*
opt
=
NULL
;
struct
msghdr
msg
;
...
...
@@ -276,7 +376,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
msg
.
msg_controllen
=
optlen
;
msg
.
msg_control
=
(
void
*
)(
opt
+
1
);
retv
=
datagram_send_ctl
(
&
msg
,
&
fl
,
opt
,
&
junk
);
retv
=
datagram_send_ctl
(
&
msg
,
&
fl
,
opt
,
&
junk
,
&
junk
);
if
(
retv
)
goto
done
;
update:
...
...
@@ -529,6 +629,17 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname,
return
-
EINVAL
;
}
int
ipv6_getsockopt_sticky
(
struct
sock
*
sk
,
struct
ipv6_opt_hdr
*
hdr
,
char
__user
*
optval
,
int
len
)
{
if
(
!
hdr
)
return
0
;
len
=
min_t
(
int
,
len
,
ipv6_optlen
(
hdr
));
if
(
copy_to_user
(
optval
,
hdr
,
ipv6_optlen
(
hdr
)))
return
-
EFAULT
;
return
len
;
}
int
ipv6_getsockopt
(
struct
sock
*
sk
,
int
level
,
int
optname
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
...
...
@@ -567,7 +678,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
return
err
;
}
case
IPV6_PKTOPTIONS
:
case
IPV6_
2292
PKTOPTIONS
:
{
struct
msghdr
msg
;
struct
sk_buff
*
skb
;
...
...
@@ -601,6 +712,16 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
int
hlim
=
np
->
mcast_hops
;
put_cmsg
(
&
msg
,
SOL_IPV6
,
IPV6_HOPLIMIT
,
sizeof
(
hlim
),
&
hlim
);
}
if
(
np
->
rxopt
.
bits
.
rxoinfo
)
{
struct
in6_pktinfo
src_info
;
src_info
.
ipi6_ifindex
=
np
->
mcast_oif
;
ipv6_addr_copy
(
&
src_info
.
ipi6_addr
,
&
np
->
daddr
);
put_cmsg
(
&
msg
,
SOL_IPV6
,
IPV6_2292PKTINFO
,
sizeof
(
src_info
),
&
src_info
);
}
if
(
np
->
rxopt
.
bits
.
rxohlim
)
{
int
hlim
=
np
->
mcast_hops
;
put_cmsg
(
&
msg
,
SOL_IPV6
,
IPV6_2292HOPLIMIT
,
sizeof
(
hlim
),
&
hlim
);
}
}
len
-=
msg
.
msg_controllen
;
return
put_user
(
len
,
optlen
);
...
...
@@ -625,26 +746,67 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname,
val
=
np
->
ipv6only
;
break
;
case
IPV6_PKTINFO
:
case
IPV6_
RECV
PKTINFO
:
val
=
np
->
rxopt
.
bits
.
rxinfo
;
break
;
case
IPV6_HOPLIMIT
:
case
IPV6_2292PKTINFO
:
val
=
np
->
rxopt
.
bits
.
rxoinfo
;
break
;
case
IPV6_RECVHOPLIMIT
:
val
=
np
->
rxopt
.
bits
.
rxhlim
;
break
;
case
IPV6_RTHDR
:
case
IPV6_2292HOPLIMIT
:
val
=
np
->
rxopt
.
bits
.
rxohlim
;
break
;
case
IPV6_RECVRTHDR
:
val
=
np
->
rxopt
.
bits
.
srcrt
;
break
;
case
IPV6_2292RTHDR
:
val
=
np
->
rxopt
.
bits
.
osrcrt
;
break
;
case
IPV6_HOPOPTS
:
case
IPV6_RTHDRDSTOPTS
:
case
IPV6_RTHDR
:
case
IPV6_DSTOPTS
:
{
lock_sock
(
sk
);
len
=
ipv6_getsockopt_sticky
(
sk
,
np
->
opt
->
hopopt
,
optval
,
len
);
release_sock
(
sk
);
return
put_user
(
len
,
optlen
);
}
case
IPV6_RECVHOPOPTS
:
val
=
np
->
rxopt
.
bits
.
hopopts
;
break
;
case
IPV6_DSTOPTS
:
case
IPV6_2292HOPOPTS
:
val
=
np
->
rxopt
.
bits
.
ohopopts
;
break
;
case
IPV6_RECVDSTOPTS
:
val
=
np
->
rxopt
.
bits
.
dstopts
;
break
;
case
IPV6_2292DSTOPTS
:
val
=
np
->
rxopt
.
bits
.
odstopts
;
break
;
case
IPV6_TCLASS
:
val
=
np
->
tclass
;
break
;
case
IPV6_RECVTCLASS
:
val
=
np
->
rxopt
.
bits
.
rxtclass
;
break
;
case
IPV6_FLOWINFO
:
val
=
np
->
rxopt
.
bits
.
rxflow
;
break
;
...
...
net/ipv6/raw.c
浏览文件 @
2e66fc41
...
...
@@ -655,6 +655,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
struct
flowi
fl
;
int
addr_len
=
msg
->
msg_namelen
;
int
hlimit
=
-
1
;
int
tclass
=
-
1
;
u16
proto
;
int
err
;
...
...
@@ -740,7 +741,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
memset
(
opt
,
0
,
sizeof
(
struct
ipv6_txoptions
));
opt
->
tot_len
=
sizeof
(
struct
ipv6_txoptions
);
err
=
datagram_send_ctl
(
msg
,
&
fl
,
opt
,
&
hlimit
);
err
=
datagram_send_ctl
(
msg
,
&
fl
,
opt
,
&
hlimit
,
&
tclass
);
if
(
err
<
0
)
{
fl6_sock_release
(
flowlabel
);
return
err
;
...
...
@@ -755,8 +756,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
}
if
(
opt
==
NULL
)
opt
=
np
->
opt
;
if
(
flowlabel
)
opt
=
fl6_merge_options
(
&
opt_space
,
flowlabel
,
opt
);
opt
=
fl6_merge_options
(
&
opt_space
,
flowlabel
,
opt
);
fl
.
proto
=
proto
;
rawv6_probe_proto_opt
(
&
fl
,
msg
);
...
...
@@ -798,6 +798,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
hlimit
=
ipv6_get_hoplimit
(
dst
->
dev
);
}
if
(
tclass
<
0
)
{
tclass
=
np
->
cork
.
tclass
;
if
(
tclass
<
0
)
tclass
=
0
;
}
if
(
msg
->
msg_flags
&
MSG_CONFIRM
)
goto
do_confirm
;
...
...
@@ -806,8 +812,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
err
=
rawv6_send_hdrinc
(
sk
,
msg
->
msg_iov
,
len
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
msg
->
msg_flags
);
}
else
{
lock_sock
(
sk
);
err
=
ip6_append_data
(
sk
,
ip_generic_getfrag
,
msg
->
msg_iov
,
len
,
0
,
hlimit
,
opt
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
msg
->
msg_flags
);
err
=
ip6_append_data
(
sk
,
ip_generic_getfrag
,
msg
->
msg_iov
,
len
,
0
,
hlimit
,
tclass
,
opt
,
&
fl
,
(
struct
rt6_info
*
)
dst
,
msg
->
msg_flags
);
if
(
err
)
ip6_flush_pending_frames
(
sk
);
...
...
net/ipv6/tcp_ipv6.c
浏览文件 @
2e66fc41
...
...
@@ -849,7 +849,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
if
(
dst
==
NULL
)
{
opt
=
np
->
opt
;
if
(
opt
==
NULL
&&
np
->
rxopt
.
bits
.
srcrt
==
2
&&
np
->
rxopt
.
bits
.
o
srcrt
==
2
&&
treq
->
pktopts
)
{
struct
sk_buff
*
pktopts
=
treq
->
pktopts
;
struct
inet6_skb_parm
*
rxopt
=
IP6CB
(
pktopts
);
...
...
@@ -915,11 +915,10 @@ static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb)
struct
inet6_skb_parm
*
opt
=
IP6CB
(
skb
);
if
(
np
->
rxopt
.
all
)
{
if
((
opt
->
hop
&&
np
->
rxopt
.
bits
.
hopopts
)
||
((
IPV6_FLOWINFO_MASK
&*
(
u32
*
)
skb
->
nh
.
raw
)
&&
np
->
rxopt
.
bits
.
rxflow
)
||
(
opt
->
srcrt
&&
np
->
rxopt
.
bits
.
srcrt
)
||
((
opt
->
dst1
||
opt
->
dst0
)
&&
np
->
rxopt
.
bits
.
dstopts
))
if
((
opt
->
hop
&&
(
np
->
rxopt
.
bits
.
hopopts
||
np
->
rxopt
.
bits
.
ohopopts
))
||
((
IPV6_FLOWINFO_MASK
&
*
(
u32
*
)
skb
->
nh
.
raw
)
&&
np
->
rxopt
.
bits
.
rxflow
)
||
(
opt
->
srcrt
&&
(
np
->
rxopt
.
bits
.
srcrt
||
np
->
rxopt
.
bits
.
osrcrt
))
||
((
opt
->
dst1
||
opt
->
dst0
)
&&
(
np
->
rxopt
.
bits
.
dstopts
||
np
->
rxopt
.
bits
.
odstopts
)))
return
1
;
}
return
0
;
...
...
@@ -1190,8 +1189,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
TCP_ECN_create_request
(
req
,
skb
->
h
.
th
);
treq
->
pktopts
=
NULL
;
if
(
ipv6_opt_accepted
(
sk
,
skb
)
||
np
->
rxopt
.
bits
.
rxinfo
||
np
->
rxopt
.
bits
.
rxhlim
)
{
np
->
rxopt
.
bits
.
rxinfo
||
np
->
rxopt
.
bits
.
rxoinfo
||
np
->
rxopt
.
bits
.
rxhlim
||
np
->
rxopt
.
bits
.
rxohlim
)
{
atomic_inc
(
&
skb
->
users
);
treq
->
pktopts
=
skb
;
}
...
...
@@ -1288,7 +1287,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if
(
sk_acceptq_is_full
(
sk
))
goto
out_overflow
;
if
(
np
->
rxopt
.
bits
.
srcrt
==
2
&&
if
(
np
->
rxopt
.
bits
.
o
srcrt
==
2
&&
opt
==
NULL
&&
treq
->
pktopts
)
{
struct
inet6_skb_parm
*
rxopt
=
IP6CB
(
treq
->
pktopts
);
if
(
rxopt
->
srcrt
)
...
...
@@ -1544,9 +1543,9 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
tp
=
tcp_sk
(
sk
);
if
(
TCP_SKB_CB
(
opt_skb
)
->
end_seq
==
tp
->
rcv_nxt
&&
!
((
1
<<
sk
->
sk_state
)
&
(
TCPF_CLOSE
|
TCPF_LISTEN
)))
{
if
(
np
->
rxopt
.
bits
.
rxinfo
)
if
(
np
->
rxopt
.
bits
.
rxinfo
||
np
->
rxopt
.
bits
.
rxoinfo
)
np
->
mcast_oif
=
inet6_iif
(
opt_skb
);
if
(
np
->
rxopt
.
bits
.
rxhlim
)
if
(
np
->
rxopt
.
bits
.
rxhlim
||
np
->
rxopt
.
bits
.
rxohlim
)
np
->
mcast_hops
=
opt_skb
->
nh
.
ipv6h
->
hop_limit
;
if
(
ipv6_opt_accepted
(
sk
,
opt_skb
))
{
skb_set_owner_r
(
opt_skb
,
sk
);
...
...
net/ipv6/udp.c
浏览文件 @
2e66fc41
...
...
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
int
addr_len
=
msg
->
msg_namelen
;
int
ulen
=
len
;
int
hlimit
=
-
1
;
int
tclass
=
-
1
;
int
corkreq
=
up
->
corkflag
||
msg
->
msg_flags
&
MSG_MORE
;
int
err
;
...
...
@@ -758,7 +759,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
memset
(
opt
,
0
,
sizeof
(
struct
ipv6_txoptions
));
opt
->
tot_len
=
sizeof
(
*
opt
);
err
=
datagram_send_ctl
(
msg
,
fl
,
opt
,
&
hlimit
);
err
=
datagram_send_ctl
(
msg
,
fl
,
opt
,
&
hlimit
,
&
tclass
);
if
(
err
<
0
)
{
fl6_sock_release
(
flowlabel
);
return
err
;
...
...
@@ -773,8 +774,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
}
if
(
opt
==
NULL
)
opt
=
np
->
opt
;
if
(
flowlabel
)
opt
=
fl6_merge_options
(
&
opt_space
,
flowlabel
,
opt
);
opt
=
fl6_merge_options
(
&
opt_space
,
flowlabel
,
opt
);
fl
->
proto
=
IPPROTO_UDP
;
ipv6_addr_copy
(
&
fl
->
fl6_dst
,
daddr
);
...
...
@@ -815,6 +815,12 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
hlimit
=
ipv6_get_hoplimit
(
dst
->
dev
);
}
if
(
tclass
<
0
)
{
tclass
=
np
->
tclass
;
if
(
tclass
<
0
)
tclass
=
0
;
}
if
(
msg
->
msg_flags
&
MSG_CONFIRM
)
goto
do_confirm
;
back_from_confirm:
...
...
@@ -834,9 +840,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk,
do_append_data:
up
->
len
+=
ulen
;
err
=
ip6_append_data
(
sk
,
ip_generic_getfrag
,
msg
->
msg_iov
,
ulen
,
sizeof
(
struct
udphdr
),
hlimit
,
opt
,
fl
,
(
struct
rt6_info
*
)
dst
,
corkreq
?
msg
->
msg_flags
|
MSG_MORE
:
msg
->
msg_flags
);
err
=
ip6_append_data
(
sk
,
ip_generic_getfrag
,
msg
->
msg_iov
,
ulen
,
sizeof
(
struct
udphdr
),
hlimit
,
tclass
,
opt
,
fl
,
(
struct
rt6_info
*
)
dst
,
corkreq
?
msg
->
msg_flags
|
MSG_MORE
:
msg
->
msg_flags
);
if
(
err
)
udp_v6_flush_pending_frames
(
sk
);
else
if
(
!
corkreq
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录