Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
dcbd39a1
Commit
dcbd39a1
authored
Oct 08, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
parents
582fd487
4f55cd10
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
319 additions
and
61 deletions
+319
-61
include/linux/atmdev.h
include/linux/atmdev.h
+10
-0
include/net/sctp/user.h
include/net/sctp/user.h
+21
-12
net/atm/addr.c
net/atm/addr.c
+38
-13
net/atm/addr.h
net/atm/addr.h
+7
-5
net/atm/br2684.c
net/atm/br2684.c
+1
-1
net/atm/resources.c
net/atm/resources.c
+15
-5
net/sctp/socket.c
net/sctp/socket.c
+227
-25
No files found.
include/linux/atmdev.h
View file @
dcbd39a1
...
...
@@ -76,6 +76,13 @@ struct atm_dev_stats {
/* set interface ESI */
#define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
/* force interface ESI */
#define ATM_ADDLECSADDR _IOW('a', ATMIOC_ITF+14, struct atmif_sioc)
/* register a LECS address */
#define ATM_DELLECSADDR _IOW('a', ATMIOC_ITF+15, struct atmif_sioc)
/* unregister a LECS address */
#define ATM_GETLECSADDR _IOW('a', ATMIOC_ITF+16, struct atmif_sioc)
/* retrieve LECS address(es) */
#define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc)
/* get AAL layer statistics */
#define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc)
...
...
@@ -328,6 +335,8 @@ struct atm_dev_addr {
struct
list_head
entry
;
/* next address */
};
enum
atm_addr_type_t
{
ATM_ADDR_LOCAL
,
ATM_ADDR_LECS
};
struct
atm_dev
{
const
struct
atmdev_ops
*
ops
;
/* device operations; NULL if unused */
const
struct
atmphy_ops
*
phy
;
/* PHY operations, may be undefined */
...
...
@@ -338,6 +347,7 @@ struct atm_dev {
void
*
phy_data
;
/* private PHY date */
unsigned
long
flags
;
/* device flags (ATM_DF_*) */
struct
list_head
local
;
/* local ATM addresses */
struct
list_head
lecs
;
/* LECS ATM addresses learned via ILMI */
unsigned
char
esi
[
ESI_LEN
];
/* ESI ("MAC" addr) */
struct
atm_cirange
ci_range
;
/* VPI/VCI range */
struct
k_atm_dev_stats
stats
;
/* statistics */
...
...
include/net/sctp/user.h
View file @
dcbd39a1
...
...
@@ -103,16 +103,20 @@ enum sctp_optname {
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
SCTP_SOCKOPT_PEELOFF
,
/* peel off association. */
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
SCTP_GET_PEER_ADDRS_NUM
,
/* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM
SCTP_GET_PEER_ADDRS_NUM_OLD
,
/* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM_OLD SCTP_GET_PEER_ADDRS_NUM_OLD
SCTP_GET_PEER_ADDRS_OLD
,
/* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS_OLD SCTP_GET_PEER_ADDRS_OLD
SCTP_GET_LOCAL_ADDRS_NUM_OLD
,
/* Get number of local addresss. */
#define SCTP_GET_LOCAL_ADDRS_NUM_OLD SCTP_GET_LOCAL_ADDRS_NUM_OLD
SCTP_GET_LOCAL_ADDRS_OLD
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS_OLD SCTP_GET_LOCAL_ADDRS_OLD
SCTP_SOCKOPT_CONNECTX
,
/* CONNECTX requests. */
#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
SCTP_GET_PEER_ADDRS
,
/* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
SCTP_GET_LOCAL_ADDRS_NUM
,
/* Get number of local addresss. */
#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
};
/*
...
...
@@ -239,7 +243,7 @@ struct sctp_paddr_change {
int
spc_state
;
int
spc_error
;
sctp_assoc_t
spc_assoc_id
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
* spc_state: 32 bits (signed integer)
...
...
@@ -464,7 +468,7 @@ struct sctp_assocparams {
struct
sctp_setpeerprim
{
sctp_assoc_t
sspp_assoc_id
;
struct
sockaddr_storage
sspp_addr
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
...
...
@@ -477,7 +481,7 @@ struct sctp_setpeerprim {
struct
sctp_prim
{
sctp_assoc_t
ssp_assoc_id
;
struct
sockaddr_storage
ssp_addr
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
* 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
...
...
@@ -504,7 +508,7 @@ struct sctp_paddrparams {
struct
sockaddr_storage
spp_address
;
__u32
spp_hbinterval
;
__u16
spp_pathmaxrxt
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
* 7.2.2 Peer Address Information
...
...
@@ -523,7 +527,7 @@ struct sctp_paddrinfo {
__u32
spinfo_srtt
;
__u32
spinfo_rto
;
__u32
spinfo_mtu
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/* Peer addresses's state. */
enum
sctp_spinfo_state
{
...
...
@@ -559,11 +563,16 @@ struct sctp_status {
* SCTP_GET_LOCAL_ADDRS socket options used internally to implement
* sctp_getpaddrs() and sctp_getladdrs() API.
*/
struct
sctp_getaddrs
{
struct
sctp_getaddrs
_old
{
sctp_assoc_t
assoc_id
;
int
addr_num
;
struct
sockaddr
__user
*
addrs
;
};
struct
sctp_getaddrs
{
sctp_assoc_t
assoc_id
;
/*input*/
__u32
addr_num
;
/*output*/
__u8
addrs
[
0
];
/*output, variable size*/
};
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */
...
...
net/atm/addr.c
View file @
dcbd39a1
...
...
@@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev)
sigd_enq
(
NULL
,
as_itf_notify
,
NULL
,
&
pvc
,
NULL
);
}
void
atm_reset_addr
(
struct
atm_dev
*
dev
)
void
atm_reset_addr
(
struct
atm_dev
*
dev
,
enum
atm_addr_type_t
atype
)
{
unsigned
long
flags
;
struct
atm_dev_addr
*
this
,
*
p
;
struct
list_head
*
head
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
list_for_each_entry_safe
(
this
,
p
,
&
dev
->
local
,
entry
)
{
if
(
atype
==
ATM_ADDR_LECS
)
head
=
&
dev
->
lecs
;
else
head
=
&
dev
->
local
;
list_for_each_entry_safe
(
this
,
p
,
head
,
entry
)
{
list_del
(
&
this
->
entry
);
kfree
(
this
);
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
notify_sigd
(
dev
);
if
(
head
==
&
dev
->
local
)
notify_sigd
(
dev
);
}
int
atm_add_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
)
int
atm_add_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
,
enum
atm_addr_type_t
atype
)
{
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
error
;
error
=
check_addr
(
addr
);
if
(
error
)
return
error
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
list_for_each_entry
(
this
,
&
dev
->
local
,
entry
)
{
if
(
atype
==
ATM_ADDR_LECS
)
head
=
&
dev
->
lecs
;
else
head
=
&
dev
->
local
;
list_for_each_entry
(
this
,
head
,
entry
)
{
if
(
identical
(
&
this
->
addr
,
addr
))
{
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
return
-
EEXIST
;
...
...
@@ -80,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
return
-
ENOMEM
;
}
this
->
addr
=
*
addr
;
list_add
(
&
this
->
entry
,
&
dev
->
local
);
list_add
(
&
this
->
entry
,
head
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
notify_sigd
(
dev
);
if
(
head
==
&
dev
->
local
)
notify_sigd
(
dev
);
return
0
;
}
int
atm_del_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
)
int
atm_del_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
,
enum
atm_addr_type_t
atype
)
{
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
error
;
error
=
check_addr
(
addr
);
if
(
error
)
return
error
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
list_for_each_entry
(
this
,
&
dev
->
local
,
entry
)
{
if
(
atype
==
ATM_ADDR_LECS
)
head
=
&
dev
->
lecs
;
else
head
=
&
dev
->
local
;
list_for_each_entry
(
this
,
head
,
entry
)
{
if
(
identical
(
&
this
->
addr
,
addr
))
{
list_del
(
&
this
->
entry
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
kfree
(
this
);
notify_sigd
(
dev
);
if
(
head
==
&
dev
->
local
)
notify_sigd
(
dev
);
return
0
;
}
}
...
...
@@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
}
int
atm_get_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
__user
*
buf
,
size_t
size
)
size_t
size
,
enum
atm_addr_type_t
atype
)
{
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
total
=
0
,
error
;
struct
sockaddr_atmsvc
*
tmp_buf
,
*
tmp_bufp
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
list_for_each_entry
(
this
,
&
dev
->
local
,
entry
)
if
(
atype
==
ATM_ADDR_LECS
)
head
=
&
dev
->
lecs
;
else
head
=
&
dev
->
local
;
list_for_each_entry
(
this
,
head
,
entry
)
total
+=
sizeof
(
struct
sockaddr_atmsvc
);
tmp_buf
=
tmp_bufp
=
kmalloc
(
total
,
GFP_ATOMIC
);
if
(
!
tmp_buf
)
{
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
return
-
ENOMEM
;
}
list_for_each_entry
(
this
,
&
dev
->
local
,
entry
)
list_for_each_entry
(
this
,
head
,
entry
)
memcpy
(
tmp_bufp
++
,
&
this
->
addr
,
sizeof
(
struct
sockaddr_atmsvc
));
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
error
=
total
>
size
?
-
E2BIG
:
total
;
...
...
net/atm/addr.h
View file @
dcbd39a1
...
...
@@ -9,10 +9,12 @@
#include <linux/atm.h>
#include <linux/atmdev.h>
void
atm_reset_addr
(
struct
atm_dev
*
dev
);
int
atm_add_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
);
int
atm_del_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
);
int
atm_get_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
__user
*
buf
,
size_t
size
);
void
atm_reset_addr
(
struct
atm_dev
*
dev
,
enum
atm_addr_type_t
type
);
int
atm_add_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
,
enum
atm_addr_type_t
type
);
int
atm_del_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
*
addr
,
enum
atm_addr_type_t
type
);
int
atm_get_addr
(
struct
atm_dev
*
dev
,
struct
sockaddr_atmsvc
__user
*
buf
,
size_t
size
,
enum
atm_addr_type_t
type
);
#endif
net/atm/br2684.c
View file @
dcbd39a1
...
...
@@ -220,7 +220,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* netif_stop_queue(dev); */
dev_kfree_skb
(
skb
);
read_unlock
(
&
devs_lock
);
return
-
EUNATCH
;
return
0
;
}
if
(
!
br2684_xmit_vcc
(
skb
,
brdev
,
brvcc
))
{
/*
...
...
net/atm/resources.c
View file @
dcbd39a1
...
...
@@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
dev
->
link_rate
=
ATM_OC3_PCR
;
spin_lock_init
(
&
dev
->
lock
);
INIT_LIST_HEAD
(
&
dev
->
local
);
INIT_LIST_HEAD
(
&
dev
->
lecs
);
return
dev
;
}
...
...
@@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
error
=
-
EPERM
;
goto
done
;
}
atm_reset_addr
(
dev
);
atm_reset_addr
(
dev
,
ATM_ADDR_LOCAL
);
break
;
case
ATM_ADDADDR
:
case
ATM_DELADDR
:
case
ATM_ADDLECSADDR
:
case
ATM_DELLECSADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
...
...
@@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
error
=
-
EFAULT
;
goto
done
;
}
if
(
cmd
==
ATM_ADDADDR
)
error
=
atm_add_addr
(
dev
,
&
addr
);
if
(
cmd
==
ATM_ADDADDR
||
cmd
==
ATM_ADDLECSADDR
)
error
=
atm_add_addr
(
dev
,
&
addr
,
(
cmd
==
ATM_ADDADDR
?
ATM_ADDR_LOCAL
:
ATM_ADDR_LECS
));
else
error
=
atm_del_addr
(
dev
,
&
addr
);
error
=
atm_del_addr
(
dev
,
&
addr
,
(
cmd
==
ATM_DELADDR
?
ATM_ADDR_LOCAL
:
ATM_ADDR_LECS
));
goto
done
;
}
case
ATM_GETADDR
:
error
=
atm_get_addr
(
dev
,
buf
,
len
);
case
ATM_GETLECSADDR
:
error
=
atm_get_addr
(
dev
,
buf
,
len
,
(
cmd
==
ATM_GETADDR
?
ATM_ADDR_LOCAL
:
ATM_ADDR_LECS
));
if
(
error
<
0
)
goto
done
;
size
=
error
;
...
...
net/sctp/socket.c
View file @
dcbd39a1
...
...
@@ -3159,8 +3159,9 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
return
0
;
}
static
int
sctp_getsockopt_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
sctp_getsockopt_peer_addrs_num_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
sctp_assoc_t
id
;
struct
sctp_association
*
asoc
;
...
...
@@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
return
cnt
;
}
static
int
sctp_getsockopt_peer_addrs
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
/*
* Old API for getting list of peer addresses. Does not work for 32-bit
* programs running on a 64-bit kernel
*/
static
int
sctp_getsockopt_peer_addrs_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_getaddrs
_old
getaddrs
;
struct
sctp_transport
*
from
;
void
__user
*
to
;
union
sctp_addr
temp
;
struct
sctp_sock
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
_old
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
_old
)))
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
...
...
@@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
getaddrs
.
addr_num
=
cnt
;
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
)))
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs_old
)))
return
-
EFAULT
;
return
0
;
}
static
int
sctp_getsockopt_peer_addrs
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_transport
*
from
;
void
__user
*
to
;
union
sctp_addr
temp
;
struct
sctp_sock
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
size_t
space_left
;
int
bytes_copied
;
if
(
len
<
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
/* For UDP-style sockets, id specifies the association to query. */
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
to
=
optval
+
offsetof
(
struct
sctp_getaddrs
,
addrs
);
space_left
=
len
-
sizeof
(
struct
sctp_getaddrs
)
-
offsetof
(
struct
sctp_getaddrs
,
addrs
);
list_for_each
(
pos
,
&
asoc
->
peer
.
transport_addr_list
)
{
from
=
list_entry
(
pos
,
struct
sctp_transport
,
transports
);
memcpy
(
&
temp
,
&
from
->
ipaddr
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
addrlen
=
sctp_get_af_specific
(
sk
->
sk_family
)
->
sockaddr_len
;
if
(
space_left
<
addrlen
)
return
-
ENOMEM
;
temp
.
v4
.
sin_port
=
htons
(
temp
.
v4
.
sin_port
);
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
return
-
EFAULT
;
to
+=
addrlen
;
cnt
++
;
space_left
-=
addrlen
;
}
if
(
put_user
(
cnt
,
&
((
struct
sctp_getaddrs
__user
*
)
optval
)
->
addr_num
))
return
-
EFAULT
;
bytes_copied
=
((
char
__user
*
)
to
)
-
optval
;
if
(
put_user
(
bytes_copied
,
optlen
))
return
-
EFAULT
;
return
0
;
}
static
int
sctp_getsockopt_local_addrs_num
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
sctp_getsockopt_local_addrs_num
_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
sctp_assoc_t
id
;
struct
sctp_bind_addr
*
bp
;
...
...
@@ -3306,8 +3366,8 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
/* Helper function that copies local addresses to user and returns the number
* of addresses copied.
*/
static
int
sctp_copy_laddrs_to_user
(
struct
sock
*
sk
,
__u16
port
,
int
max_addrs
,
void
__user
*
to
)
static
int
sctp_copy_laddrs_to_user
_old
(
struct
sock
*
sk
,
__u16
port
,
int
max_addrs
,
void
__user
*
to
)
{
struct
list_head
*
pos
;
struct
sctp_sockaddr_entry
*
addr
;
...
...
@@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs,
return
cnt
;
}
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
static
int
sctp_copy_laddrs_to_user
(
struct
sock
*
sk
,
__u16
port
,
void
*
__user
*
to
,
size_t
space_left
)
{
struct
list_head
*
pos
;
struct
sctp_sockaddr_entry
*
addr
;
unsigned
long
flags
;
union
sctp_addr
temp
;
int
cnt
=
0
;
int
addrlen
;
sctp_spin_lock_irqsave
(
&
sctp_local_addr_lock
,
flags
);
list_for_each
(
pos
,
&
sctp_local_addr_list
)
{
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
if
((
PF_INET
==
sk
->
sk_family
)
&&
(
AF_INET6
==
addr
->
a
.
sa
.
sa_family
))
continue
;
memcpy
(
&
temp
,
&
addr
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sctp_sk
(
sk
),
&
temp
);
addrlen
=
sctp_get_af_specific
(
temp
.
sa
.
sa_family
)
->
sockaddr_len
;
if
(
space_left
<
addrlen
)
return
-
ENOMEM
;
temp
.
v4
.
sin_port
=
htons
(
port
);
if
(
copy_to_user
(
*
to
,
&
temp
,
addrlen
))
{
sctp_spin_unlock_irqrestore
(
&
sctp_local_addr_lock
,
flags
);
return
-
EFAULT
;
}
*
to
+=
addrlen
;
cnt
++
;
space_left
-=
addrlen
;
}
sctp_spin_unlock_irqrestore
(
&
sctp_local_addr_lock
,
flags
);
return
cnt
;
}
/* Old API for getting list of local addresses. Does not work for 32-bit
* programs running on a 64-bit kernel
*/
static
int
sctp_getsockopt_local_addrs_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sctp_bind_addr
*
bp
;
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_getaddrs
_old
getaddrs
;
struct
sctp_sockaddr_entry
*
addr
;
void
__user
*
to
;
union
sctp_addr
temp
;
...
...
@@ -3357,10 +3457,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
rwlock_t
*
addr_lock
;
int
err
=
0
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
_old
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
_old
)))
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
...
...
@@ -3392,8 +3492,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
addr
=
list_entry
(
bp
->
address_list
.
next
,
struct
sctp_sockaddr_entry
,
list
);
if
(
sctp_is_any
(
&
addr
->
a
))
{
cnt
=
sctp_copy_laddrs_to_user
(
sk
,
bp
->
port
,
getaddrs
.
addr_num
,
to
);
cnt
=
sctp_copy_laddrs_to_user_old
(
sk
,
bp
->
port
,
getaddrs
.
addr_num
,
to
);
if
(
cnt
<
0
)
{
err
=
cnt
;
goto
unlock
;
...
...
@@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
copy_getaddrs:
getaddrs
.
addr_num
=
cnt
;
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
)))
if
(
copy_to_user
(
optval
,
&
getaddrs
,
sizeof
(
struct
sctp_getaddrs
_old
)))
err
=
-
EFAULT
;
unlock:
...
...
@@ -3427,6 +3528,99 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
return
err
;
}
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
{
struct
sctp_bind_addr
*
bp
;
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_sockaddr_entry
*
addr
;
void
__user
*
to
;
union
sctp_addr
temp
;
struct
sctp_sock
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
rwlock_t
*
addr_lock
;
int
err
=
0
;
size_t
space_left
;
int
bytes_copied
;
if
(
len
<=
sizeof
(
struct
sctp_getaddrs
))
return
-
EINVAL
;
if
(
copy_from_user
(
&
getaddrs
,
optval
,
sizeof
(
struct
sctp_getaddrs
)))
return
-
EFAULT
;
/*
* For UDP-style sockets, id specifies the association to query.
* If the id field is set to the value '0' then the locally bound
* addresses are returned without regard to any particular
* association.
*/
if
(
0
==
getaddrs
.
assoc_id
)
{
bp
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
bind_addr
;
addr_lock
=
&
sctp_sk
(
sk
)
->
ep
->
base
.
addr_lock
;
}
else
{
asoc
=
sctp_id2assoc
(
sk
,
getaddrs
.
assoc_id
);
if
(
!
asoc
)
return
-
EINVAL
;
bp
=
&
asoc
->
base
.
bind_addr
;
addr_lock
=
&
asoc
->
base
.
addr_lock
;
}
to
=
optval
+
offsetof
(
struct
sctp_getaddrs
,
addrs
);
space_left
=
len
-
sizeof
(
struct
sctp_getaddrs
)
-
offsetof
(
struct
sctp_getaddrs
,
addrs
);
sctp_read_lock
(
addr_lock
);
/* If the endpoint is bound to 0.0.0.0 or ::0, get the valid
* addresses from the global local address list.
*/
if
(
sctp_list_single_entry
(
&
bp
->
address_list
))
{
addr
=
list_entry
(
bp
->
address_list
.
next
,
struct
sctp_sockaddr_entry
,
list
);
if
(
sctp_is_any
(
&
addr
->
a
))
{
cnt
=
sctp_copy_laddrs_to_user
(
sk
,
bp
->
port
,
&
to
,
space_left
);
if
(
cnt
<
0
)
{
err
=
cnt
;
goto
unlock
;
}
goto
copy_getaddrs
;
}
}
list_for_each
(
pos
,
&
bp
->
address_list
)
{
addr
=
list_entry
(
pos
,
struct
sctp_sockaddr_entry
,
list
);
memcpy
(
&
temp
,
&
addr
->
a
,
sizeof
(
temp
));
sctp_get_pf_specific
(
sk
->
sk_family
)
->
addr_v4map
(
sp
,
&
temp
);
addrlen
=
sctp_get_af_specific
(
temp
.
sa
.
sa_family
)
->
sockaddr_len
;
if
(
space_left
<
addrlen
)
return
-
ENOMEM
;
/*fixme: right error?*/
temp
.
v4
.
sin_port
=
htons
(
temp
.
v4
.
sin_port
);
if
(
copy_to_user
(
to
,
&
temp
,
addrlen
))
{
err
=
-
EFAULT
;
goto
unlock
;
}
to
+=
addrlen
;
cnt
++
;
space_left
-=
addrlen
;
}
copy_getaddrs:
if
(
put_user
(
cnt
,
&
((
struct
sctp_getaddrs
__user
*
)
optval
)
->
addr_num
))
return
-
EFAULT
;
bytes_copied
=
((
char
__user
*
)
to
)
-
optval
;
if
(
put_user
(
bytes_copied
,
optlen
))
return
-
EFAULT
;
unlock:
sctp_read_unlock
(
addr_lock
);
return
err
;
}
/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
*
* Requests that the local SCTP stack use the enclosed peer address as
...
...
@@ -3807,12 +4001,20 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case
SCTP_INITMSG
:
retval
=
sctp_getsockopt_initmsg
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS_NUM
:
retval
=
sctp_getsockopt_peer_addrs_num
(
sk
,
len
,
optval
,
case
SCTP_GET_PEER_ADDRS_NUM_OLD
:
retval
=
sctp_getsockopt_peer_addrs_num_old
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_LOCAL_ADDRS_NUM_OLD
:
retval
=
sctp_getsockopt_local_addrs_num_old
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS_OLD
:
retval
=
sctp_getsockopt_peer_addrs_old
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_LOCAL_ADDRS_
NUM
:
retval
=
sctp_getsockopt_local_addrs_
num
(
sk
,
len
,
optval
,
case
SCTP_GET_LOCAL_ADDRS_
OLD
:
retval
=
sctp_getsockopt_local_addrs_
old
(
sk
,
len
,
optval
,
optlen
);
break
;
case
SCTP_GET_PEER_ADDRS
:
...
...
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