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
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 {
...
@@ -76,6 +76,13 @@ struct atm_dev_stats {
/* set interface ESI */
/* set interface ESI */
#define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
#define ATM_SETESIF _IOW('a',ATMIOC_ITF+13,struct atmif_sioc)
/* force interface ESI */
/* 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)
#define ATM_GETSTAT _IOW('a',ATMIOC_SARCOM+0,struct atmif_sioc)
/* get AAL layer statistics */
/* get AAL layer statistics */
#define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc)
#define ATM_GETSTATZ _IOW('a',ATMIOC_SARCOM+1,struct atmif_sioc)
...
@@ -328,6 +335,8 @@ struct atm_dev_addr {
...
@@ -328,6 +335,8 @@ struct atm_dev_addr {
struct
list_head
entry
;
/* next address */
struct
list_head
entry
;
/* next address */
};
};
enum
atm_addr_type_t
{
ATM_ADDR_LOCAL
,
ATM_ADDR_LECS
};
struct
atm_dev
{
struct
atm_dev
{
const
struct
atmdev_ops
*
ops
;
/* device operations; NULL if unused */
const
struct
atmdev_ops
*
ops
;
/* device operations; NULL if unused */
const
struct
atmphy_ops
*
phy
;
/* PHY operations, may be undefined */
const
struct
atmphy_ops
*
phy
;
/* PHY operations, may be undefined */
...
@@ -338,6 +347,7 @@ struct atm_dev {
...
@@ -338,6 +347,7 @@ struct atm_dev {
void
*
phy_data
;
/* private PHY date */
void
*
phy_data
;
/* private PHY date */
unsigned
long
flags
;
/* device flags (ATM_DF_*) */
unsigned
long
flags
;
/* device flags (ATM_DF_*) */
struct
list_head
local
;
/* local ATM addresses */
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) */
unsigned
char
esi
[
ESI_LEN
];
/* ESI ("MAC" addr) */
struct
atm_cirange
ci_range
;
/* VPI/VCI range */
struct
atm_cirange
ci_range
;
/* VPI/VCI range */
struct
k_atm_dev_stats
stats
;
/* statistics */
struct
k_atm_dev_stats
stats
;
/* statistics */
...
...
include/net/sctp/user.h
View file @
dcbd39a1
...
@@ -103,16 +103,20 @@ enum sctp_optname {
...
@@ -103,16 +103,20 @@ enum sctp_optname {
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
#define SCTP_SOCKOPT_BINDX_REM SCTP_SOCKOPT_BINDX_REM
SCTP_SOCKOPT_PEELOFF
,
/* peel off association. */
SCTP_SOCKOPT_PEELOFF
,
/* peel off association. */
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
#define SCTP_SOCKOPT_PEELOFF SCTP_SOCKOPT_PEELOFF
SCTP_GET_PEER_ADDRS_NUM
,
/* Get number of peer addresss. */
SCTP_GET_PEER_ADDRS_NUM_OLD
,
/* Get number of peer addresss. */
#define SCTP_GET_PEER_ADDRS_NUM SCTP_GET_PEER_ADDRS_NUM
#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. */
SCTP_GET_PEER_ADDRS
,
/* Get all peer addresss. */
#define SCTP_GET_PEER_ADDRS SCTP_GET_PEER_ADDRS
#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. */
SCTP_GET_LOCAL_ADDRS
,
/* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
#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 {
...
@@ -239,7 +243,7 @@ struct sctp_paddr_change {
int
spc_state
;
int
spc_state
;
int
spc_error
;
int
spc_error
;
sctp_assoc_t
spc_assoc_id
;
sctp_assoc_t
spc_assoc_id
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
/*
* spc_state: 32 bits (signed integer)
* spc_state: 32 bits (signed integer)
...
@@ -464,7 +468,7 @@ struct sctp_assocparams {
...
@@ -464,7 +468,7 @@ struct sctp_assocparams {
struct
sctp_setpeerprim
{
struct
sctp_setpeerprim
{
sctp_assoc_t
sspp_assoc_id
;
sctp_assoc_t
sspp_assoc_id
;
struct
sockaddr_storage
sspp_addr
;
struct
sockaddr_storage
sspp_addr
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
/*
* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
...
@@ -477,7 +481,7 @@ struct sctp_setpeerprim {
...
@@ -477,7 +481,7 @@ struct sctp_setpeerprim {
struct
sctp_prim
{
struct
sctp_prim
{
sctp_assoc_t
ssp_assoc_id
;
sctp_assoc_t
ssp_assoc_id
;
struct
sockaddr_storage
ssp_addr
;
struct
sockaddr_storage
ssp_addr
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
/*
* 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
* 7.1.11 Set Adaption Layer Indicator (SCTP_ADAPTION_LAYER)
...
@@ -504,7 +508,7 @@ struct sctp_paddrparams {
...
@@ -504,7 +508,7 @@ struct sctp_paddrparams {
struct
sockaddr_storage
spp_address
;
struct
sockaddr_storage
spp_address
;
__u32
spp_hbinterval
;
__u32
spp_hbinterval
;
__u16
spp_pathmaxrxt
;
__u16
spp_pathmaxrxt
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/*
/*
* 7.2.2 Peer Address Information
* 7.2.2 Peer Address Information
...
@@ -523,7 +527,7 @@ struct sctp_paddrinfo {
...
@@ -523,7 +527,7 @@ struct sctp_paddrinfo {
__u32
spinfo_srtt
;
__u32
spinfo_srtt
;
__u32
spinfo_rto
;
__u32
spinfo_rto
;
__u32
spinfo_mtu
;
__u32
spinfo_mtu
;
};
}
__attribute__
((
packed
,
aligned
(
4
)))
;
/* Peer addresses's state. */
/* Peer addresses's state. */
enum
sctp_spinfo_state
{
enum
sctp_spinfo_state
{
...
@@ -559,11 +563,16 @@ struct sctp_status {
...
@@ -559,11 +563,16 @@ struct sctp_status {
* SCTP_GET_LOCAL_ADDRS socket options used internally to implement
* SCTP_GET_LOCAL_ADDRS socket options used internally to implement
* sctp_getpaddrs() and sctp_getladdrs() API.
* sctp_getpaddrs() and sctp_getladdrs() API.
*/
*/
struct
sctp_getaddrs
{
struct
sctp_getaddrs
_old
{
sctp_assoc_t
assoc_id
;
sctp_assoc_t
assoc_id
;
int
addr_num
;
int
addr_num
;
struct
sockaddr
__user
*
addrs
;
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. */
/* 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. */
/* 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)
...
@@ -44,31 +44,43 @@ static void notify_sigd(struct atm_dev *dev)
sigd_enq
(
NULL
,
as_itf_notify
,
NULL
,
&
pvc
,
NULL
);
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
;
unsigned
long
flags
;
struct
atm_dev_addr
*
this
,
*
p
;
struct
atm_dev_addr
*
this
,
*
p
;
struct
list_head
*
head
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
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
);
list_del
(
&
this
->
entry
);
kfree
(
this
);
kfree
(
this
);
}
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
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
;
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
error
;
int
error
;
error
=
check_addr
(
addr
);
error
=
check_addr
(
addr
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
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
))
{
if
(
identical
(
&
this
->
addr
,
addr
))
{
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
return
-
EEXIST
;
return
-
EEXIST
;
...
@@ -80,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
...
@@ -80,28 +92,36 @@ int atm_add_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
this
->
addr
=
*
addr
;
this
->
addr
=
*
addr
;
list_add
(
&
this
->
entry
,
&
dev
->
local
);
list_add
(
&
this
->
entry
,
head
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
notify_sigd
(
dev
);
if
(
head
==
&
dev
->
local
)
notify_sigd
(
dev
);
return
0
;
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
;
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
error
;
int
error
;
error
=
check_addr
(
addr
);
error
=
check_addr
(
addr
);
if
(
error
)
if
(
error
)
return
error
;
return
error
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
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
))
{
if
(
identical
(
&
this
->
addr
,
addr
))
{
list_del
(
&
this
->
entry
);
list_del
(
&
this
->
entry
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
kfree
(
this
);
kfree
(
this
);
notify_sigd
(
dev
);
if
(
head
==
&
dev
->
local
)
notify_sigd
(
dev
);
return
0
;
return
0
;
}
}
}
}
...
@@ -110,22 +130,27 @@ int atm_del_addr(struct atm_dev *dev, struct sockaddr_atmsvc *addr)
...
@@ -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
,
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
;
unsigned
long
flags
;
struct
atm_dev_addr
*
this
;
struct
atm_dev_addr
*
this
;
struct
list_head
*
head
;
int
total
=
0
,
error
;
int
total
=
0
,
error
;
struct
sockaddr_atmsvc
*
tmp_buf
,
*
tmp_bufp
;
struct
sockaddr_atmsvc
*
tmp_buf
,
*
tmp_bufp
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
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
);
total
+=
sizeof
(
struct
sockaddr_atmsvc
);
tmp_buf
=
tmp_bufp
=
kmalloc
(
total
,
GFP_ATOMIC
);
tmp_buf
=
tmp_bufp
=
kmalloc
(
total
,
GFP_ATOMIC
);
if
(
!
tmp_buf
)
{
if
(
!
tmp_buf
)
{
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
return
-
ENOMEM
;
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
));
memcpy
(
tmp_bufp
++
,
&
this
->
addr
,
sizeof
(
struct
sockaddr_atmsvc
));
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
error
=
total
>
size
?
-
E2BIG
:
total
;
error
=
total
>
size
?
-
E2BIG
:
total
;
...
...
net/atm/addr.h
View file @
dcbd39a1
...
@@ -9,10 +9,12 @@
...
@@ -9,10 +9,12 @@
#include <linux/atm.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/atmdev.h>
void
atm_reset_addr
(
struct
atm_dev
*
dev
,
enum
atm_addr_type_t
type
);
void
atm_reset_addr
(
struct
atm_dev
*
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
type
);
int
atm_del_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
);
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
#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)
...
@@ -220,7 +220,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* netif_stop_queue(dev); */
/* netif_stop_queue(dev); */
dev_kfree_skb
(
skb
);
dev_kfree_skb
(
skb
);
read_unlock
(
&
devs_lock
);
read_unlock
(
&
devs_lock
);
return
-
EUNATCH
;
return
0
;
}
}
if
(
!
br2684_xmit_vcc
(
skb
,
brdev
,
brvcc
))
{
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)
...
@@ -40,6 +40,7 @@ static struct atm_dev *__alloc_atm_dev(const char *type)
dev
->
link_rate
=
ATM_OC3_PCR
;
dev
->
link_rate
=
ATM_OC3_PCR
;
spin_lock_init
(
&
dev
->
lock
);
spin_lock_init
(
&
dev
->
lock
);
INIT_LIST_HEAD
(
&
dev
->
local
);
INIT_LIST_HEAD
(
&
dev
->
local
);
INIT_LIST_HEAD
(
&
dev
->
lecs
);
return
dev
;
return
dev
;
}
}
...
@@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
...
@@ -320,10 +321,12 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
error
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
goto
done
;
}
}
atm_reset_addr
(
dev
);
atm_reset_addr
(
dev
,
ATM_ADDR_LOCAL
);
break
;
break
;
case
ATM_ADDADDR
:
case
ATM_ADDADDR
:
case
ATM_DELADDR
:
case
ATM_DELADDR
:
case
ATM_ADDLECSADDR
:
case
ATM_DELLECSADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
goto
done
;
...
@@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
...
@@ -335,14 +338,21 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg)
error
=
-
EFAULT
;
error
=
-
EFAULT
;
goto
done
;
goto
done
;
}
}
if
(
cmd
==
ATM_ADDADDR
)
if
(
cmd
==
ATM_ADDADDR
||
cmd
==
ATM_ADDLECSADDR
)
error
=
atm_add_addr
(
dev
,
&
addr
);
error
=
atm_add_addr
(
dev
,
&
addr
,
(
cmd
==
ATM_ADDADDR
?
ATM_ADDR_LOCAL
:
ATM_ADDR_LECS
));
else
else
error
=
atm_del_addr
(
dev
,
&
addr
);
error
=
atm_del_addr
(
dev
,
&
addr
,
(
cmd
==
ATM_DELADDR
?
ATM_ADDR_LOCAL
:
ATM_ADDR_LECS
));
goto
done
;
goto
done
;
}
}
case
ATM_GETADDR
:
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
)
if
(
error
<
0
)
goto
done
;
goto
done
;
size
=
error
;
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
...
@@ -3159,8 +3159,9 @@ static int sctp_getsockopt_initmsg(struct sock *sk, int len, char __user *optval
return
0
;
return
0
;
}
}
static
int
sctp_getsockopt_peer_addrs_num
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_peer_addrs_num_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
int
__user
*
optlen
)
char
__user
*
optval
,
int
__user
*
optlen
)
{
{
sctp_assoc_t
id
;
sctp_assoc_t
id
;
struct
sctp_association
*
asoc
;
struct
sctp_association
*
asoc
;
...
@@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
...
@@ -3185,23 +3186,28 @@ static int sctp_getsockopt_peer_addrs_num(struct sock *sk, int len,
return
cnt
;
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
sctp_association
*
asoc
;
struct
list_head
*
pos
;
struct
list_head
*
pos
;
int
cnt
=
0
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_getaddrs
_old
getaddrs
;
struct
sctp_transport
*
from
;
struct
sctp_transport
*
from
;
void
__user
*
to
;
void
__user
*
to
;
union
sctp_addr
temp
;
union
sctp_addr
temp
;
struct
sctp_sock
*
sp
=
sctp_sk
(
sk
);
struct
sctp_sock
*
sp
=
sctp_sk
(
sk
);
int
addrlen
;
int
addrlen
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
_old
))
return
-
EINVAL
;
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
;
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
...
@@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
...
@@ -3225,15 +3231,69 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
if
(
cnt
>=
getaddrs
.
addr_num
)
break
;
}
}
getaddrs
.
addr_num
=
cnt
;
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
-
EFAULT
;
return
0
;
return
0
;
}
}
static
int
sctp_getsockopt_local_addrs_num
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_getsockopt_local_addrs_num
_old
(
struct
sock
*
sk
,
int
len
,
char
__user
*
optval
,
char
__user
*
optval
,
int
__user
*
optlen
)
int
__user
*
optlen
)
{
{
sctp_assoc_t
id
;
sctp_assoc_t
id
;
struct
sctp_bind_addr
*
bp
;
struct
sctp_bind_addr
*
bp
;
...
@@ -3306,8 +3366,8 @@ static int sctp_getsockopt_local_addrs_num(struct sock *sk, int len,
...
@@ -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
/* Helper function that copies local addresses to user and returns the number
* of addresses copied.
* of addresses copied.
*/
*/
static
int
sctp_copy_laddrs_to_user
(
struct
sock
*
sk
,
__u16
port
,
int
max_addrs
,
static
int
sctp_copy_laddrs_to_user
_old
(
struct
sock
*
sk
,
__u16
port
,
int
max_addrs
,
void
__user
*
to
)
void
__user
*
to
)
{
{
struct
list_head
*
pos
;
struct
list_head
*
pos
;
struct
sctp_sockaddr_entry
*
addr
;
struct
sctp_sockaddr_entry
*
addr
;
...
@@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs,
...
@@ -3341,14 +3401,54 @@ static int sctp_copy_laddrs_to_user(struct sock *sk, __u16 port, int max_addrs,
return
cnt
;
return
cnt
;
}
}
static
int
sctp_getsockopt_local_addrs
(
struct
sock
*
sk
,
int
len
,
static
int
sctp_copy_laddrs_to_user
(
struct
sock
*
sk
,
__u16
port
,
char
__user
*
optval
,
int
__user
*
optlen
)
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_bind_addr
*
bp
;
struct
sctp_association
*
asoc
;
struct
sctp_association
*
asoc
;
struct
list_head
*
pos
;
struct
list_head
*
pos
;
int
cnt
=
0
;
int
cnt
=
0
;
struct
sctp_getaddrs
getaddrs
;
struct
sctp_getaddrs
_old
getaddrs
;
struct
sctp_sockaddr_entry
*
addr
;
struct
sctp_sockaddr_entry
*
addr
;
void
__user
*
to
;
void
__user
*
to
;
union
sctp_addr
temp
;
union
sctp_addr
temp
;
...
@@ -3357,10 +3457,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
...
@@ -3357,10 +3457,10 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
rwlock_t
*
addr_lock
;
rwlock_t
*
addr_lock
;
int
err
=
0
;
int
err
=
0
;
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
))
if
(
len
!=
sizeof
(
struct
sctp_getaddrs
_old
))
return
-
EINVAL
;
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
;
return
-
EFAULT
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
if
(
getaddrs
.
addr_num
<=
0
)
return
-
EINVAL
;
...
@@ -3392,8 +3492,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
...
@@ -3392,8 +3492,9 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
addr
=
list_entry
(
bp
->
address_list
.
next
,
addr
=
list_entry
(
bp
->
address_list
.
next
,
struct
sctp_sockaddr_entry
,
list
);
struct
sctp_sockaddr_entry
,
list
);
if
(
sctp_is_any
(
&
addr
->
a
))
{
if
(
sctp_is_any
(
&
addr
->
a
))
{
cnt
=
sctp_copy_laddrs_to_user
(
sk
,
bp
->
port
,
cnt
=
sctp_copy_laddrs_to_user_old
(
sk
,
bp
->
port
,
getaddrs
.
addr_num
,
to
);
getaddrs
.
addr_num
,
to
);
if
(
cnt
<
0
)
{
if
(
cnt
<
0
)
{
err
=
cnt
;
err
=
cnt
;
goto
unlock
;
goto
unlock
;
...
@@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
...
@@ -3419,7 +3520,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
copy_getaddrs:
copy_getaddrs:
getaddrs
.
addr_num
=
cnt
;
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
;
err
=
-
EFAULT
;
unlock:
unlock:
...
@@ -3427,6 +3528,99 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
...
@@ -3427,6 +3528,99 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
return
err
;
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)
/* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR)
*
*
* Requests that the local SCTP stack use the enclosed peer address as
* 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,
...
@@ -3807,12 +4001,20 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
case
SCTP_INITMSG
:
case
SCTP_INITMSG
:
retval
=
sctp_getsockopt_initmsg
(
sk
,
len
,
optval
,
optlen
);
retval
=
sctp_getsockopt_initmsg
(
sk
,
len
,
optval
,
optlen
);
break
;
break
;
case
SCTP_GET_PEER_ADDRS_NUM
:
case
SCTP_GET_PEER_ADDRS_NUM_OLD
:
retval
=
sctp_getsockopt_peer_addrs_num
(
sk
,
len
,
optval
,
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
);
optlen
);
break
;
break
;
case
SCTP_GET_LOCAL_ADDRS_
NUM
:
case
SCTP_GET_LOCAL_ADDRS_
OLD
:
retval
=
sctp_getsockopt_local_addrs_
num
(
sk
,
len
,
optval
,
retval
=
sctp_getsockopt_local_addrs_
old
(
sk
,
len
,
optval
,
optlen
);
optlen
);
break
;
break
;
case
SCTP_GET_PEER_ADDRS
:
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