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
b9bf3d83
Commit
b9bf3d83
authored
Jun 16, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/acme/net-2.5
into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents
ac59d5f3
3c81501f
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
1048 additions
and
895 deletions
+1048
-895
Makefile
Makefile
+1
-1
drivers/atm/atmtcp.c
drivers/atm/atmtcp.c
+31
-18
drivers/atm/eni.c
drivers/atm/eni.c
+29
-18
drivers/atm/fore200e.c
drivers/atm/fore200e.c
+34
-20
drivers/atm/he.c
drivers/atm/he.c
+13
-39
drivers/atm/idt77252.c
drivers/atm/idt77252.c
+17
-11
drivers/md/dm-ioctl.c
drivers/md/dm-ioctl.c
+2
-1
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_main.c
+3
-3
drivers/net/shaper.c
drivers/net/shaper.c
+18
-19
fs/namei.c
fs/namei.c
+4
-0
fs/nfs/inode.c
fs/nfs/inode.c
+0
-1
include/linux/atmdev.h
include/linux/atmdev.h
+7
-6
net/atm/atm_misc.c
net/atm/atm_misc.c
+10
-6
net/atm/clip.c
net/atm/clip.c
+4
-3
net/atm/common.c
net/atm/common.c
+284
-472
net/atm/common.h
net/atm/common.h
+12
-14
net/atm/lec.c
net/atm/lec.c
+5
-4
net/atm/mpc.c
net/atm/mpc.c
+3
-2
net/atm/mpoa_caches.c
net/atm/mpoa_caches.c
+2
-2
net/atm/proc.c
net/atm/proc.c
+32
-51
net/atm/pvc.c
net/atm/pvc.c
+45
-19
net/atm/resources.c
net/atm/resources.c
+222
-57
net/atm/resources.h
net/atm/resources.h
+1
-2
net/atm/signaling.c
net/atm/signaling.c
+23
-21
net/atm/svc.c
net/atm/svc.c
+226
-103
net/ipv4/igmp.c
net/ipv4/igmp.c
+10
-1
net/ipv6/mcast.c
net/ipv6/mcast.c
+10
-1
No files found.
Makefile
View file @
b9bf3d83
VERSION
=
2
PATCHLEVEL
=
5
SUBLEVEL
=
7
1
SUBLEVEL
=
7
2
EXTRAVERSION
=
# *DOCUMENTATION*
...
...
drivers/atm/atmtcp.c
View file @
b9bf3d83
...
...
@@ -153,9 +153,9 @@ static void atmtcp_v_close(struct atm_vcc *vcc)
static
int
atmtcp_v_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
)
{
unsigned
long
flags
;
struct
atm_cirange
ci
;
struct
atm_vcc
*
vcc
;
struct
sock
*
s
;
if
(
cmd
!=
ATM_SETCIRANGE
)
return
-
ENOIOCTLCMD
;
if
(
copy_from_user
(
&
ci
,(
void
*
)
arg
,
sizeof
(
ci
)))
return
-
EFAULT
;
...
...
@@ -163,14 +163,18 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg)
if
(
ci
.
vci_bits
==
ATM_CI_MAX
)
ci
.
vci_bits
=
MAX_VCI_BITS
;
if
(
ci
.
vpi_bits
>
MAX_VPI_BITS
||
ci
.
vpi_bits
<
0
||
ci
.
vci_bits
>
MAX_VCI_BITS
||
ci
.
vci_bits
<
0
)
return
-
EINVAL
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
vcc
=
dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
!=
dev
)
continue
;
if
((
vcc
->
vpi
>>
ci
.
vpi_bits
)
||
(
vcc
->
vci
>>
ci
.
vci_bits
))
{
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
-
EBUSY
;
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
}
read_unlock
(
&
vcc_sklist_lock
);
dev
->
ci_range
=
ci
;
return
0
;
}
...
...
@@ -233,9 +237,9 @@ static int atmtcp_v_proc(struct atm_dev *dev,loff_t *pos,char *page)
static
void
atmtcp_c_close
(
struct
atm_vcc
*
vcc
)
{
unsigned
long
flags
;
struct
atm_dev
*
atmtcp_dev
;
struct
atmtcp_dev_data
*
dev_data
;
struct
sock
*
s
;
struct
atm_vcc
*
walk
;
atmtcp_dev
=
(
struct
atm_dev
*
)
vcc
->
dev_data
;
...
...
@@ -246,19 +250,23 @@ static void atmtcp_c_close(struct atm_vcc *vcc)
kfree
(
dev_data
);
shutdown_atm_dev
(
atmtcp_dev
);
vcc
->
dev_data
=
NULL
;
spin_lock_irqsave
(
&
atmtcp_dev
->
lock
,
flags
);
for
(
walk
=
atmtcp_dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
atmtcp_dev
)
continue
;
wake_up
(
&
walk
->
sleep
);
spin_unlock_irqrestore
(
&
atmtcp_dev
->
lock
,
flags
);
}
read_unlock
(
&
vcc_sklist_lock
);
}
static
int
atmtcp_c_send
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
unsigned
long
flags
;
struct
atm_dev
*
dev
;
struct
atmtcp_hdr
*
hdr
;
struct
atm_vcc
*
out_vcc
;
struct
sock
*
s
;
struct
atm_vcc
*
out_vcc
=
NULL
;
struct
sk_buff
*
new_skb
;
int
result
=
0
;
...
...
@@ -270,13 +278,17 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
(
struct
atmtcp_control
*
)
skb
->
data
);
goto
done
;
}
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
out_vcc
=
dev
->
vccs
;
out_vcc
;
out_vcc
=
out_vcc
->
next
)
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
out_vcc
=
atm_sk
(
s
);
if
(
out_vcc
->
dev
!=
dev
)
continue
;
if
(
out_vcc
->
vpi
==
ntohs
(
hdr
->
vpi
)
&&
out_vcc
->
vci
==
ntohs
(
hdr
->
vci
)
&&
out_vcc
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
)
break
;
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
}
read_unlock
(
&
vcc_sklist_lock
);
if
(
!
out_vcc
)
{
atomic_inc
(
&
vcc
->
stats
->
tx_err
);
goto
done
;
...
...
@@ -366,7 +378,7 @@ int atmtcp_attach(struct atm_vcc *vcc,int itf)
if
(
itf
!=
-
1
)
dev
=
atm_dev_lookup
(
itf
);
if
(
dev
)
{
if
(
dev
->
ops
!=
&
atmtcp_v_dev_ops
)
{
atm_dev_
release
(
dev
);
atm_dev_
put
(
dev
);
return
-
EMEDIUMTYPE
;
}
if
(
PRIV
(
dev
)
->
vcc
)
return
-
EBUSY
;
...
...
@@ -378,7 +390,8 @@ int atmtcp_attach(struct atm_vcc *vcc,int itf)
if
(
error
)
return
error
;
}
PRIV
(
dev
)
->
vcc
=
vcc
;
bind_vcc
(
vcc
,
&
atmtcp_control_dev
);
vcc
->
dev
=
&
atmtcp_control_dev
;
vcc_insert_socket
(
vcc
->
sk
);
set_bit
(
ATM_VF_META
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
dev_data
=
dev
;
...
...
@@ -402,7 +415,7 @@ int atmtcp_remove_persistent(int itf)
dev
=
atm_dev_lookup
(
itf
);
if
(
!
dev
)
return
-
ENODEV
;
if
(
dev
->
ops
!=
&
atmtcp_v_dev_ops
)
{
atm_dev_
release
(
dev
);
atm_dev_
put
(
dev
);
return
-
EMEDIUMTYPE
;
}
dev_data
=
PRIV
(
dev
);
...
...
@@ -410,7 +423,7 @@ int atmtcp_remove_persistent(int itf)
dev_data
->
persist
=
0
;
if
(
PRIV
(
dev
)
->
vcc
)
return
0
;
kfree
(
dev_data
);
atm_dev_
release
(
dev
);
atm_dev_
put
(
dev
);
shutdown_atm_dev
(
dev
);
return
0
;
}
...
...
drivers/atm/eni.c
View file @
b9bf3d83
...
...
@@ -1887,10 +1887,10 @@ static void eni_close(struct atm_vcc *vcc)
static
int
get_ci
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
)
{
unsigned
long
flag
s
;
struct
sock
*
s
;
struct
atm_vcc
*
walk
;
spin_lock_irqsave
(
&
vcc
->
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
if
(
*
vpi
==
ATM_VPI_ANY
)
*
vpi
=
0
;
if
(
*
vci
==
ATM_VCI_ANY
)
{
for
(
*
vci
=
ATM_NOT_RSV_VCI
;
*
vci
<
NR_VCI
;
(
*
vci
)
++
)
{
...
...
@@ -1898,40 +1898,47 @@ static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci)
ENI_DEV
(
vcc
->
dev
)
->
rx_map
[
*
vci
])
continue
;
if
(
vcc
->
qos
.
txtp
.
traffic_class
!=
ATM_NONE
)
{
for
(
walk
=
vcc
->
dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
(
test_bit
(
ATM_VF_ADDR
,
&
walk
->
flags
)
&&
walk
->
vci
==
*
vci
&&
walk
->
qos
.
txtp
.
traffic_class
!=
ATM_NONE
)
break
;
if
(
walk
)
continue
;
}
if
(
s
)
continue
;
}
break
;
}
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
*
vci
==
NR_VCI
?
-
EADDRINUSE
:
0
;
}
if
(
*
vci
==
ATM_VCI_UNSPEC
)
{
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
if
(
vcc
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
&&
ENI_DEV
(
vcc
->
dev
)
->
rx_map
[
*
vci
])
{
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
-
EADDRINUSE
;
}
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_NONE
)
{
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
for
(
walk
=
vcc
->
dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
(
test_bit
(
ATM_VF_ADDR
,
&
walk
->
flags
)
&&
walk
->
vci
==
*
vci
&&
walk
->
qos
.
txtp
.
traffic_class
!=
ATM_NONE
)
{
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
-
EADDRINUSE
;
}
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
}
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
...
...
@@ -2139,7 +2146,7 @@ static unsigned char eni_phy_get(struct atm_dev *dev,unsigned long addr)
static
int
eni_proc_read
(
struct
atm_dev
*
dev
,
loff_t
*
pos
,
char
*
page
)
{
unsigned
long
flag
s
;
struct
sock
*
s
;
static
const
char
*
signal
[]
=
{
"LOST"
,
"unknown"
,
"okay"
};
struct
eni_dev
*
eni_dev
=
ENI_DEV
(
dev
);
struct
atm_vcc
*
vcc
;
...
...
@@ -2212,11 +2219,15 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
return
sprintf
(
page
,
"%10sbacklog %u packets
\n
"
,
""
,
skb_queue_len
(
&
tx
->
backlog
));
}
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
vcc
=
dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
{
struct
eni_vcc
*
eni_vcc
=
ENI_VCC
(
vcc
)
;
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_
next
)
{
struct
eni_vcc
*
eni_vcc
;
int
length
;
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
!=
dev
)
continue
;
eni_vcc
=
ENI_VCC
(
vcc
);
if
(
--
left
)
continue
;
length
=
sprintf
(
page
,
"vcc %4d: "
,
vcc
->
vci
);
if
(
eni_vcc
->
rx
)
{
...
...
@@ -2231,10 +2242,10 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page)
length
+=
sprintf
(
page
+
length
,
"tx[%d], txing %d bytes"
,
eni_vcc
->
tx
->
index
,
eni_vcc
->
txing
);
page
[
length
]
=
'\n'
;
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
length
+
1
;
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
for
(
i
=
0
;
i
<
eni_dev
->
free_len
;
i
++
)
{
struct
eni_free
*
fe
=
eni_dev
->
free_list
+
i
;
unsigned
long
offset
;
...
...
drivers/atm/fore200e.c
View file @
b9bf3d83
...
...
@@ -1069,18 +1069,22 @@ fore200e_supply(struct fore200e* fore200e)
static
struct
atm_vcc
*
fore200e_find_vcc
(
struct
fore200e
*
fore200e
,
struct
rpd
*
rpd
)
{
unsigned
long
flag
s
;
struct
sock
*
s
;
struct
atm_vcc
*
vcc
;
spin_lock_irqsave
(
&
fore200e
->
atm_dev
->
lock
,
flags
);
for
(
vcc
=
fore200e
->
atm_dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
{
if
(
vcc
->
vpi
==
rpd
->
atm_header
.
vpi
&&
vcc
->
vci
==
rpd
->
atm_header
.
vci
)
break
;
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
!=
fore200e
->
atm_dev
)
continue
;
if
(
vcc
->
vpi
==
rpd
->
atm_header
.
vpi
&&
vcc
->
vci
==
rpd
->
atm_header
.
vci
)
{
read_unlock
(
&
vcc_sklist_lock
);
return
vcc
;
}
}
spin_unlock_irqrestore
(
&
fore200e
->
atm_dev
->
lock
,
flags
);
return
vcc
;
read_unlock
(
&
vcc_sklist_lock
);
return
NULL
;
}
...
...
@@ -1350,20 +1354,23 @@ fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc*
static
int
fore200e_walk_vccs
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
)
{
unsigned
long
flags
;
struct
atm_vcc
*
walk
;
struct
sock
*
s
;
/* find a free VPI */
spin_lock_irqsave
(
&
vcc
->
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
if
(
*
vpi
==
ATM_VPI_ANY
)
{
for
(
*
vpi
=
0
,
walk
=
vcc
->
dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
{
for
(
*
vpi
=
0
,
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
((
walk
->
vci
==
*
vci
)
&&
(
walk
->
vpi
==
*
vpi
))
{
(
*
vpi
)
++
;
walk
=
vcc
->
dev
->
vccs
;
s
=
vcc_sklist
;
}
}
}
...
...
@@ -1371,16 +1378,19 @@ fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci)
/* find a free VCI */
if
(
*
vci
==
ATM_VCI_ANY
)
{
for
(
*
vci
=
ATM_NOT_RSV_VCI
,
walk
=
vcc
->
dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
{
for
(
*
vci
=
ATM_NOT_RSV_VCI
,
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
((
walk
->
vpi
=
*
vpi
)
&&
(
walk
->
vci
==
*
vci
))
{
*
vci
=
walk
->
vci
+
1
;
walk
=
vcc
->
dev
->
vccs
;
s
=
vcc_sklist
;
}
}
}
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
...
...
@@ -2642,7 +2652,7 @@ fore200e_module_cleanup(void)
static
int
fore200e_proc_read
(
struct
atm_dev
*
dev
,
loff_t
*
pos
,
char
*
page
)
{
unsigned
long
flag
s
;
struct
sock
*
s
;
struct
fore200e
*
fore200e
=
FORE200E_DEV
(
dev
);
int
len
,
left
=
*
pos
;
...
...
@@ -2889,8 +2899,12 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
len
=
sprintf
(
page
,
"
\n
"
" VCCs:
\n
address
\t
VPI.VCI:AAL
\t
(min/max tx PDU size) (min/max rx PDU size)
\n
"
);
spin_lock_irqsave
(
&
fore200e
->
atm_dev
->
lock
,
flags
);
for
(
vcc
=
fore200e
->
atm_dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
{
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
!=
fore200e
->
atm_dev
)
continue
;
fore200e_vcc
=
FORE200E_VCC
(
vcc
);
...
...
@@ -2904,7 +2918,7 @@ fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page)
fore200e_vcc
->
rx_max_pdu
);
}
spin_unlock_irqrestore
(
&
fore200e
->
atm_dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
len
;
}
...
...
drivers/atm/he.c
View file @
b9bf3d83
...
...
@@ -79,7 +79,6 @@
#include <linux/sonet.h>
#define USE_TASKLET
#define USE_HE_FIND_VCC
#undef USE_SCATTERGATHER
#undef USE_CHECKSUM_HW
/* still confused about this */
#define USE_RBPS
...
...
@@ -328,25 +327,24 @@ he_readl_internal(struct he_dev *he_dev, unsigned addr, unsigned flags)
he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 7)
static
__inline__
struct
atm_vcc
*
he
_find_vcc
(
struct
he_dev
*
he_dev
,
unsigned
cid
)
_
_find_vcc
(
struct
he_dev
*
he_dev
,
unsigned
cid
)
{
unsigned
long
flags
;
struct
atm_vcc
*
vcc
;
struct
sock
*
s
;
short
vpi
;
int
vci
;
vpi
=
cid
>>
he_dev
->
vcibits
;
vci
=
cid
&
((
1
<<
he_dev
->
vcibits
)
-
1
);
spin_lock_irqsave
(
&
he_dev
->
atm_dev
->
lock
,
flags
);
for
(
vcc
=
he_dev
->
atm_dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
if
(
vcc
->
vci
==
vci
&&
vcc
->
vpi
==
vpi
&&
vcc
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
)
{
spin_unlock_irqrestore
(
&
he_dev
->
atm_dev
->
lock
,
flags
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
==
he_dev
->
atm_dev
&&
vcc
->
vci
==
vci
&&
vcc
->
vpi
==
vpi
&&
vcc
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
)
{
return
vcc
;
}
spin_unlock_irqrestore
(
&
he_dev
->
atm_dev
->
lock
,
flags
);
}
}
return
NULL
;
}
...
...
@@ -1566,17 +1564,6 @@ he_start(struct atm_dev *dev)
reg
|=
RX_ENABLE
;
he_writel
(
he_dev
,
reg
,
RC_CONFIG
);
#ifndef USE_HE_FIND_VCC
he_dev
->
he_vcc_table
=
kmalloc
(
sizeof
(
struct
he_vcc_table
)
*
(
1
<<
(
he_dev
->
vcibits
+
he_dev
->
vpibits
)),
GFP_KERNEL
);
if
(
he_dev
->
he_vcc_table
==
NULL
)
{
hprintk
(
"failed to alloc he_vcc_table
\n
"
);
return
-
ENOMEM
;
}
memset
(
he_dev
->
he_vcc_table
,
0
,
sizeof
(
struct
he_vcc_table
)
*
(
1
<<
(
he_dev
->
vcibits
+
he_dev
->
vpibits
)));
#endif
for
(
i
=
0
;
i
<
HE_NUM_CS_STPER
;
++
i
)
{
he_dev
->
cs_stper
[
i
].
inuse
=
0
;
he_dev
->
cs_stper
[
i
].
pcr
=
-
1
;
...
...
@@ -1712,11 +1699,6 @@ he_stop(struct he_dev *he_dev)
he_dev
->
tpd_base
,
he_dev
->
tpd_base_phys
);
#endif
#ifndef USE_HE_FIND_VCC
if
(
he_dev
->
he_vcc_table
)
kfree
(
he_dev
->
he_vcc_table
);
#endif
if
(
he_dev
->
pci_dev
)
{
pci_read_config_word
(
he_dev
->
pci_dev
,
PCI_COMMAND
,
&
command
);
command
&=
~
(
PCI_COMMAND_MEMORY
|
PCI_COMMAND_MASTER
);
...
...
@@ -1798,6 +1780,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
int
pdus_assembled
=
0
;
int
updated
=
0
;
read_lock
(
&
vcc_sklist_lock
);
while
(
he_dev
->
rbrq_head
!=
rbrq_tail
)
{
++
updated
;
...
...
@@ -1823,13 +1806,10 @@ he_service_rbrq(struct he_dev *he_dev, int group)
buf_len
=
RBRQ_BUFLEN
(
he_dev
->
rbrq_head
)
*
4
;
cid
=
RBRQ_CID
(
he_dev
->
rbrq_head
);
#ifdef USE_HE_FIND_VCC
if
(
cid
!=
lastcid
)
vcc
=
he
_find_vcc
(
he_dev
,
cid
);
vcc
=
_
_find_vcc
(
he_dev
,
cid
);
lastcid
=
cid
;
#else
vcc
=
HE_LOOKUP_VCC
(
he_dev
,
cid
);
#endif
if
(
vcc
==
NULL
)
{
hprintk
(
"vcc == NULL (cid 0x%x)
\n
"
,
cid
);
if
(
!
RBRQ_HBUF_ERR
(
he_dev
->
rbrq_head
))
...
...
@@ -1966,6 +1946,7 @@ he_service_rbrq(struct he_dev *he_dev, int group)
RBRQ_MASK
(
++
he_dev
->
rbrq_head
));
}
read_unlock
(
&
vcc_sklist_lock
);
if
(
updated
)
{
if
(
updated
>
he_dev
->
rbrq_peak
)
...
...
@@ -2565,10 +2546,6 @@ he_open(struct atm_vcc *vcc, short vpi, int vci)
#endif
spin_unlock_irqrestore
(
&
he_dev
->
global_lock
,
flags
);
#ifndef USE_HE_FIND_VCC
HE_LOOKUP_VCC
(
he_dev
,
cid
)
=
vcc
;
#endif
}
open_failed:
...
...
@@ -2634,9 +2611,6 @@ he_close(struct atm_vcc *vcc)
if
(
timeout
==
0
)
hprintk
(
"close rx timeout cid 0x%x
\n
"
,
cid
);
#ifndef USE_HE_FIND_VCC
HE_LOOKUP_VCC
(
he_dev
,
cid
)
=
NULL
;
#endif
HPRINTK
(
"close rx cid 0x%x complete
\n
"
,
cid
);
}
...
...
drivers/atm/idt77252.c
View file @
b9bf3d83
...
...
@@ -2403,37 +2403,43 @@ idt77252_init_rx(struct idt77252_dev *card, struct vc_map *vc,
static
int
idt77252_find_vcc
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
)
{
unsigned
long
flag
s
;
struct
sock
*
s
;
struct
atm_vcc
*
walk
;
spin_lock_irqsave
(
&
vcc
->
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
if
(
*
vpi
==
ATM_VPI_ANY
)
{
*
vpi
=
0
;
walk
=
vcc
->
dev
->
vccs
;
while
(
walk
)
{
s
=
vcc_sklist
;
while
(
s
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
((
walk
->
vci
==
*
vci
)
&&
(
walk
->
vpi
==
*
vpi
))
{
(
*
vpi
)
++
;
walk
=
vcc
->
dev
->
vccs
;
s
=
vcc_sklist
;
continue
;
}
walk
=
walk
->
next
;
s
=
s
->
sk_
next
;
}
}
if
(
*
vci
==
ATM_VCI_ANY
)
{
*
vci
=
ATM_NOT_RSV_VCI
;
walk
=
vcc
->
dev
->
vccs
;
while
(
walk
)
{
s
=
vcc_sklist
;
while
(
s
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
((
walk
->
vci
==
*
vci
)
&&
(
walk
->
vpi
==
*
vpi
))
{
(
*
vci
)
++
;
walk
=
vcc
->
dev
->
vccs
;
s
=
vcc_sklist
;
continue
;
}
walk
=
walk
->
next
;
s
=
s
->
sk_
next
;
}
}
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
...
...
drivers/md/dm-ioctl.c
View file @
b9bf3d83
...
...
@@ -297,13 +297,14 @@ int dm_hash_rename(const char *old, const char *new)
/*
* rename and move the name cell.
*/
unregister_with_devfs
(
hc
);
list_del
(
&
hc
->
name_list
);
old_name
=
hc
->
name
;
hc
->
name
=
new_name
;
list_add
(
&
hc
->
name_list
,
_name_buckets
+
hash_str
(
new_name
));
/* rename the device node in devfs */
unregister_with_devfs
(
hc
);
register_with_devfs
(
hc
);
up_write
(
&
_hash_lock
);
...
...
drivers/net/bonding/bond_main.c
View file @
b9bf3d83
...
...
@@ -952,8 +952,6 @@ static int bond_open(struct net_device *dev)
add_timer
(
alb_timer
);
}
MOD_INC_USE_COUNT
;
if
(
miimon
>
0
)
{
/* link check interval, in milliseconds. */
init_timer
(
timer
);
timer
->
expires
=
jiffies
+
(
miimon
*
HZ
/
1000
);
...
...
@@ -1027,7 +1025,6 @@ static int bond_close(struct net_device *master)
bond_alb_deinitialize
(
bond
);
}
MOD_DEC_USE_COUNT
;
return
0
;
}
...
...
@@ -3694,6 +3691,8 @@ static int __init bond_init(struct net_device *dev)
kfree
(
bond
);
return
-
ENOMEM
;
}
bond
->
bond_proc_dir
->
owner
=
THIS_MODULE
;
bond
->
bond_proc_info_file
=
create_proc_info_entry
(
"info"
,
0
,
bond
->
bond_proc_dir
,
bond_get_info
);
...
...
@@ -3705,6 +3704,7 @@ static int __init bond_init(struct net_device *dev)
kfree
(
bond
);
return
-
ENOMEM
;
}
bond
->
bond_proc_info_file
->
owner
=
THIS_MODULE
;
#endif
/* CONFIG_PROC_FS */
if
(
first_pass
==
1
)
{
...
...
drivers/net/shaper.c
View file @
b9bf3d83
...
...
@@ -630,7 +630,7 @@ static void shaper_init_priv(struct net_device *dev)
* Add a shaper device to the system
*/
static
int
__init
shaper_probe
(
struct
net_device
*
dev
)
static
void
__init
shaper_setup
(
struct
net_device
*
dev
)
{
/*
* Set up the shaper.
...
...
@@ -642,6 +642,7 @@ static int __init shaper_probe(struct net_device *dev)
dev
->
open
=
shaper_open
;
dev
->
stop
=
shaper_close
;
dev
->
destructor
=
(
void
(
*
)(
struct
net_device
*
))
kfree
;
dev
->
hard_start_xmit
=
shaper_start_xmit
;
dev
->
get_stats
=
shaper_get_stats
;
dev
->
set_multicast_list
=
NULL
;
...
...
@@ -669,12 +670,6 @@ static int __init shaper_probe(struct net_device *dev)
dev
->
addr_len
=
0
;
dev
->
tx_queue_len
=
10
;
dev
->
flags
=
0
;
/*
* Shaper is ok
*/
return
0
;
}
static
int
shapers
=
1
;
...
...
@@ -695,35 +690,38 @@ __setup("shapers=", set_num_shapers);
#endif
/* MODULE */
static
struct
net_device
*
devs
;
static
struct
net_device
*
*
devs
;
static
unsigned
int
shapers_registered
=
0
;
static
int
__init
shaper_init
(
void
)
{
int
i
,
err
;
int
i
;
size_t
alloc_size
;
struct
shaper
*
sp
;
struct
net_device
*
dev
;
char
name
[
IFNAMSIZ
];
if
(
shapers
<
1
)
return
-
ENODEV
;
alloc_size
=
(
sizeof
(
*
devs
)
*
shapers
)
+
(
sizeof
(
struct
shaper
)
*
shapers
);
alloc_size
=
sizeof
(
*
dev
)
*
shapers
;
devs
=
kmalloc
(
alloc_size
,
GFP_KERNEL
);
if
(
!
devs
)
return
-
ENOMEM
;
memset
(
devs
,
0
,
alloc_size
);
sp
=
(
struct
shaper
*
)
&
devs
[
shapers
];
for
(
i
=
0
;
i
<
shapers
;
i
++
)
{
err
=
dev_alloc_name
(
&
devs
[
i
],
"shaper%d"
);
if
(
err
<
0
)
snprintf
(
name
,
IFNAMSIZ
,
"shaper%d"
,
i
);
dev
=
alloc_netdev
(
sizeof
(
struct
shaper
),
name
,
shaper_setup
);
if
(
!
dev
)
break
;
devs
[
i
].
init
=
shaper_probe
;
devs
[
i
].
priv
=
&
sp
[
i
];
if
(
register_netdev
(
&
devs
[
i
]))
if
(
register_netdev
(
dev
))
break
;
devs
[
i
]
=
dev
;
shapers_registered
++
;
}
...
...
@@ -740,7 +738,8 @@ static void __exit shaper_exit (void)
int
i
;
for
(
i
=
0
;
i
<
shapers_registered
;
i
++
)
unregister_netdev
(
&
devs
[
i
]);
if
(
devs
[
i
])
unregister_netdev
(
devs
[
i
]);
kfree
(
devs
);
devs
=
NULL
;
...
...
fs/namei.c
View file @
b9bf3d83
...
...
@@ -985,6 +985,8 @@ static inline int check_sticky(struct inode *dir, struct inode *inode)
* 7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
* 8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
* 9. We can't remove a root or mountpoint.
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
* nfs_async_unlink().
*/
static
inline
int
may_delete
(
struct
inode
*
dir
,
struct
dentry
*
victim
,
int
isdir
)
{
...
...
@@ -1008,6 +1010,8 @@ static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
return
-
EISDIR
;
if
(
IS_DEADDIR
(
dir
))
return
-
ENOENT
;
if
(
victim
->
d_flags
&
DCACHE_NFSFS_RENAMED
)
return
-
EBUSY
;
return
0
;
}
...
...
fs/nfs/inode.c
View file @
b9bf3d83
...
...
@@ -715,7 +715,6 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
if
(
fattr
->
valid
&
NFS_ATTR_FATTR_V4
)
nfsi
->
change_attr
=
fattr
->
change_attr
;
inode
->
i_size
=
nfs_size_to_loff_t
(
fattr
->
size
);
inode
->
i_mode
=
fattr
->
mode
;
inode
->
i_nlink
=
fattr
->
nlink
;
inode
->
i_uid
=
fattr
->
uid
;
inode
->
i_gid
=
fattr
->
gid
;
...
...
include/linux/atmdev.h
View file @
b9bf3d83
...
...
@@ -293,7 +293,6 @@ struct atm_vcc {
struct
k_atm_aal_stats
*
stats
;
/* pointer to AAL stats group */
wait_queue_head_t
sleep
;
/* if socket is busy */
struct
sock
*
sk
;
/* socket backpointer */
struct
atm_vcc
*
prev
,
*
next
;
/* SVC part --- may move later ------------------------------------- */
short
itf
;
/* interface number */
struct
sockaddr_atmsvc
local
;
...
...
@@ -320,8 +319,6 @@ struct atm_dev {
/* (NULL) */
const
char
*
type
;
/* device type name */
int
number
;
/* device index */
struct
atm_vcc
*
vccs
;
/* VCC table (or NULL) */
struct
atm_vcc
*
last
;
/* last VCC (or undefined) */
void
*
dev_data
;
/* per-device data */
void
*
phy_data
;
/* private PHY date */
unsigned
long
flags
;
/* device flags (ATM_DF_*) */
...
...
@@ -390,6 +387,9 @@ struct atm_skb_data {
unsigned
long
atm_options
;
/* ATM layer options */
};
extern
struct
sock
*
vcc_sklist
;
extern
rwlock_t
vcc_sklist_lock
;
#define ATM_SKB(skb) (((struct atm_skb_data *) (skb)->cb))
struct
atm_dev
*
atm_dev_register
(
const
char
*
type
,
const
struct
atmdev_ops
*
ops
,
...
...
@@ -397,7 +397,8 @@ struct atm_dev *atm_dev_register(const char *type,const struct atmdev_ops *ops,
struct
atm_dev
*
atm_dev_lookup
(
int
number
);
void
atm_dev_deregister
(
struct
atm_dev
*
dev
);
void
shutdown_atm_dev
(
struct
atm_dev
*
dev
);
void
bind_vcc
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
);
void
vcc_insert_socket
(
struct
sock
*
sk
);
void
vcc_remove_socket
(
struct
sock
*
sk
);
/*
...
...
@@ -436,7 +437,7 @@ static inline void atm_dev_hold(struct atm_dev *dev)
}
static
inline
void
atm_dev_
release
(
struct
atm_dev
*
dev
)
static
inline
void
atm_dev_
put
(
struct
atm_dev
*
dev
)
{
atomic_dec
(
&
dev
->
refcnt
);
...
...
@@ -452,7 +453,7 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
int
atm_find_ci
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
);
int
atm_pcr_goal
(
struct
atm_trafprm
*
tp
);
void
atm_async_release_vcc
(
struct
atm_vcc
*
vcc
,
int
reply
);
void
vcc_release_async
(
struct
atm_vcc
*
vcc
,
int
reply
);
#endif
/* __KERNEL__ */
...
...
net/atm/atm_misc.c
View file @
b9bf3d83
...
...
@@ -47,15 +47,20 @@ struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
static
int
check_ci
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
{
struct
sock
*
s
;
struct
atm_vcc
*
walk
;
for
(
walk
=
vcc
->
dev
->
vccs
;
walk
;
walk
=
walk
->
next
)
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
walk
=
atm_sk
(
s
);
if
(
walk
->
dev
!=
vcc
->
dev
)
continue
;
if
(
test_bit
(
ATM_VF_ADDR
,
&
walk
->
flags
)
&&
walk
->
vpi
==
vpi
&&
walk
->
vci
==
vci
&&
((
walk
->
qos
.
txtp
.
traffic_class
!=
ATM_NONE
&&
vcc
->
qos
.
txtp
.
traffic_class
!=
ATM_NONE
)
||
(
walk
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
&&
vcc
->
qos
.
rxtp
.
traffic_class
!=
ATM_NONE
)))
return
-
EADDRINUSE
;
}
/* allow VCCs with same VPI/VCI iff they don't collide on
TX/RX (but we may refuse such sharing for other reasons,
e.g. if protocol requires to have both channels) */
...
...
@@ -65,17 +70,16 @@ static int check_ci(struct atm_vcc *vcc,short vpi,int vci)
int
atm_find_ci
(
struct
atm_vcc
*
vcc
,
short
*
vpi
,
int
*
vci
)
{
unsigned
long
flags
;
static
short
p
=
0
;
/* poor man's per-device cache */
static
int
c
=
0
;
short
old_p
;
int
old_c
;
int
err
;
spin_lock_irqsave
(
&
vcc
->
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
if
(
*
vpi
!=
ATM_VPI_ANY
&&
*
vci
!=
ATM_VCI_ANY
)
{
err
=
check_ci
(
vcc
,
*
vpi
,
*
vci
);
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
err
;
}
/* last scan may have left values out of bounds for current device */
...
...
@@ -90,7 +94,7 @@ int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
if
(
!
check_ci
(
vcc
,
p
,
c
))
{
*
vpi
=
p
;
*
vci
=
c
;
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
0
;
}
if
(
*
vci
==
ATM_VCI_ANY
)
{
...
...
@@ -105,7 +109,7 @@ int atm_find_ci(struct atm_vcc *vcc,short *vpi,int *vci)
}
}
while
(
old_p
!=
p
||
old_c
!=
c
);
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
read_unlock
(
&
vcc_sklist_lock
);
return
-
EADDRINUSE
;
}
...
...
net/atm/clip.c
View file @
b9bf3d83
...
...
@@ -140,8 +140,8 @@ static void idle_timer_check(unsigned long dummy)
DPRINTK
(
"releasing vcc %p->%p of "
"entry %p
\n
"
,
clip_vcc
,
clip_vcc
->
vcc
,
entry
);
atm_async_release_vc
c
(
clip_vcc
->
vcc
,
-
ETIMEDOUT
);
vcc_release_asyn
c
(
clip_vcc
->
vcc
,
-
ETIMEDOUT
);
}
if
(
entry
->
vccs
||
time_before
(
jiffies
,
entry
->
expires
))
{
...
...
@@ -737,7 +737,8 @@ static int atm_init_atmarp(struct atm_vcc *vcc)
set_bit
(
ATM_VF_META
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
/* allow replies and avoid getting closed if signaling dies */
bind_vcc
(
vcc
,
&
atmarpd_dev
);
vcc
->
dev
=
&
atmarpd_dev
;
vcc_insert_socket
(
vcc
->
sk
);
vcc
->
push
=
NULL
;
vcc
->
pop
=
NULL
;
/* crash */
vcc
->
push_oam
=
NULL
;
/* crash */
...
...
net/atm/common.c
View file @
b9bf3d83
...
...
@@ -157,6 +157,38 @@ EXPORT_SYMBOL(br2684_ioctl_hook);
#endif
struct
sock
*
vcc_sklist
;
rwlock_t
vcc_sklist_lock
=
RW_LOCK_UNLOCKED
;
void
__vcc_insert_socket
(
struct
sock
*
sk
)
{
sk
->
sk_next
=
vcc_sklist
;
if
(
sk
->
sk_next
)
vcc_sklist
->
sk_pprev
=
&
sk
->
sk_next
;
vcc_sklist
=
sk
;
sk
->
sk_pprev
=
&
vcc_sklist
;
}
void
vcc_insert_socket
(
struct
sock
*
sk
)
{
write_lock_irq
(
&
vcc_sklist_lock
);
__vcc_insert_socket
(
sk
);
write_unlock_irq
(
&
vcc_sklist_lock
);
}
void
vcc_remove_socket
(
struct
sock
*
sk
)
{
write_lock_irq
(
&
vcc_sklist_lock
);
if
(
sk
->
sk_pprev
)
{
if
(
sk
->
sk_next
)
sk
->
sk_next
->
sk_pprev
=
sk
->
sk_pprev
;
*
sk
->
sk_pprev
=
sk
->
sk_next
;
sk
->
sk_pprev
=
NULL
;
}
write_unlock_irq
(
&
vcc_sklist_lock
);
}
static
struct
sk_buff
*
alloc_tx
(
struct
atm_vcc
*
vcc
,
unsigned
int
size
)
{
struct
sk_buff
*
skb
;
...
...
@@ -175,16 +207,45 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
}
int
atm_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
)
EXPORT_SYMBOL
(
vcc_sklist
);
EXPORT_SYMBOL
(
vcc_sklist_lock
);
EXPORT_SYMBOL
(
vcc_insert_socket
);
EXPORT_SYMBOL
(
vcc_remove_socket
);
static
void
vcc_sock_destruct
(
struct
sock
*
sk
)
{
struct
atm_vcc
*
vcc
=
atm_sk
(
sk
);
if
(
atomic_read
(
&
vcc
->
sk
->
sk_rmem_alloc
))
printk
(
KERN_DEBUG
"vcc_sock_destruct: rmem leakage (%d bytes) detected.
\n
"
,
atomic_read
(
&
sk
->
sk_rmem_alloc
));
if
(
atomic_read
(
&
vcc
->
sk
->
sk_wmem_alloc
))
printk
(
KERN_DEBUG
"vcc_sock_destruct: wmem leakage (%d bytes) detected.
\n
"
,
atomic_read
(
&
sk
->
sk_wmem_alloc
));
kfree
(
sk
->
sk_protinfo
);
}
int
vcc_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
)
{
struct
sock
*
sk
;
struct
atm_vcc
*
vcc
;
sock
->
sk
=
NULL
;
if
(
sock
->
type
==
SOCK_STREAM
)
return
-
EINVAL
;
if
(
!
(
sk
=
alloc_atm_vcc_sk
(
family
)))
return
-
ENOMEM
;
vcc
=
atm_sk
(
sk
);
memset
(
&
vcc
->
flags
,
0
,
sizeof
(
vcc
->
flags
));
if
(
sock
->
type
==
SOCK_STREAM
)
return
-
EINVAL
;
sk
=
sk_alloc
(
family
,
GFP_KERNEL
,
1
,
NULL
);
if
(
!
sk
)
return
-
ENOMEM
;
sock_init_data
(
NULL
,
sk
);
vcc
=
atm_sk
(
sk
)
=
kmalloc
(
sizeof
(
*
vcc
),
GFP_KERNEL
);
if
(
!
vcc
)
{
sk_free
(
sk
);
return
-
ENOMEM
;
}
memset
(
vcc
,
0
,
sizeof
(
*
vcc
));
vcc
->
sk
=
sk
;
vcc
->
dev
=
NULL
;
vcc
->
callback
=
NULL
;
memset
(
&
vcc
->
local
,
0
,
sizeof
(
struct
sockaddr_atmsvc
));
...
...
@@ -199,55 +260,63 @@ int atm_create(struct socket *sock,int protocol,int family)
vcc
->
atm_options
=
vcc
->
aal_options
=
0
;
init_waitqueue_head
(
&
vcc
->
sleep
);
sk
->
sk_sleep
=
&
vcc
->
sleep
;
sk
->
sk_destruct
=
vcc_sock_destruct
;
sock
->
sk
=
sk
;
return
0
;
}
void
atm_release_vcc_sk
(
struct
sock
*
sk
,
int
free_
sk
)
static
void
vcc_destroy_socket
(
struct
sock
*
sk
)
{
struct
atm_vcc
*
vcc
=
atm_sk
(
sk
);
struct
sk_buff
*
skb
;
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
if
(
vcc
->
dev
)
{
if
(
vcc
->
dev
->
ops
->
close
)
vcc
->
dev
->
ops
->
close
(
vcc
);
if
(
vcc
->
push
)
vcc
->
push
(
vcc
,
NULL
);
/* atmarpd has no push */
if
(
vcc
->
dev
->
ops
->
close
)
vcc
->
dev
->
ops
->
close
(
vcc
);
if
(
vcc
->
push
)
vcc
->
push
(
vcc
,
NULL
);
/* atmarpd has no push */
vcc_remove_socket
(
sk
);
/* no more receive */
while
((
skb
=
skb_dequeue
(
&
vcc
->
sk
->
sk_receive_queue
)))
{
atm_return
(
vcc
,
skb
->
truesize
);
kfree_skb
(
skb
);
}
module_put
(
vcc
->
dev
->
ops
->
owner
);
atm_dev_release
(
vcc
->
dev
);
if
(
atomic_read
(
&
vcc
->
sk
->
sk_rmem_alloc
))
printk
(
KERN_WARNING
"atm_release_vcc: strange ... "
"rmem_alloc == %d after closing
\n
"
,
atomic_read
(
&
vcc
->
sk
->
sk_rmem_alloc
));
bind_vcc
(
vcc
,
NULL
);
atm_dev_put
(
vcc
->
dev
);
}
if
(
free_sk
)
free_atm_vcc_sk
(
sk
);
}
int
atm
_release
(
struct
socket
*
sock
)
int
vcc
_release
(
struct
socket
*
sock
)
{
if
(
sock
->
sk
)
atm_release_vcc_sk
(
sock
->
sk
,
1
);
struct
sock
*
sk
=
sock
->
sk
;
if
(
sk
)
{
sock_orphan
(
sk
);
lock_sock
(
sk
);
vcc_destroy_socket
(
sock
->
sk
);
release_sock
(
sk
);
sock_put
(
sk
);
}
return
0
;
}
void
atm_async_release_vcc
(
struct
atm_vcc
*
vcc
,
int
reply
)
void
vcc_release_async
(
struct
atm_vcc
*
vcc
,
int
reply
)
{
set_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
);
vcc
->
reply
=
reply
;
vcc
->
sk
->
sk_err
=
-
reply
;
wake_up
(
&
vcc
->
sleep
);
}
EXPORT_SYMBOL
(
atm_async_release_vc
c
);
EXPORT_SYMBOL
(
vcc_release_asyn
c
);
static
int
adjust_tp
(
struct
atm_trafprm
*
tp
,
unsigned
char
aal
)
...
...
@@ -276,8 +345,8 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal)
}
static
int
atm_do_connect_dev
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
,
int
vpi
,
int
vci
)
static
int
__vcc_connect
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
,
int
vpi
,
int
vci
)
{
int
error
;
...
...
@@ -288,7 +357,8 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
if
(
vci
>
0
&&
vci
<
ATM_NOT_RSV_VCI
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
return
-
EPERM
;
error
=
0
;
bind_vcc
(
vcc
,
dev
);
vcc
->
dev
=
dev
;
vcc_insert_socket
(
vcc
->
sk
);
switch
(
vcc
->
qos
.
aal
)
{
case
ATM_AAL0
:
error
=
atm_init_aal0
(
vcc
);
...
...
@@ -312,7 +382,7 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
if
(
!
error
)
error
=
adjust_tp
(
&
vcc
->
qos
.
txtp
,
vcc
->
qos
.
aal
);
if
(
!
error
)
error
=
adjust_tp
(
&
vcc
->
qos
.
rxtp
,
vcc
->
qos
.
aal
);
if
(
error
)
{
bind_vcc
(
vcc
,
NULL
);
vcc_remove_socket
(
vcc
->
sk
);
return
error
;
}
DPRINTK
(
"VCC %d.%d, AAL %d
\n
"
,
vpi
,
vci
,
vcc
->
qos
.
aal
);
...
...
@@ -326,7 +396,7 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
error
=
dev
->
ops
->
open
(
vcc
,
vpi
,
vci
);
if
(
error
)
{
module_put
(
dev
->
ops
->
owner
);
bind_vcc
(
vcc
,
NULL
);
vcc_remove_socket
(
vcc
->
sk
);
return
error
;
}
}
...
...
@@ -334,29 +404,26 @@ static int atm_do_connect_dev(struct atm_vcc *vcc,struct atm_dev *dev,int vpi,
}
static
int
atm_do_connect
(
struct
atm_vcc
*
vcc
,
int
itf
,
int
vpi
,
int
vci
)
int
vcc_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
)
{
struct
atm_dev
*
dev
;
int
return_val
;
dev
=
atm_dev_lookup
(
itf
);
if
(
!
dev
)
return_val
=
-
ENODEV
;
else
{
return_val
=
atm_do_connect_dev
(
vcc
,
dev
,
vpi
,
vci
);
if
(
return_val
)
atm_dev_release
(
dev
);
}
return
return_val
;
}
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
DPRINTK
(
"vcc_connect (vpi %d, vci %d)
\n
"
,
vpi
,
vci
);
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
!
(
vpi
||
vci
))
return
-
EINVAL
;
int
atm_connect_vcc
(
struct
atm_vcc
*
vcc
,
int
itf
,
short
vpi
,
int
vci
)
{
if
(
vpi
!=
ATM_VPI_UNSPEC
&&
vci
!=
ATM_VCI_UNSPEC
)
clear_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
else
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
return
-
EINVAL
;
DPRINTK
(
"atm_connect (TX: cl %d,bw %d-%d,sdu %d; "
else
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
return
-
EINVAL
;
DPRINTK
(
"vcc_connect (TX: cl %d,bw %d-%d,sdu %d; "
"RX: cl %d,bw %d-%d,sdu %d,AAL %s%d)
\n
"
,
vcc
->
qos
.
txtp
.
traffic_class
,
vcc
->
qos
.
txtp
.
min_pcr
,
vcc
->
qos
.
txtp
.
max_pcr
,
vcc
->
qos
.
txtp
.
max_sdu
,
...
...
@@ -364,141 +431,135 @@ int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci)
vcc
->
qos
.
rxtp
.
max_pcr
,
vcc
->
qos
.
rxtp
.
max_sdu
,
vcc
->
qos
.
aal
==
ATM_AAL5
?
""
:
vcc
->
qos
.
aal
==
ATM_AAL0
?
""
:
" ??? code "
,
vcc
->
qos
.
aal
==
ATM_AAL0
?
0
:
vcc
->
qos
.
aal
);
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
return
-
EINVAL
;
if
(
itf
!=
ATM_ITF_ANY
)
{
int
error
;
error
=
atm_do_connect
(
vcc
,
itf
,
vpi
,
vci
);
if
(
error
)
return
error
;
}
else
{
struct
atm_dev
*
dev
=
NULL
;
dev
=
atm_dev_lookup
(
itf
)
;
error
=
__vcc_connect
(
vcc
,
dev
,
vpi
,
vci
);
if
(
error
)
{
atm_dev_put
(
dev
)
;
return
error
;
}
}
else
{
struct
list_head
*
p
,
*
next
;
dev
=
NULL
;
spin_lock
(
&
atm_dev_lock
);
list_for_each_safe
(
p
,
next
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
atm_dev_hold
(
dev
);
spin_unlock
(
&
atm_dev_lock
);
if
(
!
atm_do_connect_dev
(
vcc
,
dev
,
vpi
,
vci
))
if
(
!
__vcc_connect
(
vcc
,
dev
,
vpi
,
vci
))
break
;
atm_dev_
release
(
dev
);
atm_dev_
put
(
dev
);
dev
=
NULL
;
spin_lock
(
&
atm_dev_lock
);
}
spin_unlock
(
&
atm_dev_lock
);
if
(
!
dev
)
return
-
ENODEV
;
if
(
!
dev
)
return
-
ENODEV
;
}
if
(
vpi
==
ATM_VPI_UNSPEC
||
vci
==
ATM_VCI_UNSPEC
)
set_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
return
0
;
}
int
atm_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
)
{
int
error
;
DPRINTK
(
"atm_connect (vpi %d, vci %d)
\n
"
,
vpi
,
vci
);
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
!
(
vpi
||
vci
))
return
-
EINVAL
;
error
=
atm_connect_vcc
(
ATM_SD
(
sock
),
itf
,
vpi
,
vci
);
if
(
error
)
return
error
;
if
(
test_bit
(
ATM_VF_READY
,
&
ATM_SD
(
sock
)
->
flags
))
sock
->
state
=
SS_CONNECTED
;
return
0
;
}
int
atm_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
,
int
flags
)
int
vcc_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
)
{
DECLARE_WAITQUEUE
(
wait
,
current
)
;
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
;
struct
sk_buff
*
skb
;
int
eff_len
,
error
;
void
*
buff
;
int
size
;
int
copied
,
error
=
-
EINVAL
;
if
(
sock
->
state
!=
SS_CONNECTED
)
return
-
ENOTCONN
;
if
(
flags
&
~
MSG_DONTWAIT
)
return
-
EOPNOTSUPP
;
if
(
m
->
msg_iovlen
!=
1
)
return
-
ENOSYS
;
/* fix this later @@@ */
buff
=
m
->
msg_iov
->
iov_base
;
size
=
m
->
msg_iov
->
iov_len
;
if
(
sock
->
state
!=
SS_CONNECTED
)
return
-
ENOTCONN
;
if
(
flags
&
~
MSG_DONTWAIT
)
/* only handle MSG_DONTWAIT */
return
-
EOPNOTSUPP
;
vcc
=
ATM_SD
(
sock
);
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
set_current_state
(
TASK_INTERRUPTIBLE
);
error
=
1
;
/* <= 0 is error */
while
(
!
(
skb
=
skb_dequeue
(
&
vcc
->
sk
->
sk_receive_queue
)))
{
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
{
error
=
vcc
->
reply
;
break
;
}
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
error
=
0
;
break
;
}
if
(
flags
&
MSG_DONTWAIT
)
{
error
=
-
EAGAIN
;
break
;
}
schedule
();
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
break
;
}
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
return
vcc
->
reply
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
return
0
;
skb
=
skb_recv_datagram
(
sk
,
flags
,
flags
&
MSG_DONTWAIT
,
&
error
);
if
(
!
skb
)
return
error
;
copied
=
skb
->
len
;
if
(
copied
>
size
)
{
copied
=
size
;
msg
->
msg_flags
|=
MSG_TRUNC
;
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
<=
0
)
return
error
;
sock_recv_timestamp
(
m
,
vcc
->
sk
,
skb
);
eff_len
=
skb
->
len
>
size
?
size
:
skb
->
len
;
if
(
skb
->
len
>
size
)
/* Not fit ? Report it... */
m
->
msg_flags
|=
MSG_TRUNC
;
if
(
vcc
->
dev
->
ops
->
feedback
)
vcc
->
dev
->
ops
->
feedback
(
vcc
,
skb
,(
unsigned
long
)
skb
->
data
,
(
unsigned
long
)
buff
,
eff_len
);
DPRINTK
(
"RcvM %d -= %d
\n
"
,
atomic_read
(
&
vcc
->
sk
->
sk_rmem_alloc
),
skb
->
truesize
);
atm_return
(
vcc
,
skb
->
truesize
);
error
=
copy_to_user
(
buff
,
skb
->
data
,
eff_len
)
?
-
EFAULT
:
0
;
kfree_skb
(
skb
);
return
error
?
error
:
eff_len
;
error
=
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
if
(
error
)
return
error
;
sock_recv_timestamp
(
msg
,
sk
,
skb
);
if
(
vcc
->
dev
->
ops
->
feedback
)
vcc
->
dev
->
ops
->
feedback
(
vcc
,
skb
,
(
unsigned
long
)
skb
->
data
,
(
unsigned
long
)
msg
->
msg_iov
->
iov_base
,
copied
);
DPRINTK
(
"RcvM %d -= %d
\n
"
,
atomic_read
(
&
vcc
->
sk
->
rmem_alloc
),
skb
->
truesize
);
atm_return
(
vcc
,
skb
->
truesize
);
skb_free_datagram
(
sk
,
skb
);
return
copied
;
}
int
atm
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
struct
sock
*
sk
=
sock
->
sk
;
DEFINE_WAIT
(
wait
);
struct
atm_vcc
*
vcc
;
struct
sk_buff
*
skb
;
int
eff
,
error
;
const
void
*
buff
;
int
size
;
if
(
sock
->
state
!=
SS_CONNECTED
)
return
-
ENOTCONN
;
if
(
m
->
msg_name
)
return
-
EISCONN
;
if
(
m
->
msg_iovlen
!=
1
)
return
-
ENOSYS
;
/* fix this later @@@ */
lock_sock
(
sk
);
if
(
sock
->
state
!=
SS_CONNECTED
)
{
error
=
-
ENOTCONN
;
goto
out
;
}
if
(
m
->
msg_name
)
{
error
=
-
EISCONN
;
goto
out
;
}
if
(
m
->
msg_iovlen
!=
1
)
{
error
=
-
ENOSYS
;
/* fix this later @@@ */
goto
out
;
}
buff
=
m
->
msg_iov
->
iov_base
;
size
=
m
->
msg_iov
->
iov_len
;
vcc
=
ATM_SD
(
sock
);
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
return
vcc
->
reply
;
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
return
-
EPIPE
;
if
(
!
size
)
return
0
;
if
(
size
<
0
||
size
>
vcc
->
qos
.
txtp
.
max_sdu
)
return
-
EMSGSIZE
;
if
(
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
||
test_bit
(
ATM_VF_CLOSE
,
&
vcc
->
flags
))
{
error
=
vcc
->
reply
;
goto
out
;
}
if
(
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
error
=
-
EPIPE
;
goto
out
;
}
if
(
!
size
)
{
error
=
0
;
goto
out
;
}
if
(
size
<
0
||
size
>
vcc
->
qos
.
txtp
.
max_sdu
)
{
error
=
-
EMSGSIZE
;
goto
out
;
}
/* verify_area is done by net/socket.c */
eff
=
(
size
+
3
)
&
~
3
;
/* align to word boundary */
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
set_current_state
(
TASK_INTERRUPTIBLE
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
error
=
0
;
while
(
!
(
skb
=
alloc_tx
(
vcc
,
eff
)))
{
if
(
m
->
msg_flags
&
MSG_DONTWAIT
)
{
...
...
@@ -506,7 +567,6 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
break
;
}
schedule
();
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
break
;
...
...
@@ -520,19 +580,24 @@ int atm_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m,
error
=
-
EPIPE
;
break
;
}
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
}
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
return
error
;
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
goto
out
;
skb
->
dev
=
NULL
;
/* for paths shared with net_device interfaces */
ATM_SKB
(
skb
)
->
atm_options
=
vcc
->
atm_options
;
if
(
copy_from_user
(
skb_put
(
skb
,
size
),
buff
,
size
))
{
kfree_skb
(
skb
);
return
-
EFAULT
;
error
=
-
EFAULT
;
goto
out
;
}
if
(
eff
!=
size
)
memset
(
skb
->
data
+
size
,
0
,
eff
-
size
);
error
=
vcc
->
dev
->
ops
->
send
(
vcc
,
skb
);
return
error
?
error
:
size
;
error
=
error
?
error
:
size
;
out:
release_sock
(
sk
);
return
error
;
}
...
...
@@ -563,129 +628,51 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait)
}
static
void
copy_aal_stats
(
struct
k_atm_aal_stats
*
from
,
struct
atm_aal_stats
*
to
)
{
#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
__AAL_STAT_ITEMS
#undef __HANDLE_ITEM
}
static
void
subtract_aal_stats
(
struct
k_atm_aal_stats
*
from
,
struct
atm_aal_stats
*
to
)
{
#define __HANDLE_ITEM(i) atomic_sub(to->i,&from->i)
__AAL_STAT_ITEMS
#undef __HANDLE_ITEM
}
static
int
fetch_stats
(
struct
atm_dev
*
dev
,
struct
atm_dev_stats
*
arg
,
int
zero
)
{
struct
atm_dev_stats
tmp
;
int
error
=
0
;
copy_aal_stats
(
&
dev
->
stats
.
aal0
,
&
tmp
.
aal0
);
copy_aal_stats
(
&
dev
->
stats
.
aal34
,
&
tmp
.
aal34
);
copy_aal_stats
(
&
dev
->
stats
.
aal5
,
&
tmp
.
aal5
);
if
(
arg
)
error
=
copy_to_user
(
arg
,
&
tmp
,
sizeof
(
tmp
));
if
(
zero
&&
!
error
)
{
subtract_aal_stats
(
&
dev
->
stats
.
aal0
,
&
tmp
.
aal0
);
subtract_aal_stats
(
&
dev
->
stats
.
aal34
,
&
tmp
.
aal34
);
subtract_aal_stats
(
&
dev
->
stats
.
aal5
,
&
tmp
.
aal5
);
}
return
error
?
-
EFAULT
:
0
;
}
int
atm_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
int
vcc_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
struct
atm_vcc
*
vcc
;
int
*
tmp_buf
,
*
tmp_p
;
void
*
buf
;
int
error
,
len
,
size
,
number
,
ret_val
;
int
error
;
ret_val
=
0
;
vcc
=
ATM_SD
(
sock
);
switch
(
cmd
)
{
case
SIOCOUTQ
:
if
(
sock
->
state
!=
SS_CONNECTED
||
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
ret_val
=
-
EINVAL
;
!
test_bit
(
ATM_VF_READY
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
done
;
}
ret_val
=
put_user
(
vcc
->
sk
->
sk_sndbuf
-
atomic_read
(
&
vcc
->
sk
->
sk_wmem_alloc
),
(
int
*
)
arg
)
?
-
EFAULT
:
0
;
error
=
put_user
(
vcc
->
sk
->
sk_sndbuf
-
atomic_read
(
&
vcc
->
sk
->
sk_wmem_alloc
),
(
int
*
)
arg
)
?
-
EFAULT
:
0
;
goto
done
;
case
SIOCINQ
:
{
struct
sk_buff
*
skb
;
if
(
sock
->
state
!=
SS_CONNECTED
)
{
ret_val
=
-
EINVAL
;
error
=
-
EINVAL
;
goto
done
;
}
skb
=
skb_peek
(
&
vcc
->
sk
->
sk_receive_queue
);
ret_val
=
put_user
(
skb
?
skb
->
len
:
0
,(
int
*
)
arg
)
?
-
EFAULT
:
0
;
goto
done
;
}
case
ATM_GETNAMES
:
if
(
get_user
(
buf
,
&
((
struct
atm_iobuf
*
)
arg
)
->
buffer
))
{
ret_val
=
-
EFAULT
;
error
=
put_user
(
skb
?
skb
->
len
:
0
,
(
int
*
)
arg
)
?
-
EFAULT
:
0
;
goto
done
;
}
if
(
get_user
(
len
,
&
((
struct
atm_iobuf
*
)
arg
)
->
length
))
{
ret_val
=
-
EFAULT
;
goto
done
;
}
size
=
0
;
spin_lock
(
&
atm_dev_lock
);
list_for_each
(
p
,
&
atm_devs
)
size
+=
sizeof
(
int
);
if
(
size
>
len
)
{
spin_unlock
(
&
atm_dev_lock
);
ret_val
=
-
E2BIG
;
goto
done
;
}
tmp_buf
=
kmalloc
(
size
,
GFP_ATOMIC
);
if
(
!
tmp_buf
)
{
spin_unlock
(
&
atm_dev_lock
);
ret_val
=
-
ENOMEM
;
goto
done
;
}
tmp_p
=
tmp_buf
;
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
*
tmp_p
++
=
dev
->
number
;
}
spin_unlock
(
&
atm_dev_lock
);
ret_val
=
((
copy_to_user
(
buf
,
tmp_buf
,
size
))
||
put_user
(
size
,
&
((
struct
atm_iobuf
*
)
arg
)
->
length
)
)
?
-
EFAULT
:
0
;
kfree
(
tmp_buf
);
goto
done
;
case
SIOCGSTAMP
:
/* borrowed from IP */
if
(
!
vcc
->
sk
->
sk_stamp
.
tv_sec
)
{
ret_val
=
-
ENOENT
;
error
=
-
ENOENT
;
goto
done
;
}
ret_val
=
copy_to_user
((
void
*
)
arg
,
&
vcc
->
sk
->
sk_stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
error
=
copy_to_user
((
void
*
)
arg
,
&
vcc
->
sk
->
sk_stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
goto
done
;
case
ATM_SETSC
:
printk
(
KERN_WARNING
"ATM_SETSC is obsolete
\n
"
);
ret_val
=
0
;
error
=
0
;
goto
done
;
case
ATMSIGD_CTRL
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
/*
...
...
@@ -696,28 +683,28 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
* have the same privledges that /proc/kcore needs
*/
if
(
!
capable
(
CAP_SYS_RAWIO
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
error
=
sigd_attach
(
vcc
);
if
(
!
error
)
sock
->
state
=
SS_CONNECTED
;
ret_val
=
error
;
if
(
!
error
)
sock
->
state
=
SS_CONNECTED
;
goto
done
;
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
case
SIOCMKCLIP
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_clip_ops
())
{
ret_val
=
atm_clip_ops
->
clip_create
(
arg
);
error
=
atm_clip_ops
->
clip_create
(
arg
);
module_put
(
atm_clip_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMARPD_CTRL
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
#if defined(CONFIG_ATM_CLIP_MODULE)
...
...
@@ -728,48 +715,47 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
error
=
atm_clip_ops
->
atm_init_atmarp
(
vcc
);
if
(
!
error
)
sock
->
state
=
SS_CONNECTED
;
ret_val
=
error
;
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMARP_MKIP
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_clip_ops
())
{
ret_val
=
atm_clip_ops
->
clip_mkip
(
vcc
,
arg
);
error
=
atm_clip_ops
->
clip_mkip
(
vcc
,
arg
);
module_put
(
atm_clip_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMARP_SETENTRY
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_clip_ops
())
{
ret_val
=
atm_clip_ops
->
clip_setentry
(
vcc
,
arg
);
error
=
atm_clip_ops
->
clip_setentry
(
vcc
,
arg
);
module_put
(
atm_clip_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMARP_ENCAP
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_clip_ops
())
{
ret_val
=
atm_clip_ops
->
clip_encap
(
vcc
,
arg
);
error
=
atm_clip_ops
->
clip_encap
(
vcc
,
arg
);
module_put
(
atm_clip_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
#endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
case
ATMLEC_CTRL
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
#if defined(CONFIG_ATM_LANE_MODULE)
...
...
@@ -781,37 +767,36 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
module_put
(
atm_lane_ops
->
owner
);
if
(
error
>=
0
)
sock
->
state
=
SS_CONNECTED
;
ret_val
=
error
;
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMLEC_MCAST
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_lane_ops
())
{
ret_val
=
atm_lane_ops
->
mcast_attach
(
vcc
,
(
int
)
arg
);
error
=
atm_lane_ops
->
mcast_attach
(
vcc
,
(
int
)
arg
);
module_put
(
atm_lane_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMLEC_DATA
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_lane_ops
())
{
ret_val
=
atm_lane_ops
->
vcc_attach
(
vcc
,
(
void
*
)
arg
);
error
=
atm_lane_ops
->
vcc_attach
(
vcc
,
(
void
*
)
arg
);
module_put
(
atm_lane_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
#endif
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
case
ATMMPC_CTRL
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
#if defined(CONFIG_ATM_MPOA_MODULE)
...
...
@@ -823,63 +808,62 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
module_put
(
atm_mpoa_ops
->
owner
);
if
(
error
>=
0
)
sock
->
state
=
SS_CONNECTED
;
ret_val
=
error
;
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
case
ATMMPC_DATA
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
try_atm_mpoa_ops
())
{
ret_val
=
atm_mpoa_ops
->
vcc_attach
(
vcc
,
arg
);
error
=
atm_mpoa_ops
->
vcc_attach
(
vcc
,
arg
);
module_put
(
atm_mpoa_ops
->
owner
);
}
else
ret_val
=
-
ENOSYS
;
error
=
-
ENOSYS
;
goto
done
;
#endif
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
case
SIOCSIFATMTCP
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
!
atm_tcp_ops
.
attach
)
{
ret_val
=
-
ENOPKG
;
error
=
-
ENOPKG
;
goto
done
;
}
fops_get
(
&
atm_tcp_ops
);
error
=
atm_tcp_ops
.
attach
(
vcc
,(
int
)
arg
);
if
(
error
>=
0
)
sock
->
state
=
SS_CONNECTED
;
else
fops_put
(
&
atm_tcp_ops
);
ret_val
=
error
;
fops_get
(
&
atm_tcp_ops
);
error
=
atm_tcp_ops
.
attach
(
vcc
,
(
int
)
arg
);
if
(
error
>=
0
)
sock
->
state
=
SS_CONNECTED
;
else
fops_put
(
&
atm_tcp_ops
);
goto
done
;
case
ATMTCP_CREATE
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
!
atm_tcp_ops
.
create_persistent
)
{
ret_val
=
-
ENOPKG
;
error
=
-
ENOPKG
;
goto
done
;
}
error
=
atm_tcp_ops
.
create_persistent
((
int
)
arg
);
if
(
error
<
0
)
fops_put
(
&
atm_tcp_ops
);
ret_val
=
error
;
if
(
error
<
0
)
fops_put
(
&
atm_tcp_ops
)
;
goto
done
;
case
ATMTCP_REMOVE
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
error
=
-
EPERM
;
goto
done
;
}
if
(
!
atm_tcp_ops
.
remove_persistent
)
{
ret_val
=
-
ENOPKG
;
error
=
-
ENOPKG
;
goto
done
;
}
error
=
atm_tcp_ops
.
remove_persistent
((
int
)
arg
);
fops_put
(
&
atm_tcp_ops
);
ret_val
=
error
;
fops_put
(
&
atm_tcp_ops
);
goto
done
;
#endif
default:
...
...
@@ -887,182 +871,23 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
}
#if defined(CONFIG_PPPOATM) || defined(CONFIG_PPPOATM_MODULE)
if
(
pppoatm_ioctl_hook
)
{
ret_val
=
pppoatm_ioctl_hook
(
vcc
,
cmd
,
arg
);
if
(
ret_val
!=
-
ENOIOCTLCMD
)
error
=
pppoatm_ioctl_hook
(
vcc
,
cmd
,
arg
);
if
(
error
!=
-
ENOIOCTLCMD
)
goto
done
;
}
#endif
#if defined(CONFIG_ATM_BR2684) || defined(CONFIG_ATM_BR2684_MODULE)
if
(
br2684_ioctl_hook
)
{
ret_val
=
br2684_ioctl_hook
(
vcc
,
cmd
,
arg
);
if
(
ret_val
!=
-
ENOIOCTLCMD
)
error
=
br2684_ioctl_hook
(
vcc
,
cmd
,
arg
);
if
(
error
!=
-
ENOIOCTLCMD
)
goto
done
;
}
#endif
if
(
get_user
(
buf
,
&
((
struct
atmif_sioc
*
)
arg
)
->
arg
))
{
ret_val
=
-
EFAULT
;
goto
done
;
}
if
(
get_user
(
len
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
))
{
ret_val
=
-
EFAULT
;
goto
done
;
}
if
(
get_user
(
number
,
&
((
struct
atmif_sioc
*
)
arg
)
->
number
))
{
ret_val
=
-
EFAULT
;
goto
done
;
}
if
(
!
(
dev
=
atm_dev_lookup
(
number
)))
{
ret_val
=
-
ENODEV
;
goto
done
;
}
size
=
0
;
switch
(
cmd
)
{
case
ATM_GETTYPE
:
size
=
strlen
(
dev
->
type
)
+
1
;
if
(
copy_to_user
(
buf
,
dev
->
type
,
size
))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
break
;
case
ATM_GETESI
:
size
=
ESI_LEN
;
if
(
copy_to_user
(
buf
,
dev
->
esi
,
size
))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
break
;
case
ATM_SETESI
:
{
int
i
;
for
(
i
=
0
;
i
<
ESI_LEN
;
i
++
)
if
(
dev
->
esi
[
i
])
{
ret_val
=
-
EEXIST
;
goto
done_release
;
}
}
/* fall through */
case
ATM_SETESIF
:
{
unsigned
char
esi
[
ESI_LEN
];
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
goto
done_release
;
}
if
(
copy_from_user
(
esi
,
buf
,
ESI_LEN
))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
memcpy
(
dev
->
esi
,
esi
,
ESI_LEN
);
ret_val
=
ESI_LEN
;
goto
done_release
;
}
case
ATM_GETSTATZ
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
goto
done_release
;
}
/* fall through */
case
ATM_GETSTAT
:
size
=
sizeof
(
struct
atm_dev_stats
);
error
=
fetch_stats
(
dev
,
buf
,
cmd
==
ATM_GETSTATZ
);
if
(
error
)
{
ret_val
=
error
;
goto
done_release
;
}
break
;
case
ATM_GETCIRANGE
:
size
=
sizeof
(
struct
atm_cirange
);
if
(
copy_to_user
(
buf
,
&
dev
->
ci_range
,
size
))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
break
;
case
ATM_GETLINKRATE
:
size
=
sizeof
(
int
);
if
(
copy_to_user
(
buf
,
&
dev
->
link_rate
,
size
))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
break
;
case
ATM_RSTADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
goto
done_release
;
}
atm_reset_addr
(
dev
);
break
;
case
ATM_ADDADDR
:
case
ATM_DELADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
goto
done_release
;
}
{
struct
sockaddr_atmsvc
addr
;
if
(
copy_from_user
(
&
addr
,
buf
,
sizeof
(
addr
)))
{
ret_val
=
-
EFAULT
;
goto
done_release
;
}
if
(
cmd
==
ATM_ADDADDR
)
ret_val
=
atm_add_addr
(
dev
,
&
addr
);
else
ret_val
=
atm_del_addr
(
dev
,
&
addr
);
goto
done_release
;
}
case
ATM_GETADDR
:
size
=
atm_get_addr
(
dev
,
buf
,
len
);
if
(
size
<
0
)
ret_val
=
size
;
else
/* may return 0, but later on size == 0 means "don't
write the length" */
ret_val
=
put_user
(
size
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
)
?
-
EFAULT
:
0
;
goto
done_release
;
case
ATM_SETLOOP
:
if
(
__ATM_LM_XTRMT
((
int
)
(
long
)
buf
)
&&
__ATM_LM_XTLOC
((
int
)
(
long
)
buf
)
>
__ATM_LM_XTRMT
((
int
)
(
long
)
buf
))
{
ret_val
=
-
EINVAL
;
goto
done_release
;
}
/* fall through */
case
ATM_SETCIRANGE
:
case
SONET_GETSTATZ
:
case
SONET_SETDIAG
:
case
SONET_CLRDIAG
:
case
SONET_SETFRAMING
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
ret_val
=
-
EPERM
;
goto
done_release
;
}
/* fall through */
default:
if
(
!
dev
->
ops
->
ioctl
)
{
ret_val
=
-
EINVAL
;
goto
done_release
;
}
size
=
dev
->
ops
->
ioctl
(
dev
,
cmd
,
buf
);
if
(
size
<
0
)
{
ret_val
=
(
size
==
-
ENOIOCTLCMD
?
-
EINVAL
:
size
);
goto
done_release
;
}
}
if
(
size
)
ret_val
=
put_user
(
size
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
)
?
-
EFAULT
:
0
;
else
ret_val
=
0
;
done_release:
atm_dev_release
(
dev
);
error
=
atm_dev_ioctl
(
cmd
,
arg
);
done:
return
ret_val
;
return
error
;
}
...
...
@@ -1120,14 +945,16 @@ static int check_qos(struct atm_qos *qos)
return
check_tp
(
&
qos
->
rxtp
);
}
static
int
atm_do_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
void
*
optval
,
int
optlen
)
int
vcc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
struct
atm_vcc
*
vcc
;
unsigned
long
value
;
int
error
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
optlen
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
vcc
=
ATM_SD
(
sock
);
switch
(
optname
)
{
case
SO_ATMQOS
:
...
...
@@ -1161,10 +988,16 @@ static int atm_do_setsockopt(struct socket *sock,int level,int optname,
}
static
int
atm_do_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
void
*
optval
,
int
optlen
)
int
vcc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
struct
atm_vcc
*
vcc
;
int
len
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
len
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
vcc
=
ATM_SD
(
sock
);
switch
(
optname
)
{
...
...
@@ -1195,28 +1028,7 @@ static int atm_do_getsockopt(struct socket *sock,int level,int optname,
break
;
}
if
(
!
vcc
->
dev
||
!
vcc
->
dev
->
ops
->
getsockopt
)
return
-
EINVAL
;
return
vcc
->
dev
->
ops
->
getsockopt
(
vcc
,
level
,
optname
,
optval
,
optlen
);
}
int
atm_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
optlen
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
return
atm_do_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
}
int
atm_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
int
len
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
__SO_LEVEL_MATCH
(
optname
,
level
)
&&
len
!=
__SO_SIZE
(
optname
))
return
-
EINVAL
;
return
atm_do_getsockopt
(
sock
,
level
,
optname
,
optval
,
len
);
return
vcc
->
dev
->
ops
->
getsockopt
(
vcc
,
level
,
optname
,
optval
,
len
);
}
...
...
net/atm/common.h
View file @
b9bf3d83
...
...
@@ -10,22 +10,20 @@
#include <linux/poll.h>
/* for poll_table */
int
atm_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
);
int
atm
_release
(
struct
socket
*
sock
);
int
atm_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
);
int
atm_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
,
int
flags
);
int
atm
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
vcc_create
(
struct
socket
*
sock
,
int
protocol
,
int
family
);
int
vcc
_release
(
struct
socket
*
sock
);
int
vcc_connect
(
struct
socket
*
sock
,
int
itf
,
short
vpi
,
int
vci
);
int
vcc_recvmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
);
int
vcc
_sendmsg
(
struct
kiocb
*
iocb
,
struct
socket
*
sock
,
struct
msghdr
*
m
,
int
total_len
);
unsigned
int
atm_poll
(
struct
file
*
file
,
struct
socket
*
sock
,
poll_table
*
wait
);
int
atm_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
atm_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
);
int
atm_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
);
int
atm_connect_vcc
(
struct
atm_vcc
*
vcc
,
int
itf
,
short
vpi
,
int
vci
);
void
atm_release_vcc_sk
(
struct
sock
*
sk
,
int
free_sk
);
int
vcc_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
);
int
vcc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
);
int
vcc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
);
void
atm_shutdown_dev
(
struct
atm_dev
*
dev
);
int
atmpvc_init
(
void
);
...
...
net/atm/lec.c
View file @
b9bf3d83
...
...
@@ -48,7 +48,7 @@ extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
#include "lec.h"
#include "lec_arpc.h"
#include "resources.h"
/* for bind_vcc() */
#include "resources.h"
#if 0
#define DPRINTK printk
...
...
@@ -810,7 +810,8 @@ lecd_attach(struct atm_vcc *vcc, int arg)
lec_arp_init
(
priv
);
priv
->
itfnum
=
i
;
/* LANE2 addition */
priv
->
lecd
=
vcc
;
bind_vcc
(
vcc
,
&
lecatm_dev
);
vcc
->
dev
=
&
lecatm_dev
;
vcc_insert_socket
(
vcc
->
sk
);
vcc
->
proto_data
=
dev_lec
[
i
];
set_bit
(
ATM_VF_META
,
&
vcc
->
flags
);
...
...
@@ -1079,7 +1080,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
clear_bit(ATM_VF_READY,&entry->vcc->flags);
entry->vcc->push(entry->vcc, NULL);
#endif
atm_async_release_vc
c
(
entry
->
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
entry
->
vcc
,
-
EPIPE
);
entry
->
vcc
=
NULL
;
}
if
(
entry
->
recv_vcc
)
{
...
...
@@ -1089,7 +1090,7 @@ lec_arp_clear_vccs(struct lec_arp_table *entry)
clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
entry->recv_vcc->push(entry->recv_vcc, NULL);
#endif
atm_async_release_vc
c
(
entry
->
recv_vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
entry
->
recv_vcc
,
-
EPIPE
);
entry
->
recv_vcc
=
NULL
;
}
}
...
...
net/atm/mpc.c
View file @
b9bf3d83
...
...
@@ -28,7 +28,7 @@
#include "lec.h"
#include "mpc.h"
#include "resources.h"
/* for bind_vcc() */
#include "resources.h"
/*
* mpc.c: Implementation of MPOA client kernel part
...
...
@@ -789,7 +789,8 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
}
mpc
->
mpoad_vcc
=
vcc
;
bind_vcc
(
vcc
,
&
mpc_dev
);
vcc
->
dev
=
&
mpc_dev
;
vcc_insert_socket
(
vcc
->
sk
);
set_bit
(
ATM_VF_META
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
...
...
net/atm/mpoa_caches.c
View file @
b9bf3d83
...
...
@@ -212,7 +212,7 @@ static void in_cache_remove_entry(in_cache_entry *entry,
client
->
eg_ops
->
put
(
eg_entry
);
return
;
}
atm_async_release_vc
c
(
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
vcc
,
-
EPIPE
);
}
return
;
...
...
@@ -447,7 +447,7 @@ static void eg_cache_remove_entry(eg_cache_entry *entry,
client
->
in_ops
->
put
(
in_entry
);
return
;
}
atm_async_release_vc
c
(
vcc
,
-
EPIPE
);
vcc_release_asyn
c
(
vcc
,
-
EPIPE
);
}
return
;
...
...
net/atm/proc.c
View file @
b9bf3d83
...
...
@@ -334,9 +334,7 @@ static int atm_devices_info(loff_t pos,char *buf)
static
int
atm_pvc_info
(
loff_t
pos
,
char
*
buf
)
{
unsigned
long
flags
;
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
struct
sock
*
s
;
struct
atm_vcc
*
vcc
;
int
left
,
clip_info
=
0
;
...
...
@@ -349,25 +347,20 @@ static int atm_pvc_info(loff_t pos,char *buf)
if
(
try_atm_clip_ops
())
clip_info
=
1
;
#endif
spin_lock
(
&
atm_dev_lock
);
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
vcc
=
dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
if
(
vcc
->
sk
->
sk_family
==
PF_ATMPVC
&&
vcc
->
dev
&&
!
left
--
)
{
pvc_info
(
vcc
,
buf
,
clip_info
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock
(
&
atm_dev_lock
);
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
sk
->
sk_family
==
PF_ATMPVC
&&
vcc
->
dev
&&
!
left
--
)
{
pvc_info
(
vcc
,
buf
,
clip_info
);
read_unlock
(
&
vcc_sklist_lock
);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
if
(
clip_info
)
module_put
(
atm_clip_ops
->
owner
);
if
(
clip_info
)
module_put
(
atm_clip_ops
->
owner
);
#endif
return
strlen
(
buf
);
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
return
strlen
(
buf
);
}
}
spin_unlock
(
&
atm_dev
_lock
);
read_unlock
(
&
vcc_sklist
_lock
);
#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
if
(
clip_info
)
module_put
(
atm_clip_ops
->
owner
);
...
...
@@ -378,10 +371,8 @@ static int atm_pvc_info(loff_t pos,char *buf)
static
int
atm_vc_info
(
loff_t
pos
,
char
*
buf
)
{
unsigned
long
flags
;
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
struct
atm_vcc
*
vcc
;
struct
sock
*
s
;
int
left
;
if
(
!
pos
)
...
...
@@ -389,20 +380,16 @@ static int atm_vc_info(loff_t pos,char *buf)
"Address"
,
" Itf VPI VCI Fam Flags Reply Send buffer"
" Recv buffer
\n
"
);
left
=
pos
-
1
;
spin_lock
(
&
atm_dev_lock
);
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
vcc
=
dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
if
(
!
left
--
)
{
vc_info
(
vcc
,
buf
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock
(
&
atm_dev_lock
);
return
strlen
(
buf
);
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
!
left
--
)
{
vc_info
(
vcc
,
buf
);
read_unlock
(
&
vcc_sklist_lock
);
return
strlen
(
buf
);
}
}
spin_unlock
(
&
atm_dev
_lock
);
read_unlock
(
&
vcc_sklist
_lock
);
return
0
;
}
...
...
@@ -410,29 +397,23 @@ static int atm_vc_info(loff_t pos,char *buf)
static
int
atm_svc_info
(
loff_t
pos
,
char
*
buf
)
{
unsigned
long
flags
;
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
struct
sock
*
s
;
struct
atm_vcc
*
vcc
;
int
left
;
if
(
!
pos
)
return
sprintf
(
buf
,
"Itf VPI VCI State Remote
\n
"
);
left
=
pos
-
1
;
spin_lock
(
&
atm_dev_lock
);
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
for
(
vcc
=
dev
->
vccs
;
vcc
;
vcc
=
vcc
->
next
)
if
(
vcc
->
sk
->
sk_family
==
PF_ATMSVC
&&
!
left
--
)
{
svc_info
(
vcc
,
buf
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
spin_unlock
(
&
atm_dev_lock
);
return
strlen
(
buf
);
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
vcc
=
atm_sk
(
s
);
if
(
vcc
->
sk
->
sk_family
==
PF_ATMSVC
&&
!
left
--
)
{
svc_info
(
vcc
,
buf
);
read_unlock
(
&
vcc_sklist_lock
);
return
strlen
(
buf
);
}
}
spin_unlock
(
&
atm_dev
_lock
);
read_unlock
(
&
vcc_sklist
_lock
);
return
0
;
}
...
...
net/atm/pvc.c
View file @
b9bf3d83
...
...
@@ -17,10 +17,6 @@
#include "resources.h"
/* devs and vccs */
#include "common.h"
/* common for PVCs and SVCs */
#ifndef NULL
#define NULL 0
#endif
static
int
pvc_shutdown
(
struct
socket
*
sock
,
int
how
)
{
...
...
@@ -31,20 +27,29 @@ static int pvc_shutdown(struct socket *sock,int how)
static
int
pvc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmpvc
*
addr
;
struct
atm_vcc
*
vcc
;
int
error
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmpvc
))
return
-
EINVAL
;
addr
=
(
struct
sockaddr_atmpvc
*
)
sockaddr
;
if
(
addr
->
sap_family
!=
AF_ATMPVC
)
return
-
EAFNOSUPPORT
;
lock_sock
(
sk
);
vcc
=
ATM_SD
(
sock
);
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
if
(
test_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
))
{
if
(
vcc
->
vpi
!=
ATM_VPI_UNSPEC
)
addr
->
sap_addr
.
vpi
=
vcc
->
vpi
;
if
(
vcc
->
vci
!=
ATM_VCI_UNSPEC
)
addr
->
sap_addr
.
vci
=
vcc
->
vci
;
}
return
atm_connect
(
sock
,
addr
->
sap_addr
.
itf
,
addr
->
sap_addr
.
vpi
,
addr
->
sap_addr
.
vci
);
error
=
vcc_connect
(
sock
,
addr
->
sap_addr
.
itf
,
addr
->
sap_addr
.
vpi
,
addr
->
sap_addr
.
vci
);
out:
release_sock
(
sk
);
return
error
;
}
...
...
@@ -54,6 +59,31 @@ static int pvc_connect(struct socket *sock,struct sockaddr *sockaddr,
return
pvc_bind
(
sock
,
sockaddr
,
sockaddr_len
);
}
static
int
pvc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
error
;
lock_sock
(
sk
);
error
=
vcc_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
release_sock
(
sk
);
return
error
;
}
static
int
pvc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
error
;
lock_sock
(
sk
);
error
=
vcc_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
release_sock
(
sk
);
return
error
;
}
static
int
pvc_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
*
sockaddr_len
,
int
peer
)
...
...
@@ -72,36 +102,32 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr,
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
pvc_proto_ops
)
=
{
static
struct
proto_ops
pvc_proto_ops
=
{
.
family
=
PF_ATMPVC
,
.
release
=
atm
_release
,
.
release
=
vcc
_release
,
.
bind
=
pvc_bind
,
.
connect
=
pvc_connect
,
.
socketpair
=
sock_no_socketpair
,
.
accept
=
sock_no_accept
,
.
getname
=
pvc_getname
,
.
poll
=
atm_poll
,
.
ioctl
=
atm
_ioctl
,
.
ioctl
=
vcc
_ioctl
,
.
listen
=
sock_no_listen
,
.
shutdown
=
pvc_shutdown
,
.
setsockopt
=
atm
_setsockopt
,
.
getsockopt
=
atm
_getsockopt
,
.
sendmsg
=
atm
_sendmsg
,
.
recvmsg
=
atm
_recvmsg
,
.
setsockopt
=
pvc
_setsockopt
,
.
getsockopt
=
pvc
_getsockopt
,
.
sendmsg
=
vcc
_sendmsg
,
.
recvmsg
=
vcc
_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
};
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
pvc_proto
,
PF_ATMPVC
);
static
int
pvc_create
(
struct
socket
*
sock
,
int
protocol
)
{
sock
->
ops
=
&
pvc_proto_ops
;
return
atm_create
(
sock
,
protocol
,
PF_ATMPVC
);
return
vcc_create
(
sock
,
protocol
,
PF_ATMPVC
);
}
...
...
net/atm/resources.c
View file @
b9bf3d83
...
...
@@ -12,6 +12,7 @@
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/atmdev.h>
#include <linux/sonet.h>
#include <linux/kernel.h>
/* for barrier */
#include <linux/module.h>
#include <linux/bitops.h>
...
...
@@ -19,11 +20,7 @@
#include "common.h"
#include "resources.h"
#ifndef NULL
#define NULL 0
#endif
#include "addr.h"
LIST_HEAD
(
atm_devs
);
...
...
@@ -89,7 +86,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
spin_lock
(
&
atm_dev_lock
);
if
(
number
!=
-
1
)
{
if
((
inuse
=
__atm_dev_lookup
(
number
)))
{
atm_dev_
release
(
inuse
);
atm_dev_
put
(
inuse
);
spin_unlock
(
&
atm_dev_lock
);
__free_atm_dev
(
dev
);
return
NULL
;
...
...
@@ -98,7 +95,7 @@ struct atm_dev *atm_dev_register(const char *type, const struct atmdev_ops *ops,
}
else
{
dev
->
number
=
0
;
while
((
inuse
=
__atm_dev_lookup
(
dev
->
number
)))
{
atm_dev_
release
(
inuse
);
atm_dev_
put
(
inuse
);
dev
->
number
++
;
}
}
...
...
@@ -171,73 +168,241 @@ void shutdown_atm_dev(struct atm_dev *dev)
atm_dev_deregister
(
dev
);
}
struct
sock
*
alloc_atm_vcc_sk
(
int
family
)
static
void
copy_aal_stats
(
struct
k_atm_aal_stats
*
from
,
struct
atm_aal_stats
*
to
)
{
struct
sock
*
sk
;
struct
atm_vcc
*
vcc
;
#define __HANDLE_ITEM(i) to->i = atomic_read(&from->i)
__AAL_STAT_ITEMS
#undef __HANDLE_ITEM
}
sk
=
sk_alloc
(
family
,
GFP_KERNEL
,
1
,
NULL
);
if
(
!
sk
)
return
NULL
;
vcc
=
atm_sk
(
sk
)
=
kmalloc
(
sizeof
(
*
vcc
),
GFP_KERNEL
);
if
(
!
vcc
)
{
sk_free
(
sk
);
return
NULL
;
}
sock_init_data
(
NULL
,
sk
);
memset
(
vcc
,
0
,
sizeof
(
*
vcc
));
vcc
->
sk
=
sk
;
return
sk
;
static
void
subtract_aal_stats
(
struct
k_atm_aal_stats
*
from
,
struct
atm_aal_stats
*
to
)
{
#define __HANDLE_ITEM(i) atomic_sub(to->i, &from->i)
__AAL_STAT_ITEMS
#undef __HANDLE_ITEM
}
static
void
unlink_vcc
(
struct
atm_vcc
*
vcc
)
static
int
fetch_stats
(
struct
atm_dev
*
dev
,
struct
atm_dev_stats
*
arg
,
int
zero
)
{
unsigned
long
flags
;
if
(
vcc
->
dev
)
{
spin_lock_irqsave
(
&
vcc
->
dev
->
lock
,
flags
);
if
(
vcc
->
prev
)
vcc
->
prev
->
next
=
vcc
->
next
;
else
vcc
->
dev
->
vccs
=
vcc
->
next
;
if
(
vcc
->
next
)
vcc
->
next
->
prev
=
vcc
->
prev
;
else
vcc
->
dev
->
last
=
vcc
->
prev
;
spin_unlock_irqrestore
(
&
vcc
->
dev
->
lock
,
flags
);
struct
atm_dev_stats
tmp
;
int
error
=
0
;
copy_aal_stats
(
&
dev
->
stats
.
aal0
,
&
tmp
.
aal0
);
copy_aal_stats
(
&
dev
->
stats
.
aal34
,
&
tmp
.
aal34
);
copy_aal_stats
(
&
dev
->
stats
.
aal5
,
&
tmp
.
aal5
);
if
(
arg
)
error
=
copy_to_user
(
arg
,
&
tmp
,
sizeof
(
tmp
));
if
(
zero
&&
!
error
)
{
subtract_aal_stats
(
&
dev
->
stats
.
aal0
,
&
tmp
.
aal0
);
subtract_aal_stats
(
&
dev
->
stats
.
aal34
,
&
tmp
.
aal34
);
subtract_aal_stats
(
&
dev
->
stats
.
aal5
,
&
tmp
.
aal5
);
}
return
error
?
-
EFAULT
:
0
;
}
void
free_atm_vcc_sk
(
struct
sock
*
sk
)
int
atm_dev_ioctl
(
unsigned
int
cmd
,
unsigned
long
arg
)
{
unlink_vcc
(
atm_sk
(
sk
));
sk_free
(
sk
);
}
void
*
buf
;
int
error
,
len
,
number
,
size
=
0
;
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
int
*
tmp_buf
,
*
tmp_p
;
switch
(
cmd
)
{
case
ATM_GETNAMES
:
if
(
get_user
(
buf
,
&
((
struct
atm_iobuf
*
)
arg
)
->
buffer
))
return
-
EFAULT
;
if
(
get_user
(
len
,
&
((
struct
atm_iobuf
*
)
arg
)
->
length
))
return
-
EFAULT
;
spin_lock
(
&
atm_dev_lock
);
list_for_each
(
p
,
&
atm_devs
)
size
+=
sizeof
(
int
);
if
(
size
>
len
)
{
spin_unlock
(
&
atm_dev_lock
);
return
-
E2BIG
;
}
tmp_buf
=
kmalloc
(
size
,
GFP_ATOMIC
);
if
(
!
tmp_buf
)
{
spin_unlock
(
&
atm_dev_lock
);
return
-
ENOMEM
;
}
tmp_p
=
tmp_buf
;
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
*
tmp_p
++
=
dev
->
number
;
}
spin_unlock
(
&
atm_dev_lock
);
error
=
((
copy_to_user
(
buf
,
tmp_buf
,
size
))
||
put_user
(
size
,
&
((
struct
atm_iobuf
*
)
arg
)
->
length
))
?
-
EFAULT
:
0
;
kfree
(
tmp_buf
);
return
error
;
default:
break
;
}
void
bind_vcc
(
struct
atm_vcc
*
vcc
,
struct
atm_dev
*
dev
)
{
unsigned
long
flags
;
unlink_vcc
(
vcc
);
vcc
->
dev
=
dev
;
if
(
dev
)
{
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
vcc
->
next
=
NULL
;
vcc
->
prev
=
dev
->
last
;
if
(
dev
->
vccs
)
dev
->
last
->
next
=
vcc
;
else
dev
->
vccs
=
vcc
;
dev
->
last
=
vcc
;
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
if
(
get_user
(
buf
,
&
((
struct
atmif_sioc
*
)
arg
)
->
arg
))
return
-
EFAULT
;
if
(
get_user
(
len
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
))
return
-
EFAULT
;
if
(
get_user
(
number
,
&
((
struct
atmif_sioc
*
)
arg
)
->
number
))
return
-
EFAULT
;
if
(
!
(
dev
=
atm_dev_lookup
(
number
)))
return
-
ENODEV
;
switch
(
cmd
)
{
case
ATM_GETTYPE
:
size
=
strlen
(
dev
->
type
)
+
1
;
if
(
copy_to_user
(
buf
,
dev
->
type
,
size
))
{
error
=
-
EFAULT
;
goto
done
;
}
break
;
case
ATM_GETESI
:
size
=
ESI_LEN
;
if
(
copy_to_user
(
buf
,
dev
->
esi
,
size
))
{
error
=
-
EFAULT
;
goto
done
;
}
break
;
case
ATM_SETESI
:
{
int
i
;
for
(
i
=
0
;
i
<
ESI_LEN
;
i
++
)
if
(
dev
->
esi
[
i
])
{
error
=
-
EEXIST
;
goto
done
;
}
}
/* fall through */
case
ATM_SETESIF
:
{
unsigned
char
esi
[
ESI_LEN
];
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
}
if
(
copy_from_user
(
esi
,
buf
,
ESI_LEN
))
{
error
=
-
EFAULT
;
goto
done
;
}
memcpy
(
dev
->
esi
,
esi
,
ESI_LEN
);
error
=
ESI_LEN
;
goto
done
;
}
case
ATM_GETSTATZ
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
}
/* fall through */
case
ATM_GETSTAT
:
size
=
sizeof
(
struct
atm_dev_stats
);
error
=
fetch_stats
(
dev
,
buf
,
cmd
==
ATM_GETSTATZ
);
if
(
error
)
goto
done
;
break
;
case
ATM_GETCIRANGE
:
size
=
sizeof
(
struct
atm_cirange
);
if
(
copy_to_user
(
buf
,
&
dev
->
ci_range
,
size
))
{
error
=
-
EFAULT
;
goto
done
;
}
break
;
case
ATM_GETLINKRATE
:
size
=
sizeof
(
int
);
if
(
copy_to_user
(
buf
,
&
dev
->
link_rate
,
size
))
{
error
=
-
EFAULT
;
goto
done
;
}
break
;
case
ATM_RSTADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
}
atm_reset_addr
(
dev
);
break
;
case
ATM_ADDADDR
:
case
ATM_DELADDR
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
}
{
struct
sockaddr_atmsvc
addr
;
if
(
copy_from_user
(
&
addr
,
buf
,
sizeof
(
addr
)))
{
error
=
-
EFAULT
;
goto
done
;
}
if
(
cmd
==
ATM_ADDADDR
)
error
=
atm_add_addr
(
dev
,
&
addr
);
else
error
=
atm_del_addr
(
dev
,
&
addr
);
goto
done
;
}
case
ATM_GETADDR
:
error
=
atm_get_addr
(
dev
,
buf
,
len
);
if
(
error
<
0
)
goto
done
;
size
=
error
;
/* may return 0, but later on size == 0 means "don't
write the length" */
error
=
put_user
(
size
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
)
?
-
EFAULT
:
0
;
goto
done
;
case
ATM_SETLOOP
:
if
(
__ATM_LM_XTRMT
((
int
)
(
long
)
buf
)
&&
__ATM_LM_XTLOC
((
int
)
(
long
)
buf
)
>
__ATM_LM_XTRMT
((
int
)
(
long
)
buf
))
{
error
=
-
EINVAL
;
goto
done
;
}
/* fall through */
case
ATM_SETCIRANGE
:
case
SONET_GETSTATZ
:
case
SONET_SETDIAG
:
case
SONET_CLRDIAG
:
case
SONET_SETFRAMING
:
if
(
!
capable
(
CAP_NET_ADMIN
))
{
error
=
-
EPERM
;
goto
done
;
}
/* fall through */
default:
if
(
!
dev
->
ops
->
ioctl
)
{
error
=
-
EINVAL
;
goto
done
;
}
size
=
dev
->
ops
->
ioctl
(
dev
,
cmd
,
buf
);
if
(
size
<
0
)
{
error
=
(
size
==
-
ENOIOCTLCMD
?
-
EINVAL
:
size
);
goto
done
;
}
}
if
(
size
)
error
=
put_user
(
size
,
&
((
struct
atmif_sioc
*
)
arg
)
->
length
)
?
-
EFAULT
:
0
;
else
error
=
0
;
done:
atm_dev_put
(
dev
);
return
error
;
}
EXPORT_SYMBOL
(
atm_dev_register
);
EXPORT_SYMBOL
(
atm_dev_deregister
);
EXPORT_SYMBOL
(
atm_dev_lookup
);
EXPORT_SYMBOL
(
shutdown_atm_dev
);
EXPORT_SYMBOL
(
bind_vcc
);
net/atm/resources.h
View file @
b9bf3d83
...
...
@@ -14,8 +14,7 @@ extern struct list_head atm_devs;
extern
spinlock_t
atm_dev_lock
;
struct
sock
*
alloc_atm_vcc_sk
(
int
family
);
void
free_atm_vcc_sk
(
struct
sock
*
sk
);
int
atm_dev_ioctl
(
unsigned
int
cmd
,
unsigned
long
arg
);
#ifdef CONFIG_PROC_FS
...
...
net/atm/signaling.c
View file @
b9bf3d83
...
...
@@ -124,14 +124,16 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
reply
=
msg
->
reply
;
vcc
->
sk
->
sk_err
=
-
msg
->
reply
;
break
;
case
as_indicate
:
vcc
=
*
(
struct
atm_vcc
**
)
&
msg
->
listen_vcc
;
DPRINTK
(
"as_indicate!!!
\n
"
);
lock_sock
(
vcc
->
sk
);
if
(
vcc
->
sk
->
sk_ack_backlog
==
vcc
->
sk
->
sk_max_ack_backlog
)
{
sigd_enq
(
0
,
as_reject
,
vcc
,
NULL
,
NULL
);
return
0
;
goto
as_indicate_complete
;
}
vcc
->
sk
->
sk_ack_backlog
++
;
skb_queue_tail
(
&
vcc
->
sk
->
sk_receive_queue
,
skb
);
...
...
@@ -140,11 +142,14 @@ static int sigd_send(struct atm_vcc *vcc,struct sk_buff *skb)
&
vcc
->
sleep
);
vcc
->
callback
(
vcc
);
}
as_indicate_complete:
release_sock
(
vcc
->
sk
);
return
0
;
case
as_close
:
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
reply
=
msg
->
reply
;
vcc
->
sk
->
sk_err
=
-
msg
->
reply
;
break
;
case
as_modify
:
modify_qos
(
vcc
,
msg
);
...
...
@@ -195,25 +200,21 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type,
}
static
void
purge_vcc
s
(
struct
atm_vcc
*
vcc
)
static
void
purge_vcc
(
struct
atm_vcc
*
vcc
)
{
while
(
vcc
)
{
if
(
vcc
->
sk
->
sk_family
==
PF_ATMSVC
&&
!
test_bit
(
ATM_VF_META
,
&
vcc
->
flags
))
{
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
vcc
->
reply
=
-
EUNATCH
;
wake_up
(
&
vcc
->
sleep
);
}
vcc
=
vcc
->
next
;
if
(
vcc
->
sk
->
sk_family
==
PF_ATMSVC
&&
!
test_bit
(
ATM_VF_META
,
&
vcc
->
flags
))
{
set_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
);
vcc
->
reply
=
-
EUNATCH
;
vcc
->
sk
->
sk_err
=
EUNATCH
;
wake_up
(
&
vcc
->
sleep
);
}
}
static
void
sigd_close
(
struct
atm_vcc
*
vcc
)
{
unsigned
long
flags
;
struct
atm_dev
*
dev
;
struct
list_head
*
p
;
struct
sock
*
s
;
DPRINTK
(
"sigd_close
\n
"
);
sigd
=
NULL
;
...
...
@@ -221,14 +222,14 @@ static void sigd_close(struct atm_vcc *vcc)
printk
(
KERN_ERR
"sigd_close: closing with requests pending
\n
"
);
skb_queue_purge
(
&
vcc
->
sk
->
sk_receive_queue
);
spin_lock
(
&
atm_dev
_lock
);
list_for_each
(
p
,
&
atm_devs
)
{
dev
=
list_entry
(
p
,
struct
atm_dev
,
dev_list
);
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
purge_vccs
(
dev
->
vccs
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
read_lock
(
&
vcc_sklist
_lock
);
for
(
s
=
vcc_sklist
;
s
;
s
=
s
->
sk_next
)
{
struct
atm_vcc
*
vcc
=
atm_sk
(
s
);
if
(
vcc
->
dev
)
purge_vcc
(
vcc
);
}
spin_unlock
(
&
atm_dev
_lock
);
read_unlock
(
&
vcc_sklist
_lock
);
}
...
...
@@ -251,7 +252,8 @@ int sigd_attach(struct atm_vcc *vcc)
if
(
sigd
)
return
-
EADDRINUSE
;
DPRINTK
(
"sigd_attach
\n
"
);
sigd
=
vcc
;
bind_vcc
(
vcc
,
&
sigd_dev
);
vcc
->
dev
=
&
sigd_dev
;
vcc_insert_socket
(
vcc
->
sk
);
set_bit
(
ATM_VF_META
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
wake_up
(
&
sigd_sleep
);
...
...
net/atm/svc.c
View file @
b9bf3d83
...
...
@@ -59,18 +59,18 @@ static int svc_shutdown(struct socket *sock,int how)
static
void
svc_disconnect
(
struct
atm_vcc
*
vcc
)
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
struct
sk_buff
*
skb
;
DPRINTK
(
"svc_disconnect %p
\n
"
,
vcc
);
if
(
test_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
))
{
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
}
/* beware - socket is still in use by atmsigd until the last
as_indicate has been answered */
...
...
@@ -88,18 +88,21 @@ static void svc_disconnect(struct atm_vcc *vcc)
static
int
svc_release
(
struct
socket
*
sock
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
;
if
(
!
sock
->
sk
)
return
0
;
vcc
=
ATM_SD
(
sock
);
DPRINTK
(
"svc_release %p
\n
"
,
vcc
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
atm_release_vcc_sk
(
sock
->
sk
,
0
);
svc_disconnect
(
vcc
);
/* VCC pointer is used as a reference, so we must not free it
(thereby subjecting it to re-use) before all pending connections
are closed */
free_atm_vcc_sk
(
sock
->
sk
);
if
(
sk
)
{
vcc
=
ATM_SD
(
sock
);
DPRINTK
(
"svc_release %p
\n
"
,
vcc
);
clear_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
/* VCC pointer is used as a reference, so we must not free it
(thereby subjecting it to re-use) before all pending connections
are closed */
sock_hold
(
sk
);
vcc_release
(
sock
);
svc_disconnect
(
vcc
);
sock_put
(
sk
);
}
return
0
;
}
...
...
@@ -107,80 +110,138 @@ static int svc_release(struct socket *sock)
static
int
svc_bind
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmsvc
*
addr
;
struct
atm_vcc
*
vcc
;
int
error
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
return
-
EINVAL
;
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
return
-
EINVAL
;
lock_sock
(
sk
);
if
(
sock
->
state
==
SS_CONNECTED
)
{
error
=
-
EISCONN
;
goto
out
;
}
if
(
sock
->
state
!=
SS_UNCONNECTED
)
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
=
ATM_SD
(
sock
);
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
return
-
EAFNOSUPPORT
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
{
error
=
-
EAFNOSUPPORT
;
goto
out
;
}
clear_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
/* failing rebind will kill old binding */
/* @@@ check memory (de)allocation on rebind */
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
vcc
->
local
=
*
addr
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_bind
,
NULL
,
NULL
,
&
vcc
->
local
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
/* doesn't count */
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
!
vcc
->
reply
)
set_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
return
vcc
->
reply
;
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
if
(
!
vcc
->
reply
)
set_bit
(
ATM_VF_BOUND
,
&
vcc
->
flags
);
error
=
vcc
->
reply
;
out:
release_sock
(
sk
);
return
error
;
}
static
int
svc_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
sockaddr
,
int
sockaddr_len
,
int
flags
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_atmsvc
*
addr
;
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
DPRINTK
(
"svc_connect %p
\n
"
,
vcc
);
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
return
-
EINVAL
;
if
(
sock
->
state
==
SS_CONNECTED
)
return
-
EISCONN
;
if
(
sock
->
state
==
SS_CONNECTING
)
{
if
(
vcc
->
reply
==
WAITING
)
return
-
EALREADY
;
sock
->
state
=
SS_UNCONNECTED
;
if
(
vcc
->
reply
)
return
vcc
->
reply
;
lock_sock
(
sk
);
if
(
sockaddr_len
!=
sizeof
(
struct
sockaddr_atmsvc
))
{
error
=
-
EINVAL
;
goto
out
;
}
else
{
int
error
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
return
-
EINVAL
;
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
switch
(
sock
->
state
)
{
default:
error
=
-
EINVAL
;
goto
out
;
case
SS_CONNECTED
:
error
=
-
EISCONN
;
goto
out
;
case
SS_CONNECTING
:
if
(
vcc
->
reply
==
WAITING
)
{
error
=
-
EALREADY
;
goto
out
;
}
sock
->
state
=
SS_UNCONNECTED
;
if
(
vcc
->
reply
)
{
error
=
vcc
->
reply
;
goto
out
;
}
break
;
case
SS_UNCONNECTED
:
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
addr
=
(
struct
sockaddr_atmsvc
*
)
sockaddr
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
return
-
EAFNOSUPPORT
;
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
return
-
EBADFD
;
if
(
addr
->
sas_family
!=
AF_ATMSVC
)
{
error
=
-
EAFNOSUPPORT
;
goto
out
;
}
if
(
!
test_bit
(
ATM_VF_HASQOS
,
&
vcc
->
flags
))
{
error
=
-
EBADFD
;
goto
out
;
}
if
(
vcc
->
qos
.
txtp
.
traffic_class
==
ATM_ANYCLASS
||
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
return
-
EINVAL
;
vcc
->
qos
.
rxtp
.
traffic_class
==
ATM_ANYCLASS
)
{
error
=
-
EINVAL
;
goto
out
;
}
if
(
!
vcc
->
qos
.
txtp
.
traffic_class
&&
!
vcc
->
qos
.
rxtp
.
traffic_class
)
return
-
EINVAL
;
!
vcc
->
qos
.
rxtp
.
traffic_class
)
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
->
remote
=
*
addr
;
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_connect
,
NULL
,
NULL
,
&
vcc
->
remote
);
if
(
flags
&
O_NONBLOCK
)
{
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
sock
->
state
=
SS_CONNECTING
;
return
-
EINPROGRESS
;
error
=
-
EINPROGRESS
;
goto
out
;
}
error
=
0
;
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
schedule
();
if
(
!
signal_pending
(
current
))
continue
;
if
(
!
signal_pending
(
current
))
{
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
continue
;
}
DPRINTK
(
"*ABORT*
\n
"
);
/*
* This is tricky:
...
...
@@ -196,13 +257,13 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
*/
sigd_enq
(
vcc
,
as_close
,
NULL
,
NULL
,
NULL
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UN
INTERRUPTIBLE
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_
INTERRUPTIBLE
);
schedule
();
}
if
(
!
vcc
->
reply
)
while
(
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
set_current_state
(
TASK_UN
INTERRUPTIBLE
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_
INTERRUPTIBLE
);
schedule
();
}
clear_bit
(
ATM_VF_REGIS
,
&
vcc
->
flags
);
...
...
@@ -212,10 +273,17 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
error
=
-
EINTR
;
break
;
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
return
error
;
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
vcc
->
reply
)
return
vcc
->
reply
;
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
error
)
goto
out
;
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
if
(
vcc
->
reply
)
{
error
=
vcc
->
reply
;
goto
out
;
}
}
/*
* Not supported yet
...
...
@@ -228,56 +296,73 @@ static int svc_connect(struct socket *sock,struct sockaddr *sockaddr,
/*
* #endif
*/
if
(
!
(
error
=
atm_connect
(
sock
,
vcc
->
itf
,
vcc
->
vpi
,
vcc
->
vci
)))
if
(
!
(
error
=
vcc_connect
(
sock
,
vcc
->
itf
,
vcc
->
vpi
,
vcc
->
vci
)))
sock
->
state
=
SS_CONNECTED
;
else
(
void
)
svc_disconnect
(
vcc
);
out:
release_sock
(
sk
);
return
error
;
}
static
int
svc_listen
(
struct
socket
*
sock
,
int
backlog
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DEFINE_WAIT
(
wait
);
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
=
ATM_SD
(
sock
);
int
error
;
DPRINTK
(
"svc_listen %p
\n
"
,
vcc
);
lock_sock
(
sk
);
/* let server handle listen on unbound sockets */
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
return
-
EINVAL
;
if
(
test_bit
(
ATM_VF_SESSION
,
&
vcc
->
flags
))
{
error
=
-
EINVAL
;
goto
out
;
}
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
vcc
,
as_listen
,
NULL
,
NULL
,
&
vcc
->
local
);
while
(
vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
set_bit
(
ATM_VF_LISTEN
,
&
vcc
->
flags
);
vcc
->
sk
->
sk_max_ack_backlog
=
backlog
>
0
?
backlog
:
ATM_BACKLOG_DEFAULT
;
return
vcc
->
reply
;
error
=
vcc
->
reply
;
out:
release_sock
(
sk
);
return
error
;
}
static
int
svc_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sk_buff
*
skb
;
struct
atmsvc_msg
*
msg
;
struct
atm_vcc
*
old_vcc
=
ATM_SD
(
sock
);
struct
atm_vcc
*
new_vcc
;
int
error
;
lock_sock
(
sk
);
error
=
svc_create
(
newsock
,
0
);
if
(
error
)
return
error
;
goto
out
;
new_vcc
=
ATM_SD
(
newsock
);
DPRINTK
(
"svc_accept %p -> %p
\n
"
,
old_vcc
,
new_vcc
);
while
(
1
)
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
add_wait_queue
(
&
old_vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
old_vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
while
(
!
(
skb
=
skb_dequeue
(
&
old_vcc
->
sk
->
sk_receive_queue
))
&&
sigd
)
{
if
(
test_bit
(
ATM_VF_RELEASED
,
&
old_vcc
->
flags
))
break
;
...
...
@@ -289,46 +374,63 @@ static int svc_accept(struct socket *sock,struct socket *newsock,int flags)
error
=
-
EAGAIN
;
break
;
}
set_current_state
(
TASK_INTERRUPTIBLE
);
release_sock
(
sk
);
schedule
();
lock_sock
(
sk
);
if
(
signal_pending
(
current
))
{
error
=
-
ERESTARTSYS
;
break
;
}
prepare_to_wait
(
&
old_vcc
->
sleep
,
&
wait
,
TASK_INTERRUPTIBLE
);
}
finish_wait
(
&
old_vcc
->
sleep
,
&
wait
);
if
(
error
)
goto
out
;
if
(
!
skb
)
{
error
=
-
EUNATCH
;
goto
out
;
}
remove_wait_queue
(
&
old_vcc
->
sleep
,
&
wait
);
if
(
error
)
return
error
;
if
(
!
skb
)
return
-
EUNATCH
;
msg
=
(
struct
atmsvc_msg
*
)
skb
->
data
;
new_vcc
->
qos
=
msg
->
qos
;
set_bit
(
ATM_VF_HASQOS
,
&
new_vcc
->
flags
);
new_vcc
->
remote
=
msg
->
svc
;
new_vcc
->
local
=
msg
->
local
;
new_vcc
->
sap
=
msg
->
sap
;
error
=
atm_connect
(
newsock
,
msg
->
pvc
.
sap_addr
.
itf
,
msg
->
pvc
.
sap_addr
.
vpi
,
msg
->
pvc
.
sap_addr
.
vci
);
error
=
vcc_connect
(
newsock
,
msg
->
pvc
.
sap_addr
.
itf
,
msg
->
pvc
.
sap_addr
.
vpi
,
msg
->
pvc
.
sap_addr
.
vci
);
dev_kfree_skb
(
skb
);
old_vcc
->
sk
->
sk_ack_backlog
--
;
if
(
error
)
{
sigd_enq2
(
NULL
,
as_reject
,
old_vcc
,
NULL
,
NULL
,
&
old_vcc
->
qos
,
error
);
return
error
==
-
EAGAIN
?
-
EBUSY
:
error
;
error
=
error
==
-
EAGAIN
?
-
EBUSY
:
error
;
goto
out
;
}
/* wait should be short, so we ignore the non-blocking flag */
new_vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
new_vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
new_vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq
(
new_vcc
,
as_accept
,
old_vcc
,
NULL
,
NULL
);
while
(
new_vcc
->
reply
==
WAITING
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
release_sock
(
sk
);
schedule
();
lock_sock
(
sk
);
prepare_to_wait
(
&
new_vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
finish_wait
(
&
new_vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
{
error
=
-
EUNATCH
;
goto
out
;
}
remove_wait_queue
(
&
new_vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
if
(
!
new_vcc
->
reply
)
break
;
if
(
new_vcc
->
reply
!=
-
ERESTARTSYS
)
return
new_vcc
->
reply
;
if
(
new_vcc
->
reply
!=
-
ERESTARTSYS
)
{
error
=
new_vcc
->
reply
;
goto
out
;
}
}
newsock
->
state
=
SS_CONNECTED
;
return
0
;
out:
release_sock
(
sk
);
return
error
;
}
...
...
@@ -347,17 +449,17 @@ static int svc_getname(struct socket *sock,struct sockaddr *sockaddr,
int
svc_change_qos
(
struct
atm_vcc
*
vcc
,
struct
atm_qos
*
qos
)
{
DE
CLARE_WAITQUEUE
(
wait
,
curren
t
);
DE
FINE_WAIT
(
wai
t
);
vcc
->
reply
=
WAITING
;
add_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
sigd_enq2
(
vcc
,
as_modify
,
NULL
,
NULL
,
&
vcc
->
local
,
qos
,
0
);
while
(
vcc
->
reply
==
WAITING
&&
!
test_bit
(
ATM_VF_RELEASED
,
&
vcc
->
flags
)
&&
sigd
)
{
set_current_state
(
TASK_UNINTERRUPTIBLE
);
schedule
();
prepare_to_wait
(
&
vcc
->
sleep
,
&
wait
,
TASK_UNINTERRUPTIBLE
);
}
remove_wait_queue
(
&
vcc
->
sleep
,
&
wait
);
finish_wait
(
&
vcc
->
sleep
,
&
wait
);
if
(
!
sigd
)
return
-
EUNATCH
;
return
vcc
->
reply
;
}
...
...
@@ -366,33 +468,57 @@ int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
static
int
svc_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
struct
atm_vcc
*
vcc
;
int
error
=
0
;
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
||
optlen
!=
sizeof
(
struct
atm_sap
))
return
atm_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
optlen
!=
sizeof
(
struct
atm_sap
))
{
error
=
vcc_setsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
goto
out
;
}
vcc
=
ATM_SD
(
sock
);
if
(
copy_from_user
(
&
vcc
->
sap
,
optval
,
optlen
))
return
-
EFAULT
;
set_bit
(
ATM_VF_HASSAP
,
&
vcc
->
flags
);
return
0
;
if
(
copy_from_user
(
&
vcc
->
sap
,
optval
,
optlen
))
{
error
=
-
EFAULT
;
goto
out
;
}
set_bit
(
ATM_VF_HASSAP
,
&
vcc
->
flags
);
out:
release_sock
(
sk
);
return
error
;
}
static
int
svc_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
int
len
;
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
)
return
atm_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
if
(
len
!=
sizeof
(
struct
atm_sap
))
return
-
EINVAL
;
return
copy_to_user
(
optval
,
&
ATM_SD
(
sock
)
->
sap
,
sizeof
(
struct
atm_sap
))
?
-
EFAULT
:
0
;
struct
sock
*
sk
=
sock
->
sk
;
int
error
=
0
,
len
;
lock_sock
(
sk
);
if
(
!
__SO_LEVEL_MATCH
(
optname
,
level
)
||
optname
!=
SO_ATMSAP
)
{
error
=
vcc_getsockopt
(
sock
,
level
,
optname
,
optval
,
optlen
);
goto
out
;
}
if
(
get_user
(
len
,
optlen
))
{
error
=
-
EFAULT
;
goto
out
;
}
if
(
len
!=
sizeof
(
struct
atm_sap
))
{
error
=
-
EINVAL
;
goto
out
;
}
if
(
copy_to_user
(
optval
,
&
ATM_SD
(
sock
)
->
sap
,
sizeof
(
struct
atm_sap
)))
{
error
=
-
EFAULT
;
goto
out
;
}
out:
release_sock
(
sk
);
return
error
;
}
static
struct
proto_ops
SOCKOPS_WRAPPED
(
svc_proto_ops
)
=
{
static
struct
proto_ops
svc_proto_ops
=
{
.
family
=
PF_ATMSVC
,
.
release
=
svc_release
,
...
...
@@ -402,27 +528,24 @@ static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = {
.
accept
=
svc_accept
,
.
getname
=
svc_getname
,
.
poll
=
atm_poll
,
.
ioctl
=
atm
_ioctl
,
.
ioctl
=
vcc
_ioctl
,
.
listen
=
svc_listen
,
.
shutdown
=
svc_shutdown
,
.
setsockopt
=
svc_setsockopt
,
.
getsockopt
=
svc_getsockopt
,
.
sendmsg
=
atm
_sendmsg
,
.
recvmsg
=
atm
_recvmsg
,
.
sendmsg
=
vcc
_sendmsg
,
.
recvmsg
=
vcc
_recvmsg
,
.
mmap
=
sock_no_mmap
,
.
sendpage
=
sock_no_sendpage
,
};
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
svc_proto
,
PF_ATMSVC
);
static
int
svc_create
(
struct
socket
*
sock
,
int
protocol
)
{
int
error
;
sock
->
ops
=
&
svc_proto_ops
;
error
=
atm_create
(
sock
,
protocol
,
AF_ATMSVC
);
error
=
vcc_create
(
sock
,
protocol
,
AF_ATMSVC
);
if
(
error
)
return
error
;
ATM_SD
(
sock
)
->
callback
=
svc_callback
;
ATM_SD
(
sock
)
->
local
.
sas_family
=
AF_ATMSVC
;
...
...
net/ipv4/igmp.c
View file @
b9bf3d83
...
...
@@ -387,8 +387,17 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc,
if
(
type
==
IGMPV3_ALLOW_NEW_SOURCES
||
type
==
IGMPV3_BLOCK_OLD_SOURCES
)
return
skb
;
if
(
pmc
->
crcount
||
isquery
)
if
(
pmc
->
crcount
||
isquery
)
{
/* make sure we have room for group header and at
* least one source.
*/
if
(
skb
&&
AVAILABLE
(
skb
)
<
sizeof
(
struct
igmpv3_grec
)
+
sizeof
(
__u32
))
{
igmpv3_sendpack
(
skb
);
skb
=
0
;
/* add_grhead will get a new one */
}
skb
=
add_grhead
(
skb
,
pmc
,
type
,
&
pgr
);
}
return
skb
;
}
pih
=
skb
?
(
struct
igmpv3_report
*
)
skb
->
h
.
igmph
:
0
;
...
...
net/ipv6/mcast.c
View file @
b9bf3d83
...
...
@@ -1321,8 +1321,17 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
if
(
type
==
MLD2_ALLOW_NEW_SOURCES
||
type
==
MLD2_BLOCK_OLD_SOURCES
)
return
skb
;
if
(
pmc
->
mca_crcount
||
isquery
)
if
(
pmc
->
mca_crcount
||
isquery
)
{
/* make sure we have room for group header and at
* least one source.
*/
if
(
skb
&&
AVAILABLE
(
skb
)
<
sizeof
(
struct
mld2_grec
)
+
sizeof
(
struct
in6_addr
))
{
mld_sendpack
(
skb
);
skb
=
0
;
/* add_grhead will get a new one */
}
skb
=
add_grhead
(
skb
,
pmc
,
type
,
&
pgr
);
}
return
skb
;
}
pmr
=
skb
?
(
struct
mld2_report
*
)
skb
->
h
.
raw
:
0
;
...
...
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