Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
fb395884
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
fb395884
编写于
6月 20, 2005
作者:
L
Linus Torvalds
浏览文件
操作
浏览文件
下载
差异文件
Merge
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
上级
91b90475
246955fe
变更
40
隐藏空白更改
内联
并排
Showing
40 changed file
with
839 addition
and
318 deletion
+839
-318
include/linux/atalk.h
include/linux/atalk.h
+13
-13
include/linux/netlink.h
include/linux/netlink.h
+1
-0
include/linux/pfkeyv2.h
include/linux/pfkeyv2.h
+1
-0
include/linux/xfrm.h
include/linux/xfrm.h
+1
-0
include/net/ax25.h
include/net/ax25.h
+1
-1
include/net/ip_fib.h
include/net/ip_fib.h
+14
-0
include/net/sctp/command.h
include/net/sctp/command.h
+4
-4
include/net/sctp/constants.h
include/net/sctp/constants.h
+0
-7
include/net/sctp/sctp.h
include/net/sctp/sctp.h
+17
-0
include/net/sctp/sm.h
include/net/sctp/sm.h
+6
-2
include/net/sctp/structs.h
include/net/sctp/structs.h
+32
-9
include/net/sctp/user.h
include/net/sctp/user.h
+3
-0
include/net/xfrm.h
include/net/xfrm.h
+3
-1
net/appletalk/aarp.c
net/appletalk/aarp.c
+1
-1
net/appletalk/ddp.c
net/appletalk/ddp.c
+1
-1
net/ipv4/ah4.c
net/ipv4/ah4.c
+1
-1
net/ipv4/esp4.c
net/ipv4/esp4.c
+1
-1
net/ipv4/fib_frontend.c
net/ipv4/fib_frontend.c
+55
-0
net/ipv4/ipcomp.c
net/ipv4/ipcomp.c
+3
-8
net/ipv4/xfrm4_output.c
net/ipv4/xfrm4_output.c
+6
-2
net/ipv4/xfrm4_state.c
net/ipv4/xfrm4_state.c
+9
-0
net/ipv4/xfrm4_tunnel.c
net/ipv4/xfrm4_tunnel.c
+1
-1
net/ipv6/ah6.c
net/ipv6/ah6.c
+1
-1
net/ipv6/esp6.c
net/ipv6/esp6.c
+1
-1
net/ipv6/ipcomp6.c
net/ipv6/ipcomp6.c
+2
-7
net/ipv6/xfrm6_tunnel.c
net/ipv6/xfrm6_tunnel.c
+1
-1
net/key/af_key.c
net/key/af_key.c
+7
-9
net/sctp/associola.c
net/sctp/associola.c
+114
-37
net/sctp/endpointola.c
net/sctp/endpointola.c
+0
-1
net/sctp/input.c
net/sctp/input.c
+1
-1
net/sctp/outqueue.c
net/sctp/outqueue.c
+6
-5
net/sctp/sm_make_chunk.c
net/sctp/sm_make_chunk.c
+16
-4
net/sctp/sm_sideeffect.c
net/sctp/sm_sideeffect.c
+85
-20
net/sctp/sm_statefuns.c
net/sctp/sm_statefuns.c
+98
-50
net/sctp/sm_statetable.c
net/sctp/sm_statetable.c
+4
-2
net/sctp/socket.c
net/sctp/socket.c
+288
-117
net/sctp/transport.c
net/sctp/transport.c
+3
-1
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_policy.c
+0
-1
net/xfrm/xfrm_state.c
net/xfrm/xfrm_state.c
+37
-0
net/xfrm/xfrm_user.c
net/xfrm/xfrm_user.c
+1
-8
未找到文件。
include/linux/atalk.h
浏览文件 @
fb395884
...
...
@@ -20,7 +20,7 @@
#define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0)
struct
atalk_addr
{
__
u
16
s_net
;
__
be
16
s_net
;
__u8
s_node
;
};
...
...
@@ -33,8 +33,8 @@ struct sockaddr_at {
struct
atalk_netrange
{
__u8
nr_phase
;
__
u
16
nr_firstnet
;
__
u
16
nr_lastnet
;
__
be
16
nr_firstnet
;
__
be
16
nr_lastnet
;
};
#ifdef __KERNEL__
...
...
@@ -70,8 +70,8 @@ struct atalk_iface {
struct
atalk_sock
{
/* struct sock has to be the first member of atalk_sock */
struct
sock
sk
;
unsigned
short
dest_net
;
unsigned
short
src_net
;
__be16
dest_net
;
__be16
src_net
;
unsigned
char
dest_node
;
unsigned
char
src_node
;
unsigned
char
dest_port
;
...
...
@@ -95,9 +95,9 @@ struct ddpehdr {
deh_hops:
4
,
deh_len:
10
;
#endif
__
u
16
deh_sum
;
__
u
16
deh_dnet
;
__
u
16
deh_snet
;
__
be
16
deh_sum
;
__
be
16
deh_dnet
;
__
be
16
deh_snet
;
__u8
deh_dnode
;
__u8
deh_snode
;
__u8
deh_dport
;
...
...
@@ -142,24 +142,24 @@ struct ddpshdr {
/* AppleTalk AARP headers */
struct
elapaarp
{
__
u
16
hw_type
;
__
be
16
hw_type
;
#define AARP_HW_TYPE_ETHERNET 1
#define AARP_HW_TYPE_TOKENRING 2
__
u
16
pa_type
;
__
be
16
pa_type
;
__u8
hw_len
;
__u8
pa_len
;
#define AARP_PA_ALEN 4
__
u
16
function
;
__
be
16
function
;
#define AARP_REQUEST 1
#define AARP_REPLY 2
#define AARP_PROBE 3
__u8
hw_src
[
ETH_ALEN
]
__attribute__
((
packed
));
__u8
pa_src_zero
__attribute__
((
packed
));
__
u
16
pa_src_net
__attribute__
((
packed
));
__
be
16
pa_src_net
__attribute__
((
packed
));
__u8
pa_src_node
__attribute__
((
packed
));
__u8
hw_dst
[
ETH_ALEN
]
__attribute__
((
packed
));
__u8
pa_dst_zero
__attribute__
((
packed
));
__
u
16
pa_dst_net
__attribute__
((
packed
));
__
be
16
pa_dst_net
__attribute__
((
packed
));
__u8
pa_dst_node
__attribute__
((
packed
));
};
...
...
include/linux/netlink.h
浏览文件 @
fb395884
...
...
@@ -14,6 +14,7 @@
#define NETLINK_SELINUX 7
/* SELinux event notifications */
#define NETLINK_ARPD 8
#define NETLINK_AUDIT 9
/* auditing */
#define NETLINK_FIB_LOOKUP 10
#define NETLINK_ROUTE6 11
/* af_inet6 route comm channel */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14
/* DECnet routing messages */
...
...
include/linux/pfkeyv2.h
浏览文件 @
fb395884
...
...
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port {
/* Security Association flags */
#define SADB_SAFLAGS_PFS 1
#define SADB_SAFLAGS_NOPMTUDISC 0x20000000
#define SADB_SAFLAGS_DECAP_DSCP 0x40000000
#define SADB_SAFLAGS_NOECN 0x80000000
...
...
include/linux/xfrm.h
浏览文件 @
fb395884
...
...
@@ -196,6 +196,7 @@ struct xfrm_usersa_info {
__u8
flags
;
#define XFRM_STATE_NOECN 1
#define XFRM_STATE_DECAP_DSCP 2
#define XFRM_STATE_NOPMTUDISC 4
};
struct
xfrm_usersa_id
{
...
...
include/net/ax25.h
浏览文件 @
fb395884
...
...
@@ -220,7 +220,7 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
}
}
static
inline
unsigned
short
ax25_type_trans
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
static
inline
__be16
ax25_type_trans
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
skb
->
dev
=
dev
;
skb
->
pkt_type
=
PACKET_HOST
;
...
...
include/net/ip_fib.h
浏览文件 @
fb395884
...
...
@@ -109,6 +109,20 @@ struct fib_result {
#endif
};
struct
fib_result_nl
{
u32
fl_addr
;
/* To be looked up*/
u32
fl_fwmark
;
unsigned
char
fl_tos
;
unsigned
char
fl_scope
;
unsigned
char
tb_id_in
;
unsigned
char
tb_id
;
/* Results */
unsigned
char
prefixlen
;
unsigned
char
nh_sel
;
unsigned
char
type
;
unsigned
char
scope
;
int
err
;
};
#ifdef CONFIG_IP_ROUTE_MULTIPATH
...
...
include/net/sctp/command.h
浏览文件 @
fb395884
...
...
@@ -65,9 +65,11 @@ typedef enum {
SCTP_CMD_TIMER_START
,
/* Start a timer. */
SCTP_CMD_TIMER_RESTART
,
/* Restart a timer. */
SCTP_CMD_TIMER_STOP
,
/* Stop a timer. */
SCTP_CMD_COUNTER_RESET
,
/* Reset a counter. */
SCTP_CMD_COUNTER_INC
,
/* Increment a counter. */
SCTP_CMD_INIT_CHOOSE_TRANSPORT
,
/* Choose transport for an INIT. */
SCTP_CMD_INIT_COUNTER_RESET
,
/* Reset init counter. */
SCTP_CMD_INIT_COUNTER_INC
,
/* Increment init counter. */
SCTP_CMD_INIT_RESTART
,
/* High level, do init timer work. */
SCTP_CMD_COOKIEECHO_RESTART
,
/* High level, do cookie-echo timer work. */
SCTP_CMD_INIT_FAILED
,
/* High level, do init failure work. */
SCTP_CMD_REPORT_DUP
,
/* Report a duplicate TSN. */
SCTP_CMD_STRIKE
,
/* Mark a strike against a transport. */
...
...
@@ -118,7 +120,6 @@ typedef union {
int
error
;
sctp_state_t
state
;
sctp_event_timeout_t
to
;
sctp_counter_t
counter
;
void
*
ptr
;
struct
sctp_chunk
*
chunk
;
struct
sctp_association
*
asoc
;
...
...
@@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16, __u16, u16)
SCTP_ARG_CONSTRUCTOR
(
U8
,
__u8
,
u8
)
SCTP_ARG_CONSTRUCTOR
(
ERROR
,
int
,
error
)
SCTP_ARG_CONSTRUCTOR
(
STATE
,
sctp_state_t
,
state
)
SCTP_ARG_CONSTRUCTOR
(
COUNTER
,
sctp_counter_t
,
counter
)
SCTP_ARG_CONSTRUCTOR
(
TO
,
sctp_event_timeout_t
,
to
)
SCTP_ARG_CONSTRUCTOR
(
PTR
,
void
*
,
ptr
)
SCTP_ARG_CONSTRUCTOR
(
CHUNK
,
struct
sctp_chunk
*
,
chunk
)
...
...
include/net/sctp/constants.h
浏览文件 @
fb395884
...
...
@@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 };
enum
{
SCTP_MAX_DUP_TSNS
=
16
};
enum
{
SCTP_MAX_GABS
=
16
};
typedef
enum
{
SCTP_COUNTER_INIT_ERROR
,
}
sctp_counter_t
;
/* How many counters does an association need? */
#define SCTP_NUMBER_COUNTERS 5
/* Here we define the default timers. */
/* cookie timer def = ? seconds */
...
...
include/net/sctp/sctp.h
浏览文件 @
fb395884
...
...
@@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
extern
int
sctp_debug_flag
;
#define SCTP_DEBUG_PRINTK(whatever...) \
((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
if (sctp_debug_flag) { \
if (saddr->sa.sa_family == AF_INET6) { \
printk(KERN_DEBUG \
lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
leadparm, \
NIP6(saddr->v6.sin6_addr), \
otherparms); \
} else { \
printk(KERN_DEBUG \
lead "%u.%u.%u.%u" trail, \
leadparm, \
NIPQUAD(saddr->v4.sin_addr.s_addr), \
otherparms); \
} \
}
#define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
#define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
...
...
@@ -236,6 +252,7 @@ extern int sctp_debug_flag;
#else
/* SCTP_DEBUG */
#define SCTP_DEBUG_PRINTK(whatever...)
#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
#define SCTP_ENABLE_DEBUG
#define SCTP_DISABLE_DEBUG
#define SCTP_ASSERT(expr, str, func)
...
...
include/net/sctp/sm.h
浏览文件 @
fb395884
...
...
@@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
sctp_state_fn_t
sctp_sf_eat_sack_6_2
;
sctp_state_fn_t
sctp_sf_tabort_8_4_8
;
sctp_state_fn_t
sctp_sf_operr_notify
;
sctp_state_fn_t
sctp_sf_t1_timer_expire
;
sctp_state_fn_t
sctp_sf_t1_init_timer_expire
;
sctp_state_fn_t
sctp_sf_t1_cookie_timer_expire
;
sctp_state_fn_t
sctp_sf_t2_timer_expire
;
sctp_state_fn_t
sctp_sf_t4_timer_expire
;
sctp_state_fn_t
sctp_sf_t5_timer_expire
;
...
...
@@ -258,7 +259,10 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
void
sctp_chunk_assign_tsn
(
struct
sctp_chunk
*
);
void
sctp_chunk_assign_ssn
(
struct
sctp_chunk
*
);
void
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
);
sctp_disposition_t
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
,
const
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
transport
);
/* Prototypes for statetable processing. */
...
...
include/net/sctp/structs.h
浏览文件 @
fb395884
...
...
@@ -867,10 +867,13 @@ struct sctp_transport {
*/
unsigned
long
last_time_ecne_reduced
;
/* active : The current active state of this destination,
* : i.e. DOWN, UP, etc.
/* The number of times INIT has been sent on this transport. */
int
init_sent_count
;
/* state : The current state of this destination,
* : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN.
*/
int
activ
e
;
int
stat
e
;
/* hb_allowed : The current heartbeat state of this destination,
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
...
...
@@ -1222,9 +1225,6 @@ struct sctp_endpoint {
/* sendbuf acct. policy. */
__u32
sndbuf_policy
;
/* Name for debugging output... */
char
*
debug_name
;
};
/* Recover the outter endpoint structure. */
...
...
@@ -1314,11 +1314,23 @@ struct sctp_association {
* : association. Normally this information is
* : hashed or keyed for quick lookup and access
* : of the TCB.
* : The list is also initialized with the list
* : of addresses passed with the sctp_connectx()
* : call.
*
* It is a list of SCTP_transport's.
*/
struct
list_head
transport_addr_list
;
/* transport_count
*
* Peer : A count of the number of peer addresses
* Transport : in the Peer Transport Address List.
* Address :
* Count :
*/
__u16
transport_count
;
/* port
* The transport layer port number.
*/
...
...
@@ -1486,6 +1498,9 @@ struct sctp_association {
/* Transport to which SHUTDOWN chunk was last sent. */
struct
sctp_transport
*
shutdown_last_sent_to
;
/* Transport to which INIT chunk was last sent. */
struct
sctp_transport
*
init_last_sent_to
;
/* Next TSN : The next TSN number to be assigned to a new
* : DATA chunk. This is sent in the INIT or INIT
* : ACK chunk to the peer and incremented each
...
...
@@ -1549,8 +1564,11 @@ struct sctp_association {
/* The message size at which SCTP fragmentation will occur. */
__u32
frag_point
;
/* Currently only one counter is used to count INIT errors. */
int
counters
[
SCTP_NUMBER_COUNTERS
];
/* Counter used to count INIT errors. */
int
init_err_counter
;
/* Count the number of INIT cycles (for doubling timeout). */
int
init_cycle
;
/* Default send parameters. */
__u16
default_stream
;
...
...
@@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *);
void
sctp_association_put
(
struct
sctp_association
*
);
void
sctp_association_hold
(
struct
sctp_association
*
);
struct
sctp_transport
*
sctp_assoc_choose_init_transport
(
struct
sctp_association
*
);
struct
sctp_transport
*
sctp_assoc_choose_shutdown_transport
(
struct
sctp_association
*
);
void
sctp_assoc_update_retran_path
(
struct
sctp_association
*
);
...
...
@@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
const
union
sctp_addr
*
laddr
);
struct
sctp_transport
*
sctp_assoc_add_peer
(
struct
sctp_association
*
,
const
union
sctp_addr
*
address
,
const
int
gfp
);
const
int
gfp
,
const
int
peer_state
);
void
sctp_assoc_del_peer
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
addr
);
void
sctp_assoc_rm_peer
(
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
peer
);
void
sctp_assoc_control_transport
(
struct
sctp_association
*
,
struct
sctp_transport
*
,
sctp_transport_cmd_t
,
sctp_sn_error_t
);
...
...
include/net/sctp/user.h
浏览文件 @
fb395884
...
...
@@ -111,6 +111,8 @@ enum sctp_optname {
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
SCTP_SOCKOPT_CONNECTX
,
/* CONNECTX requests. */
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
};
/*
...
...
@@ -527,6 +529,7 @@ struct sctp_paddrinfo {
enum
sctp_spinfo_state
{
SCTP_INACTIVE
,
SCTP_ACTIVE
,
SCTP_UNKNOWN
=
0xffff
/* Value used for transport state unknown */
};
/*
...
...
include/net/xfrm.h
浏览文件 @
fb395884
...
...
@@ -204,6 +204,7 @@ struct xfrm_state_afinfo {
rwlock_t
lock
;
struct
list_head
*
state_bydst
;
struct
list_head
*
state_byspi
;
int
(
*
init_flags
)(
struct
xfrm_state
*
x
);
void
(
*
init_tempsel
)(
struct
xfrm_state
*
x
,
struct
flowi
*
fl
,
struct
xfrm_tmpl
*
tmpl
,
xfrm_address_t
*
daddr
,
xfrm_address_t
*
saddr
);
...
...
@@ -225,7 +226,7 @@ struct xfrm_type
struct
module
*
owner
;
__u8
proto
;
int
(
*
init_state
)(
struct
xfrm_state
*
x
,
void
*
args
);
int
(
*
init_state
)(
struct
xfrm_state
*
x
);
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
);
...
...
@@ -839,6 +840,7 @@ extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
extern
void
xfrm_replay_advance
(
struct
xfrm_state
*
x
,
u32
seq
);
extern
int
xfrm_state_check
(
struct
xfrm_state
*
x
,
struct
sk_buff
*
skb
);
extern
int
xfrm_state_mtu
(
struct
xfrm_state
*
x
,
int
mtu
);
extern
int
xfrm_init_state
(
struct
xfrm_state
*
x
);
extern
int
xfrm4_rcv
(
struct
sk_buff
*
skb
);
extern
int
xfrm4_output
(
struct
sk_buff
*
skb
);
extern
int
xfrm4_tunnel_register
(
struct
xfrm_tunnel
*
handler
);
...
...
net/appletalk/aarp.c
浏览文件 @
fb395884
...
...
@@ -565,7 +565,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
* numbers we just happen to need. Now put the
* length in the lower two.
*/
*
((
__
u
16
*
)
skb
->
data
)
=
htons
(
skb
->
len
);
*
((
__
be
16
*
)
skb
->
data
)
=
htons
(
skb
->
len
);
ft
=
1
;
}
/*
...
...
net/appletalk/ddp.c
浏览文件 @
fb395884
...
...
@@ -401,7 +401,7 @@ static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev)
}
/* Find a match for a specific network:node pair */
static
struct
atalk_iface
*
atalk_find_interface
(
int
net
,
int
node
)
static
struct
atalk_iface
*
atalk_find_interface
(
__be16
net
,
int
node
)
{
struct
atalk_iface
*
iface
;
...
...
net/ipv4/ah4.c
浏览文件 @
fb395884
...
...
@@ -200,7 +200,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
xfrm_state_put
(
x
);
}
static
int
ah_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
ah_init_state
(
struct
xfrm_state
*
x
)
{
struct
ah_data
*
ahp
=
NULL
;
struct
xfrm_algo_desc
*
aalg_desc
;
...
...
net/ipv4/esp4.c
浏览文件 @
fb395884
...
...
@@ -362,7 +362,7 @@ static void esp_destroy(struct xfrm_state *x)
kfree
(
esp
);
}
static
int
esp_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
esp_init_state
(
struct
xfrm_state
*
x
)
{
struct
esp_data
*
esp
=
NULL
;
...
...
net/ipv4/fib_frontend.c
浏览文件 @
fb395884
...
...
@@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
#undef BRD1_OK
}
static
void
nl_fib_lookup
(
struct
fib_result_nl
*
frn
,
struct
fib_table
*
tb
)
{
struct
fib_result
res
;
struct
flowi
fl
=
{
.
nl_u
=
{
.
ip4_u
=
{
.
daddr
=
frn
->
fl_addr
,
.
fwmark
=
frn
->
fl_fwmark
,
.
tos
=
frn
->
fl_tos
,
.
scope
=
frn
->
fl_scope
}
}
};
if
(
tb
)
{
local_bh_disable
();
frn
->
tb_id
=
tb
->
tb_id
;
frn
->
err
=
tb
->
tb_lookup
(
tb
,
&
fl
,
&
res
);
if
(
!
frn
->
err
)
{
frn
->
prefixlen
=
res
.
prefixlen
;
frn
->
nh_sel
=
res
.
nh_sel
;
frn
->
type
=
res
.
type
;
frn
->
scope
=
res
.
scope
;
}
local_bh_enable
();
}
}
static
void
nl_fib_input
(
struct
sock
*
sk
,
int
len
)
{
struct
sk_buff
*
skb
=
NULL
;
struct
nlmsghdr
*
nlh
=
NULL
;
struct
fib_result_nl
*
frn
;
int
err
;
u32
pid
;
struct
fib_table
*
tb
;
skb
=
skb_recv_datagram
(
sk
,
0
,
0
,
&
err
);
nlh
=
(
struct
nlmsghdr
*
)
skb
->
data
;
frn
=
(
struct
fib_result_nl
*
)
NLMSG_DATA
(
nlh
);
tb
=
fib_get_table
(
frn
->
tb_id_in
);
nl_fib_lookup
(
frn
,
tb
);
pid
=
nlh
->
nlmsg_pid
;
/*pid of sending process */
NETLINK_CB
(
skb
).
groups
=
0
;
/* not in mcast group */
NETLINK_CB
(
skb
).
pid
=
0
;
/* from kernel */
NETLINK_CB
(
skb
).
dst_pid
=
pid
;
NETLINK_CB
(
skb
).
dst_groups
=
0
;
/* unicast */
netlink_unicast
(
sk
,
skb
,
pid
,
MSG_DONTWAIT
);
}
static
void
nl_fib_lookup_init
(
void
)
{
netlink_kernel_create
(
NETLINK_FIB_LOOKUP
,
nl_fib_input
);
}
static
void
fib_disable_ip
(
struct
net_device
*
dev
,
int
force
)
{
if
(
fib_sync_down
(
0
,
dev
,
force
))
...
...
@@ -604,6 +658,7 @@ void __init ip_fib_init(void)
register_netdevice_notifier
(
&
fib_netdev_notifier
);
register_inetaddr_notifier
(
&
fib_inetaddr_notifier
);
nl_fib_lookup_init
();
}
EXPORT_SYMBOL
(
inet_addr_type
);
...
...
net/ipv4/ipcomp.c
浏览文件 @
fb395884
...
...
@@ -236,15 +236,10 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t
->
props
.
mode
=
1
;
t
->
props
.
saddr
.
a4
=
x
->
props
.
saddr
.
a4
;
t
->
props
.
flags
=
x
->
props
.
flags
;
t
->
type
=
xfrm_get_type
(
IPPROTO_IPIP
,
t
->
props
.
family
);
if
(
t
->
type
==
NULL
)
goto
error
;
if
(
t
->
type
->
init_state
(
t
,
NULL
))
if
(
xfrm_init_state
(
t
))
goto
error
;
t
->
km
.
state
=
XFRM_STATE_VALID
;
atomic_set
(
&
t
->
tunnel_users
,
1
);
out:
return
t
;
...
...
@@ -422,7 +417,7 @@ static void ipcomp_destroy(struct xfrm_state *x)
kfree
(
ipcd
);
}
static
int
ipcomp_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
ipcomp_init_state
(
struct
xfrm_state
*
x
)
{
int
err
;
struct
ipcomp_data
*
ipcd
;
...
...
net/ipv4/xfrm4_output.c
浏览文件 @
fb395884
...
...
@@ -33,6 +33,7 @@ static void xfrm4_encap(struct sk_buff *skb)
struct
dst_entry
*
dst
=
skb
->
dst
;
struct
xfrm_state
*
x
=
dst
->
xfrm
;
struct
iphdr
*
iph
,
*
top_iph
;
int
flags
;
iph
=
skb
->
nh
.
iph
;
skb
->
h
.
ipiph
=
iph
;
...
...
@@ -51,10 +52,13 @@ static void xfrm4_encap(struct sk_buff *skb)
/* DS disclosed */
top_iph
->
tos
=
INET_ECN_encapsulate
(
iph
->
tos
,
iph
->
tos
);
if
(
x
->
props
.
flags
&
XFRM_STATE_NOECN
)
flags
=
x
->
props
.
flags
;
if
(
flags
&
XFRM_STATE_NOECN
)
IP_ECN_clear
(
top_iph
);
top_iph
->
frag_off
=
iph
->
frag_off
&
htons
(
IP_DF
);
top_iph
->
frag_off
=
(
flags
&
XFRM_STATE_NOPMTUDISC
)
?
0
:
(
iph
->
frag_off
&
htons
(
IP_DF
));
if
(
!
top_iph
->
frag_off
)
__ip_select_ident
(
top_iph
,
dst
,
0
);
...
...
net/ipv4/xfrm4_state.c
浏览文件 @
fb395884
...
...
@@ -7,12 +7,20 @@
*
*/
#include <net/ip.h>
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
static
struct
xfrm_state_afinfo
xfrm4_state_afinfo
;
static
int
xfrm4_init_flags
(
struct
xfrm_state
*
x
)
{
if
(
ipv4_config
.
no_pmtu_disc
)
x
->
props
.
flags
|=
XFRM_STATE_NOPMTUDISC
;
return
0
;
}
static
void
__xfrm4_init_tempsel
(
struct
xfrm_state
*
x
,
struct
flowi
*
fl
,
struct
xfrm_tmpl
*
tmpl
,
...
...
@@ -109,6 +117,7 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
static
struct
xfrm_state_afinfo
xfrm4_state_afinfo
=
{
.
family
=
AF_INET
,
.
lock
=
RW_LOCK_UNLOCKED
,
.
init_flags
=
xfrm4_init_flags
,
.
init_tempsel
=
__xfrm4_init_tempsel
,
.
state_lookup
=
__xfrm4_state_lookup
,
.
find_acq
=
__xfrm4_find_acq
,
...
...
net/ipv4/xfrm4_tunnel.c
浏览文件 @
fb395884
...
...
@@ -84,7 +84,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
handler
->
err_handler
(
skb
,
&
arg
);
}
static
int
ipip_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
ipip_init_state
(
struct
xfrm_state
*
x
)
{
if
(
!
x
->
props
.
mode
)
return
-
EINVAL
;
...
...
net/ipv6/ah6.c
浏览文件 @
fb395884
...
...
@@ -339,7 +339,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
xfrm_state_put
(
x
);
}
static
int
ah6_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
ah6_init_state
(
struct
xfrm_state
*
x
)
{
struct
ah_data
*
ahp
=
NULL
;
struct
xfrm_algo_desc
*
aalg_desc
;
...
...
net/ipv6/esp6.c
浏览文件 @
fb395884
...
...
@@ -296,7 +296,7 @@ static void esp6_destroy(struct xfrm_state *x)
kfree
(
esp
);
}
static
int
esp6_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
esp6_init_state
(
struct
xfrm_state
*
x
)
{
struct
esp_data
*
esp
=
NULL
;
...
...
net/ipv6/ipcomp6.c
浏览文件 @
fb395884
...
...
@@ -234,14 +234,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t
->
props
.
mode
=
1
;
memcpy
(
t
->
props
.
saddr
.
a6
,
x
->
props
.
saddr
.
a6
,
sizeof
(
struct
in6_addr
));
t
->
type
=
xfrm_get_type
(
IPPROTO_IPV6
,
t
->
props
.
family
);
if
(
t
->
type
==
NULL
)
if
(
xfrm_init_state
(
t
))
goto
error
;
if
(
t
->
type
->
init_state
(
t
,
NULL
))
goto
error
;
t
->
km
.
state
=
XFRM_STATE_VALID
;
atomic_set
(
&
t
->
tunnel_users
,
1
);
out:
...
...
@@ -420,7 +415,7 @@ static void ipcomp6_destroy(struct xfrm_state *x)
xfrm6_tunnel_free_spi
((
xfrm_address_t
*
)
&
x
->
props
.
saddr
);
}
static
int
ipcomp6_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
ipcomp6_init_state
(
struct
xfrm_state
*
x
)
{
int
err
;
struct
ipcomp_data
*
ipcd
;
...
...
net/ipv6/xfrm6_tunnel.c
浏览文件 @
fb395884
...
...
@@ -466,7 +466,7 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return
;
}
static
int
xfrm6_tunnel_init_state
(
struct
xfrm_state
*
x
,
void
*
args
)
static
int
xfrm6_tunnel_init_state
(
struct
xfrm_state
*
x
)
{
if
(
!
x
->
props
.
mode
)
return
-
EINVAL
;
...
...
net/key/af_key.c
浏览文件 @
fb395884
...
...
@@ -690,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa
->
sadb_sa_flags
|=
SADB_SAFLAGS_NOECN
;
if
(
x
->
props
.
flags
&
XFRM_STATE_DECAP_DSCP
)
sa
->
sadb_sa_flags
|=
SADB_SAFLAGS_DECAP_DSCP
;
if
(
x
->
props
.
flags
&
XFRM_STATE_NOPMTUDISC
)
sa
->
sadb_sa_flags
|=
SADB_SAFLAGS_NOPMTUDISC
;
/* hard time */
if
(
hsc
&
2
)
{
...
...
@@ -974,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x
->
props
.
flags
|=
XFRM_STATE_NOECN
;
if
(
sa
->
sadb_sa_flags
&
SADB_SAFLAGS_DECAP_DSCP
)
x
->
props
.
flags
|=
XFRM_STATE_DECAP_DSCP
;
if
(
sa
->
sadb_sa_flags
&
SADB_SAFLAGS_NOPMTUDISC
)
x
->
props
.
flags
|=
XFRM_STATE_NOPMTUDISC
;
lifetime
=
(
struct
sadb_lifetime
*
)
ext_hdrs
[
SADB_EXT_LIFETIME_HARD
-
1
];
if
(
lifetime
!=
NULL
)
{
...
...
@@ -1096,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
}
}
x
->
type
=
xfrm_get_type
(
proto
,
x
->
props
.
family
);
if
(
x
->
type
==
NULL
)
{
err
=
-
ENOPROTOOPT
;
goto
out
;
}
if
(
x
->
type
->
init_state
(
x
,
NULL
))
{
err
=
-
EINVAL
;
err
=
xfrm_init_state
(
x
);
if
(
err
)
goto
out
;
}
x
->
km
.
seq
=
hdr
->
sadb_msg_seq
;
x
->
km
.
state
=
XFRM_STATE_VALID
;
return
x
;
out:
...
...
net/sctp/associola.c
浏览文件 @
fb395884
...
...
@@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc
->
last_cwr_tsn
=
asoc
->
ctsn_ack_point
;
asoc
->
unack_data
=
0
;
SCTP_DEBUG_PRINTK
(
"myctsnap for %s INIT as 0x%x.
\n
"
,
asoc
->
ep
->
debug_name
,
asoc
->
ctsn_ack_point
);
/* ADDIP Section 4.1 Asconf Chunk Procedures
*
* When an endpoint has an ASCONF signaled change to be sent to the
...
...
@@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
/* Make an empty list of remote transport addresses. */
INIT_LIST_HEAD
(
&
asoc
->
peer
.
transport_addr_list
);
asoc
->
peer
.
transport_count
=
0
;
/* RFC 2960 5.1 Normal Establishment of an Association
*
...
...
@@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
asoc
->
base
.
malloced
=
1
;
SCTP_DBG_OBJCNT_INC
(
assoc
);
SCTP_DEBUG_PRINTK
(
"Created asoc %p
\n
"
,
asoc
);
return
asoc
;
...
...
@@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc)
sctp_transport_free
(
transport
);
}
asoc
->
peer
.
transport_count
=
0
;
/* Free any cached ASCONF_ACK chunk. */
if
(
asoc
->
addip_last_asconf_ack
)
sctp_chunk_free
(
asoc
->
addip_last_asconf_ack
);
...
...
@@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
if
(
transport
->
active
)
if
(
transport
->
state
!=
SCTP_INACTIVE
)
asoc
->
peer
.
active_path
=
transport
;
/*
...
...
@@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
transport
->
cacc
.
next_tsn_at_change
=
asoc
->
next_tsn
;
}
/* Remove a transport from an association. */
void
sctp_assoc_rm_peer
(
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
peer
)
{
struct
list_head
*
pos
;
struct
sctp_transport
*
transport
;
SCTP_DEBUG_PRINTK_IPADDR
(
"sctp_assoc_rm_peer:association %p addr: "
,
" port: %d
\n
"
,
asoc
,
(
&
peer
->
ipaddr
),
peer
->
ipaddr
.
v4
.
sin_port
);
/* If we are to remove the current retran_path, update it
* to the next peer before removing this peer from the list.
*/
if
(
asoc
->
peer
.
retran_path
==
peer
)
sctp_assoc_update_retran_path
(
asoc
);
/* Remove this peer from the list. */
list_del
(
&
peer
->
transports
);
/* Get the first transport of asoc. */
pos
=
asoc
->
peer
.
transport_addr_list
.
next
;
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
/* Update any entries that match the peer to be deleted. */
if
(
asoc
->
peer
.
primary_path
==
peer
)
sctp_assoc_set_primary
(
asoc
,
transport
);
if
(
asoc
->
peer
.
active_path
==
peer
)
asoc
->
peer
.
active_path
=
transport
;
if
(
asoc
->
peer
.
last_data_from
==
peer
)
asoc
->
peer
.
last_data_from
=
transport
;
/* If we remove the transport an INIT was last sent to, set it to
* NULL. Combined with the update of the retran path above, this
* will cause the next INIT to be sent to the next available
* transport, maintaining the cycle.
*/
if
(
asoc
->
init_last_sent_to
==
peer
)
asoc
->
init_last_sent_to
=
NULL
;
asoc
->
peer
.
transport_count
--
;
sctp_transport_free
(
peer
);
}
/* Add a transport address to an association. */
struct
sctp_transport
*
sctp_assoc_add_peer
(
struct
sctp_association
*
asoc
,
const
union
sctp_addr
*
addr
,
int
gfp
)
const
int
gfp
,
const
int
peer_state
)
{
struct
sctp_transport
*
peer
;
struct
sctp_sock
*
sp
;
...
...
@@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* AF_INET and AF_INET6 share common port field. */
port
=
addr
->
v4
.
sin_port
;
SCTP_DEBUG_PRINTK_IPADDR
(
"sctp_assoc_add_peer:association %p addr: "
,
" port: %d state:%s
\n
"
,
asoc
,
addr
,
addr
->
v4
.
sin_port
,
peer_state
==
SCTP_UNKNOWN
?
"UNKNOWN"
:
"ACTIVE"
);
/* Set the port if it has not been set yet. */
if
(
0
==
asoc
->
peer
.
port
)
asoc
->
peer
.
port
=
port
;
/* Check to see if this is a duplicate. */
peer
=
sctp_assoc_lookup_paddr
(
asoc
,
addr
);
if
(
peer
)
if
(
peer
)
{
if
(
peer_state
==
SCTP_ACTIVE
&&
peer
->
state
==
SCTP_UNKNOWN
)
peer
->
state
=
SCTP_ACTIVE
;
return
peer
;
}
peer
=
sctp_transport_new
(
addr
,
gfp
);
if
(
!
peer
)
...
...
@@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Set the transport's RTO.initial value */
peer
->
rto
=
asoc
->
rto_initial
;
/* Set the peer's active state. */
peer
->
state
=
peer_state
;
/* Attach the remote transport to our asoc. */
list_add_tail
(
&
peer
->
transports
,
&
asoc
->
peer
.
transport_addr_list
);
asoc
->
peer
.
transport_count
++
;
/* If we do not yet have a primary path, set one. */
if
(
!
asoc
->
peer
.
primary_path
)
{
...
...
@@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
asoc
->
peer
.
retran_path
=
peer
;
}
if
(
asoc
->
peer
.
active_path
==
asoc
->
peer
.
retran_path
)
if
(
asoc
->
peer
.
active_path
==
asoc
->
peer
.
retran_path
)
{
asoc
->
peer
.
retran_path
=
peer
;
}
return
peer
;
}
...
...
@@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc,
{
struct
list_head
*
pos
;
struct
list_head
*
temp
;
struct
sctp_transport
*
peer
=
NULL
;
struct
sctp_transport
*
transport
;
list_for_each_safe
(
pos
,
temp
,
&
asoc
->
peer
.
transport_addr_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
if
(
sctp_cmp_addr_exact
(
addr
,
&
transport
->
ipaddr
))
{
peer
=
transport
;
list_del
(
pos
);
/* Do book keeping for removing the peer and free it. */
sctp_assoc_rm_peer
(
asoc
,
transport
);
break
;
}
}
/* The address we want delete is not in the association. */
if
(
!
peer
)
return
;
/* Get the first transport of asoc. */
pos
=
asoc
->
peer
.
transport_addr_list
.
next
;
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
/* Update any entries that match the peer to be deleted. */
if
(
asoc
->
peer
.
primary_path
==
peer
)
sctp_assoc_set_primary
(
asoc
,
transport
);
if
(
asoc
->
peer
.
active_path
==
peer
)
asoc
->
peer
.
active_path
=
transport
;
if
(
asoc
->
peer
.
retran_path
==
peer
)
asoc
->
peer
.
retran_path
=
transport
;
if
(
asoc
->
peer
.
last_data_from
==
peer
)
asoc
->
peer
.
last_data_from
=
transport
;
sctp_transport_free
(
peer
);
}
/* Lookup a transport by address. */
...
...
@@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* Record the transition on the transport. */
switch
(
command
)
{
case
SCTP_TRANSPORT_UP
:
transport
->
activ
e
=
SCTP_ACTIVE
;
transport
->
stat
e
=
SCTP_ACTIVE
;
spc_state
=
SCTP_ADDR_AVAILABLE
;
break
;
case
SCTP_TRANSPORT_DOWN
:
transport
->
activ
e
=
SCTP_INACTIVE
;
transport
->
stat
e
=
SCTP_INACTIVE
;
spc_state
=
SCTP_ADDR_UNREACHABLE
;
break
;
...
...
@@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
t
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
if
(
!
t
->
active
)
if
(
t
->
state
==
SCTP_INACTIVE
)
continue
;
if
(
!
first
||
t
->
last_time_heard
>
first
->
last_time_heard
)
{
second
=
first
;
...
...
@@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
if
(
asoc
->
peer
.
primary_path
->
active
&&
if
(
asoc
->
peer
.
primary_path
->
state
!=
SCTP_INACTIVE
&&
first
!=
asoc
->
peer
.
primary_path
)
{
second
=
first
;
first
=
asoc
->
peer
.
primary_path
;
...
...
@@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
transports
);
if
(
!
sctp_assoc_lookup_paddr
(
asoc
,
&
trans
->
ipaddr
))
sctp_assoc_add_peer
(
asoc
,
&
trans
->
ipaddr
,
GFP_ATOMIC
);
GFP_ATOMIC
,
SCTP_ACTIVE
);
}
asoc
->
ctsn_ack_point
=
asoc
->
next_tsn
-
1
;
...
...
@@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
/* Try to find an active transport. */
if
(
t
->
active
)
{
if
(
t
->
state
!=
SCTP_INACTIVE
)
{
break
;
}
else
{
/* Keep track of the next transport in case
...
...
@@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
}
asoc
->
peer
.
retran_path
=
t
;
SCTP_DEBUG_PRINTK_IPADDR
(
"sctp_assoc_update_retran_path:association"
" %p addr: "
,
" port: %d
\n
"
,
asoc
,
(
&
t
->
ipaddr
),
t
->
ipaddr
.
v4
.
sin_port
);
}
/* Choose the transport for sending a INIT packet. */
struct
sctp_transport
*
sctp_assoc_choose_init_transport
(
struct
sctp_association
*
asoc
)
{
struct
sctp_transport
*
t
;
/* Use the retran path. If the last INIT was sent over the
* retran path, update the retran path and use it.
*/
if
(
!
asoc
->
init_last_sent_to
)
{
t
=
asoc
->
peer
.
active_path
;
}
else
{
if
(
asoc
->
init_last_sent_to
==
asoc
->
peer
.
retran_path
)
sctp_assoc_update_retran_path
(
asoc
);
t
=
asoc
->
peer
.
retran_path
;
}
SCTP_DEBUG_PRINTK_IPADDR
(
"sctp_assoc_update_retran_path:association"
" %p addr: "
,
" port: %d
\n
"
,
asoc
,
(
&
t
->
ipaddr
),
t
->
ipaddr
.
v4
.
sin_port
);
return
t
;
}
/* Choose the transport for sending a SHUTDOWN packet. */
...
...
net/sctp/endpointola.c
浏览文件 @
fb395884
...
...
@@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep
->
last_key
=
ep
->
current_key
=
0
;
ep
->
key_changed_at
=
jiffies
;
ep
->
debug_name
=
"unnamedEndpoint"
;
return
ep
;
}
...
...
net/sctp/input.c
浏览文件 @
fb395884
...
...
@@ -353,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
sctp_do_sm
(
SCTP_EVENT_T_OTHER
,
SCTP_ST_OTHER
(
SCTP_EVENT_ICMP_PROTO_UNREACH
),
asoc
->
state
,
asoc
->
ep
,
asoc
,
NULL
,
asoc
->
state
,
asoc
->
ep
,
asoc
,
t
,
GFP_ATOMIC
);
}
...
...
net/sctp/outqueue.c
浏览文件 @
fb395884
...
...
@@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
if
(
!
new_transport
)
{
new_transport
=
asoc
->
peer
.
active_path
;
}
else
if
(
!
new_transport
->
active
)
{
/* If the chunk is Heartbeat or Heartbeat Ack,
* send it to chunk->transport, even if it's
}
else
if
(
new_transport
->
state
==
SCTP_INACTIVE
)
{
/* If the chunk is Heartbeat or Heartbeat Ack,
* send it to chunk->transport, even if it's
* inactive.
*
* 3.3.6 Heartbeat Acknowledgement:
...
...
@@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
* Otherwise, we want to use the active path.
*/
new_transport
=
chunk
->
transport
;
if
(
!
new_transport
||
!
new_transport
->
active
)
if
(
!
new_transport
||
new_transport
->
state
==
SCTP_INACTIVE
)
new_transport
=
asoc
->
peer
.
active_path
;
/* Change packets if necessary. */
...
...
@@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
if
(
!
transport
->
active
)
{
if
(
transport
->
state
==
SCTP_INACTIVE
)
{
sctp_assoc_control_transport
(
transport
->
asoc
,
transport
,
...
...
net/sctp/sm_make_chunk.c
浏览文件 @
fb395884
...
...
@@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* be a a better choice than any of the embedded addresses.
*/
if
(
peer_addr
)
if
(
!
sctp_assoc_add_peer
(
asoc
,
peer_addr
,
gfp
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
peer_addr
,
gfp
,
SCTP_ACTIVE
))
goto
nomem
;
/* Process the initialization parameters. */
...
...
@@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
goto
clean_up
;
}
/* Walk list of transports, removing transports in the UNKNOWN state. */
list_for_each_safe
(
pos
,
temp
,
&
asoc
->
peer
.
transport_addr_list
)
{
transport
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
if
(
transport
->
state
==
SCTP_UNKNOWN
)
{
sctp_assoc_rm_peer
(
asoc
,
transport
);
}
}
/* The fixed INIT headers are always in network byte
* order.
*/
...
...
@@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* stream sequence number shall be set to 0.
*/
/* Allocate storage for the negotiated streams if it is not a temporary * association.
/* Allocate storage for the negotiated streams if it is not a temporary
* association.
*/
if
(
!
asoc
->
temp
)
{
int
assoc_id
;
...
...
@@ -1952,6 +1961,9 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
list_del_init
(
pos
);
sctp_transport_free
(
transport
);
}
asoc
->
peer
.
transport_count
=
0
;
nomem:
return
0
;
}
...
...
@@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc,
af
->
from_addr_param
(
&
addr
,
param
.
addr
,
asoc
->
peer
.
port
,
0
);
scope
=
sctp_scope
(
peer_addr
);
if
(
sctp_in_scope
(
&
addr
,
scope
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
&
addr
,
gfp
))
if
(
!
sctp_assoc_add_peer
(
asoc
,
&
addr
,
gfp
,
SCTP_ACTIVE
))
return
0
;
break
;
...
...
@@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
* Due to Resource Shortage'.
*/
peer
=
sctp_assoc_add_peer
(
asoc
,
&
addr
,
GFP_ATOMIC
);
peer
=
sctp_assoc_add_peer
(
asoc
,
&
addr
,
GFP_ATOMIC
,
SCTP_ACTIVE
);
if
(
!
peer
)
return
SCTP_ERROR_RSRC_LOW
;
...
...
net/sctp/sm_sideeffect.c
浏览文件 @
fb395884
...
...
@@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
*/
asoc
->
overall_error_count
++
;
if
(
transport
->
active
&&
if
(
transport
->
state
!=
SCTP_INACTIVE
&&
(
transport
->
error_count
++
>=
transport
->
max_retrans
))
{
SCTP_DEBUG_PRINTK
(
"transport_strike: transport "
"IP:%d.%d.%d.%d failed.
\n
"
,
NIPQUAD
(
transport
->
ipaddr
.
v4
.
sin_addr
));
SCTP_DEBUG_PRINTK_IPADDR
(
"transport_strike:association %p"
,
" transport IP: port:%d failed.
\n
"
,
asoc
,
(
&
transport
->
ipaddr
),
transport
->
ipaddr
.
v4
.
sin_port
);
sctp_assoc_control_transport
(
asoc
,
transport
,
SCTP_TRANSPORT_DOWN
,
SCTP_FAILED_THRESHOLD
);
...
...
@@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
if
(
!
t
->
active
)
if
(
t
->
state
==
SCTP_INACTIVE
)
sctp_assoc_control_transport
(
asoc
,
t
,
SCTP_TRANSPORT_UP
,
SCTP_HEARTBEAT_SUCCESS
);
...
...
@@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
asoc
->
state
=
state
;
SCTP_DEBUG_PRINTK
(
"sctp_cmd_new_state: asoc %p[%s]
\n
"
,
asoc
,
sctp_state_tbl
[
state
]);
if
(
sctp_style
(
sk
,
TCP
))
{
/* Change the sk->sk_state of a TCP-style socket that has
/* Change the sk->sk_state of a TCP-style socket that has
* sucessfully completed a connect() call.
*/
if
(
sctp_state
(
asoc
,
ESTABLISHED
)
&&
sctp_sstate
(
sk
,
CLOSED
))
...
...
@@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
sk
->
sk_shutdown
|=
RCV_SHUTDOWN
;
}
if
(
sctp_state
(
asoc
,
COOKIE_WAIT
))
{
/* Reset init timeouts since they may have been
* increased due to timer expirations.
*/
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
=
asoc
->
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
];
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
=
asoc
->
ep
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
];
}
if
(
sctp_state
(
asoc
,
ESTABLISHED
)
||
sctp_state
(
asoc
,
CLOSED
)
||
sctp_state
(
asoc
,
SHUTDOWN_RECEIVED
))
{
...
...
@@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* to be executed only during failed attempts of
* association establishment.
*/
if
((
asoc
->
peer
.
retran_path
!=
asoc
->
peer
.
primary_path
)
&&
(
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
>
0
))
{
sctp_add_cmd_sf
(
commands
,
if
((
asoc
->
peer
.
retran_path
!=
asoc
->
peer
.
primary_path
)
&&
(
asoc
->
init_err_counter
>
0
))
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_FORCE_PRIM_RETRAN
,
SCTP_NULL
());
}
...
...
@@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_association_put
(
asoc
);
break
;
case
SCTP_CMD_INIT_CHOOSE_TRANSPORT
:
chunk
=
cmd
->
obj
.
ptr
;
t
=
sctp_assoc_choose_init_transport
(
asoc
);
asoc
->
init_last_sent_to
=
t
;
chunk
->
transport
=
t
;
t
->
init_sent_count
++
;
break
;
case
SCTP_CMD_INIT_RESTART
:
/* Do the needed accounting and updates
* associated with restarting an initialization
* timer.
* timer. Only multiply the timeout by two if
* all transports have been tried at the current
* timeout.
*/
t
=
asoc
->
init_last_sent_to
;
asoc
->
init_err_counter
++
;
if
(
t
->
init_sent_count
>
(
asoc
->
init_cycle
+
1
))
{
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
*=
2
;
if
(
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
>
asoc
->
max_init_timeo
)
{
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]
=
asoc
->
max_init_timeo
;
}
asoc
->
init_cycle
++
;
SCTP_DEBUG_PRINTK
(
"T1 INIT Timeout adjustment"
" init_err_counter: %d"
" cycle: %d"
" timeout: %d
\n
"
,
asoc
->
init_err_counter
,
asoc
->
init_cycle
,
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_INIT
]);
}
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_RESTART
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
break
;
case
SCTP_CMD_COOKIEECHO_RESTART
:
/* Do the needed accounting and updates
* associated with restarting an initialization
* timer. Only multiply the timeout by two if
* all transports have been tried at the current
* timeout.
*/
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
++
;
asoc
->
timeouts
[
cmd
->
obj
.
to
]
*=
2
;
if
(
asoc
->
timeouts
[
cmd
->
obj
.
to
]
>
asoc
->
init_err_counter
++
;
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
*=
2
;
if
(
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
>
asoc
->
max_init_timeo
)
{
asoc
->
timeouts
[
cmd
->
obj
.
to
]
=
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]
=
asoc
->
max_init_timeo
;
}
SCTP_DEBUG_PRINTK
(
"T1 COOKIE Timeout adjustment"
" init_err_counter: %d"
" timeout: %d
\n
"
,
asoc
->
init_err_counter
,
asoc
->
timeouts
[
SCTP_EVENT_TIMEOUT_T1_COOKIE
]);
/* If we've sent any data bundled with
* COOKIE-ECHO we need to resend.
...
...
@@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_RESTART
,
SCTP_TO
(
cmd
->
obj
.
to
));
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_COOKIE
));
break
;
case
SCTP_CMD_INIT_FAILED
:
...
...
@@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
subtype
,
chunk
,
cmd
->
obj
.
u32
);
break
;
case
SCTP_CMD_COUNTER_INC
:
asoc
->
counters
[
cmd
->
obj
.
counter
]
++
;
case
SCTP_CMD_
INIT_
COUNTER_INC
:
asoc
->
init_err_counter
++
;
break
;
case
SCTP_CMD_COUNTER_RESET
:
asoc
->
counters
[
cmd
->
obj
.
counter
]
=
0
;
case
SCTP_CMD_INIT_COUNTER_RESET
:
asoc
->
init_err_counter
=
0
;
asoc
->
init_cycle
=
0
;
break
;
case
SCTP_CMD_REPORT_DUP
:
...
...
net/sctp/sm_statefuns.c
浏览文件 @
fb395884
...
...
@@ -533,6 +533,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_PEER_INIT
,
SCTP_PEER_INIT
(
initchunk
));
/* Reset init error count upon receipt of INIT-ACK. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_COUNTER_RESET
,
SCTP_NULL
());
/* 5.1 C) "A" shall stop the T1-init timer and leave
* COOKIE-WAIT state. "A" shall then ... start the T1-cookie
* timer, and enter the COOKIE-ECHOED state.
...
...
@@ -775,8 +778,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
* from the COOKIE-ECHOED state to the COOKIE-WAIT
* state is performed.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_COUNTER_RESET
,
SCTP_COUNTER
(
SCTP_COUNTER_INIT_ERROR
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_COUNTER_RESET
,
SCTP_NULL
());
/* RFC 2960 5.1 Normal Establishment of an Association
*
...
...
@@ -1019,10 +1021,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
link
=
sctp_assoc_lookup_paddr
(
asoc
,
&
from_addr
);
/* This should never happen, but lets log it if so. */
if
(
!
link
)
{
printk
(
KERN_WARNING
"%s: Could not find address %d.%d.%d.%d
\n
"
,
__FUNCTION__
,
NIPQUAD
(
from_addr
.
v4
.
sin_addr
));
if
(
unlikely
(
!
link
))
{
if
(
from_addr
.
sa
.
sa_family
==
AF_INET6
)
{
printk
(
KERN_WARNING
"%s association %p could not find address "
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x
\n
"
,
__FUNCTION__
,
asoc
,
NIP6
(
from_addr
.
v6
.
sin6_addr
));
}
else
{
printk
(
KERN_WARNING
"%s association %p could not find address "
"%u.%u.%u.%u
\n
"
,
__FUNCTION__
,
asoc
,
NIPQUAD
(
from_addr
.
v4
.
sin_addr
.
s_addr
));
}
return
SCTP_DISPOSITION_DISCARD
;
}
...
...
@@ -2095,9 +2109,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
sctp_errhdr_t
*
err
;
struct
sctp_chunk
*
reply
;
struct
sctp_bind_addr
*
bp
;
int
attempts
;
attempts
=
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
+
1
;
int
attempts
=
asoc
->
init_err_counter
+
1
;
if
(
attempts
>=
asoc
->
max_init_attempts
)
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
...
...
@@ -2157,8 +2169,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
/* Cast away the const modifier, as we want to just
* rerun it through as a sideffect.
*/
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_COUNTER_INC
,
SCTP_COUNTER
(
SCTP_COUNTER_INIT_ERROR
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_COUNTER_INC
,
SCTP_NULL
());
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_TIMER_STOP
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_COOKIE
));
...
...
@@ -2281,8 +2292,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
if
(
len
>=
sizeof
(
struct
sctp_chunkhdr
)
+
sizeof
(
struct
sctp_errhdr
))
error
=
((
sctp_errhdr_t
*
)
chunk
->
skb
->
data
)
->
cause
;
sctp_stop_t1_and_abort
(
commands
,
error
);
return
SCTP_DISPOSITION_ABORT
;
return
sctp_stop_t1_and_abort
(
commands
,
error
,
asoc
,
chunk
->
transport
);
}
/*
...
...
@@ -2294,8 +2304,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
sctp_stop_t1_and_abort
(
commands
,
SCTP_ERROR_NO_ERROR
);
return
SCTP_DISPOSITION_ABORT
;
return
sctp_stop_t1_and_abort
(
commands
,
SCTP_ERROR_NO_ERROR
,
asoc
,
(
struct
sctp_transport
*
)
arg
)
;
}
/*
...
...
@@ -2318,8 +2328,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
*
* This is common code called by several sctp_sf_*_abort() functions above.
*/
void
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
)
sctp_disposition_t
sctp_stop_t1_and_abort
(
sctp_cmd_seq_t
*
commands
,
__u16
error
,
const
struct
sctp_association
*
asoc
,
struct
sctp_transport
*
transport
)
{
SCTP_DEBUG_PRINTK
(
"ABORT received (INIT).
\n
"
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_NEW_STATE
,
SCTP_STATE
(
SCTP_STATE_CLOSED
));
SCTP_INC_STATS
(
SCTP_MIB_ABORTEDS
);
...
...
@@ -2328,6 +2342,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
error
));
return
SCTP_DISPOSITION_ABORT
;
}
/*
...
...
@@ -3805,6 +3820,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_NEW_ASOC
,
SCTP_ASOC
((
struct
sctp_association
*
)
asoc
));
/* Choose transport for INIT. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_CHOOSE_TRANSPORT
,
SCTP_CHUNK
(
repl
));
/* After sending the INIT, "A" starts the T1-init timer and
* enters the COOKIE-WAIT state.
*/
...
...
@@ -4589,7 +4608,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
}
/*
* sctp_sf_t1_timer_expire
* sctp_sf_t1_
init_
timer_expire
*
* Section: 4 Note: 2
* Verification Tag:
...
...
@@ -4603,7 +4622,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
* endpoint MUST abort the initialization process and report the
* error to SCTP user.
*
* 3) If the T1-cookie timer expires, the endpoint MUST retransmit
* Outputs
* (timers, events)
*
*/
sctp_disposition_t
sctp_sf_t1_init_timer_expire
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_chunk
*
repl
=
NULL
;
struct
sctp_bind_addr
*
bp
;
int
attempts
=
asoc
->
init_err_counter
+
1
;
SCTP_DEBUG_PRINTK
(
"Timer T1 expired (INIT).
\n
"
);
if
(
attempts
<
asoc
->
max_init_attempts
)
{
bp
=
(
struct
sctp_bind_addr
*
)
&
asoc
->
base
.
bind_addr
;
repl
=
sctp_make_init
(
asoc
,
bp
,
GFP_ATOMIC
,
0
);
if
(
!
repl
)
return
SCTP_DISPOSITION_NOMEM
;
/* Choose transport for INIT. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_CHOOSE_TRANSPORT
,
SCTP_CHUNK
(
repl
));
/* Issue a sideeffect to do the needed accounting. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_RESTART
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_INIT
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
repl
));
}
else
{
SCTP_DEBUG_PRINTK
(
"Giving up on INIT, attempts: %d"
" max_init_attempts: %d
\n
"
,
attempts
,
asoc
->
max_init_attempts
);
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
SCTP_U32
(
SCTP_ERROR_NO_ERROR
));
return
SCTP_DISPOSITION_DELETE_TCB
;
}
return
SCTP_DISPOSITION_CONSUME
;
}
/*
* sctp_sf_t1_cookie_timer_expire
*
* Section: 4 Note: 2
* Verification Tag:
* Inputs
* (endpoint, asoc)
*
* RFC 2960 Section 4 Notes
* 3) If the T1-cookie timer expires, the endpoint MUST retransmit
* COOKIE ECHO and re-start the T1-cookie timer without changing
* state. This MUST be repeated up to 'Max.Init.Retransmits' times.
* After that, the endpoint MUST abort the initialization process and
...
...
@@ -4613,46 +4684,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
* (timers, events)
*
*/
sctp_disposition_t
sctp_sf_t1_timer_expire
(
const
struct
sctp_endpoint
*
ep
,
sctp_disposition_t
sctp_sf_t1_
cookie_
timer_expire
(
const
struct
sctp_endpoint
*
ep
,
const
struct
sctp_association
*
asoc
,
const
sctp_subtype_t
type
,
void
*
arg
,
sctp_cmd_seq_t
*
commands
)
{
struct
sctp_chunk
*
repl
;
struct
sctp_bind_addr
*
bp
;
sctp_event_timeout_t
timer
=
(
sctp_event_timeout_t
)
arg
;
int
timeout
;
int
attempts
;
timeout
=
asoc
->
timeouts
[
timer
];
attempts
=
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
+
1
;
repl
=
NULL
;
struct
sctp_chunk
*
repl
=
NULL
;
int
attempts
=
asoc
->
init_err_counter
+
1
;
SCTP_DEBUG_PRINTK
(
"Timer T1 expired.
\n
"
);
SCTP_DEBUG_PRINTK
(
"Timer T1 expired
(COOKIE-ECHO)
.
\n
"
);
if
(
attempts
<
asoc
->
max_init_attempts
)
{
switch
(
timer
)
{
case
SCTP_EVENT_TIMEOUT_T1_INIT
:
bp
=
(
struct
sctp_bind_addr
*
)
&
asoc
->
base
.
bind_addr
;
repl
=
sctp_make_init
(
asoc
,
bp
,
GFP_ATOMIC
,
0
);
break
;
case
SCTP_EVENT_TIMEOUT_T1_COOKIE
:
repl
=
sctp_make_cookie_echo
(
asoc
,
NULL
);
break
;
default:
BUG
();
break
;
};
repl
=
sctp_make_cookie_echo
(
asoc
,
NULL
);
if
(
!
repl
)
goto
nomem
;
return
SCTP_DISPOSITION_NOMEM
;
/* Issue a sideeffect to do the needed accounting. */
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_RESTART
,
SCTP_TO
(
timer
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_COOKIEECHO_RESTART
,
SCTP_TO
(
SCTP_EVENT_TIMEOUT_T1_COOKIE
));
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_REPLY
,
SCTP_CHUNK
(
repl
));
}
else
{
sctp_add_cmd_sf
(
commands
,
SCTP_CMD_INIT_FAILED
,
...
...
@@ -4661,9 +4712,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
}
return
SCTP_DISPOSITION_CONSUME
;
nomem:
return
SCTP_DISPOSITION_NOMEM
;
}
/* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN
...
...
net/sctp/sm_statetable.c
浏览文件 @
fb395884
...
...
@@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
/* SCTP_STATE_COOKIE_WAIT */
\
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */
\
{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
{.fn = sctp_sf_t1_cookie_timer_expire, \
.name = "sctp_sf_t1_cookie_timer_expire"}, \
/* SCTP_STATE_ESTABLISHED */
\
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */
\
...
...
@@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
/* SCTP_STATE_CLOSED */
\
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */
\
{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
{.fn = sctp_sf_t1_init_timer_expire, \
.name = "sctp_sf_t1_init_timer_expire"}, \
/* SCTP_STATE_COOKIE_ECHOED */
\
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */
\
...
...
net/sctp/socket.c
浏览文件 @
fb395884
...
...
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
* sockaddr_in6 [RFC 2553]),
* addr_len - the size of the address structure.
*/
SCTP_STATIC
int
sctp_bind
(
struct
sock
*
sk
,
struct
sockaddr
*
u
addr
,
int
addr_len
)
SCTP_STATIC
int
sctp_bind
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
int
addr_len
)
{
int
retval
=
0
;
sctp_lock_sock
(
sk
);
SCTP_DEBUG_PRINTK
(
"sctp_bind(sk: %p,
u
addr: %p, addr_len: %d)
\n
"
,
sk
,
u
addr
,
addr_len
);
SCTP_DEBUG_PRINTK
(
"sctp_bind(sk: %p, addr: %p, addr_len: %d)
\n
"
,
sk
,
addr
,
addr_len
);
/* Disallow binding twice. */
if
(
!
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
.
port
)
retval
=
sctp_do_bind
(
sk
,
(
union
sctp_addr
*
)
u
addr
,
retval
=
sctp_do_bind
(
sk
,
(
union
sctp_addr
*
)
addr
,
addr_len
);
else
retval
=
-
EINVAL
;
...
...
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
unsigned
short
snum
;
int
ret
=
0
;
SCTP_DEBUG_PRINTK
(
"sctp_do_bind(sk: %p, newaddr: %p, len: %d)
\n
"
,
sk
,
addr
,
len
);
/* Common sockaddr verification. */
af
=
sctp_sockaddr_af
(
sp
,
addr
,
len
);
if
(
!
af
)
if
(
!
af
)
{
SCTP_DEBUG_PRINTK
(
"sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL
\n
"
,
sk
,
addr
,
len
);
return
-
EINVAL
;
}
snum
=
ntohs
(
addr
->
v4
.
sin_port
);
SCTP_DEBUG_PRINTK_IPADDR
(
"sctp_do_bind(sk: %p, new addr: "
,
", port: %d, new port: %d, len: %d)
\n
"
,
sk
,
addr
,
bp
->
port
,
snum
,
len
);
/* PF specific bind() address verification. */
if
(
!
sp
->
pf
->
bind_verify
(
sp
,
addr
))
return
-
EADDRNOTAVAIL
;
snum
=
ntohs
(
addr
->
v4
.
sin_port
);
SCTP_DEBUG_PRINTK
(
"sctp_do_bind: port: %d, new port: %d
\n
"
,
bp
->
port
,
snum
);
/* We must either be unbound, or bind to the same port. */
if
(
bp
->
port
&&
(
snum
!=
bp
->
port
))
{
SCTP_DEBUG_PRINTK
(
"sctp_do_bind:"
...
...
@@ -816,7 +820,8 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
*
* Basically do nothing but copying the addresses from user to kernel
* land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
* This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
* This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
* from userspace.
*
* We don't use copy_from_user() for optimization: we first do the
* sanity checks (buffer size -fast- and access check-healthy
...
...
@@ -913,6 +918,243 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
return
err
;
}
/* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
*
* Common routine for handling connect() and sctp_connectx().
* Connect will come in with just a single address.
*/
static
int
__sctp_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
kaddrs
,
int
addrs_size
)
{
struct
sctp_sock
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sctp_association
*
asoc
=
NULL
;
struct
sctp_association
*
asoc2
;
struct
sctp_transport
*
transport
;
union
sctp_addr
to
;
struct
sctp_af
*
af
;
sctp_scope_t
scope
;
long
timeo
;
int
err
=
0
;
int
addrcnt
=
0
;
int
walk_size
=
0
;
struct
sockaddr
*
sa_addr
;
void
*
addr_buf
;
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
/* connect() cannot be done on a socket that is already in ESTABLISHED
* state - UDP-style peeled off socket or a TCP-style socket that
* is already connected.
* It cannot be done even on a TCP-style listening socket.
*/
if
(
sctp_sstate
(
sk
,
ESTABLISHED
)
||
(
sctp_style
(
sk
,
TCP
)
&&
sctp_sstate
(
sk
,
LISTENING
)))
{
err
=
-
EISCONN
;
goto
out_free
;
}
/* Walk through the addrs buffer and count the number of addresses. */
addr_buf
=
kaddrs
;
while
(
walk_size
<
addrs_size
)
{
sa_addr
=
(
struct
sockaddr
*
)
addr_buf
;
af
=
sctp_get_af_specific
(
sa_addr
->
sa_family
);
/* If the address family is not supported or if this address
* causes the address buffer to overflow return EINVAL.
*/
if
(
!
af
||
(
walk_size
+
af
->
sockaddr_len
)
>
addrs_size
)
{
err
=
-
EINVAL
;
goto
out_free
;
}
err
=
sctp_verify_addr
(
sk
,
(
union
sctp_addr
*
)
sa_addr
,
af
->
sockaddr_len
);
if
(
err
)
goto
out_free
;
memcpy
(
&
to
,
sa_addr
,
af
->
sockaddr_len
);
to
.
v4
.
sin_port
=
ntohs
(
to
.
v4
.
sin_port
);
/* Check if there already is a matching association on the
* endpoint (other than the one created here).
*/
asoc2
=
sctp_endpoint_lookup_assoc
(
ep
,
&
to
,
&
transport
);
if
(
asoc2
&&
asoc2
!=
asoc
)
{
if
(
asoc2
->
state
>=
SCTP_STATE_ESTABLISHED
)
err
=
-
EISCONN
;
else
err
=
-
EALREADY
;
goto
out_free
;
}
/* If we could not find a matching association on the endpoint,
* make sure that there is no peeled-off association matching
* the peer address even on another socket.
*/
if
(
sctp_endpoint_is_peeled_off
(
ep
,
&
to
))
{
err
=
-
EADDRNOTAVAIL
;
goto
out_free
;
}
if
(
!
asoc
)
{
/* If a bind() or sctp_bindx() is not called prior to
* an sctp_connectx() call, the system picks an
* ephemeral port and will choose an address set
* equivalent to binding with a wildcard address.
*/
if
(
!
ep
->
base
.
bind_addr
.
port
)
{
if
(
sctp_autobind
(
sk
))
{
err
=
-
EAGAIN
;
goto
out_free
;
}
}
scope
=
sctp_scope
(
&
to
);
asoc
=
sctp_association_new
(
ep
,
sk
,
scope
,
GFP_KERNEL
);
if
(
!
asoc
)
{
err
=
-
ENOMEM
;
goto
out_free
;
}
}
/* Prime the peer's transport structures. */
transport
=
sctp_assoc_add_peer
(
asoc
,
&
to
,
GFP_KERNEL
,
SCTP_UNKNOWN
);
if
(
!
transport
)
{
err
=
-
ENOMEM
;
goto
out_free
;
}
addrcnt
++
;
addr_buf
+=
af
->
sockaddr_len
;
walk_size
+=
af
->
sockaddr_len
;
}
err
=
sctp_assoc_set_bind_addr_from_ep
(
asoc
,
GFP_KERNEL
);
if
(
err
<
0
)
{
goto
out_free
;
}
err
=
sctp_primitive_ASSOCIATE
(
asoc
,
NULL
);
if
(
err
<
0
)
{
goto
out_free
;
}
/* Initialize sk's dport and daddr for getpeername() */
inet_sk
(
sk
)
->
dport
=
htons
(
asoc
->
peer
.
port
);
af
=
sctp_get_af_specific
(
to
.
sa
.
sa_family
);
af
->
to_sk_daddr
(
&
to
,
sk
);
timeo
=
sock_sndtimeo
(
sk
,
sk
->
sk_socket
->
file
->
f_flags
&
O_NONBLOCK
);
err
=
sctp_wait_for_connect
(
asoc
,
&
timeo
);
/* Don't free association on exit. */
asoc
=
NULL
;
out_free:
SCTP_DEBUG_PRINTK
(
"About to exit __sctp_connect() free asoc: %p"
" kaddrs: %p err: %d
\n
"
,
asoc
,
kaddrs
,
err
);
if
(
asoc
)
sctp_association_free
(
asoc
);
return
err
;
}
/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
*
* API 8.9
* int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
*
* If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
* If the sd is an IPv6 socket, the addresses passed can either be IPv4
* or IPv6 addresses.
*
* A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
* Section 3.1.2 for this usage.
*
* addrs is a pointer to an array of one or more socket addresses. Each
* address is contained in its appropriate structure (i.e. struct
* sockaddr_in or struct sockaddr_in6) the family of the address type
* must be used to distengish the address length (note that this
* representation is termed a "packed array" of addresses). The caller
* specifies the number of addresses in the array with addrcnt.
*
* On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
* -1, and sets errno to the appropriate error code.
*
* For SCTP, the port given in each socket address must be the same, or
* sctp_connectx() will fail, setting errno to EINVAL.
*
* An application can use sctp_connectx to initiate an association with
* an endpoint that is multi-homed. Much like sctp_bindx() this call
* allows a caller to specify multiple addresses at which a peer can be
* reached. The way the SCTP stack uses the list of addresses to set up
* the association is implementation dependant. This function only
* specifies that the stack will try to make use of all the addresses in
* the list when needed.
*
* Note that the list of addresses passed in is only used for setting up
* the association. It does not necessarily equal the set of addresses
* the peer uses for the resulting association. If the caller wants to
* find out the set of peer addresses, it must use sctp_getpaddrs() to
* retrieve them after the association has been set up.
*
* Basically do nothing but copying the addresses from user to kernel
* land and invoking either sctp_connectx(). This is used for tunneling
* the sctp_connectx() request through sctp_setsockopt() from userspace.
*
* We don't use copy_from_user() for optimization: we first do the
* sanity checks (buffer size -fast- and access check-healthy
* pointer); if all of those succeed, then we can alloc the memory
* (expensive operation) needed to copy the data to kernel. Then we do
* the copying without checking the user space area
* (__copy_from_user()).
*
* On exit there is no need to do sockfd_put(), sys_setsockopt() does
* it.
*
* sk The sk of the socket
* addrs The pointer to the addresses in user land
* addrssize Size of the addrs buffer
*
* Returns 0 if ok, <0 errno code on error.
*/
SCTP_STATIC
int
sctp_setsockopt_connectx
(
struct
sock
*
sk
,
struct
sockaddr
__user
*
addrs
,
int
addrs_size
)
{
int
err
=
0
;
struct
sockaddr
*
kaddrs
;
SCTP_DEBUG_PRINTK
(
"%s - sk %p addrs %p addrs_size %d
\n
"
,
__FUNCTION__
,
sk
,
addrs
,
addrs_size
);
if
(
unlikely
(
addrs_size
<=
0
))
return
-
EINVAL
;
/* Check the user passed a healthy pointer. */
if
(
unlikely
(
!
access_ok
(
VERIFY_READ
,
addrs
,
addrs_size
)))
return
-
EFAULT
;
/* Alloc space for the address array in kernel memory. */
kaddrs
=
(
struct
sockaddr
*
)
kmalloc
(
addrs_size
,
GFP_KERNEL
);
if
(
unlikely
(
!
kaddrs
))
return
-
ENOMEM
;
if
(
__copy_from_user
(
kaddrs
,
addrs
,
addrs_size
))
{
err
=
-
EFAULT
;
}
else
{
err
=
__sctp_connect
(
sk
,
kaddrs
,
addrs_size
);
}
kfree
(
kaddrs
);
return
err
;
}
/* API 3.1.4 close() - UDP Style Syntax
* Applications use close() to perform graceful shutdown (as described in
* Section 10.1 of [SCTP]) on ALL the associations currently represented
...
...
@@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
SCTP_DEBUG_PRINTK
(
"Using endpoint: %
s.
\n
"
,
ep
->
debug_name
);
SCTP_DEBUG_PRINTK
(
"Using endpoint: %
p.
\n
"
,
ep
);
/* We cannot send a message over a TCP-style listening socket. */
if
(
sctp_style
(
sk
,
TCP
)
&&
sctp_sstate
(
sk
,
LISTENING
))
{
...
...
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
/* Prime the peer's transport structures. */
transport
=
sctp_assoc_add_peer
(
asoc
,
&
to
,
GFP_KERNEL
);
transport
=
sctp_assoc_add_peer
(
asoc
,
&
to
,
GFP_KERNEL
,
SCTP_UNKNOWN
);
if
(
!
transport
)
{
err
=
-
ENOMEM
;
goto
out_free
;
...
...
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
optlen
,
SCTP_BINDX_REM_ADDR
);
break
;
case
SCTP_SOCKOPT_CONNECTX
:
/* 'optlen' is the size of the addresses buffer. */
retval
=
sctp_setsockopt_connectx
(
sk
,
(
struct
sockaddr
__user
*
)
optval
,
optlen
);
break
;
case
SCTP_DISABLE_FRAGMENTS
:
retval
=
sctp_setsockopt_disable_fragments
(
sk
,
optval
,
optlen
);
break
;
...
...
@@ -2283,112 +2531,29 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
*
* len: the size of the address.
*/
SCTP_STATIC
int
sctp_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
u
addr
,
SCTP_STATIC
int
sctp_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
int
addr_len
)
{
struct
sctp_sock
*
sp
;
struct
sctp_endpoint
*
ep
;
struct
sctp_association
*
asoc
;
struct
sctp_transport
*
transport
;
union
sctp_addr
to
;
struct
sctp_af
*
af
;
sctp_scope_t
scope
;
long
timeo
;
int
err
=
0
;
struct
sctp_af
*
af
;
sctp_lock_sock
(
sk
);
SCTP_DEBUG_PRINTK
(
"%s - sk: %p, sockaddr: %p, addr_len: %d)
\n
"
,
__FUNCTION__
,
sk
,
uaddr
,
addr_len
);
sp
=
sctp_sk
(
sk
);
ep
=
sp
->
ep
;
/* connect() cannot be done on a socket that is already in ESTABLISHED
* state - UDP-style peeled off socket or a TCP-style socket that
* is already connected.
* It cannot be done even on a TCP-style listening socket.
*/
if
(
sctp_sstate
(
sk
,
ESTABLISHED
)
||
(
sctp_style
(
sk
,
TCP
)
&&
sctp_sstate
(
sk
,
LISTENING
)))
{
err
=
-
EISCONN
;
goto
out_unlock
;
}
err
=
sctp_verify_addr
(
sk
,
(
union
sctp_addr
*
)
uaddr
,
addr_len
);
if
(
err
)
goto
out_unlock
;
if
(
addr_len
>
sizeof
(
to
))
addr_len
=
sizeof
(
to
);
memcpy
(
&
to
,
uaddr
,
addr_len
);
to
.
v4
.
sin_port
=
ntohs
(
to
.
v4
.
sin_port
);
asoc
=
sctp_endpoint_lookup_assoc
(
ep
,
&
to
,
&
transport
);
if
(
asoc
)
{
if
(
asoc
->
state
>=
SCTP_STATE_ESTABLISHED
)
err
=
-
EISCONN
;
else
err
=
-
EALREADY
;
goto
out_unlock
;
}
/* If we could not find a matching association on the endpoint,
* make sure that there is no peeled-off association matching the
* peer address even on another socket.
*/
if
(
sctp_endpoint_is_peeled_off
(
ep
,
&
to
))
{
err
=
-
EADDRNOTAVAIL
;
goto
out_unlock
;
}
/* If a bind() or sctp_bindx() is not called prior to a connect()
* call, the system picks an ephemeral port and will choose an address
* set equivalent to binding with a wildcard address.
*/
if
(
!
ep
->
base
.
bind_addr
.
port
)
{
if
(
sctp_autobind
(
sk
))
{
err
=
-
EAGAIN
;
goto
out_unlock
;
}
}
scope
=
sctp_scope
(
&
to
);
asoc
=
sctp_association_new
(
ep
,
sk
,
scope
,
GFP_KERNEL
);
if
(
!
asoc
)
{
err
=
-
ENOMEM
;
goto
out_unlock
;
}
SCTP_DEBUG_PRINTK
(
"%s - sk: %p, sockaddr: %p, addr_len: %d
\n
"
,
__FUNCTION__
,
sk
,
addr
,
addr_len
);
/* Prime the peer's transport structures. */
transport
=
sctp_assoc_add_peer
(
asoc
,
&
to
,
GFP_KERNEL
);
if
(
!
transport
)
{
sctp_association_free
(
asoc
);
goto
out_unlock
;
}
err
=
sctp_assoc_set_bind_addr_from_ep
(
asoc
,
GFP_KERNEL
);
if
(
err
<
0
)
{
sctp_association_free
(
asoc
);
goto
out_unlock
;
}
err
=
sctp_primitive_ASSOCIATE
(
asoc
,
NULL
);
if
(
err
<
0
)
{
sctp_association_free
(
asoc
);
goto
out_unlock
;
/* Validate addr_len before calling common connect/connectx routine. */
af
=
sctp_get_af_specific
(
addr
->
sa_family
);
if
(
!
af
||
addr_len
<
af
->
sockaddr_len
)
{
err
=
-
EINVAL
;
}
else
{
/* Pass correct addr len to common routine (so it knows there
* is only one address being passed.
*/
err
=
__sctp_connect
(
sk
,
addr
,
af
->
sockaddr_len
);
}
/* Initialize sk's dport and daddr for getpeername() */
inet_sk
(
sk
)
->
dport
=
htons
(
asoc
->
peer
.
port
);
af
=
sctp_get_af_specific
(
to
.
sa
.
sa_family
);
af
->
to_sk_daddr
(
&
to
,
sk
);
timeo
=
sock_sndtimeo
(
sk
,
sk
->
sk_socket
->
file
->
f_flags
&
O_NONBLOCK
);
err
=
sctp_wait_for_connect
(
asoc
,
&
timeo
);
out_unlock:
sctp_release_sock
(
sk
);
return
err
;
}
...
...
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
sk
),
(
union
sctp_addr
*
)
&
status
.
sstat_primary
.
spinfo_address
);
status
.
sstat_primary
.
spinfo_state
=
transport
->
activ
e
;
status
.
sstat_primary
.
spinfo_state
=
transport
->
stat
e
;
status
.
sstat_primary
.
spinfo_cwnd
=
transport
->
cwnd
;
status
.
sstat_primary
.
spinfo_srtt
=
transport
->
srtt
;
status
.
sstat_primary
.
spinfo_rto
=
jiffies_to_msecs
(
transport
->
rto
);
status
.
sstat_primary
.
spinfo_mtu
=
transport
->
pmtu
;
if
(
status
.
sstat_primary
.
spinfo_state
==
SCTP_UNKNOWN
)
status
.
sstat_primary
.
spinfo_state
=
SCTP_ACTIVE
;
if
(
put_user
(
len
,
optlen
))
{
retval
=
-
EFAULT
;
goto
out
;
...
...
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
return
-
EINVAL
;
pinfo
.
spinfo_assoc_id
=
sctp_assoc2id
(
transport
->
asoc
);
pinfo
.
spinfo_state
=
transport
->
activ
e
;
pinfo
.
spinfo_state
=
transport
->
stat
e
;
pinfo
.
spinfo_cwnd
=
transport
->
cwnd
;
pinfo
.
spinfo_srtt
=
transport
->
srtt
;
pinfo
.
spinfo_rto
=
jiffies_to_msecs
(
transport
->
rto
);
pinfo
.
spinfo_mtu
=
transport
->
pmtu
;
if
(
pinfo
.
spinfo_state
==
SCTP_UNKNOWN
)
pinfo
.
spinfo_state
=
SCTP_ACTIVE
;
if
(
put_user
(
len
,
optlen
))
{
retval
=
-
EFAULT
;
goto
out
;
...
...
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
int
retval
=
0
;
int
len
;
SCTP_DEBUG_PRINTK
(
"sctp_getsockopt(sk: %p, ...)
\n
"
,
sk
);
SCTP_DEBUG_PRINTK
(
"sctp_getsockopt(sk: %p... optname: %d)
\n
"
,
sk
,
optname
);
/* I can hardly begin to describe how wrong this is. This is
* so broken as to be worse than useless. The API draft
...
...
@@ -4596,8 +4768,7 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
return
err
;
do_error:
if
(
asoc
->
counters
[
SCTP_COUNTER_INIT_ERROR
]
+
1
>=
asoc
->
max_init_attempts
)
if
(
asoc
->
init_err_counter
+
1
>=
asoc
->
max_init_attempts
)
err
=
-
ETIMEDOUT
;
else
err
=
-
ECONNREFUSED
;
...
...
net/sctp/transport.c
浏览文件 @
fb395884
...
...
@@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer
->
last_time_used
=
jiffies
;
peer
->
last_time_ecne_reduced
=
jiffies
;
peer
->
active
=
SCTP_ACTIVE
;
peer
->
init_sent_count
=
0
;
peer
->
state
=
SCTP_ACTIVE
;
peer
->
hb_allowed
=
0
;
/* Initialize the default path max_retrans. */
...
...
net/xfrm/xfrm_policy.c
浏览文件 @
fb395884
...
...
@@ -118,7 +118,6 @@ struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
xfrm_policy_put_afinfo
(
afinfo
);
return
type
;
}
EXPORT_SYMBOL
(
xfrm_get_type
);
int
xfrm_dst_lookup
(
struct
xfrm_dst
**
dst
,
struct
flowi
*
fl
,
unsigned
short
family
)
...
...
net/xfrm/xfrm_state.c
浏览文件 @
fb395884
...
...
@@ -1055,6 +1055,43 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
}
EXPORT_SYMBOL
(
xfrm_state_mtu
);
int
xfrm_init_state
(
struct
xfrm_state
*
x
)
{
struct
xfrm_state_afinfo
*
afinfo
;
int
family
=
x
->
props
.
family
;
int
err
;
err
=
-
EAFNOSUPPORT
;
afinfo
=
xfrm_state_get_afinfo
(
family
);
if
(
!
afinfo
)
goto
error
;
err
=
0
;
if
(
afinfo
->
init_flags
)
err
=
afinfo
->
init_flags
(
x
);
xfrm_state_put_afinfo
(
afinfo
);
if
(
err
)
goto
error
;
err
=
-
EPROTONOSUPPORT
;
x
->
type
=
xfrm_get_type
(
x
->
id
.
proto
,
family
);
if
(
x
->
type
==
NULL
)
goto
error
;
err
=
x
->
type
->
init_state
(
x
);
if
(
err
)
goto
error
;
x
->
km
.
state
=
XFRM_STATE_VALID
;
error:
return
err
;
}
EXPORT_SYMBOL
(
xfrm_init_state
);
void
__init
xfrm_state_init
(
void
)
{
...
...
net/xfrm/xfrm_user.c
浏览文件 @
fb395884
...
...
@@ -249,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
if
((
err
=
attach_encap_tmpl
(
&
x
->
encap
,
xfrma
[
XFRMA_ENCAP
-
1
])))
goto
error
;
err
=
-
ENOENT
;
x
->
type
=
xfrm_get_type
(
x
->
id
.
proto
,
x
->
props
.
family
);
if
(
x
->
type
==
NULL
)
goto
error
;
err
=
x
->
type
->
init_state
(
x
,
NULL
);
err
=
xfrm_init_state
(
x
);
if
(
err
)
goto
error
;
x
->
curlft
.
add_time
=
(
unsigned
long
)
xtime
.
tv_sec
;
x
->
km
.
state
=
XFRM_STATE_VALID
;
x
->
km
.
seq
=
p
->
seq
;
return
x
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录