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
5c0fbae1
Commit
5c0fbae1
authored
Sep 29, 2002
by
Arnaldo Carvalho de Melo
Browse files
Options
Browse Files
Download
Plain Diff
Merge hera.kernel.org:/home/acme/BK/x25-2.5.old
into hera.kernel.org:/home/acme/BK/x25-2.5
parents
536ce362
004ffedc
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1777 additions
and
1393 deletions
+1777
-1393
drivers/net/wan/lapbether.c
drivers/net/wan/lapbether.c
+168
-137
include/linux/x25.h
include/linux/x25.h
+8
-8
include/net/lapb.h
include/net/lapb.h
+31
-29
include/net/x25.h
include/net/x25.h
+48
-13
net/lapb/lapb_iface.c
net/lapb/lapb_iface.c
+175
-133
net/lapb/lapb_in.c
net/lapb/lapb_in.c
+210
-130
net/lapb/lapb_out.c
net/lapb/lapb_out.c
+35
-34
net/lapb/lapb_subr.c
net/lapb/lapb_subr.c
+55
-30
net/lapb/lapb_timer.c
net/lapb/lapb_timer.c
+7
-7
net/x25/af_x25.c
net/x25/af_x25.c
+432
-340
net/x25/sysctl_net_x25.c
net/x25/sysctl_net_x25.c
+75
-25
net/x25/x25_dev.c
net/x25/x25_dev.c
+57
-64
net/x25/x25_facilities.c
net/x25/x25_facilities.c
+91
-78
net/x25/x25_in.c
net/x25/x25_in.c
+13
-12
net/x25/x25_link.c
net/x25/x25_link.c
+181
-176
net/x25/x25_out.c
net/x25/x25_out.c
+18
-14
net/x25/x25_route.c
net/x25/x25_route.c
+143
-131
net/x25/x25_subr.c
net/x25/x25_subr.c
+16
-16
net/x25/x25_timer.c
net/x25/x25_timer.c
+14
-16
No files found.
drivers/net/wan/lapbether.c
View file @
5c0fbae1
...
...
@@ -44,42 +44,63 @@
#include <linux/lapb.h>
#include <linux/init.h>
static
char
bcast_addr
[
6
]
=
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
};
static
char
bcast_addr
[
6
]
=
{
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
,
0xFF
};
/* If this number is made larger, check that the temporary string buffer
* in lapbeth_new_device is large enough to store the probe device name.*/
#define MAXLAPBDEV 100
static
struct
lapbethdev
{
struct
lapbethdev
*
next
;
char
ethname
[
14
];
/* ether device name */
struct
net_device
*
ethdev
;
/* link to ethernet device */
struct
net_device
axdev
;
/* lapbeth device (lapb#) */
struct
net_device_stats
stats
;
/* some statistics */
}
*
lapbeth_devices
/* = NULL initially */
;
struct
lapbethdev
{
struct
list_head
node
;
char
ethname
[
14
];
/* ether device name */
struct
net_device
*
ethdev
;
/* link to ethernet device */
struct
net_device
axdev
;
/* lapbeth device (lapb#) */
struct
net_device_stats
stats
;
/* some statistics */
atomic_t
refcnt
;
};
static
struct
list_head
lapbeth_devices
=
LIST_HEAD_INIT
(
lapbeth_devices
);
static
rwlock_t
lapbeth_devices_lock
=
RW_LOCK_UNLOCKED
;
static
__inline__
void
lapbeth_hold
(
struct
lapbethdev
*
lapbeth
)
{
atomic_inc
(
&
lapbeth
->
refcnt
);
}
static
__inline__
void
lapbeth_put
(
struct
lapbethdev
*
lapbeth
)
{
if
(
atomic_dec_and_test
(
&
lapbeth
->
refcnt
))
kfree
(
lapbeth
);
}
/* ------------------------------------------------------------------------ */
/*
* Get the LAPB device for the ethernet device
*/
static
inline
struct
net_device
*
lapbeth_get_x25_dev
(
struct
net_device
*
dev
)
static
__inline__
struct
lapbethdev
*
lapbeth_get_x25_dev
(
struct
net_device
*
dev
)
{
struct
lapbethdev
*
lapbeth
;
struct
list_head
*
entry
;
struct
lapbethdev
*
lapbeth
,
*
use
=
NULL
;
read_lock
(
&
lapbeth_devices_lock
);
for
(
lapbeth
=
lapbeth_devices
;
lapbeth
!=
NULL
;
lapbeth
=
lapbeth
->
next
)
if
(
lapbeth
->
ethdev
==
dev
)
return
&
lapbeth
->
axdev
;
list_for_each
(
entry
,
&
lapbeth_devices
)
{
lapbeth
=
list_entry
(
entry
,
struct
lapbethdev
,
node
);
if
(
lapbeth
->
ethdev
==
dev
)
{
use
=
lapbeth
;
break
;
}
}
if
(
use
)
lapbeth_hold
(
use
);
return
NULL
;
read_unlock
(
&
lapbeth_devices_lock
);
return
use
;
}
static
inline
int
dev_is_ethdev
(
struct
net_device
*
dev
)
static
__inline__
int
dev_is_ethdev
(
struct
net_device
*
dev
)
{
return
(
dev
->
type
==
ARPHRD_ETHER
&&
strncmp
(
dev
->
name
,
"dummy"
,
5
)
);
return
dev
->
type
==
ARPHRD_ETHER
&&
strncmp
(
dev
->
name
,
"dummy"
,
5
);
}
/*
...
...
@@ -88,35 +109,26 @@ static inline int dev_is_ethdev(struct net_device *dev)
*/
static
int
lapbeth_check_devices
(
struct
net_device
*
dev
)
{
struct
lapbethdev
*
lapbeth
,
*
lapbeth_prev
,
*
lapbeth_next
;
struct
lapbethdev
*
lapbeth
;
struct
list_head
*
entry
,
*
tmp
;
int
result
=
0
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
write_lock
(
&
lapbeth_devices_lock
);
lapbeth_prev
=
NULL
;
list_for_each_safe
(
entry
,
tmp
,
&
lapbeth_devices
)
{
lapbeth
=
list_entry
(
entry
,
struct
lapbethdev
,
node
);
for
(
lapbeth
=
lapbeth_devices
;
lapbeth
!=
NULL
;
lapbeth
=
lapbeth_next
)
{
lapbeth_next
=
lapbeth
->
next
;
if
(
!
dev_get
(
lapbeth
->
ethname
))
{
if
(
lapbeth_prev
)
lapbeth_prev
->
next
=
lapbeth
->
next
;
else
lapbeth_devices
=
lapbeth
->
next
;
if
(
&
lapbeth
->
axdev
==
dev
)
result
=
1
;
unregister_netdev
(
&
lapbeth
->
axdev
);
dev_put
(
lapbeth
->
ethdev
);
kfree
(
lapbeth
);
list_del
(
&
lapbeth
->
node
);
lapbeth_put
(
lapbeth
);
}
else
lapbeth_prev
=
lapbeth
;
}
restore_flags
(
flags
);
write_unlock
(
&
lapbeth_devices_lock
);
return
result
;
}
...
...
@@ -133,14 +145,12 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
skb
->
sk
=
NULL
;
/* Initially we don't know who it's for */
dev
=
lapbeth_get_x25_dev
(
dev
);
lapbeth
=
lapbeth_get_x25_dev
(
dev
);
if
(
dev
==
NULL
||
!
netif_running
(
dev
))
{
kfree_skb
(
skb
);
return
0
;
}
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
if
(
!
lapbeth
)
goto
drop
;
if
(
!
netif_running
(
&
lapbeth
->
axdev
))
goto
put_drop
;
lapbeth
->
stats
.
rx_packets
++
;
...
...
@@ -150,16 +160,22 @@ static int lapbeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
skb_trim
(
skb
,
len
);
/* Set the length of the data */
if
((
err
=
lapb_data_received
(
lapbeth
,
skb
))
!=
LAPB_OK
)
{
kfree_skb
(
skb
);
printk
(
KERN_DEBUG
"lapbether: lapb_data_received err - %d
\n
"
,
err
);
goto
put_drop
;
}
lapbeth_put
(
lapbeth
);
out:
return
0
;
put_drop:
lapbeth_put
(
lapbeth
);
drop:
kfree_skb
(
skb
);
goto
out
;
}
static
int
lapbeth_data_indication
(
void
*
token
,
struct
sk_buff
*
skb
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
unsigned
char
*
ptr
;
ptr
=
skb_push
(
skb
,
1
);
...
...
@@ -178,8 +194,8 @@ static int lapbeth_data_indication(void *token, struct sk_buff *skb)
*/
static
int
lapbeth_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
int
err
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
int
err
=
-
ENODEV
;
/*
* Just to be *really* sure not to send anything if the interface
...
...
@@ -187,50 +203,53 @@ static int lapbeth_xmit(struct sk_buff *skb, struct net_device *dev)
*/
if
(
!
netif_running
(
dev
))
{
lapbeth_check_devices
(
dev
);
kfree_skb
(
skb
);
return
-
ENODEV
;
goto
drop
;
}
switch
(
skb
->
data
[
0
])
{
case
0x00
:
break
;
case
0x01
:
if
((
err
=
lapb_connect_request
(
lapbeth
))
!=
LAPB_OK
)
printk
(
KERN_ERR
"lapbeth: lapb_connect_request error - %d
\n
"
,
err
);
kfree_skb
(
skb
);
return
0
;
case
0x02
:
if
((
err
=
lapb_disconnect_request
(
lapbeth
))
!=
LAPB_OK
)
printk
(
KERN_ERR
"lapbeth: lapb_disconnect_request err - %d
\n
"
,
err
);
kfree_skb
(
skb
);
return
0
;
default:
kfree_skb
(
skb
);
return
0
;
case
0x00
:
err
=
0
;
break
;
case
0x01
:
if
((
err
=
lapb_connect_request
(
lapbeth
))
!=
LAPB_OK
)
printk
(
KERN_ERR
"lapbeth: lapb_connect_request "
"error: %d
\n
"
,
err
)
;
goto
drop_ok
;
case
0x02
:
if
((
err
=
lapb_disconnect_request
(
lapbeth
))
!=
LAPB_OK
)
printk
(
KERN_ERR
"lapbeth: lapb_disconnect_request "
"err: %d
\n
"
,
err
)
;
/* Fall thru */
default:
goto
drop_ok
;
}
skb_pull
(
skb
,
1
);
if
((
err
=
lapb_data_request
(
lapbeth
,
skb
))
!=
LAPB_OK
)
{
printk
(
KERN_ERR
"lapbeth: lapb_data_request error - %d
\n
"
,
err
);
kfree_skb
(
skb
)
;
return
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
drop
;
}
return
0
;
err
=
0
;
out:
return
err
;
drop_ok:
err
=
0
;
drop:
kfree_skb
(
skb
);
goto
out
;
}
static
void
lapbeth_data_transmit
(
void
*
token
,
struct
sk_buff
*
skb
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
unsigned
char
*
ptr
;
struct
net_device
*
dev
;
int
size
;
int
size
=
skb
->
len
;
skb
->
protocol
=
htons
(
ETH_P_X25
);
size
=
skb
->
len
;
ptr
=
skb_push
(
skb
,
2
);
*
ptr
++
=
size
%
256
;
...
...
@@ -247,11 +266,11 @@ static void lapbeth_data_transmit(void *token, struct sk_buff *skb)
static
void
lapbeth_connected
(
void
*
token
,
int
reason
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
struct
sk_buff
*
skb
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
unsigned
char
*
ptr
;
struct
sk_buff
*
skb
=
dev_alloc_skb
(
1
);
if
(
(
skb
=
dev_alloc_skb
(
1
))
==
NULL
)
{
if
(
!
skb
)
{
printk
(
KERN_ERR
"lapbeth: out of memory
\n
"
);
return
;
}
...
...
@@ -269,11 +288,11 @@ static void lapbeth_connected(void *token, int reason)
static
void
lapbeth_disconnected
(
void
*
token
,
int
reason
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
struct
sk_buff
*
skb
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
token
;
unsigned
char
*
ptr
;
struct
sk_buff
*
skb
=
dev_alloc_skb
(
1
);
if
(
(
skb
=
dev_alloc_skb
(
1
))
==
NULL
)
{
if
(
!
skb
)
{
printk
(
KERN_ERR
"lapbeth: out of memory
\n
"
);
return
;
}
...
...
@@ -294,7 +313,7 @@ static void lapbeth_disconnected(void *token, int reason)
*/
static
struct
net_device_stats
*
lapbeth_get_stats
(
struct
net_device
*
dev
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
return
&
lapbeth
->
stats
;
}
...
...
@@ -303,9 +322,9 @@ static struct net_device_stats *lapbeth_get_stats(struct net_device *dev)
*/
static
int
lapbeth_set_mac_address
(
struct
net_device
*
dev
,
void
*
addr
)
{
struct
sockaddr
*
sa
=
(
struct
sockaddr
*
)
addr
;
memcpy
(
dev
->
dev_addr
,
sa
->
sa_data
,
dev
->
addr_len
);
return
0
;
struct
sockaddr
*
sa
=
(
struct
sockaddr
*
)
addr
;
memcpy
(
dev
->
dev_addr
,
sa
->
sa_data
,
dev
->
addr_len
);
return
0
;
}
/*
...
...
@@ -320,7 +339,7 @@ static int lapbeth_open(struct net_device *dev)
if
(
lapbeth_check_devices
(
dev
))
return
-
ENODEV
;
/* oops, it's gone */
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
lapbeth_callbacks
.
connect_confirmation
=
lapbeth_connected
;
lapbeth_callbacks
.
connect_indication
=
lapbeth_connected
;
...
...
@@ -340,7 +359,7 @@ static int lapbeth_open(struct net_device *dev)
static
int
lapbeth_close
(
struct
net_device
*
dev
)
{
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
struct
lapbethdev
*
lapbeth
=
(
struct
lapbethdev
*
)
dev
->
priv
;
int
err
;
netif_stop_queue
(
dev
);
...
...
@@ -358,20 +377,21 @@ static int lapbeth_close(struct net_device *dev)
*/
static
int
lapbeth_new_device
(
struct
net_device
*
dev
)
{
int
k
;
unsigned
char
buf
[
14
];
struct
lapbethdev
*
lapbeth
,
*
lapbeth2
;
struct
lapbethdev
*
lapbeth
;
int
k
,
rc
=
-
ENOMEM
;
if
((
lapbeth
=
kmalloc
(
sizeof
(
struct
lapbethdev
),
GFP_
KERNEL
))
==
NULL
)
return
-
ENOMEM
;
if
((
lapbeth
=
kmalloc
(
sizeof
(
struct
lapbethdev
),
GFP_
ATOMIC
))
==
NULL
)
goto
out
;
memset
(
lapbeth
,
0
,
sizeof
(
struct
lapbethdev
));
dev_hold
(
dev
);
lapbeth
->
ethdev
=
dev
;
lapbeth
->
ethname
[
sizeof
(
lapbeth
->
ethname
)
-
1
]
=
'\0'
;
strncpy
(
lapbeth
->
ethname
,
dev
->
name
,
sizeof
(
lapbeth
->
ethname
)
-
1
);
strncpy
(
lapbeth
->
ethname
,
dev
->
name
,
sizeof
(
lapbeth
->
ethname
)
-
1
);
lapbeth
->
ethname
[
sizeof
(
lapbeth
->
ethname
)
-
1
]
=
'\0'
;
atomic_set
(
&
lapbeth
->
refcnt
,
1
);
dev
=
&
lapbeth
->
axdev
;
SET_MODULE_OWNER
(
dev
);
...
...
@@ -381,24 +401,21 @@ static int lapbeth_new_device(struct net_device *dev)
sprintf
(
buf
,
"lapb%d"
,
k
);
if
((
odev
=
__dev_get_by_name
(
buf
))
==
NULL
||
lapbeth_check_devices
(
odev
))
if
((
odev
=
__dev_get_by_name
(
buf
))
==
NULL
||
lapbeth_check_devices
(
odev
))
break
;
}
if
(
k
==
MAXLAPBDEV
)
{
dev_put
(
dev
);
kfree
(
lapbeth
);
return
-
ENODEV
;
}
rc
=
-
ENODEV
;
if
(
k
==
MAXLAPBDEV
)
goto
fail
;
dev
->
priv
=
(
void
*
)
lapbeth
;
/* pointer back */
strcpy
(
dev
->
name
,
buf
);
if
(
register_netdev
(
dev
)
!=
0
)
{
dev_put
(
dev
);
kfree
(
lapbeth
);
return
-
EIO
;
}
rc
=
-
EIO
;
if
(
register_netdev
(
dev
))
goto
fail
;
dev
->
hard_start_xmit
=
lapbeth_xmit
;
dev
->
open
=
lapbeth_open
;
...
...
@@ -410,26 +427,27 @@ static int lapbeth_new_device(struct net_device *dev)
dev
->
mtu
=
1000
;
dev
->
addr_len
=
0
;
cli
();
if
(
lapbeth_devices
==
NULL
)
{
lapbeth_devices
=
lapbeth
;
}
else
{
for
(
lapbeth2
=
lapbeth_devices
;
lapbeth2
->
next
!=
NULL
;
lapbeth2
=
lapbeth2
->
next
);
lapbeth2
->
next
=
lapbeth
;
}
sti
();
return
0
;
write_lock
(
&
lapbeth_devices_lock
);
list_add
(
&
lapbeth
->
node
,
&
lapbeth_devices
);
lapbeth_hold
(
lapbeth
);
write_unlock
(
&
lapbeth_devices_lock
);
rc
=
0
;
out:
return
rc
;
fail:
dev_put
(
dev
);
kfree
(
lapbeth
);
goto
out
;
}
/*
* Handle device status changes.
*/
static
int
lapbeth_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
static
int
lapbeth_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
ptr
;
struct
lapbethdev
*
lapbeth
;
struct
net_device
*
dev
=
(
struct
net_device
*
)
ptr
;
if
(
!
dev_is_ethdev
(
dev
))
return
NOTIFY_DONE
;
...
...
@@ -437,19 +455,26 @@ static int lapbeth_device_event(struct notifier_block *this, unsigned long event
lapbeth_check_devices
(
NULL
);
switch
(
event
)
{
case
NETDEV_UP
:
/* new ethernet device -> new LAPB interface */
if
(
lapbeth_get_x25_dev
(
dev
)
==
NULL
)
lapbeth_new_device
(
dev
);
break
;
case
NETDEV_GOING_DOWN
:
case
NETDEV_DOWN
:
/* ethernet device closed -> close LAPB interface */
if
((
dev
=
lapbeth_get_x25_dev
(
dev
))
!=
NULL
)
dev_close
(
dev
);
break
;
default:
break
;
case
NETDEV_UP
:
/*
* New ethernet device -> new LAPB interface
*/
lapbeth
=
lapbeth_get_x25_dev
(
dev
);
if
(
lapbeth
)
lapbeth_put
(
lapbeth
);
else
lapbeth_new_device
(
dev
);
break
;
case
NETDEV_GOING_DOWN
:
case
NETDEV_DOWN
:
/* ethernet device closed -> close LAPB interface */
lapbeth
=
lapbeth_get_x25_dev
(
dev
);
if
(
lapbeth
)
{
dev_close
(
lapbeth
->
ethdev
);
lapbeth_put
(
lapbeth
);
}
break
;
}
return
NOTIFY_DONE
;
...
...
@@ -458,15 +483,15 @@ static int lapbeth_device_event(struct notifier_block *this, unsigned long event
/* ------------------------------------------------------------------------ */
static
struct
packet_type
lapbeth_packet_type
=
{
.
type
=
__constant_htons
(
ETH_P_DEC
),
.
func
=
lapbeth_rcv
,
.
type
=
__constant_htons
(
ETH_P_DEC
),
.
func
=
lapbeth_rcv
,
};
static
struct
notifier_block
lapbeth_dev_notifier
=
{
.
notifier_call
=
lapbeth_device_event
,
};
static
char
banner
[]
__initdata
=
KERN_INFO
"LAPB Ethernet driver version 0.0
1
\n
"
;
static
char
banner
[]
__initdata
=
KERN_INFO
"LAPB Ethernet driver version 0.0
2
\n
"
;
static
int
__init
lapbeth_init_driver
(
void
)
{
...
...
@@ -479,7 +504,7 @@ static int __init lapbeth_init_driver(void)
printk
(
banner
);
read_lock_bh
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
!=
NULL
;
dev
=
dev
->
next
)
{
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
if
(
dev_is_ethdev
(
dev
))
{
read_unlock_bh
(
&
dev_base_lock
);
lapbeth_new_device
(
dev
);
...
...
@@ -495,18 +520,24 @@ module_init(lapbeth_init_driver);
static
void
__exit
lapbeth_cleanup_driver
(
void
)
{
struct
lapbethdev
*
lapbeth
;
struct
list_head
*
entry
,
*
tmp
;
dev_remove_pack
(
&
lapbeth_packet_type
);
unregister_netdevice_notifier
(
&
lapbeth_dev_notifier
);
for
(
lapbeth
=
lapbeth_devices
;
lapbeth
!=
NULL
;
lapbeth
=
lapbeth
->
next
)
write_lock
(
&
lapbeth_devices_lock
);
list_for_each_safe
(
entry
,
tmp
,
&
lapbeth_devices
)
{
lapbeth
=
list_entry
(
entry
,
struct
lapbethdev
,
node
);
unregister_netdev
(
&
lapbeth
->
axdev
);
list_del
(
&
lapbeth
->
node
);
lapbeth_put
(
lapbeth
);
}
write_unlock
(
&
lapbeth_devices_lock
);
}
module_exit
(
lapbeth_cleanup_driver
);
MODULE_AUTHOR
(
"Jonathan Naylor <g4klx@g4klx.demon.co.uk>"
);
MODULE_DESCRIPTION
(
"The unofficial LAPB over Ethernet driver"
);
MODULE_LICENSE
(
"GPL"
);
include/linux/x25.h
View file @
5c0fbae1
...
...
@@ -39,16 +39,16 @@
* An X.121 address, it is held as ASCII text, null terminated, up to 15
* digits and a null terminator.
*/
typedef
struct
{
char
x25_addr
[
16
];
}
x25_address
;
struct
x25_address
{
char
x25_addr
[
16
];
};
/*
* Linux X.25 Address structure, used for bind, and connect mostly.
*/
struct
sockaddr_x25
{
sa_family_t
sx25_family
;
/* Must be AF_X25 */
x25_address
sx25_addr
;
/* X.121 Address */
sa_family_t
sx25_family
;
/* Must be AF_X25 */
struct
x25_address
sx25_addr
;
/* X.121 Address */
};
/*
...
...
@@ -78,9 +78,9 @@ struct x25_subscrip_struct {
* Routing table control structure.
*/
struct
x25_route_struct
{
x25_address
address
;
unsigned
int
sigdigits
;
char
device
[
200
];
struct
x25_address
address
;
unsigned
int
sigdigits
;
char
device
[
200
];
};
/*
...
...
include/net/lapb.h
View file @
5c0fbae1
...
...
@@ -78,8 +78,8 @@ struct lapb_frame {
/*
* The per LAPB connection control structure.
*/
typedef
struct
lapb_cb
{
struct
l
apb_cb
*
next
;
struct
lapb_cb
{
struct
l
ist_head
node
;
void
*
token
;
/* Link status fields */
...
...
@@ -100,43 +100,45 @@ typedef struct lapb_cb {
/* FRMR control information */
struct
lapb_frame
frmr_data
;
unsigned
char
frmr_type
;
}
lapb_cb
;
atomic_t
refcnt
;
};
/* lapb_iface.c */
extern
void
lapb_connect_confirmation
(
lapb_cb
*
,
int
);
extern
void
lapb_connect_indication
(
lapb_cb
*
,
int
);
extern
void
lapb_disconnect_confirmation
(
lapb_cb
*
,
int
);
extern
void
lapb_disconnect_indication
(
lapb_cb
*
,
int
);
extern
int
lapb_data_indication
(
lapb_cb
*
,
struct
sk_buff
*
);
extern
int
lapb_data_transmit
(
lapb_cb
*
,
struct
sk_buff
*
);
extern
void
lapb_connect_confirmation
(
struct
lapb_cb
*
lapb
,
int
);
extern
void
lapb_connect_indication
(
struct
lapb_cb
*
lapb
,
int
);
extern
void
lapb_disconnect_confirmation
(
struct
lapb_cb
*
lapb
,
int
);
extern
void
lapb_disconnect_indication
(
struct
lapb_cb
*
lapb
,
int
);
extern
int
lapb_data_indication
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
);
extern
int
lapb_data_transmit
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
);
/* lapb_in.c */
extern
void
lapb_data_input
(
lapb_cb
*
,
struct
sk_buff
*
);
extern
void
lapb_data_input
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
);
/* lapb_out.c */
extern
void
lapb_kick
(
lapb_cb
*
);
extern
void
lapb_transmit_buffer
(
lapb_cb
*
,
struct
sk_buff
*
,
int
);
extern
void
lapb_establish_data_link
(
lapb_cb
*
);
extern
void
lapb_enquiry_response
(
lapb_cb
*
);
extern
void
lapb_timeout_response
(
lapb_cb
*
);
extern
void
lapb_check_iframes_acked
(
lapb_cb
*
,
unsigned
short
);
extern
void
lapb_check_need_response
(
lapb_cb
*
,
int
,
int
);
extern
void
lapb_kick
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_transmit_buffer
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
,
int
);
extern
void
lapb_establish_data_link
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_enquiry_response
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_timeout_response
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_check_iframes_acked
(
struct
lapb_cb
*
lapb
,
unsigned
short
);
extern
void
lapb_check_need_response
(
struct
lapb_cb
*
lapb
,
int
,
int
);
/* lapb_subr.c */
extern
void
lapb_clear_queues
(
lapb_cb
*
);
extern
void
lapb_frames_acked
(
lapb_cb
*
,
unsigned
short
);
extern
void
lapb_requeue_frames
(
lapb_cb
*
);
extern
int
lapb_validate_nr
(
lapb_cb
*
,
unsigned
short
);
extern
void
lapb_decode
(
lapb_cb
*
,
struct
sk_buff
*
,
struct
lapb_frame
*
);
extern
void
lapb_send_control
(
lapb_cb
*
,
int
,
int
,
int
);
extern
void
lapb_transmit_frmr
(
lapb_cb
*
);
extern
void
lapb_clear_queues
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_frames_acked
(
struct
lapb_cb
*
lapb
,
unsigned
short
);
extern
void
lapb_requeue_frames
(
struct
lapb_cb
*
lapb
);
extern
int
lapb_validate_nr
(
struct
lapb_cb
*
lapb
,
unsigned
short
);
extern
void
lapb_decode
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
,
struct
lapb_frame
*
);
extern
void
lapb_send_control
(
struct
lapb_cb
*
lapb
,
int
,
int
,
int
);
extern
void
lapb_transmit_frmr
(
struct
lapb_cb
*
lapb
);
/* lapb_timer.c */
extern
void
lapb_start_t1timer
(
lapb_cb
*
);
extern
void
lapb_start_t2timer
(
lapb_cb
*
);
extern
void
lapb_stop_t1timer
(
lapb_cb
*
);
extern
void
lapb_stop_t2timer
(
lapb_cb
*
);
extern
int
lapb_t1timer_running
(
lapb_cb
*
);
extern
void
lapb_start_t1timer
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_start_t2timer
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_stop_t1timer
(
struct
lapb_cb
*
lapb
);
extern
void
lapb_stop_t2timer
(
struct
lapb_cb
*
lapb
);
extern
int
lapb_t1timer_running
(
struct
lapb_cb
*
lapb
);
/*
* Debug levels.
...
...
include/net/x25.h
View file @
5c0fbae1
...
...
@@ -101,26 +101,36 @@ enum {
#define X25_MAX_FAC_LEN 20
/* Plenty to spare */
#define X25_MAX_CUD_LEN 128
/**
* struct x25_route - x25 routing entry
* @node - entry in x25_list_lock
* @address - Start of address range
* @sigdigits - Number of sig digits
* @dev - More than one for MLP
* @refcnt - reference counter
*/
struct
x25_route
{
struct
x25_route
*
next
;
x25_address
address
;
/* Start of address range */
unsigned
int
sigdigits
;
/* Number of sig digits */
struct
net_device
*
dev
;
/* More than one for MLP */
struct
list_head
node
;
struct
x25_address
address
;
unsigned
int
sigdigits
;
struct
net_device
*
dev
;
atomic_t
refcnt
;
};
struct
x25_neigh
{
struct
x25_neigh
*
next
;
struct
net_device
*
dev
;
struct
list_head
node
;
struct
net_device
*
dev
;
unsigned
int
state
;
unsigned
int
extended
;
struct
sk_buff_head
queue
;
unsigned
long
t20
;
struct
timer_list
t20timer
;
unsigned
long
global_facil_mask
;
atomic_t
refcnt
;
};
typedef
struc
t
{
x25_address
source_addr
,
dest_addr
;
struct
x25_op
t
{
struct
x25_address
source_addr
,
dest_addr
;
struct
x25_neigh
*
neighbour
;
unsigned
int
lci
;
unsigned
char
state
,
condition
,
qbitincl
,
intflag
;
...
...
@@ -137,9 +147,9 @@ typedef struct {
struct
x25_facilities
facilities
;
struct
x25_calluserdata
calluserdata
;
unsigned
long
vc_facil_mask
;
/* inc_call facilities mask */
}
x25_cb
;
};
#define x25_sk(__sk) ((
x25_cb
*)(__sk)->protinfo)
#define x25_sk(__sk) ((
struct x25_opt
*)(__sk)->protinfo)
/* af_x25.c */
extern
int
sysctl_x25_restart_request_timeout
;
...
...
@@ -148,8 +158,10 @@ extern int sysctl_x25_reset_request_timeout;
extern
int
sysctl_x25_clear_request_timeout
;
extern
int
sysctl_x25_ack_holdback_timeout
;
extern
int
x25_addr_ntoa
(
unsigned
char
*
,
x25_address
*
,
x25_address
*
);
extern
int
x25_addr_aton
(
unsigned
char
*
,
x25_address
*
,
x25_address
*
);
extern
int
x25_addr_ntoa
(
unsigned
char
*
,
struct
x25_address
*
,
struct
x25_address
*
);
extern
int
x25_addr_aton
(
unsigned
char
*
,
struct
x25_address
*
,
struct
x25_address
*
);
extern
unsigned
int
x25_new_lci
(
struct
x25_neigh
*
);
extern
struct
sock
*
x25_find_socket
(
unsigned
int
,
struct
x25_neigh
*
);
extern
void
x25_destroy_socket
(
struct
sock
*
);
...
...
@@ -188,19 +200,42 @@ extern int x25_subscr_ioctl(unsigned int, void *);
extern
struct
x25_neigh
*
x25_get_neigh
(
struct
net_device
*
);
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 */
extern
int
x25_output
(
struct
sock
*
,
struct
sk_buff
*
);
extern
void
x25_kick
(
struct
sock
*
);
extern
void
x25_enquiry_response
(
struct
sock
*
);
/* x25_route.c */
extern
struct
net_device
*
x25_get_route
(
x25_address
*
);
extern
struct
x25_route
*
x25_get_route
(
struct
x25_address
*
addr
);
extern
struct
net_device
*
x25_dev_get
(
char
*
);
extern
void
x25_route_device_down
(
struct
net_device
*
);
extern
int
x25_route_ioctl
(
unsigned
int
,
void
*
);
extern
int
x25_routes_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
void
x25_route_free
(
void
);
static
__inline__
void
x25_route_hold
(
struct
x25_route
*
rt
)
{
atomic_inc
(
&
rt
->
refcnt
);
}
static
__inline__
void
x25_route_put
(
struct
x25_route
*
rt
)
{
if
(
atomic_dec_and_test
(
&
rt
->
refcnt
))
kfree
(
rt
);
}
/* x25_subr.c */
extern
void
x25_clear_queues
(
struct
sock
*
);
extern
void
x25_frames_acked
(
struct
sock
*
,
unsigned
short
);
...
...
net/lapb/lapb_iface.c
View file @
5c0fbae1
...
...
@@ -39,87 +39,93 @@
#include <linux/init.h>
#include <net/lapb.h>
static
lapb_cb
*
volatile
lapb_list
/* = NULL initially */
;
static
struct
list_head
lapb_list
=
LIST_HEAD_INIT
(
lapb_list
);
static
rwlock_t
lapb_list_lock
=
RW_LOCK_UNLOCKED
;
/*
* Free an allocated lapb control block. This is done to centralise
* the MOD count code.
*/
static
void
lapb_free_cb
(
lapb_cb
*
lapb
)
static
void
lapb_free_cb
(
struct
lapb_cb
*
lapb
)
{
kfree
(
lapb
);
MOD_DEC_USE_COUNT
;
}
static
__inline__
void
lapb_hold
(
struct
lapb_cb
*
lapb
)
{
atomic_inc
(
&
lapb
->
refcnt
);
}
static
__inline__
void
lapb_put
(
struct
lapb_cb
*
lapb
)
{
if
(
atomic_dec_and_test
(
&
lapb
->
refcnt
))
lapb_free_cb
(
lapb
);
}
/*
* Socket removal during an interrupt is now safe.
*/
static
void
lapb_remove_cb
(
lapb_cb
*
lapb
)
static
void
__lapb_remove_cb
(
struct
lapb_cb
*
lapb
)
{
lapb_cb
*
s
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
if
((
s
=
lapb_list
)
==
lapb
)
{
lapb_list
=
s
->
next
;
restore_flags
(
flags
);
return
;
if
(
lapb
->
node
.
next
)
{
list_del
(
&
lapb
->
node
);
lapb_put
(
lapb
);
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
lapb
)
{
s
->
next
=
lapb
->
next
;
restore_flags
(
flags
);
return
;
}
s
=
s
->
next
;
}
restore_flags
(
flags
);
}
/*
* Add a socket to the bound sockets list.
*/
static
void
lapb_insert_cb
(
lapb_cb
*
lapb
)
static
void
__lapb_insert_cb
(
struct
lapb_cb
*
lapb
)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
lapb
->
next
=
lapb_list
;
lapb_list
=
lapb
;
restore_flags
(
flags
);
list_add
(
&
lapb
->
node
,
&
lapb_list
);
lapb_hold
(
lapb
);
}
/*
* Convert the integer token used by the device driver into a pointer
* to a LAPB control structure.
*/
static
lapb_cb
*
lapb_tokentostruct
(
void
*
token
)
static
struct
lapb_cb
*
__
lapb_tokentostruct
(
void
*
token
)
{
lapb_cb
*
lapb
;
struct
list_head
*
entry
;
struct
lapb_cb
*
lapb
,
*
use
=
NULL
;
list_for_each
(
entry
,
&
lapb_list
)
{
lapb
=
list_entry
(
entry
,
struct
lapb_cb
,
node
);
if
(
lapb
->
token
==
token
)
{
use
=
lapb
;
break
;
}
}
for
(
lapb
=
lapb_list
;
lapb
!=
NULL
;
lapb
=
lapb
->
next
)
if
(
lapb
->
token
==
token
)
return
lapb
;
if
(
use
)
lapb_hold
(
use
);
return
NULL
;
return
use
;
}
static
struct
lapb_cb
*
lapb_tokentostruct
(
void
*
token
)
{
struct
lapb_cb
*
rc
;
read_lock_bh
(
&
lapb_list_lock
);
rc
=
__lapb_tokentostruct
(
token
);
read_unlock_bh
(
&
lapb_list_lock
);
return
rc
;
}
/*
* Create an empty LAPB control block.
*/
static
lapb_cb
*
lapb_create_cb
(
void
)
static
struct
lapb_cb
*
lapb_create_cb
(
void
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
=
kmalloc
(
sizeof
(
*
lapb
),
GFP_ATOMIC
);
if
(
(
lapb
=
kmalloc
(
sizeof
(
*
lapb
),
GFP_ATOMIC
))
==
NULL
)
return
NULL
;
if
(
!
lapb
)
goto
out
;
MOD_INC_USE_COUNT
;
...
...
@@ -137,55 +143,73 @@ static lapb_cb *lapb_create_cb(void)
lapb
->
mode
=
LAPB_DEFAULT_MODE
;
lapb
->
window
=
LAPB_DEFAULT_WINDOW
;
lapb
->
state
=
LAPB_STATE_0
;
atomic_set
(
&
lapb
->
refcnt
,
1
);
out:
return
lapb
;
}
int
lapb_register
(
void
*
token
,
struct
lapb_register_struct
*
callbacks
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
;
int
rc
=
LAPB_BADTOKEN
;
write_lock_bh
(
&
lapb_list_lock
);
if
(
lapb_tokentostruct
(
token
)
!=
NULL
)
return
LAPB_BADTOKEN
;
lapb
=
__lapb_tokentostruct
(
token
);
if
(
lapb
)
{
lapb_put
(
lapb
);
goto
out
;
}
if
((
lapb
=
lapb_create_cb
())
==
NULL
)
return
LAPB_NOMEM
;
lapb
=
lapb_create_cb
();
rc
=
LAPB_NOMEM
;
if
(
!
lapb
)
goto
out
;
lapb
->
token
=
token
;
lapb
->
callbacks
=
*
callbacks
;
lapb_insert_cb
(
lapb
);
__
lapb_insert_cb
(
lapb
);
lapb_start_t1timer
(
lapb
);
return
LAPB_OK
;
rc
=
LAPB_OK
;
out:
write_unlock_bh
(
&
lapb_list_lock
);
return
rc
;
}
int
lapb_unregister
(
void
*
token
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
;
int
rc
=
LAPB_BADTOKEN
;
if
((
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
write_unlock_bh
(
&
lapb_list_lock
);
lapb
=
__lapb_tokentostruct
(
token
);
if
(
!
lapb
)
goto
out
;
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb_clear_queues
(
lapb
);
lapb_remove_cb
(
lapb
);
__
lapb_remove_cb
(
lapb
);
lapb_free_cb
(
lapb
);
return
LAPB_OK
;
lapb_put
(
lapb
);
rc
=
LAPB_OK
;
out:
write_unlock_bh
(
&
lapb_list_lock
);
return
rc
;
}
int
lapb_getparms
(
void
*
token
,
struct
lapb_parms_struct
*
parms
)
{
lapb_cb
*
lapb
;
int
rc
=
LAPB_BADTOKEN
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
if
(
(
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
if
(
!
lapb
)
goto
out
;
parms
->
t1
=
lapb
->
t1
/
HZ
;
parms
->
t2
=
lapb
->
t2
/
HZ
;
...
...
@@ -205,33 +229,29 @@ int lapb_getparms(void *token, struct lapb_parms_struct *parms)
else
parms
->
t2timer
=
(
lapb
->
t2timer
.
expires
-
jiffies
)
/
HZ
;
return
LAPB_OK
;
lapb_put
(
lapb
);
rc
=
LAPB_OK
;
out:
return
rc
;
}
int
lapb_setparms
(
void
*
token
,
struct
lapb_parms_struct
*
parms
)
{
lapb_cb
*
lapb
;
if
((
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
if
(
parms
->
t1
<
1
)
return
LAPB_INVALUE
;
int
rc
=
LAPB_BADTOKEN
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
if
(
parms
->
t2
<
1
)
return
LAPB_INVALUE
;
if
(
!
lapb
)
goto
out
;
if
(
parms
->
n2
<
1
)
return
LAPB_INVALUE
;
rc
=
LAPB_INVALUE
;
if
(
parms
->
t1
<
1
||
parms
->
t2
<
1
||
parms
->
n2
<
1
)
goto
out_put
;
if
(
lapb
->
state
==
LAPB_STATE_0
)
{
if
(
parms
->
mode
&
LAPB_EXTENDED
)
{
if
(
parms
->
window
<
1
||
parms
->
window
>
127
)
return
LAPB_INVALUE
;
}
else
{
if
(
parms
->
window
<
1
||
parms
->
window
>
7
)
return
LAPB_INVALUE
;
}
if
(((
parms
->
mode
&
LAPB_EXTENDED
)
&&
(
parms
->
window
<
1
||
parms
->
window
>
127
))
||
(
parms
->
window
<
1
||
parms
->
window
>
7
))
goto
out_put
;
lapb
->
mode
=
parms
->
mode
;
lapb
->
window
=
parms
->
window
;
...
...
@@ -241,45 +261,55 @@ int lapb_setparms(void *token, struct lapb_parms_struct *parms)
lapb
->
t2
=
parms
->
t2
*
HZ
;
lapb
->
n2
=
parms
->
n2
;
return
LAPB_OK
;
rc
=
LAPB_OK
;
out_put:
lapb_put
(
lapb
);
out:
return
rc
;
}
int
lapb_connect_request
(
void
*
token
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
int
rc
=
LAPB_BADTOKEN
;
if
(
(
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
if
(
!
lapb
)
goto
out
;
switch
(
lapb
->
state
)
{
case
LAPB_STATE_1
:
return
LAPB_OK
;
case
LAPB_STATE_3
:
case
LAPB_STATE_4
:
return
LAPB_CONNECTED
;
}
rc
=
LAPB_OK
;
if
(
lapb
->
state
==
LAPB_STATE_1
)
goto
out_put
;
rc
=
LAPB_CONNECTED
;
if
(
lapb
->
state
==
LAPB_STATE_3
||
lapb
->
state
==
LAPB_STATE_4
)
goto
out_put
;
lapb_establish_data_link
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S0 -> S1
\n
"
,
lapb
->
token
);
#endif
lapb
->
state
=
LAPB_STATE_1
;
return
LAPB_OK
;
rc
=
LAPB_OK
;
out_put:
lapb_put
(
lapb
);
out:
return
rc
;
}
int
lapb_disconnect_request
(
void
*
token
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
int
rc
=
LAPB_BADTOKEN
;
if
(
(
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
if
(
!
lapb
)
goto
out
;
switch
(
lapb
->
state
)
{
case
LAPB_STATE_0
:
return
LAPB_NOTCONNECTED
;
rc
=
LAPB_NOTCONNECTED
;
goto
out_put
;
case
LAPB_STATE_1
:
#if LAPB_DEBUG > 1
...
...
@@ -291,10 +321,12 @@ int lapb_disconnect_request(void *token)
lapb_send_control
(
lapb
,
LAPB_DISC
,
LAPB_POLLON
,
LAPB_COMMAND
);
lapb
->
state
=
LAPB_STATE_0
;
lapb_start_t1timer
(
lapb
);
return
LAPB_NOTCONNECTED
;
rc
=
LAPB_NOTCONNECTED
;
goto
out_put
;
case
LAPB_STATE_2
:
return
LAPB_OK
;
rc
=
LAPB_OK
;
goto
out_put
;
}
lapb_clear_queues
(
lapb
);
...
...
@@ -311,77 +343,87 @@ int lapb_disconnect_request(void *token)
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S2
\n
"
,
lapb
->
token
);
#endif
return
LAPB_OK
;
rc
=
LAPB_OK
;
out_put:
lapb_put
(
lapb
);
out:
return
rc
;
}
int
lapb_data_request
(
void
*
token
,
struct
sk_buff
*
skb
)
{
lapb_cb
*
lapb
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
int
rc
=
LAPB_BADTOKEN
;
if
(
(
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
if
(
!
lapb
)
goto
out
;
rc
=
LAPB_NOTCONNECTED
;
if
(
lapb
->
state
!=
LAPB_STATE_3
&&
lapb
->
state
!=
LAPB_STATE_4
)
return
LAPB_NOTCONNECTED
;
goto
out_put
;
skb_queue_tail
(
&
lapb
->
write_queue
,
skb
);
lapb_kick
(
lapb
);
return
LAPB_OK
;
rc
=
LAPB_OK
;
out_put:
lapb_put
(
lapb
);
out:
return
rc
;
}
int
lapb_data_received
(
void
*
token
,
struct
sk_buff
*
skb
)
{
lapb_cb
*
lapb
;
if
((
lapb
=
lapb_tokentostruct
(
token
))
==
NULL
)
return
LAPB_BADTOKEN
;
struct
lapb_cb
*
lapb
=
lapb_tokentostruct
(
token
);
int
rc
=
LAPB_BADTOKEN
;
lapb_data_input
(
lapb
,
skb
);
if
(
lapb
)
{
lapb_data_input
(
lapb
,
skb
);
lapb_put
(
lapb
);
rc
=
LAPB_OK
;
}
return
LAPB_OK
;
return
rc
;
}
void
lapb_connect_confirmation
(
lapb_cb
*
lapb
,
int
reason
)
void
lapb_connect_confirmation
(
struct
lapb_cb
*
lapb
,
int
reason
)
{
if
(
lapb
->
callbacks
.
connect_confirmation
!=
NULL
)
(
lapb
->
callbacks
.
connect_confirmation
)
(
lapb
->
token
,
reason
);
if
(
lapb
->
callbacks
.
connect_confirmation
)
lapb
->
callbacks
.
connect_confirmation
(
lapb
->
token
,
reason
);
}
void
lapb_connect_indication
(
lapb_cb
*
lapb
,
int
reason
)
void
lapb_connect_indication
(
struct
lapb_cb
*
lapb
,
int
reason
)
{
if
(
lapb
->
callbacks
.
connect_indication
!=
NULL
)
(
lapb
->
callbacks
.
connect_indication
)
(
lapb
->
token
,
reason
);
if
(
lapb
->
callbacks
.
connect_indication
)
lapb
->
callbacks
.
connect_indication
(
lapb
->
token
,
reason
);
}
void
lapb_disconnect_confirmation
(
lapb_cb
*
lapb
,
int
reason
)
void
lapb_disconnect_confirmation
(
struct
lapb_cb
*
lapb
,
int
reason
)
{
if
(
lapb
->
callbacks
.
disconnect_confirmation
!=
NULL
)
(
lapb
->
callbacks
.
disconnect_confirmation
)
(
lapb
->
token
,
reason
);
if
(
lapb
->
callbacks
.
disconnect_confirmation
)
lapb
->
callbacks
.
disconnect_confirmation
(
lapb
->
token
,
reason
);
}
void
lapb_disconnect_indication
(
lapb_cb
*
lapb
,
int
reason
)
void
lapb_disconnect_indication
(
struct
lapb_cb
*
lapb
,
int
reason
)
{
if
(
lapb
->
callbacks
.
disconnect_indication
!=
NULL
)
(
lapb
->
callbacks
.
disconnect_indication
)
(
lapb
->
token
,
reason
);
if
(
lapb
->
callbacks
.
disconnect_indication
)
lapb
->
callbacks
.
disconnect_indication
(
lapb
->
token
,
reason
);
}
int
lapb_data_indication
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
int
lapb_data_indication
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
{
if
(
lapb
->
callbacks
.
data_indication
!=
NULL
)
{
return
(
lapb
->
callbacks
.
data_indication
)
(
lapb
->
token
,
skb
);
}
if
(
lapb
->
callbacks
.
data_indication
)
return
lapb
->
callbacks
.
data_indication
(
lapb
->
token
,
skb
);
kfree_skb
(
skb
);
return
NET_RX_CN_HIGH
;
/* For now; must be != NET_RX_DROP */
}
int
lapb_data_transmit
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
int
lapb_data_transmit
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
{
int
used
=
0
;
if
(
lapb
->
callbacks
.
data_transmit
!=
NULL
)
{
(
lapb
->
callbacks
.
data_transmit
)
(
lapb
->
token
,
skb
);
if
(
lapb
->
callbacks
.
data_transmit
)
{
lapb
->
callbacks
.
data_transmit
(
lapb
->
token
,
skb
);
used
=
1
;
}
...
...
net/lapb/lapb_in.c
View file @
5c0fbae1
...
...
@@ -40,26 +40,33 @@
* State machine for state 0, Disconnected State.
* The handling of the timer(s) is in file lapb_timer.c.
*/
static
void
lapb_state0_machine
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
static
void
lapb_state0_machine
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
switch
(
frame
->
type
)
{
case
LAPB_SABM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S0 -> S3
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 -> S3
\n
"
,
lapb
->
token
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
state
=
LAPB_STATE_3
;
...
...
@@ -74,16 +81,20 @@ static void lapb_state0_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_SABME
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S0 -> S3
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 -> S3
\n
"
,
lapb
->
token
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
state
=
LAPB_STATE_3
;
...
...
@@ -95,18 +106,23 @@ static void lapb_state0_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb_connect_indication
(
lapb
,
LAPB_OK
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
break
;
case
LAPB_DISC
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S0 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
default:
...
...
@@ -120,58 +136,74 @@ static void lapb_state0_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
* State machine for state 1, Awaiting Connection State.
* The handling of the timer(s) is in file lapb_timer.c.
*/
static
void
lapb_state1_machine
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
static
void
lapb_state1_machine
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
switch
(
frame
->
type
)
{
case
LAPB_SABM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
}
break
;
case
LAPB_SABME
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
break
;
case
LAPB_DISC
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
case
LAPB_UA
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
frame
->
pf
)
{
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S1 -> S3
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 -> S3
\n
"
,
lapb
->
token
);
#endif
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
...
...
@@ -187,11 +219,13 @@ static void lapb_state1_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_DM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
frame
->
pf
)
{
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S1 -> S0
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S1 -> S0
\n
"
,
lapb
->
token
);
#endif
lapb_clear_queues
(
lapb
);
lapb
->
state
=
LAPB_STATE_0
;
...
...
@@ -200,9 +234,6 @@ static void lapb_state1_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb_disconnect_indication
(
lapb
,
LAPB_REFUSED
);
}
break
;
default:
break
;
}
kfree_skb
(
skb
);
...
...
@@ -212,33 +243,42 @@ static void lapb_state1_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
* State machine for state 2, Awaiting Release State.
* The handling of the timer(s) is in file lapb_timer.c
*/
static
void
lapb_state2_machine
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
static
void
lapb_state2_machine
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
switch
(
frame
->
type
)
{
case
LAPB_SABM
:
case
LAPB_SABME
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX {SABM,SABME}(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX {SABM,SABME}(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
case
LAPB_DISC
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
case
LAPB_UA
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
frame
->
pf
)
{
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S2 -> S0
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 -> S0
\n
"
,
lapb
->
token
);
#endif
lapb
->
state
=
LAPB_STATE_0
;
lapb_start_t1timer
(
lapb
);
...
...
@@ -249,16 +289,19 @@ static void lapb_state2_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_DM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
frame
->
pf
)
{
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S2 -> S0
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 -> S0
\n
"
,
lapb
->
token
);
#endif
lapb
->
state
=
LAPB_STATE_0
;
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb_disconnect_confirmation
(
lapb
,
LAPB_NOTCONNECTED
);
lapb_disconnect_confirmation
(
lapb
,
LAPB_NOTCONNECTED
);
}
break
;
...
...
@@ -267,13 +310,14 @@ static void lapb_state2_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_RNR
:
case
LAPB_RR
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX {I,REJ,RNR,RR}(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX {I,REJ,RNR,RR}"
"(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S2 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
frame
->
pf
)
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
default:
if
(
frame
->
pf
)
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
break
;
}
...
...
@@ -284,28 +328,33 @@ static void lapb_state2_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
* State machine for state 3, Connected State.
* The handling of the timer(s) is in file lapb_timer.c
*/
static
void
lapb_state3_machine
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
static
void
lapb_state3_machine
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
int
queued
=
0
;
int
modulus
;
modulus
=
(
lapb
->
mode
&
LAPB_EXTENDED
)
?
LAPB_EMODULUS
:
LAPB_SMODULUS
;
int
modulus
=
(
lapb
->
mode
&
LAPB_EXTENDED
)
?
LAPB_EMODULUS
:
LAPB_SMODULUS
;
switch
(
frame
->
type
)
{
case
LAPB_SABM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
condition
=
0x00
;
...
...
@@ -319,13 +368,16 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_SABME
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
condition
=
0x00
;
...
...
@@ -336,21 +388,26 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb_requeue_frames
(
lapb
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
break
;
case
LAPB_DISC
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX DISC(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S0
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S0
\n
"
,
lapb
->
token
);
#endif
lapb_clear_queues
(
lapb
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
state
=
LAPB_STATE_0
;
...
...
@@ -359,10 +416,12 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_DM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S0
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S0
\n
"
,
lapb
->
token
);
#endif
lapb_clear_queues
(
lapb
);
lapb
->
state
=
LAPB_STATE_0
;
...
...
@@ -373,7 +432,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_RNR
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX RNR(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX RNR(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
#endif
lapb
->
condition
|=
LAPB_PEER_RX_BUSY_CONDITION
;
lapb_check_need_response
(
lapb
,
frame
->
cr
,
frame
->
pf
);
...
...
@@ -384,7 +444,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb
->
frmr_type
=
LAPB_FRMR_Z
;
lapb_transmit_frmr
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
#endif
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
...
...
@@ -395,7 +456,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_RR
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX RR(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX RR(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
#endif
lapb
->
condition
&=
~
LAPB_PEER_RX_BUSY_CONDITION
;
lapb_check_need_response
(
lapb
,
frame
->
cr
,
frame
->
pf
);
...
...
@@ -406,7 +468,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb
->
frmr_type
=
LAPB_FRMR_Z
;
lapb_transmit_frmr
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
#endif
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
...
...
@@ -417,7 +480,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_REJ
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX REJ(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX REJ(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
nr
);
#endif
lapb
->
condition
&=
~
LAPB_PEER_RX_BUSY_CONDITION
;
lapb_check_need_response
(
lapb
,
frame
->
cr
,
frame
->
pf
);
...
...
@@ -431,7 +495,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb
->
frmr_type
=
LAPB_FRMR_Z
;
lapb_transmit_frmr
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
#endif
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
...
...
@@ -442,14 +507,16 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_I
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX I(%d) S%d R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
ns
,
frame
->
nr
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX I(%d) S%d R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
frame
->
ns
,
frame
->
nr
);
#endif
if
(
!
lapb_validate_nr
(
lapb
,
frame
->
nr
))
{
lapb
->
frmr_data
=
*
frame
;
lapb
->
frmr_type
=
LAPB_FRMR_Z
;
lapb_transmit_frmr
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S4
\n
"
,
lapb
->
token
);
#endif
lapb_start_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
...
...
@@ -457,11 +524,11 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb
->
n2count
=
0
;
break
;
}
if
(
lapb
->
condition
&
LAPB_PEER_RX_BUSY_CONDITION
)
{
if
(
lapb
->
condition
&
LAPB_PEER_RX_BUSY_CONDITION
)
lapb_frames_acked
(
lapb
,
frame
->
nr
);
}
else
{
else
lapb_check_iframes_acked
(
lapb
,
frame
->
nr
);
}
if
(
frame
->
ns
==
lapb
->
vr
)
{
int
cn
;
cn
=
lapb_data_indication
(
lapb
,
skb
);
...
...
@@ -473,16 +540,18 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
* to re-transmit the frame later like
* a frame lost on the wire.
*/
if
(
cn
==
NET_RX_DROP
){
printk
(
KERN_DEBUG
"LAPB: rx congestion
\n
"
);
if
(
cn
==
NET_RX_DROP
)
{
printk
(
KERN_DEBUG
"LAPB: rx congestion
\n
"
);
break
;
}
lapb
->
vr
=
(
lapb
->
vr
+
1
)
%
modulus
;
lapb
->
condition
&=
~
LAPB_REJECT_CONDITION
;
if
(
frame
->
pf
)
{
if
(
frame
->
pf
)
lapb_enquiry_response
(
lapb
);
}
else
{
if
(
!
(
lapb
->
condition
&
LAPB_ACK_PENDING_CONDITION
))
{
else
{
if
(
!
(
lapb
->
condition
&
LAPB_ACK_PENDING_CONDITION
))
{
lapb
->
condition
|=
LAPB_ACK_PENDING_CONDITION
;
lapb_start_t2timer
(
lapb
);
}
...
...
@@ -493,10 +562,14 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb_enquiry_response
(
lapb
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX REJ(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
lapb
->
vr
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 TX REJ(%d) R%d
\n
"
,
lapb
->
token
,
frame
->
pf
,
lapb
->
vr
);
#endif
lapb
->
condition
|=
LAPB_REJECT_CONDITION
;
lapb_send_control
(
lapb
,
LAPB_REJ
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_REJ
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb
->
condition
&=
~
LAPB_ACK_PENDING_CONDITION
;
}
}
...
...
@@ -504,11 +577,15 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_FRMR
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX FRMR(%d) %02X %02X %02X %02X %02X
\n
"
,
lapb
->
token
,
frame
->
pf
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
],
skb
->
data
[
4
]);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX FRMR(%d) %02X "
"%02X %02X %02X %02X
\n
"
,
lapb
->
token
,
frame
->
pf
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
],
skb
->
data
[
4
]);
#endif
lapb_establish_data_link
(
lapb
);
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S1
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 -> S1
\n
"
,
lapb
->
token
);
#endif
lapb_requeue_frames
(
lapb
);
lapb
->
state
=
LAPB_STATE_1
;
...
...
@@ -516,7 +593,8 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_ILLEGAL
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX ILLEGAL(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S3 RX ILLEGAL(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb
->
frmr_data
=
*
frame
;
lapb
->
frmr_type
=
LAPB_FRMR_W
;
...
...
@@ -529,9 +607,6 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb
->
state
=
LAPB_STATE_4
;
lapb
->
n2count
=
0
;
break
;
default:
break
;
}
if
(
!
queued
)
...
...
@@ -542,26 +617,33 @@ static void lapb_state3_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
* State machine for state 4, Frame Reject State.
* The handling of the timer(s) is in file lapb_timer.c.
*/
static
void
lapb_state4_machine
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
static
void
lapb_state4_machine
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
switch
(
frame
->
type
)
{
case
LAPB_SABM
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 RX SABM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S4 -> S3
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 -> S3
\n
"
,
lapb
->
token
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
state
=
LAPB_STATE_3
;
...
...
@@ -576,16 +658,20 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
case
LAPB_SABME
:
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 RX SABME(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX UA(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
#if LAPB_DEBUG > 0
printk
(
KERN_DEBUG
"lapb: (%p) S4 -> S3
\n
"
,
lapb
->
token
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 -> S3
\n
"
,
lapb
->
token
);
#endif
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_UA
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_stop_t1timer
(
lapb
);
lapb_stop_t2timer
(
lapb
);
lapb
->
state
=
LAPB_STATE_3
;
...
...
@@ -597,14 +683,13 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
lapb_connect_indication
(
lapb
,
LAPB_OK
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
printk
(
KERN_DEBUG
"lapb: (%p) S4 TX DM(%d)
\n
"
,
lapb
->
token
,
frame
->
pf
);
#endif
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
lapb_send_control
(
lapb
,
LAPB_DM
,
frame
->
pf
,
LAPB_RESPONSE
);
}
break
;
default:
break
;
}
kfree_skb
(
skb
);
...
...
@@ -613,28 +698,23 @@ static void lapb_state4_machine(lapb_cb *lapb, struct sk_buff *skb, struct lapb_
/*
* Process an incoming LAPB frame
*/
void
lapb_data_input
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
void
lapb_data_input
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
)
{
struct
lapb_frame
frame
;
lapb_decode
(
lapb
,
skb
,
&
frame
);
switch
(
lapb
->
state
)
{
case
LAPB_STATE_0
:
lapb_state0_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_1
:
lapb_state1_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_2
:
lapb_state2_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_3
:
lapb_state3_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_4
:
lapb_state4_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_0
:
lapb_state0_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_1
:
lapb_state1_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_2
:
lapb_state2_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_3
:
lapb_state3_machine
(
lapb
,
skb
,
&
frame
);
break
;
case
LAPB_STATE_4
:
lapb_state4_machine
(
lapb
,
skb
,
&
frame
);
break
;
}
lapb_kick
(
lapb
);
...
...
net/lapb/lapb_out.c
View file @
5c0fbae1
...
...
@@ -38,56 +38,54 @@
* This procedure is passed a buffer descriptor for an iframe. It builds
* the rest of the control part of the frame and then writes it out.
*/
static
void
lapb_send_iframe
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
int
poll_bit
)
static
void
lapb_send_iframe
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
int
poll_bit
)
{
unsigned
char
*
frame
;
if
(
skb
==
NULL
)
if
(
!
skb
)
return
;
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
frame
=
skb_push
(
skb
,
2
);
frame
[
0
]
=
LAPB_I
;
frame
[
0
]
|=
(
lapb
->
vs
<<
1
)
;
frame
[
1
]
=
(
poll_bit
)
?
LAPB_EPF
:
0
;
frame
[
1
]
|=
(
lapb
->
vr
<<
1
)
;
frame
[
0
]
|=
lapb
->
vs
<<
1
;
frame
[
1
]
=
poll_bit
?
LAPB_EPF
:
0
;
frame
[
1
]
|=
lapb
->
vr
<<
1
;
}
else
{
frame
=
skb_push
(
skb
,
1
);
*
frame
=
LAPB_I
;
*
frame
|=
(
poll_bit
)
?
LAPB_SPF
:
0
;
*
frame
|=
(
lapb
->
vr
<<
5
)
;
*
frame
|=
(
lapb
->
vs
<<
1
)
;
*
frame
|=
poll_bit
?
LAPB_SPF
:
0
;
*
frame
|=
lapb
->
vr
<<
5
;
*
frame
|=
lapb
->
vs
<<
1
;
}
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX I(%d) S%d R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
poll_bit
,
lapb
->
vs
,
lapb
->
vr
);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX I(%d) S%d R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
poll_bit
,
lapb
->
vs
,
lapb
->
vr
);
#endif
lapb_transmit_buffer
(
lapb
,
skb
,
LAPB_COMMAND
);
}
void
lapb_kick
(
lapb_cb
*
lapb
)
void
lapb_kick
(
struct
lapb_cb
*
lapb
)
{
struct
sk_buff
*
skb
,
*
skbn
;
unsigned
short
modulus
,
start
,
end
;
modulus
=
(
lapb
->
mode
&
LAPB_EXTENDED
)
?
LAPB_EMODULUS
:
LAPB_SMODULUS
;
start
=
(
skb_peek
(
&
lapb
->
ack_queue
)
==
NULL
)
?
lapb
->
va
:
lapb
->
vs
;
start
=
!
skb_peek
(
&
lapb
->
ack_queue
)
?
lapb
->
va
:
lapb
->
vs
;
end
=
(
lapb
->
va
+
lapb
->
window
)
%
modulus
;
if
(
!
(
lapb
->
condition
&
LAPB_PEER_RX_BUSY_CONDITION
)
&&
start
!=
end
&&
skb_peek
(
&
lapb
->
write_queue
)
!=
NULL
)
{
start
!=
end
&&
skb_peek
(
&
lapb
->
write_queue
))
{
lapb
->
vs
=
start
;
/*
* Dequeue the frame and copy it.
*/
skb
=
skb_dequeue
(
&
lapb
->
write_queue
);
skb
=
skb_dequeue
(
&
lapb
->
write_queue
);
do
{
if
((
skbn
=
skb_clone
(
skb
,
GFP_ATOMIC
))
==
NULL
)
{
...
...
@@ -95,7 +93,7 @@ void lapb_kick(lapb_cb *lapb)
break
;
}
if
(
skb
->
sk
!=
NULL
)
if
(
skb
->
sk
)
skb_set_owner_w
(
skbn
,
skb
->
sk
);
/*
...
...
@@ -119,7 +117,7 @@ void lapb_kick(lapb_cb *lapb)
}
}
void
lapb_transmit_buffer
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
int
type
)
void
lapb_transmit_buffer
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
int
type
)
{
unsigned
char
*
ptr
;
...
...
@@ -152,26 +150,30 @@ void lapb_transmit_buffer(lapb_cb *lapb, struct sk_buff *skb, int type)
}
#if LAPB_DEBUG > 2
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
]);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
]);
#endif
if
(
!
lapb_data_transmit
(
lapb
,
skb
))
kfree_skb
(
skb
);
}
void
lapb_establish_data_link
(
lapb_cb
*
lapb
)
void
lapb_establish_data_link
(
struct
lapb_cb
*
lapb
)
{
lapb
->
condition
=
0x00
;
lapb
->
n2count
=
0
;
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX SABME(1)
\n
"
,
lapb
->
token
,
lapb
->
state
);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX SABME(1)
\n
"
,
lapb
->
token
,
lapb
->
state
);
#endif
lapb_send_control
(
lapb
,
LAPB_SABME
,
LAPB_POLLON
,
LAPB_COMMAND
);
}
else
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX SABM(1)
\n
"
,
lapb
->
token
,
lapb
->
state
);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX SABM(1)
\n
"
,
lapb
->
token
,
lapb
->
state
);
#endif
lapb_send_control
(
lapb
,
LAPB_SABM
,
LAPB_POLLON
,
LAPB_COMMAND
);
}
...
...
@@ -180,10 +182,11 @@ void lapb_establish_data_link(lapb_cb *lapb)
lapb_stop_t2timer
(
lapb
);
}
void
lapb_enquiry_response
(
lapb_cb
*
lapb
)
void
lapb_enquiry_response
(
struct
lapb_cb
*
lapb
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX RR(1) R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
lapb
->
vr
);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX RR(1) R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
lapb
->
vr
);
#endif
lapb_send_control
(
lapb
,
LAPB_RR
,
LAPB_POLLON
,
LAPB_RESPONSE
);
...
...
@@ -191,32 +194,30 @@ void lapb_enquiry_response(lapb_cb *lapb)
lapb
->
condition
&=
~
LAPB_ACK_PENDING_CONDITION
;
}
void
lapb_timeout_response
(
lapb_cb
*
lapb
)
void
lapb_timeout_response
(
struct
lapb_cb
*
lapb
)
{
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX RR(0) R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
lapb
->
vr
);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX RR(0) R%d
\n
"
,
lapb
->
token
,
lapb
->
state
,
lapb
->
vr
);
#endif
lapb_send_control
(
lapb
,
LAPB_RR
,
LAPB_POLLOFF
,
LAPB_RESPONSE
);
lapb
->
condition
&=
~
LAPB_ACK_PENDING_CONDITION
;
}
void
lapb_check_iframes_acked
(
lapb_cb
*
lapb
,
unsigned
short
nr
)
void
lapb_check_iframes_acked
(
struct
lapb_cb
*
lapb
,
unsigned
short
nr
)
{
if
(
lapb
->
vs
==
nr
)
{
lapb_frames_acked
(
lapb
,
nr
);
lapb_stop_t1timer
(
lapb
);
lapb
->
n2count
=
0
;
}
else
{
if
(
lapb
->
va
!=
nr
)
{
lapb_frames_acked
(
lapb
,
nr
);
lapb_start_t1timer
(
lapb
);
}
}
else
if
(
lapb
->
va
!=
nr
)
{
lapb_frames_acked
(
lapb
,
nr
);
lapb_start_t1timer
(
lapb
);
}
}
void
lapb_check_need_response
(
lapb_cb
*
lapb
,
int
type
,
int
pf
)
void
lapb_check_need_response
(
struct
lapb_cb
*
lapb
,
int
type
,
int
pf
)
{
if
(
type
==
LAPB_COMMAND
&&
pf
)
lapb_enquiry_response
(
lapb
);
...
...
net/lapb/lapb_subr.c
View file @
5c0fbae1
...
...
@@ -36,7 +36,7 @@
/*
* This routine purges all the queues of frames.
*/
void
lapb_clear_queues
(
lapb_cb
*
lapb
)
void
lapb_clear_queues
(
struct
lapb_cb
*
lapb
)
{
skb_queue_purge
(
&
lapb
->
write_queue
);
skb_queue_purge
(
&
lapb
->
ack_queue
);
...
...
@@ -47,7 +47,7 @@ void lapb_clear_queues(lapb_cb *lapb)
* acknowledged. This replaces the boxes labelled "V(a) <- N(r)" on the
* SDL diagram.
*/
void
lapb_frames_acked
(
lapb_cb
*
lapb
,
unsigned
short
nr
)
void
lapb_frames_acked
(
struct
lapb_cb
*
lapb
,
unsigned
short
nr
)
{
struct
sk_buff
*
skb
;
int
modulus
;
...
...
@@ -57,16 +57,15 @@ void lapb_frames_acked(lapb_cb *lapb, unsigned short nr)
/*
* Remove all the ack-ed frames from the ack queue.
*/
if
(
lapb
->
va
!=
nr
)
{
while
(
skb_peek
(
&
lapb
->
ack_queue
)
!=
NULL
&&
lapb
->
va
!=
nr
)
{
if
(
lapb
->
va
!=
nr
)
while
(
skb_peek
(
&
lapb
->
ack_queue
)
&&
lapb
->
va
!=
nr
)
{
skb
=
skb_dequeue
(
&
lapb
->
ack_queue
);
kfree_skb
(
skb
);
lapb
->
va
=
(
lapb
->
va
+
1
)
%
modulus
;
}
}
}
void
lapb_requeue_frames
(
lapb_cb
*
lapb
)
void
lapb_requeue_frames
(
struct
lapb_cb
*
lapb
)
{
struct
sk_buff
*
skb
,
*
skb_prev
=
NULL
;
...
...
@@ -76,7 +75,7 @@ void lapb_requeue_frames(lapb_cb *lapb)
* possibility of an empty output queue.
*/
while
((
skb
=
skb_dequeue
(
&
lapb
->
ack_queue
))
!=
NULL
)
{
if
(
skb_prev
==
NULL
)
if
(
!
skb_prev
)
skb_queue_head
(
&
lapb
->
write_queue
,
skb
);
else
skb_append
(
skb_prev
,
skb
);
...
...
@@ -88,7 +87,7 @@ void lapb_requeue_frames(lapb_cb *lapb)
* Validate that the value of nr is between va and vs. Return true or
* false for testing.
*/
int
lapb_validate_nr
(
lapb_cb
*
lapb
,
unsigned
short
nr
)
int
lapb_validate_nr
(
struct
lapb_cb
*
lapb
,
unsigned
short
nr
)
{
unsigned
short
vc
=
lapb
->
va
;
int
modulus
;
...
...
@@ -96,25 +95,27 @@ int lapb_validate_nr(lapb_cb *lapb, unsigned short nr)
modulus
=
(
lapb
->
mode
&
LAPB_EXTENDED
)
?
LAPB_EMODULUS
:
LAPB_SMODULUS
;
while
(
vc
!=
lapb
->
vs
)
{
if
(
nr
==
vc
)
return
1
;
if
(
nr
==
vc
)
return
1
;
vc
=
(
vc
+
1
)
%
modulus
;
}
if
(
nr
==
lapb
->
vs
)
return
1
;
return
0
;
return
nr
==
lapb
->
vs
;
}
/*
* This routine is the centralised routine for parsing the control
* information for the different frame formats.
*/
void
lapb_decode
(
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
void
lapb_decode
(
struct
lapb_cb
*
lapb
,
struct
sk_buff
*
skb
,
struct
lapb_frame
*
frame
)
{
frame
->
type
=
LAPB_ILLEGAL
;
#if LAPB_DEBUG > 2
printk
(
KERN_DEBUG
"lapb: (%p) S%d RX %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
]);
printk
(
KERN_DEBUG
"lapb: (%p) S%d RX %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
0
],
skb
->
data
[
1
],
skb
->
data
[
2
]);
#endif
if
(
lapb
->
mode
&
LAPB_MLP
)
{
...
...
@@ -146,22 +147,31 @@ void lapb_decode(lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame)
skb_pull
(
skb
,
1
);
if
(
lapb
->
mode
&
LAPB_EXTENDED
)
{
if
((
skb
->
data
[
0
]
&
LAPB_S
)
==
0
)
{
frame
->
type
=
LAPB_I
;
/* I frame - carries NR/NS/PF */
if
(
!
(
skb
->
data
[
0
]
&
LAPB_S
))
{
/*
* I frame - carries NR/NS/PF
*/
frame
->
type
=
LAPB_I
;
frame
->
ns
=
(
skb
->
data
[
0
]
>>
1
)
&
0x7F
;
frame
->
nr
=
(
skb
->
data
[
1
]
>>
1
)
&
0x7F
;
frame
->
pf
=
skb
->
data
[
1
]
&
LAPB_EPF
;
frame
->
control
[
0
]
=
skb
->
data
[
0
];
frame
->
control
[
1
]
=
skb
->
data
[
1
];
skb_pull
(
skb
,
2
);
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
1
)
{
/* S frame - take out PF/NR */
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
1
)
{
/*
* S frame - take out PF/NR
*/
frame
->
type
=
skb
->
data
[
0
]
&
0x0F
;
frame
->
nr
=
(
skb
->
data
[
1
]
>>
1
)
&
0x7F
;
frame
->
pf
=
skb
->
data
[
1
]
&
LAPB_EPF
;
frame
->
control
[
0
]
=
skb
->
data
[
0
];
frame
->
control
[
1
]
=
skb
->
data
[
1
];
skb_pull
(
skb
,
2
);
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
3
)
{
/* U frame - take out PF */
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
3
)
{
/*
* U frame - take out PF
*/
frame
->
type
=
skb
->
data
[
0
]
&
~
LAPB_SPF
;
frame
->
pf
=
skb
->
data
[
0
]
&
LAPB_SPF
;
frame
->
control
[
0
]
=
skb
->
data
[
0
];
...
...
@@ -169,16 +179,25 @@ void lapb_decode(lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame)
skb_pull
(
skb
,
1
);
}
}
else
{
if
((
skb
->
data
[
0
]
&
LAPB_S
)
==
0
)
{
frame
->
type
=
LAPB_I
;
/* I frame - carries NR/NS/PF */
if
(
!
(
skb
->
data
[
0
]
&
LAPB_S
))
{
/*
* I frame - carries NR/NS/PF
*/
frame
->
type
=
LAPB_I
;
frame
->
ns
=
(
skb
->
data
[
0
]
>>
1
)
&
0x07
;
frame
->
nr
=
(
skb
->
data
[
0
]
>>
5
)
&
0x07
;
frame
->
pf
=
skb
->
data
[
0
]
&
LAPB_SPF
;
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
1
)
{
/* S frame - take out PF/NR */
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
1
)
{
/*
* S frame - take out PF/NR
*/
frame
->
type
=
skb
->
data
[
0
]
&
0x0F
;
frame
->
nr
=
(
skb
->
data
[
0
]
>>
5
)
&
0x07
;
frame
->
pf
=
skb
->
data
[
0
]
&
LAPB_SPF
;
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
3
)
{
/* U frame - take out PF */
}
else
if
((
skb
->
data
[
0
]
&
LAPB_U
)
==
3
)
{
/*
* U frame - take out PF
*/
frame
->
type
=
skb
->
data
[
0
]
&
~
LAPB_SPF
;
frame
->
pf
=
skb
->
data
[
0
]
&
LAPB_SPF
;
}
...
...
@@ -195,7 +214,8 @@ void lapb_decode(lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame)
* Only supervisory or unnumbered frames are processed, FRMRs are handled
* by lapb_transmit_frmr below.
*/
void
lapb_send_control
(
lapb_cb
*
lapb
,
int
frametype
,
int
poll_bit
,
int
type
)
void
lapb_send_control
(
struct
lapb_cb
*
lapb
,
int
frametype
,
int
poll_bit
,
int
type
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
...
...
@@ -209,18 +229,18 @@ void lapb_send_control(lapb_cb *lapb, int frametype, int poll_bit, int type)
if
((
frametype
&
LAPB_U
)
==
LAPB_U
)
{
dptr
=
skb_put
(
skb
,
1
);
*
dptr
=
frametype
;
*
dptr
|=
(
poll_bit
)
?
LAPB_SPF
:
0
;
*
dptr
|=
poll_bit
?
LAPB_SPF
:
0
;
}
else
{
dptr
=
skb_put
(
skb
,
2
);
dptr
[
0
]
=
frametype
;
dptr
[
1
]
=
(
lapb
->
vr
<<
1
);
dptr
[
1
]
|=
(
poll_bit
)
?
LAPB_EPF
:
0
;
dptr
[
1
]
|=
poll_bit
?
LAPB_EPF
:
0
;
}
}
else
{
dptr
=
skb_put
(
skb
,
1
);
*
dptr
=
frametype
;
*
dptr
|=
(
poll_bit
)
?
LAPB_SPF
:
0
;
if
((
frametype
&
LAPB_U
)
==
LAPB_S
)
/* S frames carry NR */
*
dptr
|=
poll_bit
?
LAPB_SPF
:
0
;
if
((
frametype
&
LAPB_U
)
==
LAPB_S
)
/* S frames carry NR */
*
dptr
|=
(
lapb
->
vr
<<
5
);
}
...
...
@@ -231,7 +251,7 @@ void lapb_send_control(lapb_cb *lapb, int frametype, int poll_bit, int type)
* This routine generates FRMRs based on information previously stored in
* the LAPB control block.
*/
void
lapb_transmit_frmr
(
lapb_cb
*
lapb
)
void
lapb_transmit_frmr
(
struct
lapb_cb
*
lapb
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
...
...
@@ -254,7 +274,10 @@ void lapb_transmit_frmr(lapb_cb *lapb)
*
dptr
++
=
lapb
->
frmr_type
;
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
],
skb
->
data
[
4
],
skb
->
data
[
5
]);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX FRMR %02X %02X %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
],
skb
->
data
[
4
],
skb
->
data
[
5
]);
#endif
}
else
{
dptr
=
skb_put
(
skb
,
4
);
...
...
@@ -268,7 +291,9 @@ void lapb_transmit_frmr(lapb_cb *lapb)
*
dptr
++
=
lapb
->
frmr_type
;
#if LAPB_DEBUG > 1
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX FRMR %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
]);
printk
(
KERN_DEBUG
"lapb: (%p) S%d TX FRMR %02X %02X %02X
\n
"
,
lapb
->
token
,
lapb
->
state
,
skb
->
data
[
1
],
skb
->
data
[
2
],
skb
->
data
[
3
]);
#endif
}
...
...
net/lapb/lapb_timer.c
View file @
5c0fbae1
...
...
@@ -37,7 +37,7 @@
static
void
lapb_t1timer_expiry
(
unsigned
long
);
static
void
lapb_t2timer_expiry
(
unsigned
long
);
void
lapb_start_t1timer
(
lapb_cb
*
lapb
)
void
lapb_start_t1timer
(
struct
lapb_cb
*
lapb
)
{
del_timer
(
&
lapb
->
t1timer
);
...
...
@@ -48,7 +48,7 @@ void lapb_start_t1timer(lapb_cb *lapb)
add_timer
(
&
lapb
->
t1timer
);
}
void
lapb_start_t2timer
(
lapb_cb
*
lapb
)
void
lapb_start_t2timer
(
struct
lapb_cb
*
lapb
)
{
del_timer
(
&
lapb
->
t2timer
);
...
...
@@ -59,24 +59,24 @@ void lapb_start_t2timer(lapb_cb *lapb)
add_timer
(
&
lapb
->
t2timer
);
}
void
lapb_stop_t1timer
(
lapb_cb
*
lapb
)
void
lapb_stop_t1timer
(
struct
lapb_cb
*
lapb
)
{
del_timer
(
&
lapb
->
t1timer
);
}
void
lapb_stop_t2timer
(
lapb_cb
*
lapb
)
void
lapb_stop_t2timer
(
struct
lapb_cb
*
lapb
)
{
del_timer
(
&
lapb
->
t2timer
);
}
int
lapb_t1timer_running
(
lapb_cb
*
lapb
)
int
lapb_t1timer_running
(
struct
lapb_cb
*
lapb
)
{
return
timer_pending
(
&
lapb
->
t1timer
);
}
static
void
lapb_t2timer_expiry
(
unsigned
long
param
)
{
lapb_cb
*
lapb
=
(
lapb_cb
*
)
param
;
struct
lapb_cb
*
lapb
=
(
struct
lapb_cb
*
)
param
;
if
(
lapb
->
condition
&
LAPB_ACK_PENDING_CONDITION
)
{
lapb
->
condition
&=
~
LAPB_ACK_PENDING_CONDITION
;
...
...
@@ -86,7 +86,7 @@ static void lapb_t2timer_expiry(unsigned long param)
static
void
lapb_t1timer_expiry
(
unsigned
long
param
)
{
lapb_cb
*
lapb
=
(
lapb_cb
*
)
param
;
struct
lapb_cb
*
lapb
=
(
struct
lapb_cb
*
)
param
;
switch
(
lapb
->
state
)
{
...
...
net/x25/af_x25.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -64,13 +65,15 @@ int sysctl_x25_reset_request_timeout = X25_DEFAULT_T22;
int
sysctl_x25_clear_request_timeout
=
X25_DEFAULT_T23
;
int
sysctl_x25_ack_holdback_timeout
=
X25_DEFAULT_T2
;
static
struct
sock
*
volatile
x25_list
/* = NULL initially */
;
static
struct
sock
*
x25_list
;
static
rwlock_t
x25_list_lock
=
RW_LOCK_UNLOCKED
;
static
struct
proto_ops
x25_proto_ops
;
static
x25_address
null_x25_address
=
{
" "
};
static
struct
x25_address
null_x25_address
=
{
" "
};
int
x25_addr_ntoa
(
unsigned
char
*
p
,
x25_address
*
called_addr
,
x25_address
*
calling_addr
)
int
x25_addr_ntoa
(
unsigned
char
*
p
,
struct
x25_address
*
called_addr
,
struct
x25_address
*
calling_addr
)
{
int
called_len
,
calling_len
;
char
*
called
,
*
calling
;
...
...
@@ -101,13 +104,13 @@ int x25_addr_ntoa(unsigned char *p, x25_address *called_addr, x25_address *calli
}
}
*
called
=
'\0'
;
*
calling
=
'\0'
;
*
called
=
*
calling
=
'\0'
;
return
1
+
(
called_len
+
calling_len
+
1
)
/
2
;
}
int
x25_addr_aton
(
unsigned
char
*
p
,
x25_address
*
called_addr
,
x25_address
*
calling_addr
)
int
x25_addr_aton
(
unsigned
char
*
p
,
struct
x25_address
*
called_addr
,
struct
x25_address
*
calling_addr
)
{
unsigned
int
called_len
,
calling_len
;
char
*
called
,
*
calling
;
...
...
@@ -150,28 +153,22 @@ int x25_addr_aton(unsigned char *p, x25_address *called_addr, x25_address *calli
static
void
x25_remove_socket
(
struct
sock
*
sk
)
{
struct
sock
*
s
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
write_lock_bh
(
&
x25_list_lock
);
if
((
s
=
x25_list
)
==
sk
)
{
if
((
s
=
x25_list
)
==
sk
)
x25_list
=
s
->
next
;
restore_flags
(
flags
);
return
;
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
else
while
(
s
&&
s
->
next
)
{
if
(
s
->
next
==
sk
)
{
s
->
next
=
sk
->
next
;
restore_flags
(
flags
);
return
;
sock_put
(
sk
);
break
;
}
s
=
s
->
next
;
}
restore_flags
(
flags
);
write_unlock_bh
(
&
x25_list_lock
);
}
/*
...
...
@@ -181,18 +178,23 @@ static void x25_kill_by_device(struct net_device *dev)
{
struct
sock
*
s
;
for
(
s
=
x25_list
;
s
!=
NULL
;
s
=
s
->
next
)
write_lock_bh
(
&
x25_list_lock
);
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
(
x25_sk
(
s
)
->
neighbour
&&
x25_sk
(
s
)
->
neighbour
->
dev
==
dev
)
x25_disconnect
(
s
,
ENETUNREACH
,
0
,
0
);
write_unlock_bh
(
&
x25_list_lock
);
}
/*
* Handle device status changes.
*/
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
=
(
struct
net_device
*
)
ptr
;
struct
x25_neigh
*
n
eigh
;
struct
net_device
*
dev
=
ptr
;
struct
x25_neigh
*
n
b
;
if
(
dev
->
type
==
ARPHRD_X25
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
...
...
@@ -204,8 +206,11 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo
x25_link_device_up
(
dev
);
break
;
case
NETDEV_GOING_DOWN
:
if
((
neigh
=
x25_get_neigh
(
dev
)))
x25_terminate_link
(
neigh
);
nb
=
x25_get_neigh
(
dev
);
if
(
nb
)
{
x25_terminate_link
(
nb
);
x25_neigh_put
(
nb
);
}
break
;
case
NETDEV_DOWN
:
x25_kill_by_device
(
dev
);
...
...
@@ -223,76 +228,79 @@ static int x25_device_event(struct notifier_block *this, unsigned long event, vo
*/
static
void
x25_insert_socket
(
struct
sock
*
sk
)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
write_lock_bh
(
&
x25_list_lock
);
sk
->
next
=
x25_list
;
x25_list
=
sk
;
restore_flags
(
flags
);
sock_hold
(
sk
);
write_unlock_bh
(
&
x25_list_lock
);
}
/*
* Find a socket that wants to accept the Call Request we just
* received.
*/
static
struct
sock
*
x25_find_listener
(
x25_address
*
addr
)
static
struct
sock
*
x25_find_listener
(
struct
x25_address
*
addr
)
{
unsigned
long
flags
;
struct
sock
*
s
;
save_flags
(
flags
);
cli
();
read_lock_bh
(
&
x25_list_lock
);
for
(
s
=
x25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
((
!
strcmp
(
addr
->
x25_addr
,
x25_sk
(
s
)
->
source_addr
.
x25_addr
)
||
strcmp
(
addr
->
x25_addr
,
null_x25_address
.
x25_addr
)
==
0
)
&&
s
->
state
==
TCP_LISTEN
)
{
restore_flags
(
flags
);
return
s
;
}
}
!
strcmp
(
addr
->
x25_addr
,
null_x25_address
.
x25_addr
))
&&
s
->
state
==
TCP_LISTEN
)
break
;
restore_flags
(
flags
);
return
NULL
;
if
(
s
)
sock_hold
(
s
);
read_unlock_bh
(
&
x25_list_lock
);
return
s
;
}
/*
* Find a connected X.25 socket given my LCI and neighbour.
*/
struct
sock
*
x25_find_socket
(
unsigned
int
lci
,
struct
x25_neigh
*
neigh
)
struct
sock
*
__x25_find_socket
(
unsigned
int
lci
,
struct
x25_neigh
*
nb
)
{
struct
sock
*
s
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
(
x25_sk
(
s
)
->
lci
==
lci
&&
x25_sk
(
s
)
->
neighbour
==
nb
)
break
;
if
(
s
)
sock_hold
(
s
);
return
s
;
}
for
(
s
=
x25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
x25_sk
(
s
)
->
lci
==
lci
&&
x25_sk
(
s
)
->
neighbour
==
neigh
)
{
restore_flags
(
flags
);
return
s
;
}
}
struct
sock
*
x25_find_socket
(
unsigned
int
lci
,
struct
x25_neigh
*
nb
)
{
struct
sock
*
s
;
restore_flags
(
flags
);
return
NULL
;
read_lock_bh
(
&
x25_list_lock
);
s
=
__x25_find_socket
(
lci
,
nb
);
read_unlock_bh
(
&
x25_list_lock
);
return
s
;
}
/*
* 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
;
struct
sock
*
sk
;
while
(
x25_find_socket
(
lci
,
neigh
)
!=
NULL
)
{
lci
++
;
if
(
lci
==
4096
)
return
0
;
read_lock_bh
(
&
x25_list_lock
);
while
((
sk
=
__x25_find_socket
(
lci
,
nb
))
!=
NULL
)
{
sock_put
(
sk
);
if
(
++
lci
==
4096
)
{
lci
=
0
;
break
;
}
}
read_unlock_bh
(
&
x25_list_lock
);
return
lci
;
}
...
...
@@ -318,11 +326,9 @@ static void x25_destroy_timer(unsigned long data)
void
x25_destroy_socket
(
struct
sock
*
sk
)
/* Not static as it's used by the timer */
{
struct
sk_buff
*
skb
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
sock_hold
(
sk
);
lock_sock
(
sk
);
x25_stop_heartbeat
(
sk
);
x25_stop_timer
(
sk
);
...
...
@@ -339,7 +345,7 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
kfree_skb
(
skb
);
}
if
(
atomic_read
(
&
sk
->
wmem_alloc
)
!=
0
||
atomic_read
(
&
sk
->
rmem_alloc
)
!=
0
)
{
if
(
atomic_read
(
&
sk
->
wmem_alloc
)
||
atomic_read
(
&
sk
->
rmem_alloc
)
)
{
/* Defer: outstanding buffers */
init_timer
(
&
sk
->
timer
);
sk
->
timer
.
expires
=
jiffies
+
10
*
HZ
;
...
...
@@ -350,8 +356,8 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
sk_free
(
sk
);
MOD_DEC_USE_COUNT
;
}
restore_flags
(
flags
);
release_sock
(
sk
);
sock_put
(
sk
);
}
/*
...
...
@@ -360,81 +366,77 @@ void x25_destroy_socket(struct sock *sk) /* Not static as it's used by the timer
*/
static
int
x25_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
char
*
optval
,
int
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
opt
;
struct
sock
*
sk
=
sock
->
sk
;
int
rc
=
-
ENOPROTOOPT
;
if
(
level
!=
SOL_X25
)
return
-
ENOPROTOOPT
;
if
(
level
!=
SOL_X25
||
optname
!=
X25_QBITINCL
)
goto
out
;
rc
=
-
EINVAL
;
if
(
optlen
<
sizeof
(
int
))
return
-
EINVAL
;
goto
out
;
rc
=
-
EFAULT
;
if
(
get_user
(
opt
,
(
int
*
)
optval
))
return
-
EFAULT
;
switch
(
optname
)
{
case
X25_QBITINCL
:
x25_sk
(
sk
)
->
qbitincl
=
opt
?
1
:
0
;
return
0
;
goto
out
;
default:
return
-
ENOPROTOOPT
;
}
x25_sk
(
sk
)
->
qbitincl
=
!!
opt
;
rc
=
0
;
out:
return
rc
;
}
static
int
x25_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
char
*
optval
,
int
*
optlen
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
val
=
0
;
int
len
;
int
val
,
len
,
rc
=
-
ENOPROTOOPT
;
if
(
level
!=
SOL_X25
)
return
-
ENOPROTOOPT
;
if
(
level
!=
SOL_X25
||
optname
!=
X25_QBITINCL
)
goto
out
;
rc
=
-
EFAULT
;
if
(
get_user
(
len
,
optlen
))
return
-
EFAULT
;
switch
(
optname
)
{
case
X25_QBITINCL
:
val
=
x25_sk
(
sk
)
->
qbitincl
;
break
;
default:
return
-
ENOPROTOOPT
;
}
goto
out
;
len
=
min_t
(
unsigned
int
,
len
,
sizeof
(
int
));
rc
=
-
EINVAL
;
if
(
len
<
0
)
return
-
EINVAL
;
goto
out
;
rc
=
-
EFAULT
;
if
(
put_user
(
len
,
optlen
))
return
-
EFAULT
;
goto
out
;
return
copy_to_user
(
optval
,
&
val
,
len
)
?
-
EFAULT
:
0
;
val
=
x25_sk
(
sk
)
->
qbitincl
;
rc
=
copy_to_user
(
optval
,
&
val
,
len
)
?
-
EFAULT
:
0
;
out:
return
rc
;
}
static
int
x25_listen
(
struct
socket
*
sock
,
int
backlog
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
rc
=
-
EOPNOTSUPP
;
if
(
sk
->
state
!=
TCP_LISTEN
)
{
memset
(
&
x25_sk
(
sk
)
->
dest_addr
,
0
,
X25_ADDR_LEN
);
sk
->
max_ack_backlog
=
backlog
;
sk
->
state
=
TCP_LISTEN
;
r
eturn
0
;
r
c
=
0
;
}
return
-
EOPNOTSUPP
;
return
rc
;
}
static
struct
sock
*
x25_alloc_socket
(
void
)
{
struct
sock
*
sk
;
x25_cb
*
x25
;
struct
x25_opt
*
x25
;
MOD_INC_USE_COUNT
;
...
...
@@ -445,7 +447,7 @@ static struct sock *x25_alloc_socket(void)
if
(
!
x25
)
goto
frees
;
memset
(
x25
,
0
x00
,
sizeof
(
*
x25
));
memset
(
x25
,
0
,
sizeof
(
*
x25
));
x25
->
sk
=
sk
;
...
...
@@ -455,23 +457,28 @@ static struct sock *x25_alloc_socket(void)
skb_queue_head_init
(
&
x25
->
fragment_queue
);
skb_queue_head_init
(
&
x25
->
interrupt_in_queue
);
skb_queue_head_init
(
&
x25
->
interrupt_out_queue
);
out:
return
sk
;
frees:
sk_free
(
sk
);
out:
return
sk
;
frees:
sk_free
(
sk
);
sk
=
NULL
;
decmod:
MOD_DEC_USE_COUNT
;
decmod:
MOD_DEC_USE_COUNT
;
goto
out
;
}
static
int
x25_create
(
struct
socket
*
sock
,
int
protocol
)
{
struct
sock
*
sk
;
x25_cb
*
x25
;
struct
x25_opt
*
x25
;
int
rc
=
-
ESOCKTNOSUPPORT
;
if
(
sock
->
type
!=
SOCK_SEQPACKET
||
protocol
!=
0
)
return
-
ESOCKTNOSUPPORT
;
if
(
sock
->
type
!=
SOCK_SEQPACKET
||
protocol
)
goto
out
;
rc
=
-
ENOMEM
;
if
((
sk
=
x25_alloc_socket
())
==
NULL
)
return
-
ENOMEM
;
goto
out
;
x25
=
x25_sk
(
sk
);
...
...
@@ -495,20 +502,21 @@ static int x25_create(struct socket *sock, int protocol)
x25
->
facilities
.
pacsize_out
=
X25_DEFAULT_PACKET_SIZE
;
x25
->
facilities
.
throughput
=
X25_DEFAULT_THROUGHPUT
;
x25
->
facilities
.
reverse
=
X25_DEFAULT_REVERSE
;
return
0
;
rc
=
0
;
out:
return
rc
;
}
static
struct
sock
*
x25_make_new
(
struct
sock
*
osk
)
{
struct
sock
*
sk
;
x25_cb
*
x25
,
*
ox25
;
struct
sock
*
sk
=
NULL
;
struct
x25_opt
*
x25
,
*
ox25
;
if
(
osk
->
type
!=
SOCK_SEQPACKET
)
return
NULL
;
goto
out
;
if
((
sk
=
x25_alloc_socket
())
==
NULL
)
return
NULL
;
goto
out
;
x25
=
x25_sk
(
sk
);
...
...
@@ -533,16 +541,17 @@ static struct sock *x25_make_new(struct sock *osk)
x25
->
qbitincl
=
ox25
->
qbitincl
;
init_timer
(
&
x25
->
timer
);
out:
return
sk
;
}
static
int
x25_release
(
struct
socket
*
sock
)
{
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
;
struct
x25_opt
*
x25
;
if
(
sk
==
NULL
)
return
0
;
if
(
!
sk
)
goto
out
;
x25
=
x25_sk
(
sk
);
...
...
@@ -567,14 +576,11 @@ static int x25_release(struct socket *sock)
sk
->
dead
=
1
;
sk
->
destroy
=
1
;
break
;
default:
break
;
}
sock
->
sk
=
NULL
;
sk
->
socket
=
NULL
;
/* Not used, but we should do this */
out:
return
0
;
}
...
...
@@ -583,68 +589,98 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct
sock
*
sk
=
sock
->
sk
;
struct
sockaddr_x25
*
addr
=
(
struct
sockaddr_x25
*
)
uaddr
;
if
(
sk
->
zapped
==
0
)
return
-
EINVAL
;
if
(
addr_len
!=
sizeof
(
struct
sockaddr_x25
))
return
-
EINVAL
;
if
(
addr
->
sx25_family
!=
AF_X25
)
if
(
!
sk
->
zapped
||
addr_len
!=
sizeof
(
struct
sockaddr_x25
)
||
addr
->
sx25_family
!=
AF_X25
)
return
-
EINVAL
;
x25_sk
(
sk
)
->
source_addr
=
addr
->
sx25_addr
;
x25_insert_socket
(
sk
);
sk
->
zapped
=
0
;
SOCK_DEBUG
(
sk
,
"x25_bind: socket is bound
\n
"
);
return
0
;
}
static
int
x25_wait_for_connection_establishment
(
struct
sock
*
sk
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
int
rc
;
add_wait_queue_exclusive
(
sk
->
sleep
,
&
wait
);
for
(;;)
{
__set_current_state
(
TASK_INTERRUPTIBLE
);
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
break
;
rc
=
sock_error
(
sk
);
if
(
rc
)
{
sk
->
socket
->
state
=
SS_UNCONNECTED
;
break
;
}
rc
=
0
;
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
release_sock
(
sk
);
schedule
();
lock_sock
(
sk
);
}
else
break
;
}
__set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
sk
->
sleep
,
&
wait
);
return
rc
;
}
static
int
x25_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
,
int
flags
)
{
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
struct
sockaddr_x25
*
addr
=
(
struct
sockaddr_x25
*
)
uaddr
;
struct
net_device
*
dev
;
struct
x25_route
*
rt
;
int
rc
=
0
;
lock_sock
(
sk
);
if
(
sk
->
state
==
TCP_ESTABLISHED
&&
sock
->
state
==
SS_CONNECTING
)
{
sock
->
state
=
SS_CONNECTED
;
return
0
;
/* Connect completed during a ERESTARTSYS event */
goto
out
;
/* Connect completed during a ERESTARTSYS event */
}
rc
=
-
ECONNREFUSED
;
if
(
sk
->
state
==
TCP_CLOSE
&&
sock
->
state
==
SS_CONNECTING
)
{
sock
->
state
=
SS_UNCONNECTED
;
return
-
ECONNREFUSED
;
goto
out
;
}
rc
=
-
EISCONN
;
/* No reconnect on a seqpacket socket */
if
(
sk
->
state
==
TCP_ESTABLISHED
)
return
-
EISCONN
;
/* No reconnect on a seqpacket socket */
goto
out
;
sk
->
state
=
TCP_CLOSE
;
sock
->
state
=
SS_UNCONNECTED
;
if
(
addr_len
!=
sizeof
(
struct
sockaddr_x25
))
return
-
EINVAL
;
if
(
addr
->
sx25_family
!=
AF_X25
)
return
-
EINVAL
;
rc
=
-
EINVAL
;
if
(
addr_len
!=
sizeof
(
struct
sockaddr_x25
)
||
addr
->
sx25_family
!=
AF_X25
)
goto
out
;
if
((
dev
=
x25_get_route
(
&
addr
->
sx25_addr
))
==
NULL
)
return
-
ENETUNREACH
;
rc
=
-
ENETUNREACH
;
rt
=
x25_get_route
(
&
addr
->
sx25_addr
);
if
(
!
rt
)
goto
out
;
if
((
x25
->
neighbour
=
x25_get_neigh
(
dev
))
==
NULL
)
return
-
ENETUNREACH
;
x25
->
neighbour
=
x25_get_neigh
(
rt
->
dev
);
if
(
!
x25
->
neighbour
)
goto
out_put_route
;
x25_limit_facilities
(
&
x25
->
facilities
,
x25
->
neighbour
);
if
((
x25
->
lci
=
x25_new_lci
(
x25
->
neighbour
))
==
0
)
return
-
ENETUNREACH
;
x25
->
lci
=
x25_new_lci
(
x25
->
neighbour
);
if
(
!
x25
->
lci
)
goto
out_put_neigh
;
rc
=
-
EINVAL
;
if
(
sk
->
zapped
)
/* Must bind first - autobinding does not work */
return
-
EINVAL
;
goto
out_put_neigh
;
if
(
!
strcmp
(
x25
->
source_addr
.
x25_addr
,
null_x25_address
.
x25_addr
))
memset
(
&
x25
->
source_addr
,
'\0'
,
X25_ADDR_LEN
);
...
...
@@ -663,113 +699,119 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len
x25_start_t21timer
(
sk
);
/* Now the loop */
rc
=
-
EINPROGRESS
;
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
return
-
EINPROGRESS
;
cli
();
/* To avoid races on the sleep */
goto
out_put_neigh
;
/*
* A Clear Request or timeout or failed routing will go to closed.
*/
while
(
sk
->
state
==
TCP_SYN_SENT
)
{
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
{
sti
();
return
-
ERESTARTSYS
;
}
}
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
sti
();
sock
->
state
=
SS_UNCONNECTED
;
return
sock_error
(
sk
);
/* Always set at this point */
}
rc
=
x25_wait_for_connection_establishment
(
sk
);
if
(
rc
)
goto
out_put_neigh
;
sock
->
state
=
SS_CONNECTED
;
rc
=
0
;
out_put_neigh:
if
(
rc
)
x25_neigh_put
(
x25
->
neighbour
);
out_put_route:
x25_route_put
(
rt
);
out:
release_sock
(
sk
);
return
rc
;
}
sti
();
static
int
x25_wait_for_data
(
struct
sock
*
sk
,
int
timeout
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
int
rc
=
0
;
return
0
;
add_wait_queue_exclusive
(
sk
->
sleep
,
&
wait
);
for
(;;)
{
__set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
sk
->
shutdown
&
RCV_SHUTDOWN
)
break
;
rc
=
-
ERESTARTSYS
;
if
(
signal_pending
(
current
))
break
;
rc
=
-
EAGAIN
;
if
(
!
timeout
)
break
;
rc
=
0
;
if
(
skb_queue_empty
(
&
sk
->
receive_queue
))
{
release_sock
(
sk
);
timeout
=
schedule_timeout
(
timeout
);
lock_sock
(
sk
);
}
else
break
;
}
__set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
sk
->
sleep
,
&
wait
);
return
rc
;
}
static
int
x25_accept
(
struct
socket
*
sock
,
struct
socket
*
newsock
,
int
flags
)
{
struct
sock
*
sk
;
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
newsk
;
struct
sk_buff
*
skb
;
int
rc
=
-
EINVAL
;
if
(
(
sk
=
sock
->
sk
)
==
NULL
)
return
-
EINVAL
;
if
(
!
sk
||
sk
->
state
!=
TCP_LISTEN
)
goto
out
;
rc
=
-
EOPNOTSUPP
;
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
return
-
EOPNOTSUPP
;
if
(
sk
->
state
!=
TCP_LISTEN
)
return
-
EINVAL
;
/*
* The write queue this time is holding sockets ready to use
* hooked into the CALL INDICATION we saved
*/
do
{
cli
();
if
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
==
NULL
)
{
if
(
flags
&
O_NONBLOCK
)
{
sti
();
return
-
EWOULDBLOCK
;
}
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
{
sti
();
return
-
ERESTARTSYS
;
}
}
}
while
(
skb
==
NULL
);
newsk
=
skb
->
sk
;
newsk
->
pair
=
NULL
;
goto
out
;
rc
=
x25_wait_for_data
(
sk
,
sk
->
rcvtimeo
);
if
(
rc
)
goto
out
;
skb
=
skb_dequeue
(
&
sk
->
receive_queue
);
rc
=
-
EINVAL
;
if
(
!
skb
->
sk
)
goto
out
;
newsk
=
skb
->
sk
;
newsk
->
pair
=
NULL
;
newsk
->
socket
=
newsock
;
newsk
->
sleep
=
&
newsock
->
wait
;
sti
();
newsk
->
sleep
=
&
newsock
->
wait
;
/* Now attach up the new socket */
skb
->
sk
=
NULL
;
kfree_skb
(
skb
);
sk
->
ack_backlog
--
;
newsock
->
sk
=
newsk
;
newsock
->
sk
=
newsk
;
newsock
->
state
=
SS_CONNECTED
;
return
0
;
rc
=
0
;
out:
return
rc
;
}
static
int
x25_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
uaddr_len
,
int
peer
)
{
struct
sockaddr_x25
*
sx25
=
(
struct
sockaddr_x25
*
)
uaddr
;
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
peer
!=
0
)
{
if
(
peer
)
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
return
-
ENOTCONN
;
sx25
->
sx25_addr
=
x25
->
dest_addr
;
}
else
{
}
else
sx25
->
sx25_addr
=
x25
->
source_addr
;
}
sx25
->
sx25_family
=
AF_X25
;
*
uaddr_len
=
sizeof
(
struct
sockaddr_
x25
);
*
uaddr_len
=
sizeof
(
*
s
x25
);
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
*
make
;
x25_cb
*
makex25
;
x25_address
source_addr
,
dest_addr
;
struct
x25_opt
*
makex25
;
struct
x25_address
source_addr
,
dest_addr
;
struct
x25_facilities
facilities
;
int
len
;
int
len
,
rc
;
/*
* Remove the LCI and frame type.
...
...
@@ -790,33 +832,28 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
/*
* We can't accept the Call Request.
*/
if
(
sk
==
NULL
||
sk
->
ack_backlog
==
sk
->
max_ack_backlog
)
{
x25_transmit_clear_request
(
neigh
,
lci
,
0x01
);
return
0
;
}
if
(
!
sk
||
sk
->
ack_backlog
==
sk
->
max_ack_backlog
)
goto
out_clear_request
;
/*
* Try to reach a compromise on the requested facilities.
*/
if
((
len
=
x25_negotiate_facilities
(
skb
,
sk
,
&
facilities
))
==
-
1
)
{
x25_transmit_clear_request
(
neigh
,
lci
,
0x01
);
return
0
;
}
if
((
len
=
x25_negotiate_facilities
(
skb
,
sk
,
&
facilities
))
==
-
1
)
goto
out_sock_put
;
/*
* current neighbour/link might impose additional limits
* on certain facilties
*/
x25_limit_facilities
(
&
facilities
,
neigh
);
x25_limit_facilities
(
&
facilities
,
nb
);
/*
* Try to create a new socket.
*/
if
((
make
=
x25_make_new
(
sk
))
==
NULL
)
{
x25_transmit_clear_request
(
neigh
,
lci
,
0x01
);
return
0
;
}
make
=
x25_make_new
(
sk
);
if
(
!
make
)
goto
out_sock_put
;
/*
* Remove the facilities, leaving any Call User Data.
...
...
@@ -830,7 +867,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
makex25
->
lci
=
lci
;
makex25
->
dest_addr
=
dest_addr
;
makex25
->
source_addr
=
source_addr
;
makex25
->
neighbour
=
n
eigh
;
makex25
->
neighbour
=
n
b
;
makex25
->
facilities
=
facilities
;
makex25
->
vc_facil_mask
=
x25_sk
(
sk
)
->
vc_facil_mask
;
...
...
@@ -857,55 +894,70 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i
if
(
!
sk
->
dead
)
sk
->
data_ready
(
sk
,
skb
->
len
);
return
1
;
rc
=
1
;
sock_put
(
sk
);
out:
return
rc
;
out_sock_put:
sock_put
(
sk
);
out_clear_request:
rc
=
0
;
x25_transmit_clear_request
(
nb
,
lci
,
0x01
);
goto
out
;
}
static
int
x25_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
len
,
struct
scm_cookie
*
scm
)
{
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
struct
sockaddr_x25
*
usx25
=
(
struct
sockaddr_x25
*
)
msg
->
msg_name
;
int
err
;
struct
sockaddr_x25
sx25
;
struct
sk_buff
*
skb
;
unsigned
char
*
asmptr
;
int
size
,
qbit
=
0
;
int
noblock
=
msg
->
msg_flags
&
MSG_DONTWAIT
;
int
size
,
qbit
=
0
,
rc
=
-
EINVAL
;
if
(
msg
->
msg_flags
&
~
(
MSG_DONTWAIT
|
MSG_OOB
|
MSG_EOR
))
return
-
EINVAL
;
goto
out
;
/* we currently don't support segmented records at the user interface */
if
(
!
(
msg
->
msg_flags
&
(
MSG_EOR
|
MSG_OOB
)))
return
-
EINVAL
;
goto
out
;
rc
=
-
EADDRNOTAVAIL
;
if
(
sk
->
zapped
)
return
-
EADDRNOTAVAIL
;
goto
out
;
rc
=
-
EPIPE
;
if
(
sk
->
shutdown
&
SEND_SHUTDOWN
)
{
send_sig
(
SIGPIPE
,
current
,
0
);
return
-
EPIPE
;
goto
out
;
}
if
(
x25
->
neighbour
==
NULL
)
return
-
ENETUNREACH
;
rc
=
-
ENETUNREACH
;
if
(
!
x25
->
neighbour
)
goto
out
;
if
(
usx25
!=
NULL
)
{
if
(
usx25
)
{
rc
=
-
EINVAL
;
if
(
msg
->
msg_namelen
<
sizeof
(
sx25
))
return
-
EINVAL
;
sx25
=
*
usx25
;
goto
out
;
memcpy
(
&
sx25
,
usx25
,
sizeof
(
sx25
));
rc
=
-
EISCONN
;
if
(
strcmp
(
x25
->
dest_addr
.
x25_addr
,
sx25
.
sx25_addr
.
x25_addr
))
return
-
EISCONN
;
goto
out
;
rc
=
-
EINVAL
;
if
(
sx25
.
sx25_family
!=
AF_X25
)
return
-
EINVAL
;
goto
out
;
}
else
{
/*
* FIXME 1003.1g - if the socket is like this because
* it has become closed (not started closed) we ought
* to SIGPIPE, EPIPE;
*/
rc
=
-
ENOTCONN
;
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
return
-
ENOTCONN
;
goto
out
;
sx25
.
sx25_family
=
AF_X25
;
sx25
.
sx25_addr
=
x25
->
dest_addr
;
...
...
@@ -921,8 +973,9 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
size
=
len
+
X25_MAX_L2_LEN
+
X25_EXT_MIN_LEN
;
if
((
skb
=
sock_alloc_send_skb
(
sk
,
size
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
))
==
NULL
)
return
err
;
skb
=
sock_alloc_send_skb
(
sk
,
size
,
noblock
,
&
rc
);
if
(
!
skb
)
goto
out
;
X25_SKB_CB
(
skb
)
->
flags
=
msg
->
msg_flags
;
skb_reserve
(
skb
,
X25_MAX_L2_LEN
+
X25_EXT_MIN_LEN
);
...
...
@@ -934,7 +987,9 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
asmptr
=
skb
->
h
.
raw
=
skb_put
(
skb
,
len
);
memcpy_fromiovec
(
asmptr
,
msg
->
msg_iov
,
len
);
rc
=
memcpy_fromiovec
(
asmptr
,
msg
->
msg_iov
,
len
);
if
(
rc
)
goto
out_kfree_skb
;
/*
* If the Q BIT Include socket option is in force, the first
...
...
@@ -985,21 +1040,18 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
SOCK_DEBUG
(
sk
,
"x25_sendmsg: Built header.
\n
"
);
SOCK_DEBUG
(
sk
,
"x25_sendmsg: Transmitting buffer
\n
"
);
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
kfree_skb
(
skb
);
return
-
ENOTCONN
;
}
rc
=
-
ENOTCONN
;
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
goto
out_kfree_skb
;
if
(
msg
->
msg_flags
&
MSG_OOB
)
{
if
(
msg
->
msg_flags
&
MSG_OOB
)
skb_queue_tail
(
&
x25
->
interrupt_out_queue
,
skb
);
}
else
{
else
{
len
=
x25_output
(
sk
,
skb
);
if
(
len
<
0
){
if
(
len
<
0
)
kfree_skb
(
skb
);
}
else
{
if
(
x25
->
qbitincl
)
len
++
;
}
else
if
(
x25
->
qbitincl
)
len
++
;
}
/*
...
...
@@ -1019,31 +1071,37 @@ static int x25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
lock_sock
(
sk
);
x25_kick
(
sk
);
release_sock
(
sk
);
return
len
;
rc
=
len
;
out:
return
rc
;
out_kfree_skb:
kfree_skb
(
skb
);
goto
out
;
}
static
int
x25_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
,
struct
scm_cookie
*
scm
)
static
int
x25_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
,
struct
scm_cookie
*
scm
)
{
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
struct
sockaddr_x25
*
sx25
=
(
struct
sockaddr_x25
*
)
msg
->
msg_name
;
int
copied
,
qbit
;
struct
sk_buff
*
skb
;
unsigned
char
*
asmptr
;
int
er
;
int
rc
=
-
ENOTCONN
;
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
*/
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
return
-
ENOTCONN
;
goto
out
;
if
(
flags
&
MSG_OOB
)
{
rc
=
-
EINVAL
;
if
(
sk
->
urginline
||
!
skb_peek
(
&
x25
->
interrupt_in_queue
))
return
-
EINVAL
;
goto
out
;
skb
=
skb_dequeue
(
&
x25
->
interrupt_in_queue
);
...
...
@@ -1060,8 +1118,9 @@ static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int fl
msg
->
msg_flags
|=
MSG_OOB
;
}
else
{
/* Now we can treat all alike */
if
((
skb
=
skb_recv_datagram
(
sk
,
flags
&
~
MSG_DONTWAIT
,
flags
&
MSG_DONTWAIT
,
&
er
))
==
NULL
)
return
er
;
skb
=
skb_recv_datagram
(
sk
,
flags
&
~
MSG_DONTWAIT
,
flags
&
MSG_DONTWAIT
,
&
rc
);
if
(
!
skb
)
goto
out
;
qbit
=
(
skb
->
data
[
0
]
&
X25_Q_BIT
)
==
X25_Q_BIT
;
...
...
@@ -1086,28 +1145,33 @@ static int x25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int fl
/* Currently, each datagram always contains a complete record */
msg
->
msg_flags
|=
MSG_EOR
;
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
rc
=
skb_copy_datagram_iovec
(
skb
,
0
,
msg
->
msg_iov
,
copied
);
if
(
rc
)
goto
out_free_dgram
;
if
(
sx25
!=
NULL
)
{
if
(
sx25
)
{
sx25
->
sx25_family
=
AF_X25
;
sx25
->
sx25_addr
=
x25
->
dest_addr
;
}
msg
->
msg_namelen
=
sizeof
(
struct
sockaddr_x25
);
skb_free_datagram
(
sk
,
skb
);
lock_sock
(
sk
);
x25_check_rbuf
(
sk
);
release_sock
(
sk
);
return
copied
;
rc
=
copied
;
out_free_dgram:
skb_free_datagram
(
sk
,
skb
);
out:
return
rc
;
}
static
int
x25_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
sock
*
sk
=
sock
->
sk
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
int
rc
;
switch
(
cmd
)
{
case
TIOCOUTQ
:
{
...
...
@@ -1115,26 +1179,33 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount
=
sk
->
sndbuf
-
atomic_read
(
&
sk
->
wmem_alloc
);
if
(
amount
<
0
)
amount
=
0
;
return
put_user
(
amount
,
(
unsigned
int
*
)
arg
);
rc
=
put_user
(
amount
,
(
unsigned
int
*
)
arg
);
break
;
}
case
TIOCINQ
:
{
struct
sk_buff
*
skb
;
int
amount
=
0
;
/* These two are safe on a single CPU system as only user tasks fiddle here */
/*
* These two are safe on a single CPU system as
* only user tasks fiddle here
*/
if
((
skb
=
skb_peek
(
&
sk
->
receive_queue
))
!=
NULL
)
amount
=
skb
->
len
;
return
put_user
(
amount
,
(
unsigned
int
*
)
arg
);
rc
=
put_user
(
amount
,
(
unsigned
int
*
)
arg
);
break
;
}
case
SIOCGSTAMP
:
if
(
sk
!=
NULL
)
{
if
(
sk
->
stamp
.
tv_sec
==
0
)
return
-
ENOENT
;
return
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
if
(
sk
)
{
rc
=
-
ENOENT
;
if
(
!
sk
->
stamp
.
tv_sec
)
break
;
rc
=
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
}
r
eturn
-
EINVAL
;
r
c
=
-
EINVAL
;
break
;
case
SIOCGIFADDR
:
case
SIOCSIFADDR
:
case
SIOCGIFDSTADDR
:
...
...
@@ -1145,74 +1216,90 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case
SIOCSIFNETMASK
:
case
SIOCGIFMETRIC
:
case
SIOCSIFMETRIC
:
r
eturn
-
EINVAL
;
r
c
=
-
EINVAL
;
break
;
case
SIOCADDRT
:
case
SIOCDELRT
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
x25_route_ioctl
(
cmd
,
(
void
*
)
arg
);
rc
=
-
EPERM
;
if
(
!
capable
(
CAP_NET_ADMIN
))
break
;
rc
=
x25_route_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCX25GSUBSCRIP
:
r
eturn
x25_subscr_ioctl
(
cmd
,
(
void
*
)
arg
);
r
c
=
x25_subscr_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCX25SSUBSCRIP
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
x25_subscr_ioctl
(
cmd
,
(
void
*
)
arg
);
rc
=
-
EPERM
;
if
(
!
capable
(
CAP_NET_ADMIN
))
break
;
rc
=
x25_subscr_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCX25GFACILITIES
:
{
struct
x25_facilities
facilities
;
facilities
=
x25
->
facilities
;
return
copy_to_user
((
void
*
)
arg
,
&
facilities
,
sizeof
(
facilities
))
?
-
EFAULT
:
0
;
struct
x25_facilities
fac
=
x25
->
fac
ilities
;
rc
=
copy_to_user
((
void
*
)
arg
,
&
fac
,
sizeof
(
fac
))
?
-
EFAULT
:
0
;
break
;
}
case
SIOCX25SFACILITIES
:
{
struct
x25_facilities
facilities
;
rc
=
-
EFAULT
;
if
(
copy_from_user
(
&
facilities
,
(
void
*
)
arg
,
sizeof
(
facilities
)))
return
-
EFAULT
;
break
;
rc
=
-
EINVAL
;
if
(
sk
->
state
!=
TCP_LISTEN
&&
sk
->
state
!=
TCP_CLOSE
)
return
-
EINVAL
;
if
(
facilities
.
pacsize_in
<
X25_PS16
||
facilities
.
pacsize_in
>
X25_PS4096
)
return
-
EINVAL
;
if
(
facilities
.
pacsize_out
<
X25_PS16
||
facilities
.
pacsize_out
>
X25_PS4096
)
return
-
EINVAL
;
if
(
facilities
.
winsize_in
<
1
||
facilities
.
winsize_in
>
127
)
return
-
EINVAL
;
if
(
facilities
.
throughput
<
0x03
||
facilities
.
throughput
>
0xDD
)
return
-
EINVAL
;
if
(
facilities
.
reverse
!=
0
&&
facilities
.
reverse
!=
1
)
return
-
EINVAL
;
break
;
if
(
facilities
.
pacsize_in
<
X25_PS16
||
facilities
.
pacsize_in
>
X25_PS4096
)
break
;
if
(
facilities
.
pacsize_out
<
X25_PS16
||
facilities
.
pacsize_out
>
X25_PS4096
)
break
;
if
(
facilities
.
winsize_in
<
1
||
facilities
.
winsize_in
>
127
)
break
;
if
(
facilities
.
throughput
<
0x03
||
facilities
.
throughput
>
0xDD
)
break
;
if
(
facilities
.
reverse
&&
facilities
.
reverse
!=
1
)
break
;
x25
->
facilities
=
facilities
;
return
0
;
rc
=
0
;
break
;
}
case
SIOCX25GCALLUSERDATA
:
{
struct
x25_calluserdata
calluserdata
;
calluserdata
=
x25
->
calluserdata
;
return
copy_to_user
((
void
*
)
arg
,
&
calluserdata
,
sizeof
(
calluserdata
))
?
-
EFAULT
:
0
;
struct
x25_calluserdata
c
ud
=
x25
->
c
alluserdata
;
rc
=
copy_to_user
((
void
*
)
arg
,
&
cud
,
sizeof
(
cud
))
?
-
EFAULT
:
0
;
break
;
}
case
SIOCX25SCALLUSERDATA
:
{
struct
x25_calluserdata
calluserdata
;
rc
=
-
EFAULT
;
if
(
copy_from_user
(
&
calluserdata
,
(
void
*
)
arg
,
sizeof
(
calluserdata
)))
return
-
EFAULT
;
break
;
rc
=
-
EINVAL
;
if
(
calluserdata
.
cudlength
>
X25_MAX_CUD_LEN
)
return
-
EINVAL
;
break
;
x25
->
calluserdata
=
calluserdata
;
return
0
;
rc
=
0
;
break
;
}
case
SIOCX25GCAUSEDIAG
:
{
struct
x25_causediag
causediag
;
causediag
=
x25
->
causediag
;
return
copy_to_user
((
void
*
)
arg
,
&
causediag
,
sizeof
(
causediag
))
?
-
EFAULT
:
0
;
rc
=
copy_to_user
((
void
*
)
arg
,
&
causediag
,
sizeof
(
causediag
))
?
-
EFAULT
:
0
;
break
;
}
default:
return
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
rc
=
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
}
/*NOTREACHED*/
return
0
;
return
rc
;
}
static
int
x25_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
...
...
@@ -1220,23 +1307,24 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length)
struct
sock
*
s
;
struct
net_device
*
dev
;
const
char
*
devname
;
int
len
=
0
;
off_t
pos
=
0
;
off_t
begin
=
0
;
int
len
=
sprintf
(
buffer
,
"dest_addr src_addr dev lci st vs vr "
"va t t2 t21 t22 t23 Snd-Q Rcv-Q inode
\n
"
);
cli
(
);
read_lock_bh
(
&
x25_list_lock
);
len
+=
sprintf
(
buffer
,
"dest_addr src_addr dev lci st vs vr va t t2 t21 t22 t23 Snd-Q Rcv-Q inode
\n
"
);
for
(
s
=
x25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
x25_cb
*
x25
=
x25_sk
(
s
);
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
{
struct
x25_opt
*
x25
=
x25_sk
(
s
);
if
(
!
x25
->
neighbour
||
(
dev
=
x25
->
neighbour
->
dev
)
==
NULL
)
devname
=
"???"
;
else
devname
=
x25
->
neighbour
->
dev
->
name
;
len
+=
sprintf
(
buffer
+
len
,
"%-10s %-10s %-5s %3.3X %d %d %d %d %3lu %3lu %3lu %3lu %3lu %5d %5d %ld
\n
"
,
len
+=
sprintf
(
buffer
+
len
,
"%-10s %-10s %-5s %3.3X %d %d "
"%d %d %3lu %3lu %3lu %3lu %3lu "
"%5d %5d %ld
\n
"
,
!
x25
->
dest_addr
.
x25_addr
[
0
]
?
"*"
:
x25
->
dest_addr
.
x25_addr
,
!
x25
->
source_addr
.
x25_addr
[
0
]
?
"*"
:
...
...
@@ -1254,7 +1342,7 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length)
x25
->
t23
/
HZ
,
atomic_read
(
&
s
->
wmem_alloc
),
atomic_read
(
&
s
->
rmem_alloc
),
s
->
socket
!=
NULL
?
SOCK_INODE
(
s
->
socket
)
->
i_ino
:
0L
);
s
->
socket
?
SOCK_INODE
(
s
->
socket
)
->
i_ino
:
0L
);
pos
=
begin
+
len
;
...
...
@@ -1267,14 +1355,15 @@ static int x25_get_info(char *buffer, char **start, off_t offset, int length)
break
;
}
sti
(
);
read_unlock_bh
(
&
x25_list_lock
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
(
len
)
;
return
len
;
}
struct
net_proto_family
x25_family_ops
=
{
...
...
@@ -1308,22 +1397,25 @@ SOCKOPS_WRAP(x25_proto, AF_X25);
static
struct
packet_type
x25_packet_type
=
{
.
type
=
__constant_htons
(
ETH_P_X25
),
.
func
=
x25_lapb_receive_frame
,
.
type
=
__constant_htons
(
ETH_P_X25
),
.
func
=
x25_lapb_receive_frame
,
};
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
;
for
(
s
=
x25_list
;
s
!=
NULL
;
s
=
s
->
next
){
if
(
x25_sk
(
s
)
->
neighbour
==
neigh
)
write_lock_bh
(
&
x25_list_lock
);
for
(
s
=
x25_list
;
s
;
s
=
s
->
next
)
if
(
x25_sk
(
s
)
->
neighbour
==
nb
)
x25_disconnect
(
s
,
ENETUNREACH
,
0
,
0
);
}
write_unlock_bh
(
&
x25_list_lock
);
}
static
int
__init
x25_init
(
void
)
...
...
@@ -1351,7 +1443,7 @@ static int __init x25_init(void)
* Register any pre existing devices.
*/
read_lock
(
&
dev_base_lock
);
for
(
dev
=
dev_base
;
dev
!=
NULL
;
dev
=
dev
->
next
)
{
for
(
dev
=
dev_base
;
dev
;
dev
=
dev
->
next
)
{
if
((
dev
->
flags
&
IFF_UP
)
&&
(
dev
->
type
==
ARPHRD_X25
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
||
dev
->
type
==
ARPHRD_ETHER
...
...
net/x25/sysctl_net_x25.c
View file @
5c0fbae1
...
...
@@ -13,38 +13,88 @@
#include <linux/init.h>
#include <net/x25.h>
static
int
min_timer
[]
=
{
1
*
HZ
};
static
int
max_timer
[]
=
{
300
*
HZ
};
static
int
min_timer
[]
=
{
1
*
HZ
};
static
int
max_timer
[]
=
{
300
*
HZ
};
static
struct
ctl_table_header
*
x25_table_header
;
static
ctl_table
x25_table
[]
=
{
{
NET_X25_RESTART_REQUEST_TIMEOUT
,
"restart_request_timeout"
,
&
sysctl_x25_restart_request_timeout
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_timer
,
&
max_timer
},
{
NET_X25_CALL_REQUEST_TIMEOUT
,
"call_request_timeout"
,
&
sysctl_x25_call_request_timeout
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_timer
,
&
max_timer
},
{
NET_X25_RESET_REQUEST_TIMEOUT
,
"reset_request_timeout"
,
&
sysctl_x25_reset_request_timeout
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_timer
,
&
max_timer
},
{
NET_X25_CLEAR_REQUEST_TIMEOUT
,
"clear_request_timeout"
,
&
sysctl_x25_clear_request_timeout
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_timer
,
&
max_timer
},
{
NET_X25_ACK_HOLD_BACK_TIMEOUT
,
"acknowledgement_hold_back_timeout"
,
&
sysctl_x25_ack_holdback_timeout
,
sizeof
(
int
),
0644
,
NULL
,
&
proc_dointvec_minmax
,
&
sysctl_intvec
,
NULL
,
&
min_timer
,
&
max_timer
},
{
0
}
static
struct
ctl_table
x25_table
[]
=
{
{
.
ctl_name
=
NET_X25_RESTART_REQUEST_TIMEOUT
,
.
procname
=
"restart_request_timeout"
,
.
data
=
&
sysctl_x25_restart_request_timeout
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_timer
,
.
extra2
=
&
max_timer
,
},
{
.
ctl_name
=
NET_X25_CALL_REQUEST_TIMEOUT
,
.
procname
=
"call_request_timeout"
,
.
data
=
&
sysctl_x25_call_request_timeout
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_timer
,
.
extra2
=
&
max_timer
,
},
{
.
ctl_name
=
NET_X25_RESET_REQUEST_TIMEOUT
,
.
procname
=
"reset_request_timeout"
,
.
data
=
&
sysctl_x25_reset_request_timeout
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_timer
,
.
extra2
=
&
max_timer
,
},
{
.
ctl_name
=
NET_X25_CLEAR_REQUEST_TIMEOUT
,
.
procname
=
"clear_request_timeout"
,
.
data
=
&
sysctl_x25_clear_request_timeout
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_timer
,
.
extra2
=
&
max_timer
,
},
{
.
ctl_name
=
NET_X25_ACK_HOLD_BACK_TIMEOUT
,
.
procname
=
"acknowledgement_hold_back_timeout"
,
.
data
=
&
sysctl_x25_ack_holdback_timeout
,
.
maxlen
=
sizeof
(
int
),
.
mode
=
0644
,
.
proc_handler
=
&
proc_dointvec_minmax
,
.
strategy
=
&
sysctl_intvec
,
.
extra1
=
&
min_timer
,
.
extra2
=
&
max_timer
,
},
{
0
,
},
};
static
ctl_table
x25_dir_table
[]
=
{
{
NET_X25
,
"x25"
,
NULL
,
0
,
0555
,
x25_table
},
{
0
}
static
struct
ctl_table
x25_dir_table
[]
=
{
{
.
ctl_name
=
NET_X25
,
.
procname
=
"x25"
,
.
mode
=
0555
,
.
child
=
x25_table
,
},
{
0
,
},
};
static
ctl_table
x25_root_table
[]
=
{
{
CTL_NET
,
"net"
,
NULL
,
0
,
0555
,
x25_dir_table
},
{
0
}
static
struct
ctl_table
x25_root_table
[]
=
{
{
.
ctl_name
=
CTL_NET
,
.
procname
=
"net"
,
.
mode
=
0555
,
.
child
=
x25_dir_table
,
},
{
0
,
},
};
void
__init
x25_register_sysctl
(
void
)
...
...
net/x25/x25_dev.c
View file @
5c0fbae1
...
...
@@ -44,7 +44,7 @@
#include <linux/if_arp.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
;
unsigned
short
frametype
;
...
...
@@ -58,14 +58,14 @@ static int x25_receive_data(struct sk_buff *skb, struct x25_neigh *neigh)
* frame.
*/
if
(
lci
==
0
)
{
x25_link_control
(
skb
,
n
eigh
,
frametype
);
x25_link_control
(
skb
,
n
b
,
frametype
);
return
0
;
}
/*
* 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
;
skb
->
h
.
raw
=
skb
->
data
;
...
...
@@ -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.
*/
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.
* 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
);
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
;
int
queued
;
struct
x25_neigh
*
nb
;
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
);
kfree_skb
(
skb
);
return
0
;
goto
drop
;
}
switch
(
skb
->
data
[
0
])
{
case
0x00
:
skb_pull
(
skb
,
1
);
queued
=
x25_receive_data
(
skb
,
neigh
);
if
(
!
queued
)
/* We need to free the skb ourselves because
* net_bh() won't care about our return code.
*/
kfree_skb
(
skb
);
return
0
;
if
(
x25_receive_data
(
skb
,
nb
))
{
x25_neigh_put
(
nb
);
goto
out
;
}
break
;
case
0x01
:
x25_link_established
(
neigh
);
kfree_skb
(
skb
);
return
0
;
x25_link_established
(
nb
);
break
;
case
0x02
:
x25_link_terminated
(
neigh
);
kfree_skb
(
skb
);
return
0
;
case
0x03
:
kfree_skb
(
skb
);
return
0
;
default:
kfree_skb
(
skb
);
return
0
;
x25_link_terminated
(
nb
);
break
;
}
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
;
/*
*
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
);
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
;
unsigned
char
*
ptr
;
switch
(
n
eigh
->
dev
->
type
)
{
switch
(
n
b
->
dev
->
type
)
{
case
ARPHRD_X25
:
if
((
skb
=
alloc_skb
(
1
,
GFP_ATOMIC
))
==
NULL
)
{
printk
(
KERN_ERR
"x25_dev: out of memory
\n
"
);
...
...
@@ -186,47 +182,44 @@ void x25_establish_link(struct x25_neigh *neigh)
}
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
n
eigh
->
dev
;
skb
->
dev
=
n
b
->
dev
;
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
;
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)
case
ARPHRD_ETHER
:
return
;
if
(
nb
->
dev
->
type
==
ARPHRD_ETHER
)
return
;
#endif
default:
return
;
if
(
nb
->
dev
->
type
!=
ARPHRD_X25
)
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
);
skb
->
dev
=
neigh
->
dev
;
ptr
=
skb_put
(
skb
,
1
);
*
ptr
=
0x02
;
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
nb
->
dev
;
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
;
skb
->
nh
.
raw
=
skb
->
data
;
switch
(
n
eigh
->
dev
->
type
)
{
switch
(
n
b
->
dev
->
type
)
{
case
ARPHRD_X25
:
dptr
=
skb_push
(
skb
,
1
);
*
dptr
=
0x00
;
...
...
@@ -243,7 +236,7 @@ void x25_send_frame(struct sk_buff *skb, struct x25_neigh *neigh)
}
skb
->
protocol
=
htons
(
ETH_P_X25
);
skb
->
dev
=
n
eigh
->
dev
;
skb
->
dev
=
n
b
->
dev
;
dev_queue_xmit
(
skb
);
}
net/x25/x25_facilities.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -42,65 +43,71 @@
* Parse a set of facilities into the facilities structure. Unrecognised
* facilities are written to the debug log file.
*/
int
x25_parse_facilities
(
struct
sk_buff
*
skb
,
struct
x25_facilities
*
facilities
,
unsigned
long
*
vc_fac_mask
)
int
x25_parse_facilities
(
struct
sk_buff
*
skb
,
struct
x25_facilities
*
facilities
,
unsigned
long
*
vc_fac_mask
)
{
unsigned
int
len
;
unsigned
char
*
p
=
skb
->
data
;
unsigned
int
len
=
*
p
++
;
len
=
*
p
++
;
*
vc_fac_mask
=
0
;
while
(
len
>
0
)
{
switch
(
*
p
&
X25_FAC_CLASS_MASK
)
{
case
X25_FAC_CLASS_A
:
switch
(
*
p
)
{
case
X25_FAC_REVERSE
:
facilities
->
reverse
=
(
p
[
1
]
&
0x01
);
*
vc_fac_mask
|=
X25_MASK_REVERSE
;
break
;
case
X25_FAC_THROUGHPUT
:
facilities
->
throughput
=
p
[
1
];
*
vc_fac_mask
|=
X25_MASK_THROUGHPUT
;
break
;
default:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, value %02X
\n
"
,
p
[
0
],
p
[
1
]);
break
;
}
p
+=
2
;
len
-=
2
;
case
X25_FAC_CLASS_A
:
switch
(
*
p
)
{
case
X25_FAC_REVERSE
:
facilities
->
reverse
=
p
[
1
]
&
0x01
;
*
vc_fac_mask
|=
X25_MASK_REVERSE
;
break
;
case
X25_FAC_CLASS_B
:
switch
(
*
p
)
{
case
X25_FAC_PACKET_SIZE
:
facilities
->
pacsize_in
=
p
[
1
];
facilities
->
pacsize_out
=
p
[
2
];
*
vc_fac_mask
|=
X25_MASK_PACKET_SIZE
;
break
;
case
X25_FAC_WINDOW_SIZE
:
facilities
->
winsize_in
=
p
[
1
];
facilities
->
winsize_out
=
p
[
2
];
*
vc_fac_mask
|=
X25_MASK_WINDOW_SIZE
;
break
;
default:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, values %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
]);
break
;
}
p
+=
3
;
len
-=
3
;
case
X25_FAC_THROUGHPUT
:
facilities
->
throughput
=
p
[
1
];
*
vc_fac_mask
|=
X25_MASK_THROUGHPUT
;
break
;
case
X25_FAC_CLASS_C
:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, values %02X, %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
]);
p
+=
4
;
len
-=
4
;
default:
printk
(
KERN_DEBUG
"X.25: unknown facility "
"%02X, value %02X
\n
"
,
p
[
0
],
p
[
1
]);
break
;
case
X25_FAC_CLASS_D
:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, length %d, values %02X, %02X, %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
],
p
[
5
]);
p
+=
p
[
1
]
+
2
;
len
-=
p
[
1
]
+
2
;
}
p
+=
2
;
len
-=
2
;
break
;
case
X25_FAC_CLASS_B
:
switch
(
*
p
)
{
case
X25_FAC_PACKET_SIZE
:
facilities
->
pacsize_in
=
p
[
1
];
facilities
->
pacsize_out
=
p
[
2
];
*
vc_fac_mask
|=
X25_MASK_PACKET_SIZE
;
break
;
case
X25_FAC_WINDOW_SIZE
:
facilities
->
winsize_in
=
p
[
1
];
facilities
->
winsize_out
=
p
[
2
];
*
vc_fac_mask
|=
X25_MASK_WINDOW_SIZE
;
break
;
default:
printk
(
KERN_DEBUG
"X.25: unknown facility "
"%02X, values %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
]);
break
;
}
p
+=
3
;
len
-=
3
;
break
;
case
X25_FAC_CLASS_C
:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, "
"values %02X, %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
]);
p
+=
4
;
len
-=
4
;
break
;
case
X25_FAC_CLASS_D
:
printk
(
KERN_DEBUG
"X.25: unknown facility %02X, "
"length %d, values %02X, %02X, %02X, %02X
\n
"
,
p
[
0
],
p
[
1
],
p
[
2
],
p
[
3
],
p
[
4
],
p
[
5
]);
p
+=
p
[
1
]
+
2
;
len
-=
p
[
1
]
+
2
;
break
;
}
}
...
...
@@ -110,37 +117,45 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
/*
* Create a set of facilities.
*/
int
x25_create_facilities
(
unsigned
char
*
buffer
,
struct
x25_facilities
*
facilities
,
unsigned
long
facil_mask
)
int
x25_create_facilities
(
unsigned
char
*
buffer
,
struct
x25_facilities
*
facilities
,
unsigned
long
facil_mask
)
{
unsigned
char
*
p
=
buffer
+
1
;
int
len
;
if
(
facil_mask
==
0
)
{
buffer
[
0
]
=
0
;
/* length of the facilities field in call_req or call_accept packets */
if
(
!
facil_mask
)
{
/*
* Length of the facilities field in call_req or
* call_accept packets
*/
buffer
[
0
]
=
0
;
len
=
1
;
/* 1 byte for the length field */
return
len
;
}
if
(
(
facilities
->
reverse
!=
0
)
&&
(
facil_mask
&
X25_MASK_REVERSE
))
{
if
(
facilities
->
reverse
&&
(
facil_mask
&
X25_MASK_REVERSE
))
{
*
p
++
=
X25_FAC_REVERSE
;
*
p
++
=
(
facilities
->
reverse
)
?
0x01
:
0x00
;
*
p
++
=
!!
facilities
->
reverse
;
}
if
(
(
facilities
->
throughput
!=
0
)
&&
(
facil_mask
&
X25_MASK_THROUGHPUT
))
{
if
(
facilities
->
throughput
&&
(
facil_mask
&
X25_MASK_THROUGHPUT
))
{
*
p
++
=
X25_FAC_THROUGHPUT
;
*
p
++
=
facilities
->
throughput
;
}
if
((
facilities
->
pacsize_in
!=
0
||
facilities
->
pacsize_out
!=
0
)
&&
(
facil_mask
&
X25_MASK_PACKET_SIZE
))
{
if
((
facilities
->
pacsize_in
||
facilities
->
pacsize_out
)
&&
(
facil_mask
&
X25_MASK_PACKET_SIZE
))
{
*
p
++
=
X25_FAC_PACKET_SIZE
;
*
p
++
=
(
facilities
->
pacsize_in
==
0
)
?
facilities
->
pacsize_out
:
facilities
->
pacsize_in
;
*
p
++
=
(
facilities
->
pacsize_out
==
0
)
?
facilities
->
pacsize_in
:
facilities
->
pacsize_out
;
*
p
++
=
facilities
->
pacsize_in
?
:
facilities
->
pacsize_out
;
*
p
++
=
facilities
->
pacsize_out
?
:
facilities
->
pacsize_in
;
}
if
((
facilities
->
winsize_in
!=
0
||
facilities
->
winsize_out
!=
0
)
&&
(
facil_mask
&
X25_MASK_WINDOW_SIZE
))
{
if
((
facilities
->
winsize_in
||
facilities
->
winsize_out
)
&&
(
facil_mask
&
X25_MASK_WINDOW_SIZE
))
{
*
p
++
=
X25_FAC_WINDOW_SIZE
;
*
p
++
=
(
facilities
->
winsize_in
==
0
)
?
facilities
->
winsize_out
:
facilities
->
winsize_in
;
*
p
++
=
(
facilities
->
winsize_out
==
0
)
?
facilities
->
winsize_in
:
facilities
->
winsize_out
;
*
p
++
=
facilities
->
winsize_in
?
:
facilities
->
winsize_out
;
*
p
++
=
facilities
->
winsize_out
?
:
facilities
->
winsize_in
;
}
len
=
p
-
buffer
;
...
...
@@ -154,39 +169,37 @@ int x25_create_facilities(unsigned char *buffer, struct x25_facilities *faciliti
*
* The only real problem is with reverse charging.
*/
int
x25_negotiate_facilities
(
struct
sk_buff
*
skb
,
struct
sock
*
sk
,
struct
x25_facilities
*
new
)
int
x25_negotiate_facilities
(
struct
sk_buff
*
skb
,
struct
sock
*
sk
,
struct
x25_facilities
*
new
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_facilities
*
ours
;
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
struct
x25_facilities
*
ours
=
&
x25
->
facilities
;
struct
x25_facilities
theirs
;
int
len
;
memset
(
&
theirs
,
0x00
,
sizeof
(
struct
x25_facilities
));
ours
=
&
x25
->
facilities
;
*
new
=
*
ours
;
memset
(
&
theirs
,
0
,
sizeof
(
theirs
));
memcpy
(
new
,
ours
,
sizeof
(
*
new
));
len
=
x25_parse_facilities
(
skb
,
&
theirs
,
&
x25
->
vc_facil_mask
);
/*
* They want reverse charging, we won't accept it.
*/
if
(
theirs
.
reverse
!=
0
&&
ours
->
reverse
==
0
)
{
if
(
theirs
.
reverse
&&
ours
->
reverse
)
{
SOCK_DEBUG
(
sk
,
"X.25: rejecting reverse charging request"
);
return
-
1
;
}
new
->
reverse
=
theirs
.
reverse
;
if
(
theirs
.
throughput
!=
0
)
{
if
(
theirs
.
throughput
)
{
if
(
theirs
.
throughput
<
ours
->
throughput
)
{
SOCK_DEBUG
(
sk
,
"X.25: throughput negotiated down"
);
new
->
throughput
=
theirs
.
throughput
;
}
}
if
(
theirs
.
pacsize_in
!=
0
&&
theirs
.
pacsize_out
!=
0
)
{
if
(
theirs
.
pacsize_in
&&
theirs
.
pacsize_out
)
{
if
(
theirs
.
pacsize_in
<
ours
->
pacsize_in
)
{
SOCK_DEBUG
(
sk
,
"X.25: packet size inwards negotiated down"
);
new
->
pacsize_in
=
theirs
.
pacsize_in
;
...
...
@@ -197,7 +210,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa
}
}
if
(
theirs
.
winsize_in
!=
0
&&
theirs
.
winsize_out
!=
0
)
{
if
(
theirs
.
winsize_in
&&
theirs
.
winsize_out
)
{
if
(
theirs
.
winsize_in
<
ours
->
winsize_in
)
{
SOCK_DEBUG
(
sk
,
"X.25: window size inwards negotiated down"
);
new
->
winsize_in
=
theirs
.
winsize_in
;
...
...
@@ -216,15 +229,15 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa
* currently attached x25 link.
*/
void
x25_limit_facilities
(
struct
x25_facilities
*
facilities
,
struct
x25_neigh
*
n
eighbour
)
struct
x25_neigh
*
n
b
)
{
if
(
!
neighbour
->
extended
)
{
if
(
facilities
->
winsize_in
>
7
)
{
if
(
!
nb
->
extended
)
{
if
(
facilities
->
winsize_in
>
7
)
{
printk
(
KERN_DEBUG
"X.25: incoming winsize limited to 7
\n
"
);
facilities
->
winsize_in
=
7
;
}
if
(
facilities
->
winsize_out
>
7
)
{
if
(
facilities
->
winsize_out
>
7
)
{
facilities
->
winsize_out
=
7
;
printk
(
KERN_DEBUG
"X.25: outgoing winsize limited to 7
\n
"
);
}
...
...
net/x25/x25_in.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -47,7 +48,7 @@
static
int
x25_queue_rx_frame
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
more
)
{
struct
sk_buff
*
skbo
,
*
skbn
=
skb
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
more
)
{
x25
->
fraglen
+=
skb
->
len
;
...
...
@@ -86,7 +87,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
skb_set_owner_r
(
skbn
,
sk
);
skb_queue_tail
(
&
sk
->
receive_queue
,
skbn
);
if
(
!
sk
->
dead
)
sk
->
data_ready
(
sk
,
skbn
->
len
);
sk
->
data_ready
(
sk
,
skbn
->
len
);
return
0
;
}
...
...
@@ -98,11 +99,11 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
*/
static
int
x25_state1_machine
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
frametype
)
{
x25_address
source_addr
,
dest_addr
;
struct
x25_address
source_addr
,
dest_addr
;
switch
(
frametype
)
{
case
X25_CALL_ACCEPTED
:
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
x25_stop_timer
(
sk
);
x25
->
condition
=
0x00
;
...
...
@@ -178,7 +179,7 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp
{
int
queued
=
0
;
int
modulus
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
modulus
=
(
x25
->
neighbour
->
extended
)
?
X25_EMODULUS
:
X25_SMODULUS
;
...
...
@@ -307,7 +308,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
case
X25_RESET_REQUEST
:
x25_write_internal
(
sk
,
X25_RESET_CONFIRMATION
);
case
X25_RESET_CONFIRMATION
:
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
x25_stop_timer
(
sk
);
x25
->
condition
=
0x00
;
...
...
@@ -334,7 +335,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
/* Higher level upcall for a LAPB frame */
int
x25_process_rx_frame
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
int
queued
=
0
,
frametype
,
ns
,
nr
,
q
,
d
,
m
;
if
(
x25
->
state
==
X25_STATE_0
)
...
...
@@ -364,10 +365,10 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
int
x25_backlog_rcv
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
int
queued
;
int
queued
=
x25_process_rx_frame
(
sk
,
skb
)
;
queued
=
x25_process_rx_frame
(
sk
,
skb
);
if
(
!
queued
)
kfree_skb
(
skb
);
if
(
!
queued
)
kfree_skb
(
skb
);
return
0
;
}
net/x25/x25_link.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -42,98 +43,102 @@
#include <linux/init.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
);
/*
* 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
eigh
->
t20timer
.
function
=
&
x25_t20timer_expiry
;
n
eigh
->
t20timer
.
expires
=
jiffies
+
neigh
->
t20
;
n
b
->
t20timer
.
data
=
(
unsigned
long
)
nb
;
n
b
->
t20timer
.
function
=
&
x25_t20timer_expiry
;
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
)
{
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.
*/
void
x25_link_control
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
neigh
,
unsigned
short
frametype
)
void
x25_link_control
(
struct
sk_buff
*
skb
,
struct
x25_neigh
*
nb
,
unsigned
short
frametype
)
{
struct
sk_buff
*
skbn
;
int
confirm
;
switch
(
frametype
)
{
case
X25_RESTART_REQUEST
:
confirm
=
!
x25_t20timer_pending
(
neigh
);
x25_stop_t20timer
(
neigh
);
neigh
->
state
=
X25_LINK_STATE_3
;
if
(
confirm
)
x25_transmit_restart_confirmation
(
neigh
);
confirm
=
!
x25_t20timer_pending
(
nb
);
x25_stop_t20timer
(
nb
);
nb
->
state
=
X25_LINK_STATE_3
;
if
(
confirm
)
x25_transmit_restart_confirmation
(
nb
);
break
;
case
X25_RESTART_CONFIRMATION
:
x25_stop_t20timer
(
n
eigh
);
n
eigh
->
state
=
X25_LINK_STATE_3
;
x25_stop_t20timer
(
n
b
);
n
b
->
state
=
X25_LINK_STATE_3
;
break
;
case
X25_DIAGNOSTIC
:
printk
(
KERN_WARNING
"x25: diagnostic #%d - %02X %02X %02X
\n
"
,
skb
->
data
[
3
],
skb
->
data
[
4
],
skb
->
data
[
5
],
skb
->
data
[
6
]);
printk
(
KERN_WARNING
"x25: diagnostic #%d - "
"%02X %02X %02X
\n
"
,
skb
->
data
[
3
],
skb
->
data
[
4
],
skb
->
data
[
5
],
skb
->
data
[
6
]);
break
;
default:
printk
(
KERN_WARNING
"x25: received unknown %02X with LCI 000
\n
"
,
frametype
);
printk
(
KERN_WARNING
"x25: received unknown %02X "
"with LCI 000
\n
"
,
frametype
);
break
;
}
if
(
neigh
->
state
==
X25_LINK_STATE_3
)
{
while
((
skbn
=
skb_dequeue
(
&
neigh
->
queue
))
!=
NULL
)
x25_send_frame
(
skbn
,
neigh
);
}
if
(
nb
->
state
==
X25_LINK_STATE_3
)
while
((
skbn
=
skb_dequeue
(
&
nb
->
queue
))
!=
NULL
)
x25_send_frame
(
skbn
,
nb
);
}
/*
* 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
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
int
len
;
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
struct
sk_buff
*
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
);
if
(
(
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
))
==
NULL
)
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
X25_MAX_L2_LEN
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
*
dptr
++
=
(
neigh
->
extended
)
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
nb
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_RESTART_REQUEST
;
*
dptr
++
=
0x00
;
...
...
@@ -141,108 +146,104 @@ void x25_transmit_restart_request(struct x25_neigh *neigh)
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
*/
void
x25_transmit_restart_confirmation
(
struct
x25_neigh
*
n
eigh
)
void
x25_transmit_restart_confirmation
(
struct
x25_neigh
*
n
b
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
int
len
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
;
struct
sk_buff
*
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
);
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
;
if
((
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
))
==
NULL
)
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
X25_MAX_L2_LEN
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
);
*
dptr
++
=
(
neigh
->
extended
)
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
nb
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_RESTART_CONFIRMATION
;
skb
->
sk
=
NULL
;
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
}
/*
* 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
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
int
len
;
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
1
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
1
;
struct
sk_buff
*
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
);
if
(
(
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
))
==
NULL
)
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
X25_MAX_L2_LEN
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
1
);
*
dptr
++
=
(
neigh
->
extended
)
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
nb
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
0x00
;
*
dptr
++
=
X25_DIAGNOSTIC
;
*
dptr
++
=
diag
;
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
* 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
)
{
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
int
len
;
int
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
struct
sk_buff
*
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
);
len
=
X25_MAX_L2_LEN
+
X25_STD_MIN_LEN
+
2
;
if
((
skb
=
alloc_skb
(
len
,
GFP_ATOMIC
))
==
NULL
)
if
(
!
skb
)
return
;
skb_reserve
(
skb
,
X25_MAX_L2_LEN
);
dptr
=
skb_put
(
skb
,
X25_STD_MIN_LEN
+
2
);
*
dptr
++
=
((
lci
>>
8
)
&
0x0F
)
|
(
neigh
->
extended
)
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
((
lci
>>
0
)
&
0xFF
);
*
dptr
++
=
((
lci
>>
8
)
&
0x0F
)
|
nb
->
extended
?
X25_GFI_EXTSEQ
:
X25_GFI_STDSEQ
;
*
dptr
++
=
(
lci
>>
0
)
&
0xFF
;
*
dptr
++
=
X25_CLEAR_REQUEST
;
*
dptr
++
=
cause
;
*
dptr
++
=
0x00
;
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
:
skb_queue_tail
(
&
n
eigh
->
queue
,
skb
);
n
eigh
->
state
=
X25_LINK_STATE_1
;
x25_establish_link
(
n
eigh
);
skb_queue_tail
(
&
n
b
->
queue
,
skb
);
n
b
->
state
=
X25_LINK_STATE_1
;
x25_establish_link
(
n
b
);
break
;
case
X25_LINK_STATE_1
:
case
X25_LINK_STATE_2
:
skb_queue_tail
(
&
n
eigh
->
queue
,
skb
);
skb_queue_tail
(
&
n
b
->
queue
,
skb
);
break
;
case
X25_LINK_STATE_3
:
x25_send_frame
(
skb
,
n
eigh
);
x25_send_frame
(
skb
,
n
b
);
break
;
}
}
...
...
@@ -250,16 +251,16 @@ void x25_transmit_link(struct sk_buff *skb, struct x25_neigh *neigh)
/*
* 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
:
n
eigh
->
state
=
X25_LINK_STATE_2
;
n
b
->
state
=
X25_LINK_STATE_2
;
break
;
case
X25_LINK_STATE_1
:
x25_transmit_restart_request
(
n
eigh
);
n
eigh
->
state
=
X25_LINK_STATE_2
;
x25_start_t20timer
(
n
eigh
);
x25_transmit_restart_request
(
n
b
);
n
b
->
state
=
X25_LINK_STATE_2
;
x25_start_t20timer
(
n
b
);
break
;
}
}
...
...
@@ -269,11 +270,11 @@ void x25_link_established(struct x25_neigh *neigh)
* 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) */
x25_kill_by_neigh
(
n
eigh
);
x25_kill_by_neigh
(
n
b
);
}
/*
...
...
@@ -281,59 +282,50 @@ void x25_link_terminated(struct x25_neigh *neigh)
*/
void
x25_link_device_up
(
struct
net_device
*
dev
)
{
struct
x25_neigh
*
x25_neigh
;
unsigned
long
flags
;
struct
x25_neigh
*
nb
=
kmalloc
(
sizeof
(
*
nb
),
GFP_ATOMIC
);
if
(
(
x25_neigh
=
kmalloc
(
sizeof
(
*
x25_neigh
),
GFP_ATOMIC
))
==
NULL
)
if
(
!
nb
)
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
);
x25_neigh
->
dev
=
dev
;
x25_neigh
->
state
=
X25_LINK_STATE_0
;
x25_neigh
->
extended
=
0
;
x25_neigh
->
global_facil_mask
=
(
X25_MASK_REVERSE
|
X25_MASK_THROUGHPUT
|
X25_MASK_PACKET_SIZE
|
X25_MASK_WINDOW_SIZE
);
/* enables negotiation */
x25_neigh
->
t20
=
sysctl_x25_restart_request_timeout
;
save_flags
(
flags
);
cli
();
x25_neigh
->
next
=
x25_neigh_list
;
x25_neigh_list
=
x25_neigh
;
restore_flags
(
flags
);
nb
->
dev
=
dev
;
nb
->
state
=
X25_LINK_STATE_0
;
nb
->
extended
=
0
;
/*
* Enables negotiation
*/
nb
->
global_facil_mask
=
X25_MASK_REVERSE
|
X25_MASK_THROUGHPUT
|
X25_MASK_PACKET_SIZE
|
X25_MASK_WINDOW_SIZE
;
nb
->
t20
=
sysctl_x25_restart_request_timeout
;
atomic_set
(
&
nb
->
refcnt
,
1
);
write_lock_bh
(
&
x25_neigh_list_lock
);
list_add
(
&
nb
->
node
,
&
x25_neigh_list
);
write_unlock_bh
(
&
x25_neigh_list_lock
);
}
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
;
unsigned
long
flags
;
skb_queue_purge
(
&
x25_neigh
->
queue
);
skb_queue_purge
(
&
nb
->
queue
);
x25_stop_t20timer
(
nb
);
x25_stop_t20timer
(
x25_neigh
);
save_flags
(
flags
);
cli
();
if
((
s
=
x25_neigh_list
)
==
x25_neigh
)
{
x25_neigh_list
=
x25_neigh
->
next
;
restore_flags
(
flags
);
kfree
(
x25_neigh
);
return
;
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
x25_neigh
)
{
s
->
next
=
x25_neigh
->
next
;
restore_flags
(
flags
);
kfree
(
x25_neigh
);
return
;
}
s
=
s
->
next
;
if
(
nb
->
node
.
next
)
{
list_del
(
&
nb
->
node
);
x25_neigh_put
(
nb
);
}
restore_flags
(
flags
);
}
/*
...
...
@@ -341,17 +333,21 @@ static void x25_remove_neigh(struct x25_neigh *x25_neigh)
*/
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
!=
NULL
)
{
neigh
=
x25_neigh
;
x25_neigh
=
x25_neigh
->
next
;
write_lock_bh
(
&
x25_neigh_list_lock
);
if
(
neigh
->
dev
==
dev
){
x25_remove_neigh
(
neigh
);
list_for_each_safe
(
entry
,
tmp
,
&
x25_neigh_list
)
{
nb
=
list_entry
(
entry
,
struct
x25_neigh
,
node
);
if
(
nb
->
dev
==
dev
)
{
__x25_remove_neigh
(
nb
);
dev_put
(
dev
);
}
}
write_unlock_bh
(
&
x25_neigh_list_lock
);
}
/*
...
...
@@ -359,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_neigh
;
struct
x25_neigh
*
nb
,
*
use
=
NULL
;
struct
list_head
*
entry
;
for
(
x25_neigh
=
x25_neigh_list
;
x25_neigh
!=
NULL
;
x25_neigh
=
x25_neigh
->
next
)
if
(
x25_neigh
->
dev
==
dev
)
return
x25_neigh
;
read_lock_bh
(
&
x25_neigh_list_lock
);
list_for_each
(
entry
,
&
x25_neigh_list
)
{
nb
=
list_entry
(
entry
,
struct
x25_neigh
,
node
);
if
(
nb
->
dev
==
dev
)
{
use
=
nb
;
break
;
}
}
return
NULL
;
if
(
use
)
x25_neigh_hold
(
use
);
read_unlock_bh
(
&
x25_neigh_list_lock
);
return
use
;
}
/*
...
...
@@ -374,48 +380,45 @@ struct x25_neigh *x25_get_neigh(struct net_device *dev)
int
x25_subscr_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
{
struct
x25_subscrip_struct
x25_subscr
;
struct
x25_neigh
*
x25_neigh
;
struct
x25_neigh
*
nb
;
struct
net_device
*
dev
;
switch
(
cmd
)
{
case
SIOCX25GSUBSCRIP
:
if
(
copy_from_user
(
&
x25_subscr
,
arg
,
sizeof
(
struct
x25_subscrip_struct
)))
return
-
EFAULT
;
if
((
dev
=
x25_dev_get
(
x25_subscr
.
device
))
==
NULL
)
return
-
EINVAL
;
if
((
x25_neigh
=
x25_get_neigh
(
dev
))
==
NULL
)
{
dev_put
(
dev
);
return
-
EINVAL
;
}
dev_put
(
dev
);
x25_subscr
.
extended
=
x25_neigh
->
extended
;
x25_subscr
.
global_facil_mask
=
x25_neigh
->
global_facil_mask
;
if
(
copy_to_user
(
arg
,
&
x25_subscr
,
sizeof
(
struct
x25_subscrip_struct
)))
return
-
EFAULT
;
break
;
case
SIOCX25SSUBSCRIP
:
if
(
copy_from_user
(
&
x25_subscr
,
arg
,
sizeof
(
struct
x25_subscrip_struct
)))
return
-
EFAULT
;
if
((
dev
=
x25_dev_get
(
x25_subscr
.
device
))
==
NULL
)
return
-
EINVAL
;
if
((
x25_neigh
=
x25_get_neigh
(
dev
))
==
NULL
)
{
dev_put
(
dev
);
return
-
EINVAL
;
}
dev_put
(
dev
);
if
(
x25_subscr
.
extended
!=
0
&&
x25_subscr
.
extended
!=
1
)
return
-
EINVAL
;
x25_neigh
->
extended
=
x25_subscr
.
extended
;
x25_neigh
->
global_facil_mask
=
x25_subscr
.
global_facil_mask
;
break
;
default:
return
-
EINVAL
;
int
rc
=
-
EINVAL
;
if
(
cmd
!=
SIOCX25GSUBSCRIP
&&
cmd
!=
SIOCX25SSUBSCRIP
)
goto
out
;
rc
=
-
EFAULT
;
if
(
copy_from_user
(
&
x25_subscr
,
arg
,
sizeof
(
x25_subscr
)))
goto
out
;
rc
=
-
EINVAL
;
if
((
dev
=
x25_dev_get
(
x25_subscr
.
device
))
==
NULL
)
goto
out
;
if
((
nb
=
x25_get_neigh
(
dev
))
==
NULL
)
goto
out_dev_put
;
dev_put
(
dev
);
if
(
cmd
==
SIOCX25GSUBSCRIP
)
{
x25_subscr
.
extended
=
nb
->
extended
;
x25_subscr
.
global_facil_mask
=
nb
->
global_facil_mask
;
rc
=
copy_to_user
(
arg
,
&
x25_subscr
,
sizeof
(
x25_subscr
))
?
-
EFAULT
:
0
;
}
else
{
rc
=
-
EINVAL
;
if
(
!
(
x25_subscr
.
extended
&&
x25_subscr
.
extended
!=
1
))
{
rc
=
0
;
nb
->
extended
=
x25_subscr
.
extended
;
nb
->
global_facil_mask
=
x25_subscr
.
global_facil_mask
;
}
}
return
0
;
x25_neigh_put
(
nb
);
out:
return
rc
;
out_dev_put:
dev_put
(
dev
);
goto
out
;
}
...
...
@@ -424,12 +427,14 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg)
*/
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
!=
NULL
)
{
neigh
=
x25_neigh
;
x25_neigh
=
x25_neigh
->
next
;
write_lock_bh
(
&
x25_neigh_list_lock
);
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
);
}
net/x25/x25_out.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -45,7 +46,7 @@ static int x25_pacsize_to_bytes(unsigned int pacsize)
{
int
bytes
=
1
;
if
(
pacsize
==
0
)
if
(
!
pacsize
)
return
128
;
while
(
pacsize
--
>
0
)
...
...
@@ -66,7 +67,7 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
unsigned
char
header
[
X25_EXT_MIN_LEN
];
int
err
,
frontlen
,
len
;
int
sent
=
0
,
noblock
=
X25_SKB_CB
(
skb
)
->
flags
&
MSG_DONTWAIT
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
int
header_len
=
x25
->
neighbour
->
extended
?
X25_EXT_MIN_LEN
:
X25_STD_MIN_LEN
;
int
max_len
=
x25_pacsize_to_bytes
(
x25
->
facilities
.
pacsize_out
);
...
...
@@ -79,18 +80,21 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
frontlen
=
skb_headroom
(
skb
);
while
(
skb
->
len
>
0
)
{
if
((
skbn
=
sock_alloc_send_skb
(
sk
,
frontlen
+
max_len
,
noblock
,
&
err
))
==
NULL
){
if
(
err
==
-
EWOULDBLOCK
&&
noblock
){
if
((
skbn
=
sock_alloc_send_skb
(
sk
,
frontlen
+
max_len
,
noblock
,
&
err
))
==
NULL
){
if
(
err
==
-
EWOULDBLOCK
&&
noblock
){
kfree_skb
(
skb
);
return
sent
;
}
SOCK_DEBUG
(
sk
,
"x25_output: fragment allocation failed, err=%d, %d bytes sent
\n
"
,
err
,
sent
);
SOCK_DEBUG
(
sk
,
"x25_output: fragment alloc"
" failed, err=%d, %d bytes "
"sent
\n
"
,
err
,
sent
);
return
err
;
}
skb_reserve
(
skbn
,
frontlen
);
len
=
(
max_len
>
skb
->
len
)
?
skb
->
len
:
max_len
;
len
=
max_len
>
skb
->
len
?
skb
->
len
:
max_len
;
/* Copy the user data */
memcpy
(
skb_put
(
skbn
,
len
),
skb
->
data
,
len
);
...
...
@@ -125,9 +129,9 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
*/
static
void
x25_send_iframe
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
skb
==
NULL
)
if
(
!
skb
)
return
;
if
(
x25
->
neighbour
->
extended
)
{
...
...
@@ -148,7 +152,7 @@ void x25_kick(struct sock *sk)
struct
sk_buff
*
skb
,
*
skbn
;
unsigned
short
start
,
end
;
int
modulus
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
x25
->
state
!=
X25_STATE_3
)
return
;
...
...
@@ -168,9 +172,9 @@ void x25_kick(struct sock *sk)
if
(
skb_peek
(
&
sk
->
write_queue
)
==
NULL
)
return
;
modulus
=
(
x25
->
neighbour
->
extended
)
?
X25_EMODULUS
:
X25_SMODULUS
;
modulus
=
x25
->
neighbour
->
extended
?
X25_EMODULUS
:
X25_SMODULUS
;
start
=
(
skb_peek
(
&
x25
->
ack_queue
)
==
NULL
)
?
x25
->
va
:
x25
->
vs
;
start
=
skb_peek
(
&
x25
->
ack_queue
)
?
x25
->
vs
:
x25
->
va
;
end
=
(
x25
->
va
+
x25
->
facilities
.
winsize_out
)
%
modulus
;
if
(
start
==
end
)
...
...
@@ -220,7 +224,7 @@ void x25_kick(struct sock *sk)
void
x25_enquiry_response
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
x25
->
condition
&
X25_COND_OWN_RX_BUSY
)
x25_write_internal
(
sk
,
X25_RNR
);
...
...
net/x25/x25_route.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -43,78 +44,85 @@
#include <linux/init.h>
#include <net/x25.h>
static
struct
x25_route
*
x25_route_list
/* = NULL initially */
;
static
struct
list_head
x25_route_list
=
LIST_HEAD_INIT
(
x25_route_list
);
static
rwlock_t
x25_route_list_lock
=
RW_LOCK_UNLOCKED
;
/*
* Add a new route.
*/
static
int
x25_add_route
(
x25_address
*
address
,
unsigned
int
sigdigits
,
struct
net_device
*
dev
)
static
int
x25_add_route
(
struct
x25_address
*
address
,
unsigned
int
sigdigits
,
struct
net_device
*
dev
)
{
struct
x25_route
*
x25_route
;
unsigned
long
flags
;
struct
x25_route
*
rt
;
struct
list_head
*
entry
;
int
rc
=
-
EINVAL
;
for
(
x25_route
=
x25_route_list
;
x25_route
!=
NULL
;
x25_route
=
x25_route
->
next
)
if
(
memcmp
(
&
x25_route
->
address
,
address
,
sigdigits
)
==
0
&&
x25_route
->
sigdigits
==
sigdigits
)
return
-
EINVAL
;
write_lock_bh
(
&
x25_route_list_lock
);
if
((
x25_route
=
kmalloc
(
sizeof
(
*
x25_route
),
GFP_ATOMIC
))
==
NULL
)
r
eturn
-
ENOMEM
;
list_for_each
(
entry
,
&
x25_route_list
)
{
r
t
=
list_entry
(
entry
,
struct
x25_route
,
node
)
;
strcpy
(
x25_route
->
address
.
x25_addr
,
"000000000000000"
);
memcpy
(
x25_route
->
address
.
x25_addr
,
address
->
x25_addr
,
sigdigits
);
if
(
!
memcmp
(
&
rt
->
address
,
address
,
sigdigits
)
&&
rt
->
sigdigits
==
sigdigits
)
goto
out
;
}
rt
=
kmalloc
(
sizeof
(
*
rt
),
GFP_ATOMIC
);
rc
=
-
ENOMEM
;
if
(
!
rt
)
goto
out
;
x25_route
->
sigdigits
=
sigdigits
;
x25_route
->
dev
=
dev
;
strcpy
(
rt
->
address
.
x25_addr
,
"000000000000000"
)
;
memcpy
(
rt
->
address
.
x25_addr
,
address
->
x25_addr
,
sigdigits
)
;
save_flags
(
flags
);
cli
();
x25_route
->
next
=
x25_route_list
;
x25_route_list
=
x25_route
;
restore_flags
(
flags
);
rt
->
sigdigits
=
sigdigits
;
rt
->
dev
=
dev
;
atomic_set
(
&
rt
->
refcnt
,
1
);
return
0
;
list_add
(
&
rt
->
node
,
&
x25_route_list
);
rc
=
0
;
out:
write_unlock_bh
(
&
x25_route_list_lock
);
return
rc
;
}
static
void
x25_remove_route
(
struct
x25_route
*
x25_route
)
/**
* __x25_remove_route - remove route from x25_route_list
* @rt - route to remove
*
* Remove route from x25_route_list. If it was there.
* Caller must hold x25_route_list_lock.
*/
static
void
__x25_remove_route
(
struct
x25_route
*
rt
)
{
struct
x25_route
*
s
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
if
((
s
=
x25_route_list
)
==
x25_route
)
{
x25_route_list
=
x25_route
->
next
;
restore_flags
(
flags
);
kfree
(
x25_route
);
return
;
if
(
rt
->
node
.
next
)
{
list_del
(
&
rt
->
node
);
x25_route_put
(
rt
);
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
x25_route
)
{
s
->
next
=
x25_route
->
next
;
restore_flags
(
flags
);
kfree
(
x25_route
);
return
;
}
s
=
s
->
next
;
}
restore_flags
(
flags
);
}
static
int
x25_del_route
(
x25_address
*
address
,
unsigned
int
sigdigits
,
struct
net_device
*
dev
)
static
int
x25_del_route
(
struct
x25_address
*
address
,
unsigned
int
sigdigits
,
struct
net_device
*
dev
)
{
struct
x25_route
*
x25_route
;
struct
x25_route
*
rt
;
struct
list_head
*
entry
;
int
rc
=
-
EINVAL
;
write_lock_bh
(
&
x25_route_list_lock
);
list_for_each
(
entry
,
&
x25_route_list
)
{
rt
=
list_entry
(
entry
,
struct
x25_route
,
node
);
for
(
x25_route
=
x25_route_list
;
x25_route
!=
NULL
;
x25_route
=
x25_route
->
next
)
{
if
(
memcmp
(
&
x25_route
->
address
,
address
,
sigdigits
)
==
0
&&
x25_route
->
sigdigits
==
sigdigits
&&
x25_route
->
dev
==
dev
)
{
x25_remove_route
(
x25_route
);
return
0
;
if
(
!
memcmp
(
&
rt
->
address
,
address
,
sigdigits
)
&&
rt
->
sigdigits
==
sigdigits
&&
rt
->
dev
==
dev
)
{
__x25_remove_route
(
rt
);
rc
=
0
;
break
;
}
}
return
-
EINVAL
;
write_unlock_bh
(
&
x25_route_list_lock
);
return
rc
;
}
/*
...
...
@@ -122,15 +130,18 @@ static int x25_del_route(x25_address *address, unsigned int sigdigits, struct ne
*/
void
x25_route_device_down
(
struct
net_device
*
dev
)
{
struct
x25_route
*
route
,
*
x25_route
=
x25_route_list
;
struct
x25_route
*
rt
;
struct
list_head
*
entry
,
*
tmp
;
write_lock_bh
(
&
x25_route_list_lock
);
while
(
x25_route
!=
NULL
)
{
route
=
x25_route
;
x25_route
=
x25_route
->
next
;
list_for_each_safe
(
entry
,
tmp
,
&
x25_route_list
)
{
rt
=
list_entry
(
entry
,
struct
x25_route
,
node
);
if
(
r
oute
->
dev
==
dev
)
x25_remove_route
(
route
);
if
(
r
t
->
dev
==
dev
)
__x25_remove_route
(
rt
);
}
write_unlock_bh
(
&
x25_route_list_lock
);
}
/*
...
...
@@ -138,42 +149,48 @@ void x25_route_device_down(struct net_device *dev)
*/
struct
net_device
*
x25_dev_get
(
char
*
devname
)
{
struct
net_device
*
dev
;
if
((
dev
=
dev_get_by_name
(
devname
))
==
NULL
)
return
NULL
;
struct
net_device
*
dev
=
dev_get_by_name
(
devname
);
if
((
dev
->
flags
&
IFF_UP
)
&&
(
dev
->
type
==
ARPHRD_X25
if
(
dev
&&
(
!
(
dev
->
flags
&
IFF_UP
)
||
(
dev
->
type
!=
ARPHRD_X25
#if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
||
dev
->
type
=
=
ARPHRD_ETHER
&&
dev
->
type
!
=
ARPHRD_ETHER
#endif
))
return
dev
;
)
))
dev_put
(
dev
)
;
dev_put
(
dev
);
return
NULL
;
return
dev
;
}
/*
* Find a device given an X.25 address.
/**
* x25_get_route - Find a route given an X.25 address.
* @addr - address to find a route for
*
* Find a route given an X.25 address.
*/
struct
net_device
*
x25_get_route
(
x25_address
*
addr
)
struct
x25_route
*
x25_get_route
(
struct
x25_address
*
addr
)
{
struct
x25_route
*
route
,
*
use
=
NULL
;
for
(
route
=
x25_route_list
;
route
!=
NULL
;
route
=
route
->
next
)
{
if
(
memcmp
(
&
route
->
address
,
addr
,
route
->
sigdigits
)
==
0
)
{
if
(
use
==
NULL
)
{
use
=
route
;
}
else
{
if
(
route
->
sigdigits
>
use
->
sigdigits
)
use
=
route
;
}
struct
x25_route
*
rt
,
*
use
=
NULL
;
struct
list_head
*
entry
;
read_lock_bh
(
&
x25_route_list_lock
);
list_for_each
(
entry
,
&
x25_route_list
)
{
rt
=
list_entry
(
entry
,
struct
x25_route
,
node
);
if
(
!
memcmp
(
&
rt
->
address
,
addr
,
rt
->
sigdigits
))
{
if
(
!
use
)
use
=
rt
;
else
if
(
rt
->
sigdigits
>
use
->
sigdigits
)
use
=
rt
;
}
}
return
(
use
!=
NULL
)
?
use
->
dev
:
NULL
;
if
(
use
)
x25_route_hold
(
use
);
read_unlock_bh
(
&
x25_route_list_lock
);
return
use
;
}
/*
...
...
@@ -181,57 +198,50 @@ struct net_device *x25_get_route(x25_address *addr)
*/
int
x25_route_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
{
struct
x25_route_struct
x25_route
;
struct
x25_route_struct
rt
;
struct
net_device
*
dev
;
int
err
;
switch
(
cmd
)
{
case
SIOCADDRT
:
if
(
copy_from_user
(
&
x25_route
,
arg
,
sizeof
(
struct
x25_route_struct
)))
return
-
EFAULT
;
if
(
x25_route
.
sigdigits
<
0
||
x25_route
.
sigdigits
>
15
)
return
-
EINVAL
;
if
((
dev
=
x25_dev_get
(
x25_route
.
device
))
==
NULL
)
return
-
EINVAL
;
err
=
x25_add_route
(
&
x25_route
.
address
,
x25_route
.
sigdigits
,
dev
);
dev_put
(
dev
);
return
err
;
case
SIOCDELRT
:
if
(
copy_from_user
(
&
x25_route
,
arg
,
sizeof
(
struct
x25_route_struct
)))
return
-
EFAULT
;
if
(
x25_route
.
sigdigits
<
0
||
x25_route
.
sigdigits
>
15
)
return
-
EINVAL
;
if
((
dev
=
x25_dev_get
(
x25_route
.
device
))
==
NULL
)
return
-
EINVAL
;
err
=
x25_del_route
(
&
x25_route
.
address
,
x25_route
.
sigdigits
,
dev
);
dev_put
(
dev
);
return
err
;
default:
return
-
EINVAL
;
}
int
rc
=
-
EINVAL
;
if
(
cmd
!=
SIOCADDRT
&&
cmd
!=
SIOCDELRT
)
goto
out
;
rc
=
-
EFAULT
;
if
(
copy_from_user
(
&
rt
,
arg
,
sizeof
(
rt
)))
goto
out
;
rc
=
-
EINVAL
;
if
(
rt
.
sigdigits
<
0
||
rt
.
sigdigits
>
15
)
goto
out
;
return
0
;
dev
=
x25_dev_get
(
rt
.
device
);
if
(
!
dev
)
goto
out
;
if
(
cmd
==
SIOCADDRT
)
rc
=
x25_add_route
(
&
rt
.
address
,
rt
.
sigdigits
,
dev
);
else
rc
=
x25_del_route
(
&
rt
.
address
,
rt
.
sigdigits
,
dev
);
dev_put
(
dev
);
out:
return
rc
;
}
int
x25_routes_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
struct
x25_route
*
x25_route
;
int
len
=
0
;
struct
x25_route
*
rt
;
struct
list_head
*
entry
;
off_t
pos
=
0
;
off_t
begin
=
0
;
int
len
=
sprintf
(
buffer
,
"address digits device
\n
"
);
cli
(
);
read_lock_bh
(
&
x25_route_list_lock
);
len
+=
sprintf
(
buffer
,
"address digits device
\n
"
);
for
(
x25_route
=
x25_route_list
;
x25_route
!=
NULL
;
x25_route
=
x25_route
->
next
)
{
list_for_each
(
entry
,
&
x25_route_list
)
{
rt
=
list_entry
(
entry
,
struct
x25_route
,
node
);
len
+=
sprintf
(
buffer
+
len
,
"%-15s %-6d %-5s
\n
"
,
x25_route
->
address
.
x25_addr
,
x25_route
->
sigdigits
,
(
x25_route
->
dev
!=
NULL
)
?
x25_route
->
dev
->
name
:
"???"
);
rt
->
address
.
x25_addr
,
rt
->
sigdigits
,
rt
->
dev
?
rt
->
dev
->
name
:
"???"
);
pos
=
begin
+
len
;
...
...
@@ -244,12 +254,13 @@ int x25_routes_get_info(char *buffer, char **start, off_t offset, int length)
break
;
}
sti
(
);
read_unlock_bh
(
&
x25_route_list_lock
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
len
;
}
...
...
@@ -259,12 +270,13 @@ int x25_routes_get_info(char *buffer, char **start, off_t offset, int length)
*/
void
__exit
x25_route_free
(
void
)
{
struct
x25_route
*
route
,
*
x25_route
=
x25_route_list
;
while
(
x25_route
!=
NULL
)
{
route
=
x25_route
;
x25_route
=
x25_route
->
next
;
struct
x25_route
*
rt
;
struct
list_head
*
entry
,
*
tmp
;
x25_remove_route
(
route
);
write_lock_bh
(
&
x25_route_list_lock
);
list_for_each_safe
(
entry
,
tmp
,
&
x25_route_list
)
{
rt
=
list_entry
(
entry
,
struct
x25_route
,
node
);
__x25_remove_route
(
rt
);
}
write_unlock_bh
(
&
x25_route_list_lock
);
}
net/x25/x25_subr.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -15,7 +16,7 @@
* History
* X.25 001 Jonathan Naylor Started coding.
* X.25 002 Jonathan Naylor Centralised disconnection processing.
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
* jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups
*/
...
...
@@ -46,7 +47,7 @@
*/
void
x25_clear_queues
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
skb_queue_purge
(
&
sk
->
write_queue
);
skb_queue_purge
(
&
x25
->
ack_queue
);
...
...
@@ -64,7 +65,7 @@ void x25_clear_queues(struct sock *sk)
void
x25_frames_acked
(
struct
sock
*
sk
,
unsigned
short
nr
)
{
struct
sk_buff
*
skb
;
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
int
modulus
=
x25
->
neighbour
->
extended
?
X25_EMODULUS
:
X25_SMODULUS
;
/*
...
...
@@ -88,7 +89,7 @@ void x25_requeue_frames(struct sock *sk)
* output queue.
*/
while
((
skb
=
skb_dequeue
(
&
x25_sk
(
sk
)
->
ack_queue
))
!=
NULL
)
{
if
(
skb_prev
==
NULL
)
if
(
!
skb_prev
)
skb_queue_head
(
&
sk
->
write_queue
,
skb
);
else
skb_append
(
skb_prev
,
skb
);
...
...
@@ -102,36 +103,35 @@ void x25_requeue_frames(struct sock *sk)
*/
int
x25_validate_nr
(
struct
sock
*
sk
,
unsigned
short
nr
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
unsigned
short
vc
=
x25
->
va
;
int
modulus
=
x25
->
neighbour
->
extended
?
X25_EMODULUS
:
X25_SMODULUS
;
while
(
vc
!=
x25
->
vs
)
{
if
(
nr
==
vc
)
return
1
;
if
(
nr
==
vc
)
return
1
;
vc
=
(
vc
+
1
)
%
modulus
;
}
return
nr
==
x25
->
vs
?
1
:
0
;
}
/*
/*
* This routine is called when the packet layer internally generates a
* control frame.
*/
void
x25_write_internal
(
struct
sock
*
sk
,
int
frametype
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
struct
sk_buff
*
skb
;
unsigned
char
*
dptr
;
unsigned
char
facilities
[
X25_MAX_FAC_LEN
];
unsigned
char
addresses
[
1
+
X25_ADDR_LEN
];
unsigned
char
lci1
,
lci2
;
int
len
;
/*
* Default safe frame size.
*/
len
=
X25_MAX_L2_LEN
+
X25_EXT_MIN_LEN
;
int
len
=
X25_MAX_L2_LEN
+
X25_EXT_MIN_LEN
;
/*
* Adjust frame size.
...
...
@@ -262,7 +262,7 @@ void x25_write_internal(struct sock *sk, int frametype)
int
x25_decode
(
struct
sock
*
sk
,
struct
sk_buff
*
skb
,
int
*
ns
,
int
*
nr
,
int
*
q
,
int
*
d
,
int
*
m
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
unsigned
char
*
frame
=
skb
->
data
;
*
ns
=
*
nr
=
*
q
=
*
d
=
*
m
=
0
;
...
...
@@ -329,7 +329,7 @@ int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
void
x25_disconnect
(
struct
sock
*
sk
,
int
reason
,
unsigned
char
cause
,
unsigned
char
diagnostic
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
x25_clear_queues
(
sk
);
x25_stop_timer
(
sk
);
...
...
@@ -356,7 +356,7 @@ void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
*/
void
x25_check_rbuf
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
atomic_read
(
&
sk
->
rmem_alloc
)
<
(
sk
->
rcvbuf
/
2
)
&&
(
x25
->
condition
&
X25_COND_OWN_RX_BUSY
))
{
...
...
net/x25/x25_timer.c
View file @
5c0fbae1
/*
* X.25 Packet Layer release 002
*
* This is ALPHA test software. This code may break your machine, randomly fail to work with new
* releases, misbehave and/or generally screw up. It might even work.
* This is ALPHA test software. This code may break your machine,
* randomly fail to work with new releases, misbehave and/or generally
* screw up. It might even work.
*
* This code REQUIRES 2.1.15 or higher
*
...
...
@@ -60,7 +61,7 @@ void x25_stop_heartbeat(struct sock *sk)
void
x25_start_t2timer
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
del_timer
(
&
x25
->
timer
);
...
...
@@ -73,7 +74,7 @@ void x25_start_t2timer(struct sock *sk)
void
x25_start_t21timer
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
del_timer
(
&
x25
->
timer
);
...
...
@@ -86,7 +87,7 @@ void x25_start_t21timer(struct sock *sk)
void
x25_start_t22timer
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
del_timer
(
&
x25
->
timer
);
...
...
@@ -99,7 +100,7 @@ void x25_start_t22timer(struct sock *sk)
void
x25_start_t23timer
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
del_timer
(
&
x25
->
timer
);
...
...
@@ -117,7 +118,7 @@ void x25_stop_timer(struct sock *sk)
unsigned
long
x25_display_timer
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
if
(
!
timer_pending
(
&
x25
->
timer
))
return
0
;
...
...
@@ -130,9 +131,8 @@ static void x25_heartbeat_expiry(unsigned long param)
struct
sock
*
sk
=
(
struct
sock
*
)
param
;
bh_lock_sock
(
sk
);
if
(
sk
->
lock
.
users
)
{
/* can currently only occur in state 3 */
if
(
sk
->
lock
.
users
)
/* can currently only occur in state 3 */
goto
restart_heartbeat
;
}
switch
(
x25_sk
(
sk
)
->
state
)
{
...
...
@@ -152,9 +152,9 @@ static void x25_heartbeat_expiry(unsigned long param)
x25_check_rbuf
(
sk
);
break
;
}
restart_heartbeat:
restart_heartbeat:
x25_start_heartbeat
(
sk
);
unlock:
unlock:
bh_unlock_sock
(
sk
);
}
...
...
@@ -164,7 +164,7 @@ static void x25_heartbeat_expiry(unsigned long param)
*/
static
inline
void
x25_do_timer_expiry
(
struct
sock
*
sk
)
{
x25_cb
*
x25
=
x25_sk
(
sk
);
struct
x25_opt
*
x25
=
x25_sk
(
sk
);
switch
(
x25
->
state
)
{
...
...
@@ -194,11 +194,9 @@ static void x25_timer_expiry(unsigned long param)
bh_lock_sock
(
sk
);
if
(
sk
->
lock
.
users
)
{
/* can currently only occur in state 3 */
if
(
x25_sk
(
sk
)
->
state
==
X25_STATE_3
)
{
if
(
x25_sk
(
sk
)
->
state
==
X25_STATE_3
)
x25_start_t2timer
(
sk
);
}
}
else
{
}
else
x25_do_timer_expiry
(
sk
);
}
bh_unlock_sock
(
sk
);
}
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