Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
d9a91e70
Commit
d9a91e70
authored
Nov 07, 2002
by
Sridhar Samudrala
Committed by
Jon Grimm
Nov 07, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SCTP] udp-style connect support(non-blocking).
parent
16f3fd6b
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
138 additions
and
30 deletions
+138
-30
include/net/sctp/structs.h
include/net/sctp/structs.h
+1
-0
net/sctp/endpointola.c
net/sctp/endpointola.c
+24
-0
net/sctp/socket.c
net/sctp/socket.c
+113
-30
No files found.
include/net/sctp/structs.h
View file @
d9a91e70
...
...
@@ -1060,6 +1060,7 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *, sctp_association_t *asoc);
sctp_association_t
*
sctp_endpoint_lookup_assoc
(
const
sctp_endpoint_t
*
ep
,
const
union
sctp_addr
*
paddr
,
sctp_transport_t
**
);
int
sctp_endpoint_is_peeled_off
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
sctp_endpoint_t
*
sctp_endpoint_is_match
(
sctp_endpoint_t
*
,
const
union
sctp_addr
*
);
...
...
net/sctp/endpointola.c
View file @
d9a91e70
...
...
@@ -301,6 +301,30 @@ sctp_association_t *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
return
asoc
;
}
/* Look for any peeled off association from the endpoint that matches the
* given peer address.
*/
int
sctp_endpoint_is_peeled_off
(
sctp_endpoint_t
*
ep
,
const
union
sctp_addr
*
paddr
)
{
struct
list_head
*
pos
;
struct
sockaddr_storage_list
*
addr
;
sctp_bind_addr_t
*
bp
;
sctp_read_lock
(
&
ep
->
base
.
addr_lock
);
bp
=
&
ep
->
base
.
bind_addr
;
list_for_each
(
pos
,
&
bp
->
address_list
)
{
addr
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
if
(
sctp_has_association
(
&
addr
->
a
,
paddr
))
{
sctp_read_unlock
(
&
ep
->
base
.
addr_lock
);
return
1
;
}
}
sctp_read_unlock
(
&
ep
->
base
.
addr_lock
);
return
0
;
}
/* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time.
*/
...
...
net/sctp/socket.c
View file @
d9a91e70
...
...
@@ -91,7 +91,7 @@ static inline void sctp_sk_addr_set(struct sock *,
union
sctp_addr
*
saveaddr
);
static
inline
void
sctp_sk_addr_restore
(
struct
sock
*
,
const
union
sctp_addr
*
);
static
inline
int
sctp_
sendmsg_verify_name
(
struct
sock
*
,
struct
msghdr
*
);
static
inline
int
sctp_
verify_addr
(
struct
sock
*
,
struct
sockaddr
*
,
int
);
static
int
sctp_bindx_add
(
struct
sock
*
,
struct
sockaddr_storage
*
,
int
);
static
int
sctp_bindx_rem
(
struct
sock
*
,
struct
sockaddr_storage
*
,
int
);
static
int
sctp_do_bind
(
struct
sock
*
,
union
sctp_addr
*
,
int
);
...
...
@@ -777,7 +777,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
* For a peeled-off socket, msg_name is ignored.
*/
if
((
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
!=
sp
->
type
)
&&
msg
->
msg_name
)
{
err
=
sctp_sendmsg_verify_name
(
sk
,
msg
);
err
=
sctp_verify_addr
(
sk
,
(
struct
sockaddr
*
)
msg
->
msg_name
,
msg
->
msg_namelen
);
if
(
err
)
return
err
;
...
...
@@ -826,29 +827,15 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
/* Look for a matching association on the endpoint. */
asoc
=
sctp_endpoint_lookup_assoc
(
ep
,
&
to
,
&
transport
);
if
(
!
asoc
)
{
struct
list_head
*
pos
;
struct
sockaddr_storage_list
*
addr
;
sctp_bind_addr_t
*
bp
=
&
ep
->
base
.
bind_addr
;
sctp_read_lock
(
&
ep
->
base
.
addr_lock
);
/* If we could not find a matching association on
* the endpoint, make sure that there is no peeled-
* off association.
/* If we could not find a matching association on the
* endpoint, make sure that there is no peeled-off
* association on another socket.
*/
list_for_each
(
pos
,
&
bp
->
address_list
)
{
addr
=
list_entry
(
pos
,
struct
sockaddr_storage_list
,
list
);
if
(
sctp_has_association
(
&
addr
->
a
,
&
to
))
{
err
=
-
EINVAL
;
sctp_read_unlock
(
&
ep
->
base
.
addr_lock
);
if
(
sctp_endpoint_is_peeled_off
(
ep
,
&
to
))
{
err
=
-
EADDRNOTAVAIL
;
goto
out_unlock
;
}
}
sctp_read_unlock
(
&
ep
->
base
.
addr_lock
);
}
}
else
{
/* For a peeled-off socket, ignore any associd specified by
* the user with SNDRCVINFO.
...
...
@@ -1420,11 +1407,107 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
return
retval
;
}
/* FIXME: Write comments. */
/* API 3.1.6 connect() - UDP Style Syntax
*
* An application may use the connect() call in the UDP model to initiate an
* association without sending data.
*
* The syntax is:
*
* ret = connect(int sd, const struct sockaddr *nam, socklen_t len);
*
* sd: the socket descriptor to have a new association added to.
*
* nam: the address structure (either struct sockaddr_in or struct
* sockaddr_in6 defined in RFC2553 [7]).
*
* len: the size of the address.
*/
SCTP_STATIC
int
sctp_connect
(
struct
sock
*
sk
,
struct
sockaddr
*
uaddr
,
int
addr_len
)
{
return
-
EOPNOTSUPP
;
/* STUB */
sctp_opt_t
*
sp
;
sctp_endpoint_t
*
ep
;
sctp_association_t
*
asoc
;
sctp_transport_t
*
transport
;
union
sctp_addr
to
;
sctp_scope_t
scope
;
int
err
=
0
;
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 peeled-off socket. */
if
(
SCTP_SOCKET_UDP_HIGH_BANDWIDTH
==
sp
->
type
)
{
err
=
-
EISCONN
;
goto
out_unlock
;
}
err
=
sctp_verify_addr
(
sk
,
uaddr
,
addr_len
);
if
(
err
)
goto
out_unlock
;
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
;
}
/* Prime the peer's transport structures. */
transport
=
sctp_assoc_add_peer
(
asoc
,
&
to
,
GFP_KERNEL
);
err
=
sctp_primitive_ASSOCIATE
(
asoc
,
NULL
);
if
(
err
<
0
)
sctp_association_free
(
asoc
);
/* FIXME: Currently we support only non-blocking connect().
* To support blocking connect(), we need to wait for the association
* to be ESTABLISHED before returning.
*/
err
=
-
EINPROGRESS
;
out_unlock:
sctp_release_sock
(
sk
);
return
err
;
}
/* FIXME: Write comments. */
...
...
@@ -2608,17 +2691,17 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, int no
return
NULL
;
}
static
inline
int
sctp_
sendmsg_verify_name
(
struct
sock
*
sk
,
struct
msghdr
*
msg
)
static
inline
int
sctp_
verify_addr
(
struct
sock
*
sk
,
struct
sockaddr
*
addr
,
int
addrlen
)
{
union
sctp_addr
*
sa
;
if
(
msg
->
msg_name
len
<
sizeof
(
struct
sockaddr
))
if
(
addr
len
<
sizeof
(
struct
sockaddr
))
return
-
EINVAL
;
sa
=
(
union
sctp_addr
*
)
msg
->
msg_name
;
sa
=
(
union
sctp_addr
*
)
addr
;
switch
(
sa
->
sa
.
sa_family
)
{
case
AF_INET
:
if
(
msg
->
msg_name
len
<
sizeof
(
struct
sockaddr_in
))
if
(
addr
len
<
sizeof
(
struct
sockaddr_in
))
return
-
EINVAL
;
break
;
...
...
@@ -2626,7 +2709,7 @@ static inline int sctp_sendmsg_verify_name(struct sock *sk, struct msghdr *msg)
if
(
PF_INET
==
sk
->
family
)
return
-
EINVAL
;
SCTP_V6
(
if
(
msg
->
msg_name
len
<
sizeof
(
struct
sockaddr_in6
))
if
(
addr
len
<
sizeof
(
struct
sockaddr_in6
))
return
-
EINVAL
;
break
;
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment