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
b498a583
Commit
b498a583
authored
Sep 28, 2002
by
Arnaldo Carvalho de Melo
Committed by
David S. Miller
Sep 28, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
o X25: use refcnts and protect x25_neigh structs and list
Simplify some other code.
parent
92acfab5
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
218 additions
and
202 deletions
+218
-202
include/net/x25.h
include/net/x25.h
+14
-1
net/x25/af_x25.c
net/x25/af_x25.c
+22
-16
net/x25/x25_dev.c
net/x25/x25_dev.c
+57
-64
net/x25/x25_facilities.c
net/x25/x25_facilities.c
+2
-2
net/x25/x25_link.c
net/x25/x25_link.c
+123
-119
No files found.
include/net/x25.h
View file @
b498a583
...
@@ -118,7 +118,7 @@ struct x25_route {
...
@@ -118,7 +118,7 @@ struct x25_route {
};
};
struct
x25_neigh
{
struct
x25_neigh
{
struct
x25_neigh
*
next
;
struct
list_head
node
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
unsigned
int
state
;
unsigned
int
state
;
unsigned
int
extended
;
unsigned
int
extended
;
...
@@ -126,6 +126,7 @@ struct x25_neigh {
...
@@ -126,6 +126,7 @@ struct x25_neigh {
unsigned
long
t20
;
unsigned
long
t20
;
struct
timer_list
t20timer
;
struct
timer_list
t20timer
;
unsigned
long
global_facil_mask
;
unsigned
long
global_facil_mask
;
atomic_t
refcnt
;
};
};
struct
x25_opt
{
struct
x25_opt
{
...
@@ -199,6 +200,18 @@ extern int x25_subscr_ioctl(unsigned int, void *);
...
@@ -199,6 +200,18 @@ extern int x25_subscr_ioctl(unsigned int, void *);
extern
struct
x25_neigh
*
x25_get_neigh
(
struct
net_device
*
);
extern
struct
x25_neigh
*
x25_get_neigh
(
struct
net_device
*
);
extern
void
x25_link_free
(
void
);
extern
void
x25_link_free
(
void
);
/* x25_neigh.c */
static
__inline__
void
x25_neigh_hold
(
struct
x25_neigh
*
nb
)
{
atomic_inc
(
&
nb
->
refcnt
);
}
static
__inline__
void
x25_neigh_put
(
struct
x25_neigh
*
nb
)
{
if
(
atomic_dec_and_test
(
&
nb
->
refcnt
))
kfree
(
nb
);
}
/* x25_out.c */
/* x25_out.c */
extern
int
x25_output
(
struct
sock
*
,
struct
sk_buff
*
);
extern
int
x25_output
(
struct
sock
*
,
struct
sk_buff
*
);
extern
void
x25_kick
(
struct
sock
*
);
extern
void
x25_kick
(
struct
sock
*
);
...
...
net/x25/af_x25.c
View file @
b498a583
...
@@ -188,7 +188,7 @@ static void x25_kill_by_device(struct net_device *dev)
...
@@ -188,7 +188,7 @@ static void x25_kill_by_device(struct net_device *dev)
static
int
x25_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
static
int
x25_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
{
{
struct
net_device
*
dev
=
ptr
;
struct
net_device
*
dev
=
ptr
;
struct
x25_neigh
*
n
eigh
;
struct
x25_neigh
*
n
b
;
if
(
dev
->
type
==
ARPHRD_X25
if
(
dev
->
type
==
ARPHRD_X25
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
...
@@ -200,8 +200,11 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo
...
@@ -200,8 +200,11 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo
x25_link_device_up
(
dev
);
x25_link_device_up
(
dev
);
break
;
break
;
case
NETDEV_GOING_DOWN
:
case
NETDEV_GOING_DOWN
:
if
((
neigh
=
x25_get_neigh
(
dev
)))
nb
=
x25_get_neigh
(
dev
);
x25_terminate_link
(
neigh
);
if
(
nb
)
{
x25_terminate_link
(
nb
);
x25_neigh_put
(
nb
);
}
break
;
break
;
case
NETDEV_DOWN
:
case
NETDEV_DOWN
:
x25_kill_by_device
(
dev
);
x25_kill_by_device
(
dev
);
...
@@ -255,7 +258,7 @@ static struct sock *x25_find_listener(struct x25_address *addr)
...
@@ -255,7 +258,7 @@ static struct sock *x25_find_listener(struct x25_address *addr)
/*
/*
* Find a connected X.25 socket given my LCI and neighbour.
* Find a connected X.25 socket given my LCI and neighbour.
*/
*/
struct
sock
*
x25_find_socket
(
unsigned
int
lci
,
struct
x25_neigh
*
n
eigh
)
struct
sock
*
x25_find_socket
(
unsigned
int
lci
,
struct
x25_neigh
*
n
b
)
{
{
struct
sock
*
s
;
struct
sock
*
s
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -264,7 +267,7 @@ struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
...
@@ -264,7 +267,7 @@ struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
cli
();
cli
();
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
(
x25_sk
(
s
)
->
lci
==
lci
&&
x25_sk
(
s
)
->
neighbour
==
n
eigh
)
if
(
x25_sk
(
s
)
->
lci
==
lci
&&
x25_sk
(
s
)
->
neighbour
==
n
b
)
break
;
break
;
restore_flags
(
flags
);
restore_flags
(
flags
);
...
@@ -274,11 +277,11 @@ struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
...
@@ -274,11 +277,11 @@ struct sock *x25_find_socket(unsigned int lci, struct x25_neigh *neigh)
/*
/*
* Find a unique LCI for a given device.
* Find a unique LCI for a given device.
*/
*/
unsigned
int
x25_new_lci
(
struct
x25_neigh
*
n
eigh
)
unsigned
int
x25_new_lci
(
struct
x25_neigh
*
n
b
)
{
{
unsigned
int
lci
=
1
;
unsigned
int
lci
=
1
;
while
(
x25_find_socket
(
lci
,
n
eigh
))
while
(
x25_find_socket
(
lci
,
n
b
))
if
(
++
lci
==
4096
)
{
if
(
++
lci
==
4096
)
{
lci
=
0
;
lci
=
0
;
break
;
break
;
...
@@ -631,11 +634,11 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
...
@@ -631,11 +634,11 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
x25
->
lci
=
x25_new_lci
(
x25
->
neighbour
);
x25
->
lci
=
x25_new_lci
(
x25
->
neighbour
);
if
(
!
x25
->
lci
)
if
(
!
x25
->
lci
)
goto
out_put_
route
;
goto
out_put_
neigh
;
rc
=
-
EINVAL
;
rc
=
-
EINVAL
;
if
(
sk
->
zapped
)
/* Must bind first - autobinding does not work */
if
(
sk
->
zapped
)
/* Must bind first - autobinding does not work */
goto
out_put_
route
;
goto
out_put_
neigh
;
if
(
!
strcmp
(
x25
->
source_addr
.
x25_addr
,
null_x25_address
.
x25_addr
))
if
(
!
strcmp
(
x25
->
source_addr
.
x25_addr
,
null_x25_address
.
x25_addr
))
memset
(
&
x25
->
source_addr
,
'\0'
,
X25_ADDR_LEN
);
memset
(
&
x25
->
source_addr
,
'\0'
,
X25_ADDR_LEN
);
...
@@ -656,7 +659,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
...
@@ -656,7 +659,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
/* Now the loop */
/* Now the loop */
rc
=
-
EINPROGRESS
;
rc
=
-
EINPROGRESS
;
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
goto
out_put_
route
;
goto
out_put_
neigh
;
cli
();
/* To avoid races on the sleep */
cli
();
/* To avoid races on the sleep */
...
@@ -681,6 +684,9 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
...
@@ -681,6 +684,9 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
rc
=
0
;
rc
=
0
;
out_unlock:
out_unlock:
sti
();
sti
();
out_put_neigh:
if
(
rc
)
x25_neigh_put
(
x25
->
neighbour
);
out_put_route:
out_put_route:
x25_route_put
(
rt
);
x25_route_put
(
rt
);
out:
out:
...
@@ -758,7 +764,7 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_l
...
@@ -758,7 +764,7 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_l
return
0
;
return
0
;
}
}
int
x25_rx_call_request
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
eigh
,
unsigned
int
lci
)
int
x25_rx_call_request
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
b
,
unsigned
int
lci
)
{
{
struct
sock
*
sk
;
struct
sock
*
sk
;
struct
sock
*
make
;
struct
sock
*
make
;
...
@@ -800,7 +806,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
...
@@ -800,7 +806,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
* on certain facilties
* on certain facilties
*/
*/
x25_limit_facilities
(
&
facilities
,
neigh
);
x25_limit_facilities
(
&
facilities
,
nb
);
/*
/*
* Try to create a new socket.
* Try to create a new socket.
...
@@ -821,7 +827,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
...
@@ -821,7 +827,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
makex25
->
lci
=
lci
;
makex25
->
lci
=
lci
;
makex25
->
dest_addr
=
dest_addr
;
makex25
->
dest_addr
=
dest_addr
;
makex25
->
source_addr
=
source_addr
;
makex25
->
source_addr
=
source_addr
;
makex25
->
neighbour
=
n
eigh
;
makex25
->
neighbour
=
n
b
;
makex25
->
facilities
=
facilities
;
makex25
->
facilities
=
facilities
;
makex25
->
vc_facil_mask
=
x25_sk
(
sk
)
->
vc_facil_mask
;
makex25
->
vc_facil_mask
=
x25_sk
(
sk
)
->
vc_facil_mask
;
...
@@ -853,7 +859,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
...
@@ -853,7 +859,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
return
rc
;
return
rc
;
out_clear_request:
out_clear_request:
rc
=
0
;
rc
=
0
;
x25_transmit_clear_request
(
n
eigh
,
lci
,
0x01
);
x25_transmit_clear_request
(
n
b
,
lci
,
0x01
);
goto
out
;
goto
out
;
}
}
...
@@ -1358,12 +1364,12 @@ struct notifier_block x25_dev_notifier = {
...
@@ -1358,12 +1364,12 @@ struct notifier_block x25_dev_notifier = {
.
notifier_call
=
x25_device_event
,
.
notifier_call
=
x25_device_event
,
};
};
void
x25_kill_by_neigh
(
struct
x25_neigh
*
n
eigh
)
void
x25_kill_by_neigh
(
struct
x25_neigh
*
n
b
)
{
{
struct
sock
*
s
;
struct
sock
*
s
;
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
(
x25_sk
(
s
)
->
neighbour
==
n
eigh
)
if
(
x25_sk
(
s
)
->
neighbour
==
n
b
)
x25_disconnect
(
s
,
ENETUNREACH
,
0
,
0
);
x25_disconnect
(
s
,
ENETUNREACH
,
0
,
0
);
}
}
...
...
net/x25/x25_dev.c
View file @
b498a583
...
@@ -44,7 +44,7 @@
...
@@ -44,7 +44,7 @@
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <net/x25.h>
#include <net/x25.h>
static
int
x25_receive_data
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
eigh
)
static
int
x25_receive_data
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
b
)
{
{
struct
sock
*
sk
;
struct
sock
*
sk
;
unsigned
short
frametype
;
unsigned
short
frametype
;
...
@@ -58,14 +58,14 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
...
@@ -58,14 +58,14 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
* frame.
* frame.
*/
*/
if
(
lci
==
0
)
{
if
(
lci
==
0
)
{
x25_link_control
(
skb
,
n
eigh
,
frametype
);
x25_link_control
(
skb
,
n
b
,
frametype
);
return
0
;
return
0
;
}
}
/*
/*
* Find an existing socket.
* Find an existing socket.
*/
*/
if
((
sk
=
x25_find_socket
(
lci
,
n
eigh
))
!=
NULL
)
{
if
((
sk
=
x25_find_socket
(
lci
,
n
b
))
!=
NULL
)
{
int
queued
=
1
;
int
queued
=
1
;
skb
->
h
.
raw
=
skb
->
data
;
skb
->
h
.
raw
=
skb
->
data
;
...
@@ -83,91 +83,87 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
...
@@ -83,91 +83,87 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
* Is is a Call Request ? if so process it.
* Is is a Call Request ? if so process it.
*/
*/
if
(
frametype
==
X25_CALL_REQUEST
)
if
(
frametype
==
X25_CALL_REQUEST
)
return
x25_rx_call_request
(
skb
,
n
eigh
,
lci
);
return
x25_rx_call_request
(
skb
,
n
b
,
lci
);
/*
/*
* Its not a Call Request, nor is it a control frame.
* Its not a Call Request, nor is it a control frame.
* Let caller throw it away.
* Let caller throw it away.
*/
*/
/*
/*
x25_transmit_clear_request(n
eigh
, lci, 0x0D);
x25_transmit_clear_request(n
b
, lci, 0x0D);
*/
*/
printk
(
KERN_DEBUG
"x25_receive_data(): unknown frame type %2x
\n
"
,
frametype
);
printk
(
KERN_DEBUG
"x25_receive_data(): unknown frame type %2x
\n
"
,
frametype
);
return
0
;
return
0
;
}
}
int
x25_lapb_receive_frame
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
ptype
)
int
x25_lapb_receive_frame
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
ptype
)
{
{
struct
x25_neigh
*
neigh
;
struct
x25_neigh
*
nb
;
int
queued
;
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
/*
/*
*
Packet received from unrecognised device, throw it away.
*
Packet received from unrecognised device, throw it away.
*/
*/
if
((
neigh
=
x25_get_neigh
(
dev
))
==
NULL
)
{
nb
=
x25_get_neigh
(
dev
);
if
(
!
nb
)
{
printk
(
KERN_DEBUG
"X.25: unknown neighbour - %s
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"X.25: unknown neighbour - %s
\n
"
,
dev
->
name
);
kfree_skb
(
skb
);
goto
drop
;
return
0
;
}
}
switch
(
skb
->
data
[
0
])
{
switch
(
skb
->
data
[
0
])
{
case
0x00
:
case
0x00
:
skb_pull
(
skb
,
1
);
skb_pull
(
skb
,
1
);
queued
=
x25_receive_data
(
skb
,
neigh
);
if
(
x25_receive_data
(
skb
,
nb
))
{
if
(
!
queued
)
x25_neigh_put
(
nb
);
/* We need to free the skb ourselves because
goto
out
;
* net_bh() won't care about our return code.
}
*/
break
;
kfree_skb
(
skb
);
return
0
;
case
0x01
:
case
0x01
:
x25_link_established
(
neigh
);
x25_link_established
(
nb
);
kfree_skb
(
skb
);
break
;
return
0
;
case
0x02
:
case
0x02
:
x25_link_terminated
(
neigh
);
x25_link_terminated
(
nb
);
kfree_skb
(
skb
);
break
;
return
0
;
case
0x03
:
kfree_skb
(
skb
);
return
0
;
default:
kfree_skb
(
skb
);
return
0
;
}
}
x25_neigh_put
(
nb
);
drop:
kfree_skb
(
skb
);
out:
return
0
;
}
}
int
x25_llc_receive_frame
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
ptype
)
int
x25_llc_receive_frame
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
struct
packet_type
*
ptype
)
{
{
struct
x25_neigh
*
neigh
;
struct
x25_neigh
*
nb
;
int
rc
=
0
;
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
/*
/*
*
Packet received from unrecognised device, throw it away.
*
Packet received from unrecognised device, throw it away.
*/
*/
if
((
neigh
=
x25_get_neigh
(
dev
))
==
NULL
)
{
nb
=
x25_get_neigh
(
dev
);
if
(
!
nb
)
{
printk
(
KERN_DEBUG
"X.25: unknown_neighbour - %s
\n
"
,
dev
->
name
);
printk
(
KERN_DEBUG
"X.25: unknown_neighbour - %s
\n
"
,
dev
->
name
);
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
0
;
}
else
{
rc
=
x25_receive_data
(
skb
,
nb
);
x25_neigh_put
(
nb
);
}
}
return
x25_receive_data
(
skb
,
neigh
)
;
return
rc
;
}
}
void
x25_establish_link
(
struct
x25_neigh
*
n
eigh
)
void
x25_establish_link
(
struct
x25_neigh
*
n
b
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
unsigned
char
*
ptr
;
unsigned
char
*
ptr
;
switch
(
n
eigh
->
dev
->
type
)
{
switch
(
n
b
->
dev
->
type
)
{
case
ARPHRD_X25
:
case
ARPHRD_X25
:
if
((
skb
=
alloc_skb
(
1
,
GFP_ATOMIC
))
==
NULL
)
{
if
((
skb
=
alloc_skb
(
1
,
GFP_ATOMIC
))
==
NULL
)
{
printk
(
KERN_ERR
"x25_dev: out of memory
\n
"
);
printk
(
KERN_ERR
"x25_dev: out of memory
\n
"
);
...
@@ -186,47 +182,44 @@ void x25_establish_link(struct x25_neigh *neigh)
...
@@ -186,47 +182,44 @@ void x25_establish_link(struct x25_neigh *neigh)
}
}
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
n
eigh
->
dev
;
skb
->
dev
=
n
b
->
dev
;
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
}
}
void
x25_terminate_link
(
struct
x25_neigh
*
n
eigh
)
void
x25_terminate_link
(
struct
x25_neigh
*
n
b
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
unsigned
char
*
ptr
;
unsigned
char
*
ptr
;
switch
(
neigh
->
dev
->
type
)
{
case
ARPHRD_X25
:
if
((
skb
=
alloc_skb
(
1
,
GFP_ATOMIC
))
==
NULL
)
{
printk
(
KERN_ERR
"x25_dev: out of memory
\n
"
);
return
;
}
ptr
=
skb_put
(
skb
,
1
);
*
ptr
=
0x02
;
break
;
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
case
ARPHRD_ETHER
:
if
(
nb
->
dev
->
type
==
ARPHRD_ETHER
)
return
;
return
;
#endif
#endif
default:
if
(
nb
->
dev
->
type
!=
ARPHRD_X25
)
return
;
return
;
skb
=
alloc_skb
(
1
,
GFP_ATOMIC
);
if
(
!
skb
)
{
printk
(
KERN_ERR
"x25_dev: out of memory
\n
"
);
return
;
}
}
skb
->
protocol
=
htons
(
ETH_P_X25
);
ptr
=
skb_put
(
skb
,
1
);
skb
->
dev
=
neigh
->
dev
;
*
ptr
=
0x02
;
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
nb
->
dev
;
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
}
}
void
x25_send_frame
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
eigh
)
void
x25_send_frame
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
b
)
{
{
unsigned
char
*
dptr
;
unsigned
char
*
dptr
;
skb
->
nh
.
raw
=
skb
->
data
;
skb
->
nh
.
raw
=
skb
->
data
;
switch
(
n
eigh
->
dev
->
type
)
{
switch
(
n
b
->
dev
->
type
)
{
case
ARPHRD_X25
:
case
ARPHRD_X25
:
dptr
=
skb_push
(
skb
,
1
);
dptr
=
skb_push
(
skb
,
1
);
*
dptr
=
0x00
;
*
dptr
=
0x00
;
...
@@ -243,7 +236,7 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh)
...
@@ -243,7 +236,7 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh)
}
}
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
n
eigh
->
dev
;
skb
->
dev
=
n
b
->
dev
;
dev_queue_xmit
(
skb
);
dev_queue_xmit
(
skb
);
}
}
net/x25/x25_facilities.c
View file @
b498a583
...
@@ -229,10 +229,10 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
...
@@ -229,10 +229,10 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
* currently attached x25 link.
* currently attached x25 link.
*/
*/
void
x25_limit_facilities
(
struct
x25_facilities
*
facilities
,
void
x25_limit_facilities
(
struct
x25_facilities
*
facilities
,
struct
x25_neigh
*
n
eighbour
)
struct
x25_neigh
*
n
b
)
{
{
if
(
!
n
eighbour
->
extended
)
{
if
(
!
n
b
->
extended
)
{
if
(
facilities
->
winsize_in
>
7
)
{
if
(
facilities
->
winsize_in
>
7
)
{
printk
(
KERN_DEBUG
"X.25: incoming winsize limited to 7
\n
"
);
printk
(
KERN_DEBUG
"X.25: incoming winsize limited to 7
\n
"
);
facilities
->
winsize_in
=
7
;
facilities
->
winsize_in
=
7
;
...
...
net/x25/x25_link.c
View file @
b498a583
...
@@ -43,47 +43,48 @@
...
@@ -43,47 +43,48 @@
#include <linux/init.h>
#include <linux/init.h>
#include <net/x25.h>
#include <net/x25.h>
static
struct
x25_neigh
*
x25_neigh_list
;
/* = NULL initially */
static
struct
list_head
x25_neigh_list
=
LIST_HEAD_INIT
(
x25_neigh_list
);
static
rwlock_t
x25_neigh_list_lock
=
RW_LOCK_UNLOCKED
;
static
void
x25_t20timer_expiry
(
unsigned
long
);
static
void
x25_t20timer_expiry
(
unsigned
long
);
/*
/*
* Linux set/reset timer routines
* Linux set/reset timer routines
*/
*/
static
void
x25_start_t20timer
(
struct
x25_neigh
*
n
eigh
)
static
void
x25_start_t20timer
(
struct
x25_neigh
*
n
b
)
{
{
del_timer
(
&
n
eigh
->
t20timer
);
del_timer
(
&
n
b
->
t20timer
);
n
eigh
->
t20timer
.
data
=
(
unsigned
long
)
neigh
;
n
b
->
t20timer
.
data
=
(
unsigned
long
)
nb
;
n
eigh
->
t20timer
.
function
=
&
x25_t20timer_expiry
;
n
b
->
t20timer
.
function
=
&
x25_t20timer_expiry
;
n
eigh
->
t20timer
.
expires
=
jiffies
+
neigh
->
t20
;
n
b
->
t20timer
.
expires
=
jiffies
+
nb
->
t20
;
add_timer
(
&
n
eigh
->
t20timer
);
add_timer
(
&
n
b
->
t20timer
);
}
}
static
void
x25_t20timer_expiry
(
unsigned
long
param
)
static
void
x25_t20timer_expiry
(
unsigned
long
param
)
{
{
struct
x25_neigh
*
n
eigh
=
(
struct
x25_neigh
*
)
param
;
struct
x25_neigh
*
n
b
=
(
struct
x25_neigh
*
)
param
;
x25_transmit_restart_request
(
n
eigh
);
x25_transmit_restart_request
(
n
b
);
x25_start_t20timer
(
n
eigh
);
x25_start_t20timer
(
n
b
);
}
}
static
void
x25_stop_t20timer
(
struct
x25_neigh
*
n
eigh
)
static
void
x25_stop_t20timer
(
struct
x25_neigh
*
n
b
)
{
{
del_timer
(
&
n
eigh
->
t20timer
);
del_timer
(
&
n
b
->
t20timer
);
}
}
static
int
x25_t20timer_pending
(
struct
x25_neigh
*
n
eigh
)
static
int
x25_t20timer_pending
(
struct
x25_neigh
*
n
b
)
{
{
return
timer_pending
(
&
n
eigh
->
t20timer
);
return
timer_pending
(
&
n
b
->
t20timer
);
}
}
/*
/*
* This handles all restart and diagnostic frames.
* This handles all restart and diagnostic frames.
*/
*/
void
x25_link_control
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
eigh
,
void
x25_link_control
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
b
,
unsigned
short
frametype
)
unsigned
short
frametype
)
{
{
struct
sk_buff
*
skbn
;
struct
sk_buff
*
skbn
;
...
@@ -91,16 +92,16 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh,
...
@@ -91,16 +92,16 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh,
switch
(
frametype
)
{
switch
(
frametype
)
{
case
X25_RESTART_REQUEST
:
case
X25_RESTART_REQUEST
:
confirm
=
!
x25_t20timer_pending
(
n
eigh
);
confirm
=
!
x25_t20timer_pending
(
n
b
);
x25_stop_t20timer
(
n
eigh
);
x25_stop_t20timer
(
n
b
);
n
eigh
->
state
=
X25_LINK_STATE_3
;
n
b
->
state
=
X25_LINK_STATE_3
;
if
(
confirm
)
if
(
confirm
)
x25_transmit_restart_confirmation
(
n
eigh
);
x25_transmit_restart_confirmation
(
n
b
);
break
;
break
;
case
X25_RESTART_CONFIRMATION
:
case
X25_RESTART_CONFIRMATION
:
x25_stop_t20timer
(
n
eigh
);
x25_stop_t20timer
(
n
b
);
n
eigh
->
state
=
X25_LINK_STATE_3
;
n
b
->
state
=
X25_LINK_STATE_3
;
break
;
break
;
case
X25_DIAGNOSTIC
:
case
X25_DIAGNOSTIC
:
...
@@ -116,15 +117,15 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh,
...
@@ -116,15 +117,15 @@ void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh,
break
;
break
;
}
}
if
(
n
eigh
->
state
==
X25_LINK_STATE_3
)
if
(
n
b
->
state
==
X25_LINK_STATE_3
)
while
((
skbn
=
skb_dequeue
(
&
n
eigh
->
queue
))
!=
NULL
)
while
((
skbn
=
skb_dequeue
(
&
n
b
->
queue
))
!=
NULL
)
x25_send_frame
(
skbn
,
n
eigh
);
x25_send_frame
(
skbn
,
n
b
);
}
}
/*
/*
* This routine is called when a Restart Request is needed
* This routine is called when a Restart Request is needed
*/
*/
void
x25_transmit_restart_request
(
struct
x25_neigh
*
n
eigh
)
void
x25_transmit_restart_request
(
struct
x25_neigh
*
n
b
)
{
{
unsigned
char
*
dptr
;
unsigned
char
*
dptr
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
...
@@ -137,7 +138,7 @@ void x25_transmit_restart_request(struct x25_neigh *neigh)
...
@@ -137,7 +138,7 @@ void x25_transmit_restart_request(struct x25_neigh *neigh)
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
*
dptr
++
=
n
eigh
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
n
b
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_RESTART_REQUEST
;
*
dptr
++
=
X25_RESTART_REQUEST
;
*
dptr
++
=
0x00
;
*
dptr
++
=
0x00
;
...
@@ -145,13 +146,13 @@ void x25_transmit_restart_request(struct x25_neigh *neigh)
...
@@ -145,13 +146,13 @@ void x25_transmit_restart_request(struct x25_neigh *neigh)
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
}
}
/*
/*
* This routine is called when a Restart Confirmation is needed
* This routine is called when a Restart Confirmation is needed
*/
*/
void
x25_transmit_restart_confirmation
(
struct
x25_neigh
*
n
eigh
)
void
x25_transmit_restart_confirmation
(
struct
x25_neigh
*
n
b
)
{
{
unsigned
char
*
dptr
;
unsigned
char
*
dptr
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
;
...
@@ -164,19 +165,19 @@ void x25_transmit_restart_confirmation(struct x25_neigh *neigh)
...
@@ -164,19 +165,19 @@ void x25_transmit_restart_confirmation(struct x25_neigh *neigh)
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
);
*
dptr
++
=
n
eigh
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
n
b
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_RESTART_CONFIRMATION
;
*
dptr
++
=
X25_RESTART_CONFIRMATION
;
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
}
}
/*
/*
* This routine is called when a Diagnostic is required.
* This routine is called when a Diagnostic is required.
*/
*/
void
x25_transmit_diagnostic
(
struct
x25_neigh
*
n
eigh
,
unsigned
char
diag
)
void
x25_transmit_diagnostic
(
struct
x25_neigh
*
n
b
,
unsigned
char
diag
)
{
{
unsigned
char
*
dptr
;
unsigned
char
*
dptr
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
1
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
1
;
...
@@ -189,21 +190,22 @@ void x25_transmit_diagnostic(struct x25_neigh *neigh, unsigned char diag)
...
@@ -189,21 +190,22 @@ void x25_transmit_diagnostic(struct x25_neigh *neigh, unsigned char diag)
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
1
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
1
);
*
dptr
++
=
n
eigh
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
n
b
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_DIAGNOSTIC
;
*
dptr
++
=
X25_DIAGNOSTIC
;
*
dptr
++
=
diag
;
*
dptr
++
=
diag
;
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
}
}
/*
/*
* This routine is called when a Clear Request is needed outside of the context
* This routine is called when a Clear Request is needed outside of the context
* of a connected socket.
* of a connected socket.
*/
*/
void
x25_transmit_clear_request
(
struct
x25_neigh
*
neigh
,
unsigned
int
lci
,
unsigned
char
cause
)
void
x25_transmit_clear_request
(
struct
x25_neigh
*
nb
,
unsigned
int
lci
,
unsigned
char
cause
)
{
{
unsigned
char
*
dptr
;
unsigned
char
*
dptr
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
...
@@ -216,7 +218,7 @@ void x25_transmit_clear_request(struct x25_neigh *neigh, unsigned int lci, unsig
...
@@ -216,7 +218,7 @@ void x25_transmit_clear_request(struct x25_neigh *neigh, unsigned int lci, unsig
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
*
dptr
++
=
((
lci
>>
8
)
&
0x0F
)
|
n
eigh
->
extended
?
X25_GFI_EXTSEQ
:
*
dptr
++
=
((
lci
>>
8
)
&
0x0F
)
|
n
b
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
X25_GFI_STDSEQ
;
*
dptr
++
=
(
lci
>>
0
)
&
0xFF
;
*
dptr
++
=
(
lci
>>
0
)
&
0xFF
;
*
dptr
++
=
X25_CLEAR_REQUEST
;
*
dptr
++
=
X25_CLEAR_REQUEST
;
...
@@ -225,23 +227,23 @@ void x25_transmit_clear_request(struct x25_neigh *neigh, unsigned int lci, unsig
...
@@ -225,23 +227,23 @@ void x25_transmit_clear_request(struct x25_neigh *neigh, unsigned int lci, unsig
skb
->
sk
=
NULL
;
skb
->
sk
=
NULL
;
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
}
}
void
x25_transmit_link
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
eigh
)
void
x25_transmit_link
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
n
b
)
{
{
switch
(
n
eigh
->
state
)
{
switch
(
n
b
->
state
)
{
case
X25_LINK_STATE_0
:
case
X25_LINK_STATE_0
:
skb_queue_tail
(
&
n
eigh
->
queue
,
skb
);
skb_queue_tail
(
&
n
b
->
queue
,
skb
);
n
eigh
->
state
=
X25_LINK_STATE_1
;
n
b
->
state
=
X25_LINK_STATE_1
;
x25_establish_link
(
n
eigh
);
x25_establish_link
(
n
b
);
break
;
break
;
case
X25_LINK_STATE_1
:
case
X25_LINK_STATE_1
:
case
X25_LINK_STATE_2
:
case
X25_LINK_STATE_2
:
skb_queue_tail
(
&
n
eigh
->
queue
,
skb
);
skb_queue_tail
(
&
n
b
->
queue
,
skb
);
break
;
break
;
case
X25_LINK_STATE_3
:
case
X25_LINK_STATE_3
:
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
break
;
break
;
}
}
}
}
...
@@ -249,16 +251,16 @@ void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *neigh)
...
@@ -249,16 +251,16 @@ void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *neigh)
/*
/*
* Called when the link layer has become established.
* Called when the link layer has become established.
*/
*/
void
x25_link_established
(
struct
x25_neigh
*
n
eigh
)
void
x25_link_established
(
struct
x25_neigh
*
n
b
)
{
{
switch
(
n
eigh
->
state
)
{
switch
(
n
b
->
state
)
{
case
X25_LINK_STATE_0
:
case
X25_LINK_STATE_0
:
n
eigh
->
state
=
X25_LINK_STATE_2
;
n
b
->
state
=
X25_LINK_STATE_2
;
break
;
break
;
case
X25_LINK_STATE_1
:
case
X25_LINK_STATE_1
:
x25_transmit_restart_request
(
n
eigh
);
x25_transmit_restart_request
(
n
b
);
n
eigh
->
state
=
X25_LINK_STATE_2
;
n
b
->
state
=
X25_LINK_STATE_2
;
x25_start_t20timer
(
n
eigh
);
x25_start_t20timer
(
n
b
);
break
;
break
;
}
}
}
}
...
@@ -268,11 +270,11 @@ void x25_link_established(struct x25_neigh *neigh)
...
@@ -268,11 +270,11 @@ void x25_link_established(struct x25_neigh *neigh)
* request has failed.
* request has failed.
*/
*/
void
x25_link_terminated
(
struct
x25_neigh
*
n
eigh
)
void
x25_link_terminated
(
struct
x25_neigh
*
n
b
)
{
{
n
eigh
->
state
=
X25_LINK_STATE_0
;
n
b
->
state
=
X25_LINK_STATE_0
;
/* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */
/* Out of order: clear existing virtual calls (X.25 03/93 4.6.3) */
x25_kill_by_neigh
(
n
eigh
);
x25_kill_by_neigh
(
n
b
);
}
}
/*
/*
...
@@ -280,65 +282,50 @@ void x25_link_terminated(struct x25_neigh *neigh)
...
@@ -280,65 +282,50 @@ void x25_link_terminated(struct x25_neigh *neigh)
*/
*/
void
x25_link_device_up
(
struct
net_device
*
dev
)
void
x25_link_device_up
(
struct
net_device
*
dev
)
{
{
unsigned
long
flags
;
struct
x25_neigh
*
nb
=
kmalloc
(
sizeof
(
*
nb
),
GFP_ATOMIC
);
struct
x25_neigh
*
x25_neigh
=
kmalloc
(
sizeof
(
*
x25_neigh
),
GFP_ATOMIC
);
if
(
!
x25_neigh
)
if
(
!
nb
)
return
;
return
;
skb_queue_head_init
(
&
x25_neigh
->
queue
);
skb_queue_head_init
(
&
nb
->
queue
);
init_timer
(
&
x25_neigh
->
t20timer
);
init_timer
(
&
nb
->
t20timer
);
dev_hold
(
dev
);
dev_hold
(
dev
);
x25_neigh
->
dev
=
dev
;
nb
->
dev
=
dev
;
x25_neigh
->
state
=
X25_LINK_STATE_0
;
nb
->
state
=
X25_LINK_STATE_0
;
x25_neigh
->
extended
=
0
;
nb
->
extended
=
0
;
/*
/*
* Enables negotiation
* Enables negotiation
*/
*/
x25_neigh
->
global_facil_mask
=
X25_MASK_REVERSE
|
nb
->
global_facil_mask
=
X25_MASK_REVERSE
|
X25_MASK_THROUGHPUT
|
X25_MASK_THROUGHPUT
|
X25_MASK_PACKET_SIZE
|
X25_MASK_PACKET_SIZE
|
X25_MASK_WINDOW_SIZE
;
X25_MASK_WINDOW_SIZE
;
x25_neigh
->
t20
=
sysctl_x25_restart_request_timeout
;
nb
->
t20
=
sysctl_x25_restart_request_timeout
;
atomic_set
(
&
nb
->
refcnt
,
1
);
save_flags
(
flags
);
cli
();
write_lock_bh
(
&
x25_neigh_list_lock
);
x25_neigh
->
next
=
x25_neigh_list
;
list_add
(
&
nb
->
node
,
&
x25_neigh_list
);
x25_neigh_list
=
x25_neigh
;
write_unlock_bh
(
&
x25_neigh_list_lock
);
restore_flags
(
flags
);
}
}
static
void
x25_remove_neigh
(
struct
x25_neigh
*
x25_neigh
)
/**
* __x25_remove_neigh - remove neighbour from x25_neigh_list
* @nb - neigh to remove
*
* Remove neighbour from x25_neigh_list. If it was there.
* Caller must hold x25_neigh_list_lock.
*/
static
void
__x25_remove_neigh
(
struct
x25_neigh
*
nb
)
{
{
struct
x25_neigh
*
s
;
skb_queue_purge
(
&
nb
->
queue
);
unsigned
long
flags
;
x25_stop_t20timer
(
nb
);
skb_queue_purge
(
&
x25_neigh
->
queue
);
x25_stop_t20timer
(
x25_neigh
);
save_flags
(
flags
);
cli
();
if
((
s
=
x25_neigh_list
)
==
x25_neigh
)
{
x25_neigh_list
=
x25_neigh
->
next
;
goto
out_kfree_neigh
;
}
while
(
s
&&
s
->
next
)
{
if
(
s
->
next
==
x25_neigh
)
{
s
->
next
=
x25_neigh
->
next
;
goto
out_kfree_neigh
;
}
s
=
s
->
next
;
if
(
nb
->
node
.
next
)
{
list_del
(
&
nb
->
node
);
x25_neigh_put
(
nb
);
}
}
out:
restore_flags
(
flags
);
return
;
out_kfree_neigh:
kfree
(
x25_neigh
);
goto
out
;
}
}
/*
/*
...
@@ -346,17 +333,21 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh)
...
@@ -346,17 +333,21 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh)
*/
*/
void
x25_link_device_down
(
struct
net_device
*
dev
)
void
x25_link_device_down
(
struct
net_device
*
dev
)
{
{
struct
x25_neigh
*
neigh
,
*
x25_neigh
=
x25_neigh_list
;
struct
x25_neigh
*
nb
;
struct
list_head
*
entry
,
*
tmp
;
while
(
x25_neigh
)
{
write_lock_bh
(
&
x25_neigh_list_lock
);
neigh
=
x25_neigh
;
x25_neigh
=
x25_neigh
->
next
;
if
(
neigh
->
dev
==
dev
)
{
list_for_each_safe
(
entry
,
tmp
,
&
x25_neigh_list
)
{
x25_remove_neigh
(
neigh
);
nb
=
list_entry
(
entry
,
struct
x25_neigh
,
node
);
if
(
nb
->
dev
==
dev
)
{
__x25_remove_neigh
(
nb
);
dev_put
(
dev
);
dev_put
(
dev
);
}
}
}
}
write_unlock_bh
(
&
x25_neigh_list_lock
);
}
}
/*
/*
...
@@ -364,13 +355,23 @@ void x25_link_device_down(struct net_device *dev)
...
@@ -364,13 +355,23 @@ void x25_link_device_down(struct net_device *dev)
*/
*/
struct
x25_neigh
*
x25_get_neigh
(
struct
net_device
*
dev
)
struct
x25_neigh
*
x25_get_neigh
(
struct
net_device
*
dev
)
{
{
struct
x25_neigh
*
x25_neigh
=
x25_neigh_list
;
struct
x25_neigh
*
nb
,
*
use
=
NULL
;
struct
list_head
*
entry
;
for
(;
x25_neigh
;
x25_neigh
=
x25_neigh
->
next
)
read_lock_bh
(
&
x25_neigh_list_lock
);
if
(
x25_neigh
->
dev
==
dev
)
list_for_each
(
entry
,
&
x25_neigh_list
)
{
nb
=
list_entry
(
entry
,
struct
x25_neigh
,
node
);
if
(
nb
->
dev
==
dev
)
{
use
=
nb
;
break
;
break
;
}
}
return
x25_neigh
;
if
(
use
)
x25_neigh_hold
(
use
);
read_unlock_bh
(
&
x25_neigh_list_lock
);
return
use
;
}
}
/*
/*
...
@@ -379,7 +380,7 @@ struct x25_neigh *x25_get_neigh(struct net_device *dev)
...
@@ -379,7 +380,7 @@ struct x25_neigh *x25_get_neigh(struct net_device *dev)
int
x25_subscr_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
int
x25_subscr_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
{
{
struct
x25_subscrip_struct
x25_subscr
;
struct
x25_subscrip_struct
x25_subscr
;
struct
x25_neigh
*
x25_neigh
;
struct
x25_neigh
*
nb
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
int
rc
=
-
EINVAL
;
int
rc
=
-
EINVAL
;
...
@@ -394,27 +395,28 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
...
@@ -394,27 +395,28 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
if
((
dev
=
x25_dev_get
(
x25_subscr
.
device
))
==
NULL
)
if
((
dev
=
x25_dev_get
(
x25_subscr
.
device
))
==
NULL
)
goto
out
;
goto
out
;
if
((
x25_neigh
=
x25_get_neigh
(
dev
))
==
NULL
)
if
((
nb
=
x25_get_neigh
(
dev
))
==
NULL
)
goto
out_put
;
goto
out_
dev_
put
;
dev_put
(
dev
);
dev_put
(
dev
);
if
(
cmd
==
SIOCX25GSUBSCRIP
)
{
if
(
cmd
==
SIOCX25GSUBSCRIP
)
{
x25_subscr
.
extended
=
x25_neigh
->
extended
;
x25_subscr
.
extended
=
nb
->
extended
;
x25_subscr
.
global_facil_mask
=
x25_neigh
->
global_facil_mask
;
x25_subscr
.
global_facil_mask
=
nb
->
global_facil_mask
;
rc
=
copy_to_user
(
arg
,
&
x25_subscr
,
rc
=
copy_to_user
(
arg
,
&
x25_subscr
,
sizeof
(
x25_subscr
))
?
-
EFAULT
:
0
;
sizeof
(
x25_subscr
))
?
-
EFAULT
:
0
;
}
else
{
}
else
{
rc
=
-
EINVAL
;
rc
=
-
EINVAL
;
if
(
x25_subscr
.
extended
&&
x25_subscr
.
extended
!=
1
)
if
(
!
(
x25_subscr
.
extended
&&
x25_subscr
.
extended
!=
1
))
{
goto
out
;
rc
=
0
;
rc
=
0
;
nb
->
extended
=
x25_subscr
.
extended
;
x25_neigh
->
extended
=
x25_subscr
.
extended
;
nb
->
global_facil_mask
=
x25_subscr
.
global_facil_mask
;
x25_neigh
->
global_facil_mask
=
x25_subscr
.
global_facil_mask
;
}
}
}
x25_neigh_put
(
nb
);
out:
out:
return
rc
;
return
rc
;
out_put:
out_
dev_
put:
dev_put
(
dev
);
dev_put
(
dev
);
goto
out
;
goto
out
;
}
}
...
@@ -425,12 +427,14 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
...
@@ -425,12 +427,14 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
*/
*/
void
__exit
x25_link_free
(
void
)
void
__exit
x25_link_free
(
void
)
{
{
struct
x25_neigh
*
neigh
,
*
x25_neigh
=
x25_neigh_list
;
struct
x25_neigh
*
nb
;
struct
list_head
*
entry
,
*
tmp
;
while
(
x25_neigh
)
{
write_lock_bh
(
&
x25_neigh_list_lock
);
neigh
=
x25_neigh
;
x25_neigh
=
x25_neigh
->
next
;
x25_remove_neigh
(
neigh
);
list_for_each_safe
(
entry
,
tmp
,
&
x25_neigh_list
)
{
nb
=
list_entry
(
entry
,
struct
x25_neigh
,
node
);
__x25_remove_neigh
(
nb
);
}
}
write_unlock_bh
(
&
x25_neigh_list_lock
);
}
}
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