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
0dfe6e55
Commit
0dfe6e55
authored
Aug 04, 2002
by
Ralf Bächle
Browse files
Options
Browse Files
Download
Plain Diff
Resolve merge conflicts.
parents
35aa61ec
e39aa73c
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
1909 additions
and
1540 deletions
+1909
-1540
include/net/ax25.h
include/net/ax25.h
+12
-4
net/ax25/TODO
net/ax25/TODO
+14
-0
net/ax25/af_ax25.c
net/ax25/af_ax25.c
+674
-494
net/ax25/ax25_dev.c
net/ax25/ax25_dev.c
+45
-29
net/ax25/ax25_ds_in.c
net/ax25/ax25_ds_in.c
+194
-192
net/ax25/ax25_ds_subr.c
net/ax25/ax25_ds_subr.c
+13
-3
net/ax25/ax25_ds_timer.c
net/ax25/ax25_ds_timer.c
+62
-58
net/ax25/ax25_iface.c
net/ax25/ax25_iface.c
+55
-50
net/ax25/ax25_in.c
net/ax25/ax25_in.c
+49
-49
net/ax25/ax25_ip.c
net/ax25/ax25_ip.c
+21
-17
net/ax25/ax25_out.c
net/ax25/ax25_out.c
+34
-33
net/ax25/ax25_route.c
net/ax25/ax25_route.c
+238
-143
net/ax25/ax25_std_in.c
net/ax25/ax25_std_in.c
+292
-290
net/ax25/ax25_std_timer.c
net/ax25/ax25_std_timer.c
+64
-65
net/ax25/ax25_subr.c
net/ax25/ax25_subr.c
+12
-12
net/ax25/ax25_timer.c
net/ax25/ax25_timer.c
+46
-46
net/ax25/ax25_uid.c
net/ax25/ax25_uid.c
+79
-55
net/ax25/sysctl_net_ax25.c
net/ax25/sysctl_net_ax25.c
+5
-0
No files found.
include/net/ax25.h
View file @
0dfe6e55
...
@@ -3,11 +3,14 @@
...
@@ -3,11 +3,14 @@
*
*
* Alan Cox (GW4PTS) 10/11/93
* Alan Cox (GW4PTS) 10/11/93
*/
*/
#ifndef _AX25_H
#ifndef _AX25_H
#define _AX25_H
#define _AX25_H
#include <linux/config.h>
#include <linux/config.h>
#include <linux/ax25.h>
#include <linux/ax25.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <asm/atomic.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
#define AX25_T1CLAMPHI (30 * HZ)
...
@@ -147,10 +150,12 @@ typedef struct {
...
@@ -147,10 +150,12 @@ typedef struct {
typedef
struct
ax25_route
{
typedef
struct
ax25_route
{
struct
ax25_route
*
next
;
struct
ax25_route
*
next
;
atomic_t
ref
;
ax25_address
callsign
;
ax25_address
callsign
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
ax25_digi
*
digipeat
;
ax25_digi
*
digipeat
;
char
ip_mode
;
char
ip_mode
;
struct
timer_list
timer
;
}
ax25_route
;
}
ax25_route
;
typedef
struct
{
typedef
struct
{
...
@@ -197,7 +202,8 @@ typedef struct ax25_cb {
...
@@ -197,7 +202,8 @@ typedef struct ax25_cb {
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
/* af_ax25.c */
/* af_ax25.c */
extern
ax25_cb
*
volatile
ax25_list
;
extern
ax25_cb
*
ax25_list
;
extern
spinlock_t
ax25_list_lock
;
extern
void
ax25_free_cb
(
ax25_cb
*
);
extern
void
ax25_free_cb
(
ax25_cb
*
);
extern
void
ax25_insert_socket
(
ax25_cb
*
);
extern
void
ax25_insert_socket
(
ax25_cb
*
);
struct
sock
*
ax25_find_listener
(
ax25_address
*
,
int
,
struct
net_device
*
,
int
);
struct
sock
*
ax25_find_listener
(
ax25_address
*
,
int
,
struct
net_device
*
,
int
);
...
@@ -224,6 +230,7 @@ extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
...
@@ -224,6 +230,7 @@ extern void ax25_digi_invert(ax25_digi *, ax25_digi *);
/* ax25_dev.c */
/* ax25_dev.c */
extern
ax25_dev
*
ax25_dev_list
;
extern
ax25_dev
*
ax25_dev_list
;
extern
spinlock_t
ax25_dev_lock
;
extern
ax25_dev
*
ax25_dev_ax25dev
(
struct
net_device
*
);
extern
ax25_dev
*
ax25_dev_ax25dev
(
struct
net_device
*
);
extern
ax25_dev
*
ax25_addr_ax25dev
(
ax25_address
*
);
extern
ax25_dev
*
ax25_addr_ax25dev
(
ax25_address
*
);
extern
void
ax25_dev_device_up
(
struct
net_device
*
);
extern
void
ax25_dev_device_up
(
struct
net_device
*
);
...
@@ -286,7 +293,8 @@ extern void ax25_rt_device_down(struct net_device *);
...
@@ -286,7 +293,8 @@ extern void ax25_rt_device_down(struct net_device *);
extern
int
ax25_rt_ioctl
(
unsigned
int
,
void
*
);
extern
int
ax25_rt_ioctl
(
unsigned
int
,
void
*
);
extern
int
ax25_rt_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
ax25_rt_get_info
(
char
*
,
char
**
,
off_t
,
int
);
extern
int
ax25_rt_autobind
(
ax25_cb
*
,
ax25_address
*
);
extern
int
ax25_rt_autobind
(
ax25_cb
*
,
ax25_address
*
);
extern
ax25_route
*
ax25_rt_find_route
(
ax25_address
*
,
struct
net_device
*
);
extern
ax25_route
*
ax25_rt_find_route
(
ax25_route
*
,
ax25_address
*
,
struct
net_device
*
);
extern
struct
sk_buff
*
ax25_rt_build_path
(
struct
sk_buff
*
,
ax25_address
*
,
ax25_address
*
,
ax25_digi
*
);
extern
struct
sk_buff
*
ax25_rt_build_path
(
struct
sk_buff
*
,
ax25_address
*
,
ax25_address
*
,
ax25_digi
*
);
extern
void
ax25_rt_free
(
void
);
extern
void
ax25_rt_free
(
void
);
...
...
net/ax25/TODO
0 → 100644
View file @
0dfe6e55
af_ax25.c:ax25_connect:
There is a race with changing the socket state here which should be
fixed by introduction of proper socket locking:
if (sk->state != TCP_ESTABLISHED) {
/* Not in ABM, not in WAIT_UA -> failed */
sock->state = SS_UNCONNECTED;
return sock_error(sk); /* Always set at this point */
}
Do the ax25_list_lock, ax25_uid_lock, ax25_route_lock, protocol_list_lock,
ax25_dev_lock, linkfail_lockreally, ax25_frag_lock and listen_lock have to
be interrupt safe?
net/ax25/af_ax25.c
View file @
0dfe6e55
...
@@ -114,6 +114,7 @@
...
@@ -114,6 +114,7 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <net/ax25.h>
...
@@ -134,13 +135,15 @@
...
@@ -134,13 +135,15 @@
#include <linux/netfilter.h>
#include <linux/netfilter.h>
#include <linux/sysctl.h>
#include <linux/sysctl.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <net/tcp.h>
#include <net/tcp.h>
#include <net/ip.h>
#include <net/ip.h>
#include <net/arp.h>
#include <net/arp.h>
ax25_cb
*
volatile
ax25_list
;
ax25_cb
*
ax25_list
;
spinlock_t
ax25_list_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
proto_ops
ax25_proto_ops
;
static
struct
proto_ops
ax25_proto_ops
;
...
@@ -173,25 +176,25 @@ static void ax25_remove_socket(ax25_cb *ax25)
...
@@ -173,25 +176,25 @@ static void ax25_remove_socket(ax25_cb *ax25)
ax25_cb
*
s
;
ax25_cb
*
s
;
unsigned
long
flags
;
unsigned
long
flags
;
s
ave_flags
(
flags
);
cli
(
);
s
pin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
if
((
s
=
ax25_list
)
==
ax25
)
{
if
((
s
=
ax25_list
)
==
ax25
)
{
ax25_list
=
s
->
next
;
ax25_list
=
s
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
;
return
;
}
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25
)
{
if
(
s
->
next
==
ax25
)
{
s
->
next
=
ax25
->
next
;
s
->
next
=
ax25
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
;
return
;
}
}
s
=
s
->
next
;
s
=
s
->
next
;
}
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
}
/*
/*
...
@@ -199,24 +202,28 @@ static void ax25_remove_socket(ax25_cb *ax25)
...
@@ -199,24 +202,28 @@ static void ax25_remove_socket(ax25_cb *ax25)
*/
*/
static
void
ax25_kill_by_device
(
struct
net_device
*
dev
)
static
void
ax25_kill_by_device
(
struct
net_device
*
dev
)
{
{
unsigned
long
flags
;
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
;
ax25_cb
*
s
;
ax25_cb
*
s
;
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
return
;
return
;
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
ax25_dev
==
ax25_dev
)
{
if
(
s
->
ax25_dev
==
ax25_dev
)
{
s
->
ax25_dev
=
NULL
;
s
->
ax25_dev
=
NULL
;
ax25_disconnect
(
s
,
ENETUNREACH
);
ax25_disconnect
(
s
,
ENETUNREACH
);
}
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
}
/*
/*
* Handle device status changes.
* Handle device status changes.
*/
*/
static
int
ax25_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
static
int
ax25_device_event
(
struct
notifier_block
*
this
,
unsigned
long
event
,
void
*
ptr
)
{
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
ptr
;
struct
net_device
*
dev
=
(
struct
net_device
*
)
ptr
;
...
@@ -247,62 +254,58 @@ void ax25_insert_socket(ax25_cb *ax25)
...
@@ -247,62 +254,58 @@ void ax25_insert_socket(ax25_cb *ax25)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
cli
();
ax25
->
next
=
ax25_list
;
ax25
->
next
=
ax25_list
;
ax25_list
=
ax25
;
ax25_list
=
ax25
;
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
}
}
/*
/*
* Find a socket that wants to accept the SABM we have just
* Find a socket that wants to accept the SABM we have just
* received.
* received.
*/
*/
struct
sock
*
ax25_find_listener
(
ax25_address
*
addr
,
int
digi
,
struct
net_device
*
dev
,
int
type
)
struct
sock
*
ax25_find_listener
(
ax25_address
*
addr
,
int
digi
,
struct
net_device
*
dev
,
int
type
)
{
{
unsigned
long
flags
;
unsigned
long
flags
;
ax25_cb
*
s
;
ax25_cb
*
s
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
cli
();
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
((
s
->
iamdigi
&&
!
digi
)
||
(
!
s
->
iamdigi
&&
digi
))
if
((
s
->
iamdigi
&&
!
digi
)
||
(
!
s
->
iamdigi
&&
digi
))
continue
;
continue
;
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
addr
)
==
0
&&
s
->
sk
->
type
==
type
&&
s
->
sk
->
state
==
TCP_LISTEN
)
{
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
addr
)
==
0
&&
s
->
sk
->
type
==
type
&&
s
->
sk
->
state
==
TCP_LISTEN
)
{
/* If device is null we match any device */
/* If device is null we match any device */
if
(
s
->
ax25_dev
==
NULL
||
s
->
ax25_dev
->
dev
==
dev
)
{
if
(
s
->
ax25_dev
==
NULL
||
s
->
ax25_dev
->
dev
==
dev
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
->
sk
;
return
s
->
sk
;
}
}
}
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
return
NULL
;
return
NULL
;
}
}
/*
/*
* Find an AX.25 socket given both ends.
* Find an AX.25 socket given both ends.
*/
*/
struct
sock
*
ax25_find_socket
(
ax25_address
*
my_addr
,
ax25_address
*
dest_addr
,
int
type
)
struct
sock
*
ax25_find_socket
(
ax25_address
*
my_addr
,
ax25_address
*
dest_addr
,
int
type
)
{
{
ax25_cb
*
s
;
ax25_cb
*
s
;
unsigned
long
flags
;
unsigned
long
flags
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
cli
();
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
my_addr
)
==
0
&&
ax25cmp
(
&
s
->
dest_addr
,
dest_addr
)
==
0
&&
s
->
sk
->
type
==
type
)
{
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
my_addr
)
==
0
&&
ax25cmp
(
&
s
->
dest_addr
,
dest_addr
)
==
0
&&
s
->
sk
->
type
==
type
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
->
sk
;
return
s
->
sk
;
}
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
return
NULL
;
return
NULL
;
}
}
...
@@ -311,14 +314,13 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in
...
@@ -311,14 +314,13 @@ struct sock *ax25_find_socket(ax25_address *my_addr, ax25_address *dest_addr, in
* Find an AX.25 control block given both ends. It will only pick up
* Find an AX.25 control block given both ends. It will only pick up
* floating AX.25 control blocks or non Raw socket bound control blocks.
* floating AX.25 control blocks or non Raw socket bound control blocks.
*/
*/
ax25_cb
*
ax25_find_cb
(
ax25_address
*
src_addr
,
ax25_address
*
dest_addr
,
ax25_digi
*
digi
,
struct
net_device
*
dev
)
ax25_cb
*
ax25_find_cb
(
ax25_address
*
src_addr
,
ax25_address
*
dest_addr
,
ax25_digi
*
digi
,
struct
net_device
*
dev
)
{
{
ax25_cb
*
s
;
ax25_cb
*
s
;
unsigned
long
flags
;
unsigned
long
flags
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
cli
();
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
sk
!=
NULL
&&
s
->
sk
->
type
!=
SOCK_SEQPACKET
)
if
(
s
->
sk
!=
NULL
&&
s
->
sk
->
type
!=
SOCK_SEQPACKET
)
continue
;
continue
;
...
@@ -334,12 +336,12 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi
...
@@ -334,12 +336,12 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, ax25_digi
if
(
s
->
digipeat
!=
NULL
&&
s
->
digipeat
->
ndigi
!=
0
)
if
(
s
->
digipeat
!=
NULL
&&
s
->
digipeat
->
ndigi
!=
0
)
continue
;
continue
;
}
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
;
return
s
;
}
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
return
NULL
;
return
NULL
;
}
}
...
@@ -352,17 +354,14 @@ struct sock *ax25_addr_match(ax25_address *addr)
...
@@ -352,17 +354,14 @@ struct sock *ax25_addr_match(ax25_address *addr)
unsigned
long
flags
;
unsigned
long
flags
;
ax25_cb
*
s
;
ax25_cb
*
s
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
cli
();
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
addr
)
==
0
&&
s
->
sk
->
type
==
SOCK_RAW
)
{
if
(
s
->
sk
!=
NULL
&&
ax25cmp
(
&
s
->
source_addr
,
addr
)
==
0
&&
s
->
sk
->
type
==
SOCK_RAW
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
->
sk
;
return
s
->
sk
;
}
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
return
NULL
;
return
NULL
;
}
}
...
@@ -400,12 +399,12 @@ static void ax25_destroy_timer(unsigned long data)
...
@@ -400,12 +399,12 @@ static void ax25_destroy_timer(unsigned long data)
}
}
/*
/*
* This is called from user mode and the timers. Thus it protects itself
against
* This is called from user mode and the timers. Thus it protects itself
*
interrupt users but doesn't worry about being called during work.
*
against interrupt users but doesn't worry about being called during
*
Once it is removed from the queue no interrupt or bottom half will
*
work. Once it is removed from the queue no interrupt or bottom half
* touch it and we are (fairly 8-) ) safe.
*
will
touch it and we are (fairly 8-) ) safe.
*/
*/
void
ax25_destroy_socket
(
ax25_cb
*
ax25
)
/* Not static as it's used by the timer */
void
ax25_destroy_socket
(
ax25_cb
*
ax25
)
{
{
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
unsigned
long
flags
;
unsigned
long
flags
;
...
@@ -631,13 +630,14 @@ ax25_cb *ax25_create_cb(void)
...
@@ -631,13 +630,14 @@ ax25_cb *ax25_create_cb(void)
* AX25 socket object
* AX25 socket object
*/
*/
static
int
ax25_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
static
int
ax25_setsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
optlen
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
char
devname
[
IFNAMSIZ
];
char
devname
[
IFNAMSIZ
];
int
opt
;
int
opt
,
res
=
0
;
if
(
level
!=
SOL_AX25
)
if
(
level
!=
SOL_AX25
)
return
-
ENOPROTOOPT
;
return
-
ENOPROTOOPT
;
...
@@ -648,98 +648,131 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
...
@@ -648,98 +648,131 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
if
(
get_user
(
opt
,
(
int
*
)
optval
))
if
(
get_user
(
opt
,
(
int
*
)
optval
))
return
-
EFAULT
;
return
-
EFAULT
;
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
switch
(
optname
)
{
switch
(
optname
)
{
case
AX25_WINDOW
:
case
AX25_WINDOW
:
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
if
(
opt
<
1
||
opt
>
7
)
if
(
opt
<
1
||
opt
>
7
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
}
else
{
}
else
{
if
(
opt
<
1
||
opt
>
63
)
if
(
opt
<
1
||
opt
>
63
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
}
}
ax25
->
window
=
opt
;
ax25
->
window
=
opt
;
return
0
;
break
;
case
AX25_T1
:
case
AX25_T1
:
if
(
opt
<
1
)
if
(
opt
<
1
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
rtt
=
(
opt
*
HZ
)
/
2
;
ax25
->
rtt
=
(
opt
*
HZ
)
/
2
;
ax25
->
t1
=
opt
*
HZ
;
ax25
->
t1
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_T2
:
case
AX25_T2
:
if
(
opt
<
1
)
if
(
opt
<
1
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
t2
=
opt
*
HZ
;
ax25
->
t2
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_N2
:
case
AX25_N2
:
if
(
opt
<
1
||
opt
>
31
)
if
(
opt
<
1
||
opt
>
31
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
n2
=
opt
;
ax25
->
n2
=
opt
;
return
0
;
break
;
case
AX25_T3
:
case
AX25_T3
:
if
(
opt
<
1
)
if
(
opt
<
1
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
t3
=
opt
*
HZ
;
ax25
->
t3
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_IDLE
:
case
AX25_IDLE
:
if
(
opt
<
0
)
if
(
opt
<
0
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
idle
=
opt
*
60
*
HZ
;
ax25
->
idle
=
opt
*
60
*
HZ
;
return
0
;
break
;
case
AX25_BACKOFF
:
case
AX25_BACKOFF
:
if
(
opt
<
0
||
opt
>
2
)
if
(
opt
<
0
||
opt
>
2
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
backoff
=
opt
;
ax25
->
backoff
=
opt
;
return
0
;
break
;
case
AX25_EXTSEQ
:
case
AX25_EXTSEQ
:
ax25
->
modulus
=
opt
?
AX25_EMODULUS
:
AX25_MODULUS
;
ax25
->
modulus
=
opt
?
AX25_EMODULUS
:
AX25_MODULUS
;
return
0
;
break
;
case
AX25_PIDINCL
:
case
AX25_PIDINCL
:
ax25
->
pidincl
=
opt
?
1
:
0
;
ax25
->
pidincl
=
opt
?
1
:
0
;
return
0
;
break
;
case
AX25_IAMDIGI
:
case
AX25_IAMDIGI
:
ax25
->
iamdigi
=
opt
?
1
:
0
;
ax25
->
iamdigi
=
opt
?
1
:
0
;
return
0
;
break
;
case
AX25_PACLEN
:
case
AX25_PACLEN
:
if
(
opt
<
16
||
opt
>
65535
)
if
(
opt
<
16
||
opt
>
65535
)
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
ax25
->
paclen
=
opt
;
ax25
->
paclen
=
opt
;
return
0
;
break
;
case
SO_BINDTODEVICE
:
case
SO_BINDTODEVICE
:
if
(
optlen
>
IFNAMSIZ
)
optlen
=
IFNAMSIZ
;
if
(
optlen
>
IFNAMSIZ
)
if
(
copy_from_user
(
devname
,
optval
,
optlen
))
optlen
=
IFNAMSIZ
;
return
-
EFAULT
;
if
(
copy_from_user
(
devname
,
optval
,
optlen
))
{
res
=
-
EFAULT
;
break
;
}
dev
=
dev_get_by_name
(
devname
);
dev
=
dev_get_by_name
(
devname
);
if
(
dev
==
NULL
)
return
-
ENODEV
;
if
(
dev
==
NULL
)
{
res
=
-
ENODEV
;
break
;
}
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
(
sock
->
state
!=
SS_UNCONNECTED
||
sk
->
state
==
TCP_LISTEN
))
(
sock
->
state
!=
SS_UNCONNECTED
||
sk
->
state
==
TCP_LISTEN
))
{
return
-
EADDRNOTAVAIL
;
res
=
-
EADDRNOTAVAIL
;
break
;
}
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
dev
);
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
dev
);
ax25_fillin_cb
(
ax25
,
ax25
->
ax25_dev
);
ax25_fillin_cb
(
ax25
,
ax25
->
ax25_dev
);
return
0
;
break
;
default:
default:
return
-
ENOPROTOOPT
;
res
=
-
ENOPROTOOPT
;
}
}
unlock_kernel
();
return
res
;
}
}
static
int
ax25_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
static
int
ax25_getsockopt
(
struct
socket
*
sock
,
int
level
,
int
optname
,
char
*
optval
,
int
*
optlen
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
ax25_dev
*
ax25_dev
;
struct
ax25_dev
*
ax25_dev
;
char
devname
[
IFNAMSIZ
];
char
devname
[
IFNAMSIZ
];
void
*
valptr
;
void
*
valptr
;
...
@@ -758,6 +791,9 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
...
@@ -758,6 +791,9 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
valptr
=
(
void
*
)
&
val
;
valptr
=
(
void
*
)
&
val
;
length
=
min_t
(
unsigned
int
,
maxlen
,
sizeof
(
int
));
length
=
min_t
(
unsigned
int
,
maxlen
,
sizeof
(
int
));
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
switch
(
optname
)
{
switch
(
optname
)
{
case
AX25_WINDOW
:
case
AX25_WINDOW
:
val
=
ax25
->
window
;
val
=
ax25
->
window
;
...
@@ -819,8 +855,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
...
@@ -819,8 +855,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
break
;
break
;
default:
default:
unlock_kernel
();
return
-
ENOPROTOOPT
;
return
-
ENOPROTOOPT
;
}
}
unlock_kernel
();
if
(
put_user
(
length
,
optlen
))
if
(
put_user
(
length
,
optlen
))
return
-
EFAULT
;
return
-
EFAULT
;
...
@@ -832,11 +870,14 @@ static int ax25_listen(struct socket *sock, int backlog)
...
@@ -832,11 +870,14 @@ static int ax25_listen(struct socket *sock, int backlog)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
lock_kernel
();
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
!=
TCP_LISTEN
)
{
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
!=
TCP_LISTEN
)
{
sk
->
max_ack_backlog
=
backlog
;
sk
->
max_ack_backlog
=
backlog
;
sk
->
state
=
TCP_LISTEN
;
sk
->
state
=
TCP_LISTEN
;
unlock_kernel
();
return
0
;
return
0
;
}
}
unlock_kernel
();
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
}
}
...
@@ -851,6 +892,7 @@ int ax25_create(struct socket *sock, int protocol)
...
@@ -851,6 +892,7 @@ int ax25_create(struct socket *sock, int protocol)
if
(
protocol
==
0
||
protocol
==
PF_AX25
)
if
(
protocol
==
0
||
protocol
==
PF_AX25
)
protocol
=
AX25_P_TEXT
;
protocol
=
AX25_P_TEXT
;
break
;
break
;
case
SOCK_SEQPACKET
:
case
SOCK_SEQPACKET
:
switch
(
protocol
)
{
switch
(
protocol
)
{
case
0
:
case
0
:
...
@@ -883,6 +925,7 @@ int ax25_create(struct socket *sock, int protocol)
...
@@ -883,6 +925,7 @@ int ax25_create(struct socket *sock, int protocol)
break
;
break
;
}
}
break
;
break
;
case
SOCK_RAW
:
case
SOCK_RAW
:
break
;
break
;
default:
default:
...
@@ -985,7 +1028,11 @@ static int ax25_release(struct socket *sock)
...
@@ -985,7 +1028,11 @@ static int ax25_release(struct socket *sock)
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
;
ax25_cb
*
ax25
;
if
(
sk
==
NULL
)
return
0
;
lock_kernel
();
if
(
sk
==
NULL
)
{
unlock_kernel
();
return
0
;
}
ax25
=
ax25_sk
(
sk
);
ax25
=
ax25_sk
(
sk
);
...
@@ -1048,6 +1095,7 @@ static int ax25_release(struct socket *sock)
...
@@ -1048,6 +1095,7 @@ static int ax25_release(struct socket *sock)
sock
->
sk
=
NULL
;
sock
->
sk
=
NULL
;
sk
->
socket
=
NULL
;
/* Not used, but we should do this */
sk
->
socket
=
NULL
;
/* Not used, but we should do this */
unlock_kernel
();
return
0
;
return
0
;
}
}
...
@@ -1066,26 +1114,35 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
...
@@ -1066,26 +1114,35 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
ax25_address
*
call
;
ax25_address
*
call
;
ax25_dev
*
ax25_dev
=
NULL
;
ax25_dev
*
ax25_dev
=
NULL
;
if
(
sk
->
zapped
==
0
)
lock_kernel
();
if
(
sk
->
zapped
==
0
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
addr_len
!=
sizeof
(
struct
sockaddr_ax25
)
&&
if
(
addr_len
!=
sizeof
(
struct
sockaddr_ax25
)
&&
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
/* support for old structure may go away some time */
/* support for old structure may go away some time */
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
printk
(
KERN_WARNING
"ax25_bind(): %s uses old (6 digipeater) socket structure.
\n
"
,
printk
(
KERN_WARNING
"ax25_bind(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
current
->
comm
);
}
}
if
(
addr
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
if
(
addr
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
call
=
ax25_findbyuid
(
current
->
euid
);
call
=
ax25_findbyuid
(
current
->
euid
);
if
(
call
==
NULL
&&
ax25_uid_policy
&&
!
capable
(
CAP_NET_ADMIN
))
if
(
call
==
NULL
&&
ax25_uid_policy
&&
!
capable
(
CAP_NET_ADMIN
))
{
unlock_kernel
();
return
-
EACCES
;
return
-
EACCES
;
}
if
(
call
==
NULL
)
if
(
call
==
NULL
)
ax25
->
source_addr
=
addr
->
fsa_ax25
.
sax25_call
;
ax25
->
source_addr
=
addr
->
fsa_ax25
.
sax25_call
;
...
@@ -1101,12 +1158,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
...
@@ -1101,12 +1158,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if
(
addr_len
>
sizeof
(
struct
sockaddr_ax25
)
&&
addr
->
fsa_ax25
.
sax25_ndigis
==
1
)
{
if
(
addr_len
>
sizeof
(
struct
sockaddr_ax25
)
&&
addr
->
fsa_ax25
.
sax25_ndigis
==
1
)
{
if
(
ax25cmp
(
&
addr
->
fsa_digipeater
[
0
],
&
null_ax25_address
)
!=
0
&&
if
(
ax25cmp
(
&
addr
->
fsa_digipeater
[
0
],
&
null_ax25_address
)
!=
0
&&
(
ax25_dev
=
ax25_addr_ax25dev
(
&
addr
->
fsa_digipeater
[
0
]))
==
NULL
)
(
ax25_dev
=
ax25_addr_ax25dev
(
&
addr
->
fsa_digipeater
[
0
]))
==
NULL
)
{
unlock_kernel
();
return
-
EADDRNOTAVAIL
;
return
-
EADDRNOTAVAIL
;
}
}
else
{
}
else
{
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
addr
->
fsa_ax25
.
sax25_call
))
==
NULL
)
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
addr
->
fsa_ax25
.
sax25_call
))
==
NULL
)
{
unlock_kernel
();
return
-
EADDRNOTAVAIL
;
return
-
EADDRNOTAVAIL
;
}
}
}
if
(
ax25_dev
!=
NULL
)
if
(
ax25_dev
!=
NULL
)
ax25_fillin_cb
(
ax25
,
ax25_dev
);
ax25_fillin_cb
(
ax25
,
ax25_dev
);
...
@@ -1114,13 +1175,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
...
@@ -1114,13 +1175,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
done:
done:
ax25_insert_socket
(
ax25
);
ax25_insert_socket
(
ax25
);
sk
->
zapped
=
0
;
sk
->
zapped
=
0
;
unlock_kernel
();
return
0
;
return
0
;
}
}
/*
/*
* FIXME: nonblock behaviour looks like it may have a bug.
* FIXME: nonblock behaviour looks like it may have a bug.
*/
*/
static
int
ax25_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
,
int
flags
)
static
int
ax25_connect
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
addr_len
,
int
flags
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
);
ax25_cb
*
ax25
=
ax25_sk
(
sk
);
...
@@ -1128,24 +1192,30 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1128,24 +1192,30 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_digi
*
digi
=
NULL
;
ax25_digi
*
digi
=
NULL
;
int
ct
=
0
,
err
;
int
ct
=
0
,
err
;
lock_kernel
();
/* deal with restarts */
/* deal with restarts */
if
(
sock
->
state
==
SS_CONNECTING
)
{
if
(
sock
->
state
==
SS_CONNECTING
)
{
switch
(
sk
->
state
)
{
switch
(
sk
->
state
)
{
case
TCP_SYN_SENT
:
/* still trying */
case
TCP_SYN_SENT
:
/* still trying */
unlock_kernel
();
return
-
EINPROGRESS
;
return
-
EINPROGRESS
;
case
TCP_ESTABLISHED
:
/* connection established */
case
TCP_ESTABLISHED
:
/* connection established */
unlock_kernel
();
sock
->
state
=
SS_CONNECTED
;
sock
->
state
=
SS_CONNECTED
;
return
0
;
return
0
;
case
TCP_CLOSE
:
/* connection refused */
case
TCP_CLOSE
:
/* connection refused */
unlock_kernel
();
sock
->
state
=
SS_UNCONNECTED
;
sock
->
state
=
SS_UNCONNECTED
;
return
-
ECONNREFUSED
;
return
-
ECONNREFUSED
;
}
}
}
}
if
(
sk
->
state
==
TCP_ESTABLISHED
&&
sk
->
type
==
SOCK_SEQPACKET
)
if
(
sk
->
state
==
TCP_ESTABLISHED
&&
sk
->
type
==
SOCK_SEQPACKET
)
{
unlock_kernel
();
return
-
EISCONN
;
/* No reconnect on a seqpacket socket */
return
-
EISCONN
;
/* No reconnect on a seqpacket socket */
}
sk
->
state
=
TCP_CLOSE
;
sk
->
state
=
TCP_CLOSE
;
sock
->
state
=
SS_UNCONNECTED
;
sock
->
state
=
SS_UNCONNECTED
;
...
@@ -1162,15 +1232,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1162,15 +1232,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
else
if
(
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
else
if
(
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
/* support for old structure may go away some time */
/* support for old structure may go away some time */
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
printk
(
KERN_WARNING
"ax25_connect(): %s uses old (6 digipeater) socket structure.
\n
"
,
printk
(
KERN_WARNING
"ax25_connect(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
current
->
comm
);
}
}
if
(
fsa
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
if
(
fsa
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
ax25
->
digipeat
!=
NULL
)
{
if
(
ax25
->
digipeat
!=
NULL
)
{
kfree
(
ax25
->
digipeat
);
kfree
(
ax25
->
digipeat
);
...
@@ -1182,11 +1256,15 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1182,11 +1256,15 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
*/
*/
if
(
addr_len
>
sizeof
(
struct
sockaddr_ax25
)
&&
fsa
->
fsa_ax25
.
sax25_ndigis
!=
0
)
{
if
(
addr_len
>
sizeof
(
struct
sockaddr_ax25
)
&&
fsa
->
fsa_ax25
.
sax25_ndigis
!=
0
)
{
/* Valid number of digipeaters ? */
/* Valid number of digipeaters ? */
if
(
fsa
->
fsa_ax25
.
sax25_ndigis
<
1
||
fsa
->
fsa_ax25
.
sax25_ndigis
>
AX25_MAX_DIGIS
)
if
(
fsa
->
fsa_ax25
.
sax25_ndigis
<
1
||
fsa
->
fsa_ax25
.
sax25_ndigis
>
AX25_MAX_DIGIS
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
((
digi
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_KERNEL
))
==
NULL
)
if
((
digi
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_KERNEL
))
==
NULL
)
{
unlock_kernel
();
return
-
ENOBUFS
;
return
-
ENOBUFS
;
}
digi
->
ndigi
=
fsa
->
fsa_ax25
.
sax25_ndigis
;
digi
->
ndigi
=
fsa
->
fsa_ax25
.
sax25_ndigis
;
digi
->
lastrepeat
=
-
1
;
digi
->
lastrepeat
=
-
1
;
...
@@ -1218,14 +1296,18 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1218,14 +1296,18 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_fillin_cb
(
ax25
,
ax25
->
ax25_dev
);
ax25_fillin_cb
(
ax25
,
ax25
->
ax25_dev
);
ax25_insert_socket
(
ax25
);
ax25_insert_socket
(
ax25
);
}
else
{
}
else
{
if
(
ax25
->
ax25_dev
==
NULL
)
if
(
ax25
->
ax25_dev
==
NULL
)
{
unlock_kernel
();
return
-
EHOSTUNREACH
;
return
-
EHOSTUNREACH
;
}
}
}
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
ax25_find_cb
(
&
ax25
->
source_addr
,
&
fsa
->
fsa_ax25
.
sax25_call
,
digi
,
ax25_find_cb
(
&
ax25
->
source_addr
,
&
fsa
->
fsa_ax25
.
sax25_call
,
digi
,
ax25
->
ax25_dev
->
dev
))
{
ax25
->
ax25_dev
->
dev
))
{
if
(
digi
!=
NULL
)
kfree
(
digi
);
if
(
digi
!=
NULL
)
kfree
(
digi
);
unlock_kernel
();
return
-
EADDRINUSE
;
/* Already such a connection */
return
-
EADDRINUSE
;
/* Already such a connection */
}
}
...
@@ -1236,6 +1318,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1236,6 +1318,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
{
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
{
sock
->
state
=
SS_CONNECTED
;
sock
->
state
=
SS_CONNECTED
;
sk
->
state
=
TCP_ESTABLISHED
;
sk
->
state
=
TCP_ESTABLISHED
;
unlock_kernel
();
return
0
;
return
0
;
}
}
...
@@ -1252,8 +1335,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1252,8 +1335,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
#ifdef CONFIG_AX25_DAMA_SLAVE
#ifdef CONFIG_AX25_DAMA_SLAVE
case
AX25_PROTO_DAMA_SLAVE
:
case
AX25_PROTO_DAMA_SLAVE
:
ax25
->
modulus
=
AX25_MODULUS
;
ax25
->
modulus
=
AX25_MODULUS
;
ax25
->
window
=
ax25
->
window
=
ax25
->
ax25_dev
->
values
[
AX25_VALUES_WINDOW
];
ax25
->
ax25_dev
->
values
[
AX25_VALUES_WINDOW
];
if
(
ax25
->
ax25_dev
->
dama
.
slave
)
if
(
ax25
->
ax25_dev
->
dama
.
slave
)
ax25_ds_establish_data_link
(
ax25
);
ax25_ds_establish_data_link
(
ax25
);
else
else
...
@@ -1267,30 +1349,38 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
...
@@ -1267,30 +1349,38 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_start_heartbeat
(
ax25
);
ax25_start_heartbeat
(
ax25
);
/* Now the loop */
/* Now the loop */
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
{
unlock_kernel
();
return
-
EINPROGRESS
;
return
-
EINPROGRESS
;
}
cli
();
/* To avoid races on the sleep */
if
(
sk
->
state
==
TCP_SYN_SENT
)
{
struct
task_struct
*
tsk
=
current
;
DECLARE_WAITQUEUE
(
wait
,
tsk
);
/* A DM or timeout will go to closed, a UA will go to ABM */
add_wait_queue
(
sk
->
sleep
,
&
wait
);
while
(
sk
->
state
==
TCP_SYN_SENT
)
{
for
(;;)
{
interruptible_sleep_on
(
sk
->
sleep
);
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
signal_pending
(
current
))
{
if
(
sk
->
state
!=
TCP_SYN_SENT
)
sti
();
break
;
if
(
!
signal_pending
(
tsk
))
{
schedule
();
continue
;
}
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
}
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
sk
->
sleep
,
&
wait
);
}
}
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
/* Not in ABM, not in WAIT_UA -> failed */
/* Not in ABM, not in WAIT_UA -> failed */
sti
();
sock
->
state
=
SS_UNCONNECTED
;
sock
->
state
=
SS_UNCONNECTED
;
return
sock_error
(
sk
);
/* Always set at this point */
return
sock_error
(
sk
);
/* Always set at this point */
}
}
sock
->
state
=
SS_CONNECTED
;
sock
->
state
=
SS_CONNECTED
;
unlock_kernel
();
sti
();
return
0
;
return
0
;
}
}
...
@@ -1302,17 +1392,26 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
...
@@ -1302,17 +1392,26 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
struct
sock
*
newsk
;
struct
sock
*
newsk
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
lock_kernel
();
if
(
sock
->
state
!=
SS_UNCONNECTED
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
((
sk
=
sock
->
sk
)
==
NULL
)
if
((
sk
=
sock
->
sk
)
==
NULL
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
{
unlock_kernel
();
return
-
EOPNOTSUPP
;
return
-
EOPNOTSUPP
;
}
if
(
sk
->
state
!=
TCP_LISTEN
)
if
(
sk
->
state
!=
TCP_LISTEN
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
/*
/*
* The read queue this time is holding sockets ready to use
* The read queue this time is holding sockets ready to use
...
@@ -1320,13 +1419,17 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
...
@@ -1320,13 +1419,17 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
*/
*/
do
{
do
{
if
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
==
NULL
)
{
if
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
==
NULL
)
{
if
(
flags
&
O_NONBLOCK
)
if
(
flags
&
O_NONBLOCK
)
{
unlock_kernel
();
return
-
EWOULDBLOCK
;
return
-
EWOULDBLOCK
;
}
interruptible_sleep_on
(
sk
->
sleep
);
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
if
(
signal_pending
(
current
))
{
unlock_kernel
();
return
-
ERESTARTSYS
;
return
-
ERESTARTSYS
;
}
}
}
}
while
(
skb
==
NULL
);
}
while
(
skb
==
NULL
);
newsk
=
skb
->
sk
;
newsk
=
skb
->
sk
;
...
@@ -1339,20 +1442,28 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
...
@@ -1339,20 +1442,28 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
sk
->
ack_backlog
--
;
sk
->
ack_backlog
--
;
newsock
->
sk
=
newsk
;
newsock
->
sk
=
newsk
;
newsock
->
state
=
SS_CONNECTED
;
newsock
->
state
=
SS_CONNECTED
;
unlock_kernel
();
return
0
;
return
0
;
}
}
static
int
ax25_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
uaddr_len
,
int
peer
)
static
int
ax25_getname
(
struct
socket
*
sock
,
struct
sockaddr
*
uaddr
,
int
*
uaddr_len
,
int
peer
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
full_sockaddr_ax25
*
fsa
=
(
struct
full_sockaddr_ax25
*
)
uaddr
;
struct
full_sockaddr_ax25
*
fsa
=
(
struct
full_sockaddr_ax25
*
)
uaddr
;
unsigned
char
ndigi
,
i
;
unsigned
char
ndigi
,
i
;
lock_kernel
();
sk
=
sock
->
sk
;
ax25
=
ax25_sk
(
sk
);
if
(
peer
!=
0
)
{
if
(
peer
!=
0
)
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
unlock_kernel
();
return
-
ENOTCONN
;
return
-
ENOTCONN
;
}
fsa
->
fsa_ax25
.
sax25_family
=
AF_AX25
;
fsa
->
fsa_ax25
.
sax25_family
=
AF_AX25
;
fsa
->
fsa_ax25
.
sax25_call
=
ax25
->
dest_addr
;
fsa
->
fsa_ax25
.
sax25_call
=
ax25
->
dest_addr
;
...
@@ -1377,13 +1488,16 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
...
@@ -1377,13 +1488,16 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
}
}
}
}
*
uaddr_len
=
sizeof
(
struct
full_sockaddr_ax25
);
*
uaddr_len
=
sizeof
(
struct
full_sockaddr_ax25
);
unlock_kernel
();
return
0
;
return
0
;
}
}
static
int
ax25_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
len
,
struct
scm_cookie
*
scm
)
static
int
ax25_sendmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
len
,
struct
scm_cookie
*
scm
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
sockaddr_ax25
*
usax
=
(
struct
sockaddr_ax25
*
)
msg
->
msg_name
;
struct
sockaddr_ax25
*
usax
=
(
struct
sockaddr_ax25
*
)
msg
->
msg_name
;
int
err
;
int
err
;
struct
sockaddr_ax25
sax
;
struct
sockaddr_ax25
sax
;
...
@@ -1395,23 +1509,34 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1395,23 +1509,34 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
int
lv
;
int
lv
;
int
addr_len
=
msg
->
msg_namelen
;
int
addr_len
=
msg
->
msg_namelen
;
if
(
msg
->
msg_flags
&
~
(
MSG_DONTWAIT
|
MSG_EOR
))
if
(
msg
->
msg_flags
&
~
(
MSG_DONTWAIT
|
MSG_EOR
))
{
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
sk
->
zapped
)
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
if
(
sk
->
zapped
)
{
unlock_kernel
();
return
-
EADDRNOTAVAIL
;
return
-
EADDRNOTAVAIL
;
}
if
(
sk
->
shutdown
&
SEND_SHUTDOWN
)
{
if
(
sk
->
shutdown
&
SEND_SHUTDOWN
)
{
unlock_kernel
();
send_sig
(
SIGPIPE
,
current
,
0
);
send_sig
(
SIGPIPE
,
current
,
0
);
return
-
EPIPE
;
return
-
EPIPE
;
}
}
if
(
ax25
->
ax25_dev
==
NULL
)
if
(
ax25
->
ax25_dev
==
NULL
)
{
unlock_kernel
();
return
-
ENETUNREACH
;
return
-
ENETUNREACH
;
}
if
(
usax
!=
NULL
)
{
if
(
usax
!=
NULL
)
{
if
(
usax
->
sax25_family
!=
AF_AX25
)
if
(
usax
->
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
if
(
addr_len
==
sizeof
(
struct
sockaddr_ax25
))
{
if
(
addr_len
==
sizeof
(
struct
sockaddr_ax25
))
{
printk
(
KERN_WARNING
"ax25_sendmsg(): %s uses obsolete socket structure
\n
"
,
printk
(
KERN_WARNING
"ax25_sendmsg(): %s uses obsolete socket structure
\n
"
,
...
@@ -1420,8 +1545,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1420,8 +1545,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
else
if
(
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
else
if
(
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
/* support for old structure may go away some time */
/* support for old structure may go away some time */
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
if
((
addr_len
<
sizeof
(
struct
sockaddr_ax25
)
+
sizeof
(
ax25_address
)
*
6
)
||
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
(
addr_len
>
sizeof
(
struct
full_sockaddr_ax25
)))
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
printk
(
KERN_WARNING
"ax25_sendmsg(): %s uses old (6 digipeater) socket structure.
\n
"
,
printk
(
KERN_WARNING
"ax25_sendmsg(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
current
->
comm
);
...
@@ -1432,8 +1559,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1432,8 +1559,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
struct
full_sockaddr_ax25
*
fsa
=
(
struct
full_sockaddr_ax25
*
)
usax
;
struct
full_sockaddr_ax25
*
fsa
=
(
struct
full_sockaddr_ax25
*
)
usax
;
/* Valid number of digipeaters ? */
/* Valid number of digipeaters ? */
if
(
usax
->
sax25_ndigis
<
1
||
usax
->
sax25_ndigis
>
AX25_MAX_DIGIS
)
if
(
usax
->
sax25_ndigis
<
1
||
usax
->
sax25_ndigis
>
AX25_MAX_DIGIS
)
{
unlock_kernel
();
return
-
EINVAL
;
return
-
EINVAL
;
}
dtmp
.
ndigi
=
usax
->
sax25_ndigis
;
dtmp
.
ndigi
=
usax
->
sax25_ndigis
;
...
@@ -1447,8 +1576,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1447,8 +1576,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
}
}
sax
=
*
usax
;
sax
=
*
usax
;
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
ax25cmp
(
&
ax25
->
dest_addr
,
&
sax
.
sax25_call
)
!=
0
)
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
ax25cmp
(
&
ax25
->
dest_addr
,
&
sax
.
sax25_call
)
!=
0
)
{
unlock_kernel
();
return
-
EISCONN
;
return
-
EISCONN
;
}
if
(
usax
->
sax25_ndigis
==
0
)
if
(
usax
->
sax25_ndigis
==
0
)
dp
=
NULL
;
dp
=
NULL
;
else
else
...
@@ -1474,8 +1605,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1474,8 +1605,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* Assume the worst case */
/* Assume the worst case */
size
=
len
+
3
+
ax25_addr_size
(
dp
)
+
AX25_BPQ_HEADER_LEN
;
size
=
len
+
3
+
ax25_addr_size
(
dp
)
+
AX25_BPQ_HEADER_LEN
;
if
((
skb
=
sock_alloc_send_skb
(
sk
,
size
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
))
==
NULL
)
if
((
skb
=
sock_alloc_send_skb
(
sk
,
size
,
msg
->
msg_flags
&
MSG_DONTWAIT
,
&
err
))
==
NULL
)
{
unlock_kernel
();
return
err
;
return
err
;
}
skb_reserve
(
skb
,
size
-
len
);
skb_reserve
(
skb
,
size
-
len
);
...
@@ -1497,11 +1630,13 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1497,11 +1630,13 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* Connected mode sockets go via the LAPB machine */
/* Connected mode sockets go via the LAPB machine */
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
unlock_kernel
();
return
-
ENOTCONN
;
return
-
ENOTCONN
;
}
}
/* Shove it onto the queue and kick */
/* Shove it onto the queue and kick */
ax25_output
(
ax25
,
ax25
->
paclen
,
skb
);
ax25_output
(
ax25
,
ax25
->
paclen
,
skb
);
unlock_kernel
();
return
len
;
return
len
;
}
else
{
}
else
{
...
@@ -1529,28 +1664,37 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
...
@@ -1529,28 +1664,37 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
skb
->
dev
=
ax25
->
ax25_dev
->
dev
;
skb
->
dev
=
ax25
->
ax25_dev
->
dev
;
ax25_queue_xmit
(
skb
);
ax25_queue_xmit
(
skb
);
unlock_kernel
();
return
len
;
return
len
;
}
}
}
}
static
int
ax25_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
,
struct
scm_cookie
*
scm
)
static
int
ax25_recvmsg
(
struct
socket
*
sock
,
struct
msghdr
*
msg
,
int
size
,
int
flags
,
struct
scm_cookie
*
scm
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
;
int
copied
;
int
copied
;
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
int
er
;
int
er
;
lock_kernel
();
sk
=
sock
->
sk
;
/*
/*
* This works for seqpacket too. The receiver has ordered the
* This works for seqpacket too. The receiver has ordered the
* queue for us! We do one quick check first though
* queue for us! We do one quick check first though
*/
*/
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
!=
TCP_ESTABLISHED
)
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
!=
TCP_ESTABLISHED
)
{
unlock_kernel
();
return
-
ENOTCONN
;
return
-
ENOTCONN
;
}
/* Now we can treat all alike */
/* Now we can treat all alike */
if
((
skb
=
skb_recv_datagram
(
sk
,
flags
&
~
MSG_DONTWAIT
,
flags
&
MSG_DONTWAIT
,
&
er
))
==
NULL
)
if
((
skb
=
skb_recv_datagram
(
sk
,
flags
&
~
MSG_DONTWAIT
,
flags
&
MSG_DONTWAIT
,
&
er
))
==
NULL
)
{
unlock_kernel
();
return
er
;
return
er
;
}
if
(
!
ax25_sk
(
sk
)
->
pidincl
)
if
(
!
ax25_sk
(
sk
)
->
pidincl
)
skb_pull
(
skb
,
1
);
/* Remove PID */
skb_pull
(
skb
,
1
);
/* Remove PID */
...
@@ -1590,6 +1734,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
...
@@ -1590,6 +1734,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
}
}
skb_free_datagram
(
sk
,
skb
);
skb_free_datagram
(
sk
,
skb
);
unlock_kernel
();
return
copied
;
return
copied
;
}
}
...
@@ -1603,14 +1748,17 @@ static int ax25_shutdown(struct socket *sk, int how)
...
@@ -1603,14 +1748,17 @@ static int ax25_shutdown(struct socket *sk, int how)
static
int
ax25_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
static
int
ax25_ioctl
(
struct
socket
*
sock
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
{
struct
sock
*
sk
=
sock
->
sk
;
struct
sock
*
sk
=
sock
->
sk
;
int
res
=
0
;
lock_kernel
();
switch
(
cmd
)
{
switch
(
cmd
)
{
case
TIOCOUTQ
:
{
case
TIOCOUTQ
:
{
long
amount
;
long
amount
;
amount
=
sk
->
sndbuf
-
atomic_read
(
&
sk
->
wmem_alloc
);
amount
=
sk
->
sndbuf
-
atomic_read
(
&
sk
->
wmem_alloc
);
if
(
amount
<
0
)
if
(
amount
<
0
)
amount
=
0
;
amount
=
0
;
return
put_user
(
amount
,
(
int
*
)
arg
);
res
=
put_user
(
amount
,
(
int
*
)
arg
);
break
;
}
}
case
TIOCINQ
:
{
case
TIOCINQ
:
{
...
@@ -1619,49 +1767,70 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
...
@@ -1619,49 +1767,70 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* 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
)
if
((
skb
=
skb_peek
(
&
sk
->
receive_queue
))
!=
NULL
)
amount
=
skb
->
len
;
amount
=
skb
->
len
;
return
put_user
(
amount
,
(
int
*
)
arg
);
res
=
put_user
(
amount
,
(
int
*
)
arg
);
break
;
}
}
case
SIOCGSTAMP
:
case
SIOCGSTAMP
:
if
(
sk
!=
NULL
)
{
if
(
sk
!=
NULL
)
{
if
(
sk
->
stamp
.
tv_sec
==
0
)
if
(
sk
->
stamp
.
tv_sec
==
0
)
{
return
-
ENOENT
;
res
=
-
ENOENT
;
return
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
break
;
}
}
return
-
EINVAL
;
res
=
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
break
;
}
res
=
-
EINVAL
;
break
;
case
SIOCAX25ADDUID
:
/* Add a uid to the uid/call map table */
case
SIOCAX25ADDUID
:
/* Add a uid to the uid/call map table */
case
SIOCAX25DELUID
:
/* Delete a uid from the uid/call map table */
case
SIOCAX25DELUID
:
/* Delete a uid from the uid/call map table */
case
SIOCAX25GETUID
:
{
case
SIOCAX25GETUID
:
{
struct
sockaddr_ax25
sax25
;
struct
sockaddr_ax25
sax25
;
if
(
copy_from_user
(
&
sax25
,
(
void
*
)
arg
,
sizeof
(
sax25
)))
if
(
copy_from_user
(
&
sax25
,
(
void
*
)
arg
,
sizeof
(
sax25
)))
{
return
-
EFAULT
;
res
=
-
EFAULT
;
return
ax25_uid_ioctl
(
cmd
,
&
sax25
);
break
;
}
res
=
ax25_uid_ioctl
(
cmd
,
&
sax25
);
break
;
}
}
case
SIOCAX25NOUID
:
{
/* Set the default policy (default/bar) */
case
SIOCAX25NOUID
:
{
/* Set the default policy (default/bar) */
long
amount
;
long
amount
;
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
{
return
-
EPERM
;
res
=
-
EPERM
;
if
(
get_user
(
amount
,
(
long
*
)
arg
))
break
;
return
-
EFAULT
;
}
if
(
amount
>
AX25_NOUID_BLOCK
)
if
(
get_user
(
amount
,
(
long
*
)
arg
))
{
return
-
EINVAL
;
res
=
-
EFAULT
;
break
;
}
if
(
amount
>
AX25_NOUID_BLOCK
)
{
res
=
-
EINVAL
;
break
;
}
ax25_uid_policy
=
amount
;
ax25_uid_policy
=
amount
;
return
0
;
res
=
0
;
break
;
}
}
case
SIOCADDRT
:
case
SIOCADDRT
:
case
SIOCDELRT
:
case
SIOCDELRT
:
case
SIOCAX25OPTRT
:
case
SIOCAX25OPTRT
:
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
{
return
-
EPERM
;
res
=
-
EPERM
;
return
ax25_rt_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
}
res
=
ax25_rt_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCAX25CTLCON
:
case
SIOCAX25CTLCON
:
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
{
return
-
EPERM
;
res
=
-
EPERM
;
return
ax25_ctl_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
}
res
=
ax25_ctl_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCAX25GETINFO
:
case
SIOCAX25GETINFO
:
case
SIOCAX25GETINFOOLD
:
{
case
SIOCAX25GETINFOOLD
:
{
...
@@ -1697,23 +1866,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
...
@@ -1697,23 +1866,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
warned
=
1
;
warned
=
1
;
}
}
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct_depreciated
)))
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct_depreciated
)))
{
return
-
EFAULT
;
res
=
-
EFAULT
;
break
;
}
}
else
{
}
else
{
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct
)))
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct
)))
{
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
}
}
return
0
;
}
res
=
0
;
break
;
}
}
case
SIOCAX25ADDFWD
:
case
SIOCAX25ADDFWD
:
case
SIOCAX25DELFWD
:
{
case
SIOCAX25DELFWD
:
{
struct
ax25_fwd_struct
ax25_fwd
;
struct
ax25_fwd_struct
ax25_fwd
;
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
{
return
-
EPERM
;
res
=
-
EPERM
;
if
(
copy_from_user
(
&
ax25_fwd
,
(
void
*
)
arg
,
sizeof
(
ax25_fwd
)))
break
;
return
-
EFAULT
;
}
return
ax25_fwd_ioctl
(
cmd
,
&
ax25_fwd
);
if
(
copy_from_user
(
&
ax25_fwd
,
(
void
*
)
arg
,
sizeof
(
ax25_fwd
)))
{
res
=
-
EFAULT
;
break
;
}
res
=
ax25_fwd_ioctl
(
cmd
,
&
ax25_fwd
);
break
;
}
}
case
SIOCGIFADDR
:
case
SIOCGIFADDR
:
...
@@ -1726,25 +1905,28 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
...
@@ -1726,25 +1905,28 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case
SIOCSIFNETMASK
:
case
SIOCSIFNETMASK
:
case
SIOCGIFMETRIC
:
case
SIOCGIFMETRIC
:
case
SIOCSIFMETRIC
:
case
SIOCSIFMETRIC
:
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
default:
default:
return
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
res
=
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
}
}
/*NOTREACHED*/
unlock_kernel
();
return
0
;
return
res
;
}
}
static
int
ax25_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
static
int
ax25_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
{
unsigned
long
flags
;
ax25_cb
*
ax25
;
ax25_cb
*
ax25
;
int
k
;
int
k
;
int
len
=
0
;
int
len
=
0
;
off_t
pos
=
0
;
off_t
pos
=
0
;
off_t
begin
=
0
;
off_t
begin
=
0
;
cli
(
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
/*
/*
* New format:
* New format:
...
@@ -1799,7 +1981,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -1799,7 +1981,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
break
;
break
;
}
}
s
ti
(
);
s
pin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
*
start
=
buffer
+
(
offset
-
begin
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
...
@@ -1814,7 +1996,6 @@ static struct net_proto_family ax25_family_ops = {
...
@@ -1814,7 +1996,6 @@ static struct net_proto_family ax25_family_ops = {
.
create
=
ax25_create
,
.
create
=
ax25_create
,
};
};
static
struct
proto_ops
SOCKOPS_WRAPPED
(
ax25_proto_ops
)
=
{
.
family
=
PF_AX25
,
.
family
=
PF_AX25
,
.
release
=
ax25_release
,
.
release
=
ax25_release
,
...
@@ -1835,15 +2016,14 @@ static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = {
...
@@ -1835,15 +2016,14 @@ static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = {
.
sendpage
=
sock_no_sendpage
,
.
sendpage
=
sock_no_sendpage
,
}
;
}
;
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
ax25_proto
,
PF_AX25
);
/*
/*
* Called by socket.c on kernel start up
* Called by socket.c on kernel start up
*/
*/
static
struct
packet_type
ax25_packet_type
=
{
static
struct
packet_type
ax25_packet_type
=
{
.
type
=
__constant_htons
(
ETH_P_AX25
),
.
type
=
__constant_htons
(
ETH_P_AX25
),
.
dev
=
NULL
,
/* All devices */
.
func
=
ax25_kiss_rcv
,
.
func
=
ax25_kiss_rcv
,
.
data
=
(
void
*
)
1
};
};
static
struct
notifier_block
ax25_dev_notifier
=
{
static
struct
notifier_block
ax25_dev_notifier
=
{
...
...
net/ax25/ax25_dev.c
View file @
0dfe6e55
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
#include <linux/string.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
...
@@ -41,27 +42,37 @@
...
@@ -41,27 +42,37 @@
#include <linux/init.h>
#include <linux/init.h>
ax25_dev
*
ax25_dev_list
;
ax25_dev
*
ax25_dev_list
;
spinlock_t
ax25_dev_lock
=
SPIN_LOCK_UNLOCKED
;
ax25_dev
*
ax25_dev_ax25dev
(
struct
net_device
*
dev
)
ax25_dev
*
ax25_dev_ax25dev
(
struct
net_device
*
dev
)
{
{
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
,
*
res
=
NULL
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
for
(
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
for
(
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
if
(
ax25_dev
->
dev
==
dev
)
if
(
ax25_dev
->
dev
==
dev
)
{
return
ax25_dev
;
res
=
ax25_dev
;
break
;
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
return
NULL
;
return
res
;
}
}
ax25_dev
*
ax25_addr_ax25dev
(
ax25_address
*
addr
)
ax25_dev
*
ax25_addr_ax25dev
(
ax25_address
*
addr
)
{
{
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
,
*
res
=
NULL
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
for
(
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
for
(
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
if
(
ax25cmp
(
addr
,
(
ax25_address
*
)
ax25_dev
->
dev
->
dev_addr
)
==
0
)
if
(
ax25cmp
(
addr
,
(
ax25_address
*
)
ax25_dev
->
dev
->
dev_addr
)
==
0
)
{
return
ax25_dev
;
res
=
ax25_dev
;
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
return
NULL
;
return
res
;
}
}
/*
/*
...
@@ -100,10 +111,10 @@ void ax25_dev_device_up(struct net_device *dev)
...
@@ -100,10 +111,10 @@ void ax25_dev_device_up(struct net_device *dev)
ax25_dev
->
values
[
AX25_VALUES_PROTOCOL
]
=
AX25_DEF_PROTOCOL
;
ax25_dev
->
values
[
AX25_VALUES_PROTOCOL
]
=
AX25_DEF_PROTOCOL
;
ax25_dev
->
values
[
AX25_VALUES_DS_TIMEOUT
]
=
AX25_DEF_DS_TIMEOUT
;
ax25_dev
->
values
[
AX25_VALUES_DS_TIMEOUT
]
=
AX25_DEF_DS_TIMEOUT
;
s
ave_flags
(
flags
);
cli
(
);
s
pin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
ax25_dev
->
next
=
ax25_dev_list
;
ax25_dev
->
next
=
ax25_dev_list
;
ax25_dev_list
=
ax25_dev
;
ax25_dev_list
=
ax25_dev
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
ax25_register_sysctl
();
ax25_register_sysctl
();
}
}
...
@@ -118,7 +129,7 @@ void ax25_dev_device_down(struct net_device *dev)
...
@@ -118,7 +129,7 @@ void ax25_dev_device_down(struct net_device *dev)
ax25_unregister_sysctl
();
ax25_unregister_sysctl
();
s
ave_flags
(
flags
);
cli
(
);
s
pin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
#ifdef CONFIG_AX25_DAMA_SLAVE
#ifdef CONFIG_AX25_DAMA_SLAVE
ax25_ds_del_timer
(
ax25_dev
);
ax25_ds_del_timer
(
ax25_dev
);
...
@@ -133,7 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
...
@@ -133,7 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
if
((
s
=
ax25_dev_list
)
==
ax25_dev
)
{
if
((
s
=
ax25_dev_list
)
==
ax25_dev
)
{
ax25_dev_list
=
s
->
next
;
ax25_dev_list
=
s
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
kfree
(
ax25_dev
);
kfree
(
ax25_dev
);
ax25_register_sysctl
();
ax25_register_sysctl
();
return
;
return
;
...
@@ -142,7 +153,7 @@ void ax25_dev_device_down(struct net_device *dev)
...
@@ -142,7 +153,7 @@ void ax25_dev_device_down(struct net_device *dev)
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25_dev
)
{
if
(
s
->
next
==
ax25_dev
)
{
s
->
next
=
ax25_dev
->
next
;
s
->
next
=
ax25_dev
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
kfree
(
ax25_dev
);
kfree
(
ax25_dev
);
ax25_register_sysctl
();
ax25_register_sysctl
();
return
;
return
;
...
@@ -150,8 +161,8 @@ void ax25_dev_device_down(struct net_device *dev)
...
@@ -150,8 +161,8 @@ void ax25_dev_device_down(struct net_device *dev)
s
=
s
->
next
;
s
=
s
->
next
;
}
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
restore_flags
(
flags
);
ax25_register_sysctl
();
ax25_register_sysctl
();
}
}
...
@@ -202,12 +213,17 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
...
@@ -202,12 +213,17 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
*/
*/
void
__exit
ax25_dev_free
(
void
)
void
__exit
ax25_dev_free
(
void
)
{
{
ax25_dev
*
s
,
*
ax25_dev
=
ax25_dev_list
;
ax25_dev
*
s
,
*
ax25_dev
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
ax25_dev
=
ax25_dev_list
;
while
(
ax25_dev
!=
NULL
)
{
while
(
ax25_dev
!=
NULL
)
{
s
=
ax25_dev
;
s
=
ax25_dev
;
ax25_dev
=
ax25_dev
->
next
;
ax25_dev
=
ax25_dev
->
next
;
kfree
(
s
);
kfree
(
s
);
}
}
ax25_dev_list
=
NULL
;
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
}
}
net/ax25/ax25_ds_in.c
View file @
0dfe6e55
...
@@ -95,11 +95,13 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
...
@@ -95,11 +95,13 @@ static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int framet
break
;
break
;
case
AX25_DM
:
case
AX25_DM
:
if
(
pf
)
ax25_disconnect
(
ax25
,
ECONNREFUSED
);
if
(
pf
)
ax25_disconnect
(
ax25
,
ECONNREFUSED
);
break
;
break
;
default:
default:
if
(
pf
)
ax25_send_control
(
ax25
,
AX25_SABM
,
AX25_POLLON
,
AX25_COMMAND
);
if
(
pf
)
ax25_send_control
(
ax25
,
AX25_SABM
,
AX25_POLLON
,
AX25_COMMAND
);
break
;
break
;
}
}
...
...
net/ax25/ax25_ds_subr.c
View file @
0dfe6e55
...
@@ -31,6 +31,7 @@
...
@@ -31,6 +31,7 @@
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/inet.h>
...
@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
...
@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
*/
*/
void
ax25_ds_enquiry_response
(
ax25_cb
*
ax25
)
void
ax25_ds_enquiry_response
(
ax25_cb
*
ax25
)
{
{
unsigned
long
flags
;
ax25_cb
*
ax25o
;
ax25_cb
*
ax25o
;
/* Please note that neither DK4EGs nor DG2FEFs
/* Please note that neither DK4EGs nor DG2FEFs
...
@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
...
@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_start_t3timer
(
ax25
);
ax25_start_t3timer
(
ax25
);
ax25_ds_set_timer
(
ax25
->
ax25_dev
);
ax25_ds_set_timer
(
ax25
->
ax25_dev
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
ax25o
=
ax25_list
;
ax25o
!=
NULL
;
ax25o
=
ax25o
->
next
)
{
for
(
ax25o
=
ax25_list
;
ax25o
!=
NULL
;
ax25o
=
ax25o
->
next
)
{
if
(
ax25o
==
ax25
)
if
(
ax25o
==
ax25
)
continue
;
continue
;
...
@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
...
@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
if
(
ax25o
->
state
!=
AX25_STATE_0
)
if
(
ax25o
->
state
!=
AX25_STATE_0
)
ax25_start_t3timer
(
ax25o
);
ax25_start_t3timer
(
ax25o
);
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
}
void
ax25_ds_establish_data_link
(
ax25_cb
*
ax25
)
void
ax25_ds_establish_data_link
(
ax25_cb
*
ax25
)
...
@@ -170,13 +174,19 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
...
@@ -170,13 +174,19 @@ static void ax25_kiss_cmd(ax25_dev *ax25_dev, unsigned char cmd, unsigned char p
*/
*/
static
int
ax25_check_dama_slave
(
ax25_dev
*
ax25_dev
)
static
int
ax25_check_dama_slave
(
ax25_dev
*
ax25_dev
)
{
{
unsigned
long
flags
;
ax25_cb
*
ax25
;
ax25_cb
*
ax25
;
int
res
=
0
;
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
ax25
=
ax25_list
;
ax25
!=
NULL
;
ax25
=
ax25
->
next
)
for
(
ax25
=
ax25_list
;
ax25
!=
NULL
;
ax25
=
ax25
->
next
)
if
(
ax25
->
ax25_dev
==
ax25_dev
&&
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
)
&&
ax25
->
state
>
AX25_STATE_1
)
if
(
ax25
->
ax25_dev
==
ax25_dev
&&
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
)
&&
ax25
->
state
>
AX25_STATE_1
)
{
return
1
;
res
=
1
;
break
;
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
0
;
return
res
;
}
}
void
ax25_dev_dama_on
(
ax25_dev
*
ax25_dev
)
void
ax25_dev_dama_on
(
ax25_dev
*
ax25_dev
)
...
...
net/ax25/ax25_ds_timer.c
View file @
0dfe6e55
...
@@ -18,6 +18,7 @@
...
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/jiffies.h>
...
@@ -58,7 +59,8 @@ static void ax25_ds_add_timer(ax25_dev *ax25_dev)
...
@@ -58,7 +59,8 @@ static void ax25_ds_add_timer(ax25_dev *ax25_dev)
void
ax25_ds_del_timer
(
ax25_dev
*
ax25_dev
)
void
ax25_ds_del_timer
(
ax25_dev
*
ax25_dev
)
{
{
if
(
ax25_dev
)
del_timer
(
&
ax25_dev
->
dama
.
slave_timer
);
if
(
ax25_dev
)
del_timer
(
&
ax25_dev
->
dama
.
slave_timer
);
}
}
void
ax25_ds_set_timer
(
ax25_dev
*
ax25_dev
)
void
ax25_ds_set_timer
(
ax25_dev
*
ax25_dev
)
...
@@ -79,6 +81,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
...
@@ -79,6 +81,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
static
void
ax25_ds_timeout
(
unsigned
long
arg
)
static
void
ax25_ds_timeout
(
unsigned
long
arg
)
{
{
ax25_dev
*
ax25_dev
=
(
struct
ax25_dev
*
)
arg
;
ax25_dev
*
ax25_dev
=
(
struct
ax25_dev
*
)
arg
;
unsigned
long
flags
;
ax25_cb
*
ax25
;
ax25_cb
*
ax25
;
if
(
ax25_dev
==
NULL
||
!
ax25_dev
->
dama
.
slave
)
if
(
ax25_dev
==
NULL
||
!
ax25_dev
->
dama
.
slave
)
...
@@ -89,6 +92,7 @@ static void ax25_ds_timeout(unsigned long arg)
...
@@ -89,6 +92,7 @@ static void ax25_ds_timeout(unsigned long arg)
return
;
return
;
}
}
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
ax25
=
ax25_list
;
ax25
!=
NULL
;
ax25
=
ax25
->
next
)
{
for
(
ax25
=
ax25_list
;
ax25
!=
NULL
;
ax25
=
ax25
->
next
)
{
if
(
ax25
->
ax25_dev
!=
ax25_dev
||
!
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
))
if
(
ax25
->
ax25_dev
!=
ax25_dev
||
!
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
))
continue
;
continue
;
...
@@ -96,6 +100,7 @@ static void ax25_ds_timeout(unsigned long arg)
...
@@ -96,6 +100,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control
(
ax25
,
AX25_DISC
,
AX25_POLLON
,
AX25_COMMAND
);
ax25_send_control
(
ax25
,
AX25_DISC
,
AX25_POLLON
,
AX25_COMMAND
);
ax25_disconnect
(
ax25
,
ETIMEDOUT
);
ax25_disconnect
(
ax25
,
ETIMEDOUT
);
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
ax25_dev_dama_off
(
ax25_dev
);
ax25_dev_dama_off
(
ax25_dev
);
}
}
...
@@ -178,7 +183,6 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
...
@@ -178,7 +183,6 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
void
ax25_ds_t1_timeout
(
ax25_cb
*
ax25
)
void
ax25_ds_t1_timeout
(
ax25_cb
*
ax25
)
{
{
switch
(
ax25
->
state
)
{
switch
(
ax25
->
state
)
{
case
AX25_STATE_1
:
case
AX25_STATE_1
:
if
(
ax25
->
n2count
==
ax25
->
n2
)
{
if
(
ax25
->
n2count
==
ax25
->
n2
)
{
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
...
...
net/ax25/ax25_iface.c
View file @
0dfe6e55
...
@@ -20,6 +20,7 @@
...
@@ -20,6 +20,7 @@
#include <linux/in.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
...
@@ -40,22 +41,25 @@ static struct protocol_struct {
...
@@ -40,22 +41,25 @@ static struct protocol_struct {
unsigned
int
pid
;
unsigned
int
pid
;
int
(
*
func
)(
struct
sk_buff
*
,
ax25_cb
*
);
int
(
*
func
)(
struct
sk_buff
*
,
ax25_cb
*
);
}
*
protocol_list
;
}
*
protocol_list
;
static
rwlock_t
protocol_list_lock
=
RW_LOCK_UNLOCKED
;
static
struct
linkfail_struct
{
static
struct
linkfail_struct
{
struct
linkfail_struct
*
next
;
struct
linkfail_struct
*
next
;
void
(
*
func
)(
ax25_cb
*
,
int
);
void
(
*
func
)(
ax25_cb
*
,
int
);
}
*
linkfail_list
;
}
*
linkfail_list
;
static
spinlock_t
linkfail_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
listen_struct
{
static
struct
listen_struct
{
struct
listen_struct
*
next
;
struct
listen_struct
*
next
;
ax25_address
callsign
;
ax25_address
callsign
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
}
*
listen_list
;
}
*
listen_list
;
static
spinlock_t
listen_lock
=
SPIN_LOCK_UNLOCKED
;
int
ax25_protocol_register
(
unsigned
int
pid
,
int
(
*
func
)(
struct
sk_buff
*
,
ax25_cb
*
))
int
ax25_protocol_register
(
unsigned
int
pid
,
int
(
*
func
)(
struct
sk_buff
*
,
ax25_cb
*
))
{
{
struct
protocol_struct
*
protocol
;
struct
protocol_struct
*
protocol
;
unsigned
long
flags
;
if
(
pid
==
AX25_P_TEXT
||
pid
==
AX25_P_SEGMENT
)
if
(
pid
==
AX25_P_TEXT
||
pid
==
AX25_P_SEGMENT
)
return
0
;
return
0
;
...
@@ -69,31 +73,28 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
...
@@ -69,31 +73,28 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol
->
pid
=
pid
;
protocol
->
pid
=
pid
;
protocol
->
func
=
func
;
protocol
->
func
=
func
;
save_flags
(
flags
);
write_lock
(
&
protocol_list_lock
);
cli
();
protocol
->
next
=
protocol_list
;
protocol
->
next
=
protocol_list
;
protocol_list
=
protocol
;
protocol_list
=
protocol
;
write_unlock
(
&
protocol_list_lock
);
restore_flags
(
flags
);
return
1
;
return
1
;
}
}
void
ax25_protocol_release
(
unsigned
int
pid
)
void
ax25_protocol_release
(
unsigned
int
pid
)
{
{
struct
protocol_struct
*
s
,
*
protocol
=
protocol_list
;
struct
protocol_struct
*
s
,
*
protocol
;
unsigned
long
flags
;
if
(
protocol
==
NULL
)
write_lock
(
&
protocol_list_lock
);
protocol
=
protocol_list
;
if
(
protocol
==
NULL
)
{
write_unlock
(
&
protocol_list_lock
);
return
;
return
;
}
save_flags
(
flags
);
cli
();
if
(
protocol
->
pid
==
pid
)
{
if
(
protocol
->
pid
==
pid
)
{
protocol_list
=
protocol
->
next
;
protocol_list
=
protocol
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
kfree
(
protocol
);
kfree
(
protocol
);
return
;
return
;
}
}
...
@@ -102,15 +103,14 @@ void ax25_protocol_release(unsigned int pid)
...
@@ -102,15 +103,14 @@ void ax25_protocol_release(unsigned int pid)
if
(
protocol
->
next
->
pid
==
pid
)
{
if
(
protocol
->
next
->
pid
==
pid
)
{
s
=
protocol
->
next
;
s
=
protocol
->
next
;
protocol
->
next
=
protocol
->
next
->
next
;
protocol
->
next
=
protocol
->
next
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
kfree
(
s
);
kfree
(
s
);
return
;
return
;
}
}
protocol
=
protocol
->
next
;
protocol
=
protocol
->
next
;
}
}
write_unlock
(
&
protocol_list_lock
);
restore_flags
(
flags
);
}
}
int
ax25_linkfail_register
(
void
(
*
func
)(
ax25_cb
*
,
int
))
int
ax25_linkfail_register
(
void
(
*
func
)(
ax25_cb
*
,
int
))
...
@@ -123,31 +123,27 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
...
@@ -123,31 +123,27 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int))
linkfail
->
func
=
func
;
linkfail
->
func
=
func
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
cli
();
linkfail
->
next
=
linkfail_list
;
linkfail
->
next
=
linkfail_list
;
linkfail_list
=
linkfail
;
linkfail_list
=
linkfail
;
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
restore_flags
(
flags
);
return
1
;
return
1
;
}
}
void
ax25_linkfail_release
(
void
(
*
func
)(
ax25_cb
*
,
int
))
void
ax25_linkfail_release
(
void
(
*
func
)(
ax25_cb
*
,
int
))
{
{
struct
linkfail_struct
*
s
,
*
linkfail
=
linkfail_list
;
struct
linkfail_struct
*
s
,
*
linkfail
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
linkfail
=
linkfail_list
;
if
(
linkfail
==
NULL
)
if
(
linkfail
==
NULL
)
return
;
return
;
save_flags
(
flags
);
cli
();
if
(
linkfail
->
func
==
func
)
{
if
(
linkfail
->
func
==
func
)
{
linkfail_list
=
linkfail
->
next
;
linkfail_list
=
linkfail
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
kfree
(
linkfail
);
kfree
(
linkfail
);
return
;
return
;
}
}
...
@@ -156,15 +152,14 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
...
@@ -156,15 +152,14 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
if
(
linkfail
->
next
->
func
==
func
)
{
if
(
linkfail
->
next
->
func
==
func
)
{
s
=
linkfail
->
next
;
s
=
linkfail
->
next
;
linkfail
->
next
=
linkfail
->
next
->
next
;
linkfail
->
next
=
linkfail
->
next
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
kfree
(
s
);
kfree
(
s
);
return
;
return
;
}
}
linkfail
=
linkfail
->
next
;
linkfail
=
linkfail
->
next
;
}
}
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
restore_flags
(
flags
);
}
}
int
ax25_listen_register
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
int
ax25_listen_register
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
...
@@ -181,31 +176,27 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
...
@@ -181,31 +176,27 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
listen
->
callsign
=
*
callsign
;
listen
->
callsign
=
*
callsign
;
listen
->
dev
=
dev
;
listen
->
dev
=
dev
;
save_flags
(
flags
);
spin_lock_irqsave
(
&
listen_lock
,
flags
);
cli
();
listen
->
next
=
listen_list
;
listen
->
next
=
listen_list
;
listen_list
=
listen
;
listen_list
=
listen
;
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
restore_flags
(
flags
);
return
1
;
return
1
;
}
}
void
ax25_listen_release
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
void
ax25_listen_release
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
{
{
struct
listen_struct
*
s
,
*
listen
=
listen_list
;
struct
listen_struct
*
s
,
*
listen
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
listen_lock
,
flags
);
listen
=
listen_list
;
if
(
listen
==
NULL
)
if
(
listen
==
NULL
)
return
;
return
;
save_flags
(
flags
);
cli
();
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
listen
->
dev
==
dev
)
{
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
listen
->
dev
==
dev
)
{
listen_list
=
listen
->
next
;
listen_list
=
listen
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
kfree
(
listen
);
kfree
(
listen
);
return
;
return
;
}
}
...
@@ -214,35 +205,42 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
...
@@ -214,35 +205,42 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev)
if
(
ax25cmp
(
&
listen
->
next
->
callsign
,
callsign
)
==
0
&&
listen
->
next
->
dev
==
dev
)
{
if
(
ax25cmp
(
&
listen
->
next
->
callsign
,
callsign
)
==
0
&&
listen
->
next
->
dev
==
dev
)
{
s
=
listen
->
next
;
s
=
listen
->
next
;
listen
->
next
=
listen
->
next
->
next
;
listen
->
next
=
listen
->
next
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
kfree
(
s
);
kfree
(
s
);
return
;
return
;
}
}
listen
=
listen
->
next
;
listen
=
listen
->
next
;
}
}
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
restore_flags
(
flags
);
}
}
int
(
*
ax25_protocol_function
(
unsigned
int
pid
))(
struct
sk_buff
*
,
ax25_cb
*
)
int
(
*
ax25_protocol_function
(
unsigned
int
pid
))(
struct
sk_buff
*
,
ax25_cb
*
)
{
{
int
(
*
res
)(
struct
sk_buff
*
,
ax25_cb
*
)
=
NULL
;
struct
protocol_struct
*
protocol
;
struct
protocol_struct
*
protocol
;
read_lock
(
&
protocol_list_lock
);
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
if
(
protocol
->
pid
==
pid
)
if
(
protocol
->
pid
==
pid
)
{
return
protocol
->
func
;
res
=
protocol
->
func
;
break
;
}
read_unlock
(
&
protocol_list_lock
);
return
NULL
;
return
res
;
}
}
int
ax25_listen_mine
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
int
ax25_listen_mine
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
{
{
struct
listen_struct
*
listen
;
struct
listen_struct
*
listen
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
listen_lock
,
flags
);
for
(
listen
=
listen_list
;
listen
!=
NULL
;
listen
=
listen
->
next
)
for
(
listen
=
listen_list
;
listen
!=
NULL
;
listen
=
listen
->
next
)
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
(
listen
->
dev
==
dev
||
listen
->
dev
==
NULL
))
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
(
listen
->
dev
==
dev
||
listen
->
dev
==
NULL
))
return
1
;
return
1
;
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
return
0
;
return
0
;
}
}
...
@@ -250,19 +248,26 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
...
@@ -250,19 +248,26 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
void
ax25_link_failed
(
ax25_cb
*
ax25
,
int
reason
)
void
ax25_link_failed
(
ax25_cb
*
ax25
,
int
reason
)
{
{
struct
linkfail_struct
*
linkfail
;
struct
linkfail_struct
*
linkfail
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
for
(
linkfail
=
linkfail_list
;
linkfail
!=
NULL
;
linkfail
=
linkfail
->
next
)
for
(
linkfail
=
linkfail_list
;
linkfail
!=
NULL
;
linkfail
=
linkfail
->
next
)
(
linkfail
->
func
)(
ax25
,
reason
);
(
linkfail
->
func
)(
ax25
,
reason
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
}
}
int
ax25_protocol_is_registered
(
unsigned
int
pid
)
int
ax25_protocol_is_registered
(
unsigned
int
pid
)
{
{
struct
protocol_struct
*
protocol
;
struct
protocol_struct
*
protocol
;
int
res
=
0
;
read_lock
(
&
protocol_list_lock
);
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
if
(
protocol
->
pid
==
pid
)
if
(
protocol
->
pid
==
pid
)
{
return
1
;
res
=
1
;
break
;
}
read_unlock
(
&
protocol_list_lock
);
return
0
;
return
res
;
}
}
net/ax25/ax25_in.c
View file @
0dfe6e55
...
@@ -217,7 +217,8 @@ static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, i
...
@@ -217,7 +217,8 @@ static int ax25_process_rx_frame(ax25_cb *ax25, struct sk_buff *skb, int type, i
return
queued
;
return
queued
;
}
}
static
int
ax25_rcv
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
ax25_address
*
dev_addr
,
struct
packet_type
*
ptype
)
static
int
ax25_rcv
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
,
ax25_address
*
dev_addr
,
struct
packet_type
*
ptype
)
{
{
struct
sock
*
make
;
struct
sock
*
make
;
struct
sock
*
sk
;
struct
sock
*
sk
;
...
@@ -486,4 +487,3 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
...
@@ -486,4 +487,3 @@ int ax25_kiss_rcv(struct sk_buff *skb, struct net_device *dev,
return
ax25_rcv
(
skb
,
dev
,
(
ax25_address
*
)
dev
->
dev_addr
,
ptype
);
return
ax25_rcv
(
skb
,
dev
,
(
ax25_address
*
)
dev
->
dev_addr
,
ptype
);
}
}
net/ax25/ax25_ip.c
View file @
0dfe6e55
...
@@ -112,8 +112,8 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -112,8 +112,8 @@ int ax25_rebuild_header(struct sk_buff *skb)
unsigned
char
*
bp
=
skb
->
data
;
unsigned
char
*
bp
=
skb
->
data
;
struct
net_device
*
dev
;
struct
net_device
*
dev
;
ax25_address
*
src
,
*
dst
;
ax25_address
*
src
,
*
dst
;
ax25_route
*
route
;
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
;
ax25_route
_route
,
*
route
=
&
_route
;
dst
=
(
ax25_address
*
)(
bp
+
1
);
dst
=
(
ax25_address
*
)(
bp
+
1
);
src
=
(
ax25_address
*
)(
bp
+
8
);
src
=
(
ax25_address
*
)(
bp
+
8
);
...
@@ -121,14 +121,15 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -121,14 +121,15 @@ int ax25_rebuild_header(struct sk_buff *skb)
if
(
arp_find
(
bp
+
1
,
skb
))
if
(
arp_find
(
bp
+
1
,
skb
))
return
1
;
return
1
;
route
=
ax25_rt_find_route
(
dst
,
NULL
);
route
=
ax25_rt_find_route
(
route
,
dst
,
NULL
);
dev
=
route
->
dev
;
dev
=
route
->
dev
;
if
(
dev
==
NULL
)
if
(
dev
==
NULL
)
dev
=
skb
->
dev
;
dev
=
skb
->
dev
;
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
{
return
1
;
goto
put
;
}
if
(
bp
[
16
]
==
AX25_P_IP
)
{
if
(
bp
[
16
]
==
AX25_P_IP
)
{
if
(
route
->
ip_mode
==
'V'
||
(
route
->
ip_mode
==
' '
&&
ax25_dev
->
values
[
AX25_VALUES_IPDEFMODE
]))
{
if
(
route
->
ip_mode
==
'V'
||
(
route
->
ip_mode
==
' '
&&
ax25_dev
->
values
[
AX25_VALUES_IPDEFMODE
]))
{
...
@@ -153,7 +154,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -153,7 +154,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
if
((
ourskb
=
skb_copy
(
skb
,
GFP_ATOMIC
))
==
NULL
)
{
if
((
ourskb
=
skb_copy
(
skb
,
GFP_ATOMIC
))
==
NULL
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
1
;
goto
put
;
}
}
if
(
skb
->
sk
!=
NULL
)
if
(
skb
->
sk
!=
NULL
)
...
@@ -170,7 +171,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -170,7 +171,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_send_frame
(
ourskb
,
ax25_dev
->
values
[
AX25_VALUES_PACLEN
],
&
src_c
,
ax25_send_frame
(
ourskb
,
ax25_dev
->
values
[
AX25_VALUES_PACLEN
],
&
src_c
,
&
dst_c
,
route
->
digipeat
,
dev
);
&
dst_c
,
route
->
digipeat
,
dev
);
return
1
;
goto
put
;
}
}
}
}
...
@@ -187,7 +188,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -187,7 +188,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
if
(
route
->
digipeat
!=
NULL
)
{
if
(
route
->
digipeat
!=
NULL
)
{
if
((
ourskb
=
ax25_rt_build_path
(
skb
,
src
,
dst
,
route
->
digipeat
))
==
NULL
)
{
if
((
ourskb
=
ax25_rt_build_path
(
skb
,
src
,
dst
,
route
->
digipeat
))
==
NULL
)
{
kfree_skb
(
skb
);
kfree_skb
(
skb
);
return
1
;
goto
put
;
}
}
skb
=
ourskb
;
skb
=
ourskb
;
...
@@ -197,6 +198,9 @@ int ax25_rebuild_header(struct sk_buff *skb)
...
@@ -197,6 +198,9 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_queue_xmit
(
skb
);
ax25_queue_xmit
(
skb
);
put:
ax25_put_route
(
route
);
return
1
;
return
1
;
}
}
...
...
net/ax25/ax25_out.c
View file @
0dfe6e55
...
@@ -44,6 +44,7 @@
...
@@ -44,6 +44,7 @@
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/inet.h>
...
@@ -57,6 +58,8 @@
...
@@ -57,6 +58,8 @@
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/interrupt.h>
static
spinlock_t
ax25_frag_lock
=
SPIN_LOCK_UNLOCKED
;
ax25_cb
*
ax25_send_frame
(
struct
sk_buff
*
skb
,
int
paclen
,
ax25_address
*
src
,
ax25_address
*
dest
,
ax25_digi
*
digi
,
struct
net_device
*
dev
)
ax25_cb
*
ax25_send_frame
(
struct
sk_buff
*
skb
,
int
paclen
,
ax25_address
*
src
,
ax25_address
*
dest
,
ax25_digi
*
digi
,
struct
net_device
*
dev
)
{
{
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
;
...
@@ -155,11 +158,9 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
...
@@ -155,11 +158,9 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
frontlen
=
skb_headroom
(
skb
);
/* Address space + CTRL */
frontlen
=
skb_headroom
(
skb
);
/* Address space + CTRL */
while
(
skb
->
len
>
0
)
{
while
(
skb
->
len
>
0
)
{
save_flags
(
flags
);
spin_lock_irqsave
(
&
ax25_frag_lock
,
flags
);
cli
();
if
((
skbn
=
alloc_skb
(
paclen
+
2
+
frontlen
,
GFP_ATOMIC
))
==
NULL
)
{
if
((
skbn
=
alloc_skb
(
paclen
+
2
+
frontlen
,
GFP_ATOMIC
))
==
NULL
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_frag_lock
,
flags
);
printk
(
KERN_CRIT
"AX.25: ax25_output - out of memory
\n
"
);
printk
(
KERN_CRIT
"AX.25: ax25_output - out of memory
\n
"
);
return
;
return
;
}
}
...
@@ -167,7 +168,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
...
@@ -167,7 +168,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
if
(
skb
->
sk
!=
NULL
)
if
(
skb
->
sk
!=
NULL
)
skb_set_owner_w
(
skbn
,
skb
->
sk
);
skb_set_owner_w
(
skbn
,
skb
->
sk
);
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_frag_lock
,
flags
);
len
=
(
paclen
>
skb
->
len
)
?
skb
->
len
:
paclen
;
len
=
(
paclen
>
skb
->
len
)
?
skb
->
len
:
paclen
;
...
...
net/ax25/ax25_route.c
View file @
0dfe6e55
...
@@ -40,10 +40,10 @@
...
@@ -40,10 +40,10 @@
* Jonathan(G4KLX) Support for packet forwarding.
* Jonathan(G4KLX) Support for packet forwarding.
* Arnaldo C. Melo s/suser/capable/
* Arnaldo C. Melo s/suser/capable/
*/
*/
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/socket.h>
#include <linux/timer.h>
#include <linux/in.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched.h>
...
@@ -56,6 +56,7 @@
...
@@ -56,6 +56,7 @@
#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <net/sock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/system.h>
...
@@ -65,8 +66,9 @@
...
@@ -65,8 +66,9 @@
#include <linux/init.h>
#include <linux/init.h>
static
ax25_route
*
ax25_route_list
;
static
ax25_route
*
ax25_route_list
;
static
rwlock_t
ax25_route_lock
=
RW_LOCK_UNLOCKED
;
static
ax25_route
*
ax25_
find
_route
(
ax25_address
*
,
struct
net_device
*
);
static
ax25_route
*
ax25_
get
_route
(
ax25_address
*
,
struct
net_device
*
);
/*
/*
* small macro to drop non-digipeated digipeaters and reverse path
* small macro to drop non-digipeated digipeaters and reverse path
...
@@ -86,8 +88,10 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
...
@@ -86,8 +88,10 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
void
ax25_rt_device_down
(
struct
net_device
*
dev
)
void
ax25_rt_device_down
(
struct
net_device
*
dev
)
{
{
ax25_route
*
s
,
*
t
,
*
ax25_rt
=
ax25_route_list
;
ax25_route
*
s
,
*
t
,
*
ax25_rt
;
write_lock
(
&
ax25_route_lock
);
ax25_rt
=
ax25_route_list
;
while
(
ax25_rt
!=
NULL
)
{
while
(
ax25_rt
!=
NULL
)
{
s
=
ax25_rt
;
s
=
ax25_rt
;
ax25_rt
=
ax25_rt
->
next
;
ax25_rt
=
ax25_rt
->
next
;
...
@@ -111,129 +115,196 @@ void ax25_rt_device_down(struct net_device *dev)
...
@@ -111,129 +115,196 @@ void ax25_rt_device_down(struct net_device *dev)
}
}
}
}
}
}
write_unlock
(
&
ax25_route_lock
);
}
}
int
ax25_rt_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
static
int
ax25_rt_add
(
struct
ax25_routes_struct
*
route
)
{
{
unsigned
long
flags
;
ax25_route
*
ax25_rt
;
ax25_route
*
s
,
*
t
,
*
ax25_rt
;
struct
ax25_routes_struct
route
;
struct
ax25_route_opt_struct
rt_option
;
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
;
int
i
;
int
i
;
switch
(
cmd
)
{
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
->
port_addr
))
==
NULL
)
case
SIOCADDRT
:
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
.
port_addr
))
==
NULL
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
route
.
digi_count
>
AX25_MAX_DIGIS
)
if
(
route
->
digi_count
>
AX25_MAX_DIGIS
)
return
-
EINVAL
;
return
-
EINVAL
;
for
(
ax25_rt
=
ax25_route_list
;
ax25_rt
!=
NULL
;
ax25_rt
=
ax25_rt
->
next
)
{
if
(
ax25cmp
(
&
ax25_rt
->
callsign
,
&
route
.
dest_addr
)
==
0
&&
ax25_rt
->
dev
==
ax25_dev
->
dev
)
{
write_lock
(
&
ax25_route_lock
);
ax25_rt
=
ax25_route_list
;
while
(
ax25_rt
!=
NULL
)
{
if
(
ax25cmp
(
&
ax25_rt
->
callsign
,
&
route
->
dest_addr
)
==
0
&&
ax25_rt
->
dev
==
ax25_dev
->
dev
)
{
if
(
ax25_rt
->
digipeat
!=
NULL
)
{
if
(
ax25_rt
->
digipeat
!=
NULL
)
{
kfree
(
ax25_rt
->
digipeat
);
kfree
(
ax25_rt
->
digipeat
);
ax25_rt
->
digipeat
=
NULL
;
ax25_rt
->
digipeat
=
NULL
;
}
}
if
(
route
.
digi_count
!=
0
)
{
if
(
route
->
digi_count
!=
0
)
{
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
write_unlock
(
&
ax25_route_lock
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
ndigi
=
route
.
digi_count
;
ax25_rt
->
digipeat
->
ndigi
=
route
->
digi_count
;
for
(
i
=
0
;
i
<
route
.
digi_count
;
i
++
)
{
for
(
i
=
0
;
i
<
route
->
digi_count
;
i
++
)
{
ax25_rt
->
digipeat
->
repeated
[
i
]
=
0
;
ax25_rt
->
digipeat
->
repeated
[
i
]
=
0
;
ax25_rt
->
digipeat
->
calls
[
i
]
=
route
.
digi_addr
[
i
];
ax25_rt
->
digipeat
->
calls
[
i
]
=
route
->
digi_addr
[
i
];
}
}
}
}
return
0
;
return
0
;
}
}
ax25_rt
=
ax25_rt
->
next
;
}
}
if
((
ax25_rt
=
kmalloc
(
sizeof
(
ax25_route
),
GFP_ATOMIC
))
==
NULL
)
if
((
ax25_rt
=
kmalloc
(
sizeof
(
ax25_route
),
GFP_ATOMIC
))
==
NULL
)
{
write_unlock
(
&
ax25_route_lock
);
return
-
ENOMEM
;
return
-
ENOMEM
;
ax25_rt
->
callsign
=
route
.
dest_addr
;
}
atomic_set
(
&
ax25_rt
->
ref
,
0
);
ax25_rt
->
callsign
=
route
->
dest_addr
;
ax25_rt
->
dev
=
ax25_dev
->
dev
;
ax25_rt
->
dev
=
ax25_dev
->
dev
;
ax25_rt
->
digipeat
=
NULL
;
ax25_rt
->
digipeat
=
NULL
;
ax25_rt
->
ip_mode
=
' '
;
ax25_rt
->
ip_mode
=
' '
;
if
(
route
.
digi_count
!=
0
)
{
if
(
route
->
digi_count
!=
0
)
{
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
write_unlock
(
&
ax25_route_lock
);
kfree
(
ax25_rt
);
kfree
(
ax25_rt
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
ndigi
=
route
.
digi_count
;
ax25_rt
->
digipeat
->
ndigi
=
route
->
digi_count
;
for
(
i
=
0
;
i
<
route
.
digi_count
;
i
++
)
{
for
(
i
=
0
;
i
<
route
->
digi_count
;
i
++
)
{
ax25_rt
->
digipeat
->
repeated
[
i
]
=
0
;
ax25_rt
->
digipeat
->
repeated
[
i
]
=
0
;
ax25_rt
->
digipeat
->
calls
[
i
]
=
route
.
digi_addr
[
i
];
ax25_rt
->
digipeat
->
calls
[
i
]
=
route
->
digi_addr
[
i
];
}
}
}
}
save_flags
(
flags
);
cli
();
ax25_rt
->
next
=
ax25_route_list
;
ax25_rt
->
next
=
ax25_route_list
;
ax25_route_list
=
ax25_rt
;
ax25_route_list
=
ax25_rt
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_route_lock
);
break
;
case
SIOCDELRT
:
return
0
;
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
}
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
.
port_addr
))
==
NULL
)
static
int
ax25_rt_destroy
(
ax25_route
*
ax25_rt
)
{
if
(
atomic_read
(
&
ax25_rt
->
ref
)
==
0
)
{
if
(
ax25_rt
->
digipeat
!=
NULL
)
kfree
(
ax25_rt
->
digipeat
);
kfree
(
ax25_rt
);
}
/*
* Uh... Route is still in use; we can't yet destroy it. Retry later.
*/
init_timer
(
&
ax25_rt
->
timer
);
ax25_rt
->
timer
.
data
=
(
unsigned
long
)
ax25_rt
;
ax25_rt
->
timer
.
function
=
(
void
*
)
ax25_rt_destroy
;
ax25_rt
->
timer
.
expires
=
jiffies
+
5
*
HZ
;
add_timer
(
&
ax25_rt
->
timer
);
}
static
int
ax25_rt_del
(
struct
ax25_routes_struct
*
route
)
{
ax25_route
*
s
,
*
t
,
*
ax25_rt
;
ax25_dev
*
ax25_dev
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
->
port_addr
))
==
NULL
)
return
-
EINVAL
;
return
-
EINVAL
;
write_lock
(
&
ax25_route_lock
);
ax25_rt
=
ax25_route_list
;
ax25_rt
=
ax25_route_list
;
while
(
ax25_rt
!=
NULL
)
{
while
(
ax25_rt
!=
NULL
)
{
s
=
ax25_rt
;
s
=
ax25_rt
;
ax25_rt
=
ax25_rt
->
next
;
ax25_rt
=
ax25_rt
->
next
;
if
(
s
->
dev
==
ax25_dev
->
dev
&&
ax25cmp
(
&
route
.
dest_addr
,
&
s
->
callsign
)
==
0
)
{
if
(
s
->
dev
==
ax25_dev
->
dev
&&
ax25cmp
(
&
route
->
dest_addr
,
&
s
->
callsign
)
==
0
)
{
if
(
ax25_route_list
==
s
)
{
if
(
ax25_route_list
==
s
)
{
ax25_route_list
=
s
->
next
;
ax25_route_list
=
s
->
next
;
if
(
s
->
digipeat
!=
NULL
)
ax25_rt_destroy
(
s
);
kfree
(
s
->
digipeat
);
kfree
(
s
);
}
else
{
}
else
{
for
(
t
=
ax25_route_list
;
t
!=
NULL
;
t
=
t
->
next
)
{
for
(
t
=
ax25_route_list
;
t
!=
NULL
;
t
=
t
->
next
)
{
if
(
t
->
next
==
s
)
{
if
(
t
->
next
==
s
)
{
t
->
next
=
s
->
next
;
t
->
next
=
s
->
next
;
if
(
s
->
digipeat
!=
NULL
)
ax25_rt_destroy
(
s
);
kfree
(
s
->
digipeat
);
kfree
(
s
);
break
;
break
;
}
}
}
}
}
}
}
}
}
}
break
;
write_unlock
(
&
ax25_route_lock
)
;
case
SIOCAX25OPTRT
:
return
0
;
if
(
copy_from_user
(
&
rt_option
,
arg
,
sizeof
(
rt_option
)))
}
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
rt_option
.
port_addr
))
==
NULL
)
static
int
ax25_rt_opt
(
struct
ax25_route_opt_struct
*
rt_option
)
{
ax25_route
*
ax25_rt
;
ax25_dev
*
ax25_dev
;
int
err
=
0
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
rt_option
->
port_addr
))
==
NULL
)
return
-
EINVAL
;
return
-
EINVAL
;
for
(
ax25_rt
=
ax25_route_list
;
ax25_rt
!=
NULL
;
ax25_rt
=
ax25_rt
->
next
)
{
if
(
ax25_rt
->
dev
==
ax25_dev
->
dev
&&
ax25cmp
(
&
rt_option
.
dest_addr
,
&
ax25_rt
->
callsign
)
==
0
)
{
write_lock
(
&
ax25_route_lock
);
switch
(
rt_option
.
cmd
)
{
ax25_rt
=
ax25_route_list
;
while
(
ax25_rt
!=
NULL
)
{
if
(
ax25_rt
->
dev
==
ax25_dev
->
dev
&&
ax25cmp
(
&
rt_option
->
dest_addr
,
&
ax25_rt
->
callsign
)
==
0
)
{
switch
(
rt_option
->
cmd
)
{
case
AX25_SET_RT_IPMODE
:
case
AX25_SET_RT_IPMODE
:
switch
(
rt_option
.
arg
)
{
switch
(
rt_option
->
arg
)
{
case
' '
:
case
' '
:
case
'D'
:
case
'D'
:
case
'V'
:
case
'V'
:
ax25_rt
->
ip_mode
=
rt_option
.
arg
;
ax25_rt
->
ip_mode
=
rt_option
->
arg
;
break
;
break
;
default:
default:
return
-
EINVAL
;
err
=
-
EINVAL
;
goto
out
;
}
}
break
;
break
;
default:
default:
return
-
EINVAL
;
err
=
-
EINVAL
;
goto
out
;
}
}
}
}
ax25_rt
=
ax25_rt
->
next
;
}
}
break
;
out:
write_unlock
(
&
ax25_route_lock
);
return
err
;
}
int
ax25_rt_ioctl
(
unsigned
int
cmd
,
void
*
arg
)
{
struct
ax25_route_opt_struct
rt_option
;
struct
ax25_routes_struct
route
;
switch
(
cmd
)
{
case
SIOCADDRT
:
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
return
-
EFAULT
;
return
ax25_rt_add
(
&
route
);
case
SIOCDELRT
:
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
return
-
EFAULT
;
return
ax25_rt_del
(
&
route
);
case
SIOCAX25OPTRT
:
if
(
copy_from_user
(
&
rt_option
,
arg
,
sizeof
(
rt_option
)))
return
-
EFAULT
;
return
ax25_rt_opt
(
&
rt_option
);
default:
default:
return
-
EINVAL
;
return
-
EINVAL
;
}
}
return
0
;
}
}
int
ax25_rt_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
int
ax25_rt_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
...
@@ -245,7 +316,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -245,7 +316,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
char
*
callsign
;
char
*
callsign
;
int
i
;
int
i
;
cli
(
);
read_lock
(
&
ax25_route_lock
);
len
+=
sprintf
(
buffer
,
"callsign dev mode digipeaters
\n
"
);
len
+=
sprintf
(
buffer
,
"callsign dev mode digipeaters
\n
"
);
...
@@ -286,26 +357,29 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -286,26 +357,29 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length)
if
(
pos
>
offset
+
length
)
if
(
pos
>
offset
+
length
)
break
;
break
;
}
}
read_unlock
(
&
ax25_route_lock
);
sti
();
*
start
=
buffer
+
(
offset
-
begin
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
len
;
return
len
;
}
}
/*
/*
* Find AX.25 route
* Find AX.25 route
*
* Only routes with a refernce rout of zero can be destroyed.
*/
*/
static
ax25_route
*
ax25_
find
_route
(
ax25_address
*
addr
,
struct
net_device
*
dev
)
static
ax25_route
*
ax25_
get
_route
(
ax25_address
*
addr
,
struct
net_device
*
dev
)
{
{
ax25_route
*
ax25_spe_rt
=
NULL
;
ax25_route
*
ax25_spe_rt
=
NULL
;
ax25_route
*
ax25_def_rt
=
NULL
;
ax25_route
*
ax25_def_rt
=
NULL
;
ax25_route
*
ax25_rt
;
ax25_route
*
ax25_rt
;
read_lock
(
&
ax25_route_lock
);
/*
/*
* Bind to the physical interface we heard them on, or the default
* Bind to the physical interface we heard them on, or the default
* route if none is found;
* route if none is found;
...
@@ -324,10 +398,21 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
...
@@ -324,10 +398,21 @@ static ax25_route *ax25_find_route(ax25_address *addr, struct net_device *dev)
}
}
}
}
ax25_rt
=
ax25_def_rt
;
if
(
ax25_spe_rt
!=
NULL
)
if
(
ax25_spe_rt
!=
NULL
)
return
ax25_spe_rt
;
ax25_rt
=
ax25_spe_rt
;
if
(
ax25_rt
!=
NULL
)
atomic_inc
(
&
ax25_rt
->
ref
);
return
ax25_def_rt
;
read_unlock
(
&
ax25_route_lock
);
return
ax25_rt
;
}
static
inline
void
ax25_put_route
(
ax25_route
*
ax25_rt
)
{
atomic_dec
(
&
ax25_rt
->
ref
);
}
}
/*
/*
...
@@ -355,24 +440,31 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
...
@@ -355,24 +440,31 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
{
{
ax25_route
*
ax25_rt
;
ax25_route
*
ax25_rt
;
ax25_address
*
call
;
ax25_address
*
call
;
int
err
;
if
((
ax25_rt
=
ax25_
find
_route
(
addr
,
NULL
))
==
NULL
)
if
((
ax25_rt
=
ax25_
get
_route
(
addr
,
NULL
))
==
NULL
)
return
-
EHOSTUNREACH
;
return
-
EHOSTUNREACH
;
if
((
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
ax25_rt
->
dev
))
==
NULL
)
if
((
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
ax25_rt
->
dev
))
==
NULL
)
{
return
-
EHOSTUNREACH
;
err
=
-
EHOSTUNREACH
;
goto
put
;
}
if
((
call
=
ax25_findbyuid
(
current
->
euid
))
==
NULL
)
{
if
((
call
=
ax25_findbyuid
(
current
->
euid
))
==
NULL
)
{
if
(
ax25_uid_policy
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
if
(
ax25_uid_policy
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
{
return
-
EPERM
;
err
=
-
EPERM
;
goto
put
;
}
call
=
(
ax25_address
*
)
ax25
->
ax25_dev
->
dev
->
dev_addr
;
call
=
(
ax25_address
*
)
ax25
->
ax25_dev
->
dev
->
dev_addr
;
}
}
ax25
->
source_addr
=
*
call
;
ax25
->
source_addr
=
*
call
;
if
(
ax25_rt
->
digipeat
!=
NULL
)
{
if
(
ax25_rt
->
digipeat
!=
NULL
)
{
if
((
ax25
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
if
((
ax25
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
return
-
ENOMEM
;
err
=
-
ENOMEM
;
goto
put
;
}
memcpy
(
ax25
->
digipeat
,
ax25_rt
->
digipeat
,
sizeof
(
ax25_digi
));
memcpy
(
ax25
->
digipeat
,
ax25_rt
->
digipeat
,
sizeof
(
ax25_digi
));
ax25_adjust_path
(
addr
,
ax25
->
digipeat
);
ax25_adjust_path
(
addr
,
ax25
->
digipeat
);
}
}
...
@@ -380,31 +472,32 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
...
@@ -380,31 +472,32 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
if
(
ax25
->
sk
!=
NULL
)
if
(
ax25
->
sk
!=
NULL
)
ax25
->
sk
->
zapped
=
0
;
ax25
->
sk
->
zapped
=
0
;
put:
ax25_put_route
(
ax25_rt
);
return
0
;
return
0
;
}
}
/*
ax25_route
*
ax25_rt_find_route
(
ax25_route
*
route
,
ax25_address
*
addr
,
* dl1bke 960117: build digipeater path
struct
net_device
*
dev
)
* dl1bke 960301: use the default route if it exists
*/
ax25_route
*
ax25_rt_find_route
(
ax25_address
*
addr
,
struct
net_device
*
dev
)
{
{
static
ax25_route
route
;
ax25_route
*
ax25_rt
;
ax25_route
*
ax25_rt
;
if
((
ax25_rt
=
ax25_find_route
(
addr
,
dev
))
==
NULL
)
{
if
((
ax25_rt
=
ax25_get_route
(
addr
,
dev
)))
route
.
next
=
NULL
;
route
.
callsign
=
*
addr
;
route
.
dev
=
dev
;
route
.
digipeat
=
NULL
;
route
.
ip_mode
=
' '
;
return
&
route
;
}
return
ax25_rt
;
return
ax25_rt
;
route
->
next
=
NULL
;
atomic_set
(
&
route
->
ref
,
1
);
route
->
callsign
=
*
addr
;
route
->
dev
=
dev
;
route
->
digipeat
=
NULL
;
route
->
ip_mode
=
' '
;
return
route
;
}
}
struct
sk_buff
*
ax25_rt_build_path
(
struct
sk_buff
*
skb
,
ax25_address
*
src
,
ax25_address
*
dest
,
ax25_digi
*
digi
)
struct
sk_buff
*
ax25_rt_build_path
(
struct
sk_buff
*
skb
,
ax25_address
*
src
,
ax25_address
*
dest
,
ax25_digi
*
digi
)
{
{
struct
sk_buff
*
skbn
;
struct
sk_buff
*
skbn
;
unsigned
char
*
bp
;
unsigned
char
*
bp
;
...
@@ -440,6 +533,7 @@ void __exit ax25_rt_free(void)
...
@@ -440,6 +533,7 @@ void __exit ax25_rt_free(void)
{
{
ax25_route
*
s
,
*
ax25_rt
=
ax25_route_list
;
ax25_route
*
s
,
*
ax25_rt
=
ax25_route_list
;
write_unlock
(
&
ax25_route_lock
);
while
(
ax25_rt
!=
NULL
)
{
while
(
ax25_rt
!=
NULL
)
{
s
=
ax25_rt
;
s
=
ax25_rt
;
ax25_rt
=
ax25_rt
->
next
;
ax25_rt
=
ax25_rt
->
next
;
...
@@ -449,4 +543,5 @@ void __exit ax25_rt_free(void)
...
@@ -449,4 +543,5 @@ void __exit ax25_rt_free(void)
kfree
(
s
);
kfree
(
s
);
}
}
write_unlock
(
&
ax25_route_lock
);
}
}
net/ax25/ax25_std_in.c
View file @
0dfe6e55
...
@@ -142,7 +142,8 @@ static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
...
@@ -142,7 +142,8 @@ static int ax25_std_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
case
AX25_DM
:
case
AX25_DM
:
case
AX25_UA
:
case
AX25_UA
:
if
(
pf
)
ax25_disconnect
(
ax25
,
0
);
if
(
pf
)
ax25_disconnect
(
ax25
,
0
);
break
;
break
;
case
AX25_I
:
case
AX25_I
:
...
@@ -397,7 +398,8 @@ static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
...
@@ -397,7 +398,8 @@ static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
}
}
ax25_frames_acked
(
ax25
,
nr
);
ax25_frames_acked
(
ax25
,
nr
);
if
(
ax25
->
condition
&
AX25_COND_OWN_RX_BUSY
)
{
if
(
ax25
->
condition
&
AX25_COND_OWN_RX_BUSY
)
{
if
(
pf
)
ax25_std_enquiry_response
(
ax25
);
if
(
pf
)
ax25_std_enquiry_response
(
ax25
);
break
;
break
;
}
}
if
(
ns
==
ax25
->
vr
)
{
if
(
ns
==
ax25
->
vr
)
{
...
...
net/ax25/ax25_std_timer.c
View file @
0dfe6e55
...
@@ -47,7 +47,6 @@
...
@@ -47,7 +47,6 @@
void
ax25_std_heartbeat_expiry
(
ax25_cb
*
ax25
)
void
ax25_std_heartbeat_expiry
(
ax25_cb
*
ax25
)
{
{
switch
(
ax25
->
state
)
{
switch
(
ax25
->
state
)
{
case
AX25_STATE_0
:
case
AX25_STATE_0
:
/* Magic here: If we listen() and a new link dies before it
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
is accepted() it isn't 'dead' so doesn't get removed. */
...
...
net/ax25/ax25_subr.c
View file @
0dfe6e55
net/ax25/ax25_timer.c
View file @
0dfe6e55
net/ax25/ax25_uid.c
View file @
0dfe6e55
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include <linux/string.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
...
@@ -47,17 +48,23 @@
...
@@ -47,17 +48,23 @@
*/
*/
static
ax25_uid_assoc
*
ax25_uid_list
;
static
ax25_uid_assoc
*
ax25_uid_list
;
static
rwlock_t
ax25_uid_lock
=
RW_LOCK_UNLOCKED
;
int
ax25_uid_policy
=
0
;
int
ax25_uid_policy
=
0
;
ax25_address
*
ax25_findbyuid
(
uid_t
uid
)
ax25_address
*
ax25_findbyuid
(
uid_t
uid
)
{
{
ax25_uid_assoc
*
ax25_uid
;
ax25_uid_assoc
*
ax25_uid
;
ax25_address
*
res
=
NULL
;
read_lock
(
&
ax25_uid_lock
);
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
if
(
ax25_uid
->
uid
==
uid
)
if
(
ax25_uid
->
uid
==
uid
)
{
return
&
ax25_uid
->
call
;
res
=
&
ax25_uid
->
call
;
break
;
}
}
}
read_unlock
(
&
ax25_uid_lock
);
return
NULL
;
return
NULL
;
}
}
...
@@ -65,15 +72,21 @@ ax25_address *ax25_findbyuid(uid_t uid)
...
@@ -65,15 +72,21 @@ ax25_address *ax25_findbyuid(uid_t uid)
int
ax25_uid_ioctl
(
int
cmd
,
struct
sockaddr_ax25
*
sax
)
int
ax25_uid_ioctl
(
int
cmd
,
struct
sockaddr_ax25
*
sax
)
{
{
ax25_uid_assoc
*
s
,
*
ax25_uid
;
ax25_uid_assoc
*
s
,
*
ax25_uid
;
unsigned
long
flag
s
;
unsigned
long
re
s
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
SIOCAX25GETUID
:
case
SIOCAX25GETUID
:
res
=
-
ENOENT
;
read_lock
(
&
ax25_uid_lock
);
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
{
return
ax25_uid
->
uid
;
res
=
ax25_uid
->
uid
;
break
;
}
}
return
-
ENOENT
;
}
read_unlock
(
&
ax25_uid_lock
);
return
res
;
case
SIOCAX25ADDUID
:
case
SIOCAX25ADDUID
:
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
...
@@ -84,40 +97,48 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
...
@@ -84,40 +97,48 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return
-
EINVAL
;
return
-
EINVAL
;
if
((
ax25_uid
=
kmalloc
(
sizeof
(
*
ax25_uid
),
GFP_KERNEL
))
==
NULL
)
if
((
ax25_uid
=
kmalloc
(
sizeof
(
*
ax25_uid
),
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
return
-
ENOMEM
;
ax25_uid
->
uid
=
sax
->
sax25_uid
;
ax25_uid
->
uid
=
sax
->
sax25_uid
;
ax25_uid
->
call
=
sax
->
sax25_call
;
ax25_uid
->
call
=
sax
->
sax25_call
;
save_flags
(
flags
);
cli
();
write_lock
(
&
ax25_uid_lock
);
ax25_uid
->
next
=
ax25_uid_list
;
ax25_uid
->
next
=
ax25_uid_list
;
ax25_uid_list
=
ax25_uid
;
ax25_uid_list
=
ax25_uid
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
return
0
;
return
0
;
case
SIOCAX25DELUID
:
case
SIOCAX25DELUID
:
if
(
!
capable
(
CAP_NET_ADMIN
))
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
-
EPERM
;
write_lock
(
&
ax25_uid_lock
);
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
{
break
;
break
;
}
}
if
(
ax25_uid
==
NULL
)
}
if
(
ax25_uid
==
NULL
)
{
write_unlock
(
&
ax25_uid_lock
);
return
-
ENOENT
;
return
-
ENOENT
;
save_flags
(
flags
);
cli
();
}
if
((
s
=
ax25_uid_list
)
==
ax25_uid
)
{
if
((
s
=
ax25_uid_list
)
==
ax25_uid
)
{
ax25_uid_list
=
s
->
next
;
ax25_uid_list
=
s
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
kfree
(
ax25_uid
);
kfree
(
ax25_uid
);
return
0
;
return
0
;
}
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25_uid
)
{
if
(
s
->
next
==
ax25_uid
)
{
s
->
next
=
ax25_uid
->
next
;
s
->
next
=
ax25_uid
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
kfree
(
ax25_uid
);
kfree
(
ax25_uid
);
return
0
;
return
0
;
}
}
s
=
s
->
next
;
s
=
s
->
next
;
}
}
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
return
-
ENOENT
;
return
-
ENOENT
;
default:
default:
...
@@ -134,8 +155,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -134,8 +155,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
off_t
pos
=
0
;
off_t
pos
=
0
;
off_t
begin
=
0
;
off_t
begin
=
0
;
cli
();
read_lock
(
&
ax25_uid_lock
);
len
+=
sprintf
(
buffer
,
"Policy: %d
\n
"
,
ax25_uid_policy
);
len
+=
sprintf
(
buffer
,
"Policy: %d
\n
"
,
ax25_uid_policy
);
for
(
pt
=
ax25_uid_list
;
pt
!=
NULL
;
pt
=
pt
->
next
)
{
for
(
pt
=
ax25_uid_list
;
pt
!=
NULL
;
pt
=
pt
->
next
)
{
...
@@ -151,13 +171,13 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -151,13 +171,13 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
if
(
pos
>
offset
+
length
)
if
(
pos
>
offset
+
length
)
break
;
break
;
}
}
read_unlock
(
&
ax25_uid_lock
);
sti
();
*
start
=
buffer
+
(
offset
-
begin
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
offset
-
begin
;
len
-=
offset
-
begin
;
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
len
;
return
len
;
}
}
...
@@ -167,12 +187,16 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
...
@@ -167,12 +187,16 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
*/
*/
void
__exit
ax25_uid_free
(
void
)
void
__exit
ax25_uid_free
(
void
)
{
{
ax25_uid_assoc
*
s
,
*
ax25_uid
=
ax25_uid_list
;
ax25_uid_assoc
*
s
,
*
ax25_uid
;
write_lock
(
&
ax25_uid_lock
);
ax25_uid
=
ax25_uid_list
;
while
(
ax25_uid
!=
NULL
)
{
while
(
ax25_uid
!=
NULL
)
{
s
=
ax25_uid
;
s
=
ax25_uid
;
ax25_uid
=
ax25_uid
->
next
;
ax25_uid
=
ax25_uid
->
next
;
kfree
(
s
);
kfree
(
s
);
}
}
ax25_uid_list
=
NULL
;
write_unlock
(
&
ax25_uid_lock
);
}
}
net/ax25/sysctl_net_ax25.c
View file @
0dfe6e55
...
@@ -8,6 +8,7 @@
...
@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <net/ax25.h>
static
int
min_ipdefmode
[]
=
{
0
},
max_ipdefmode
[]
=
{
1
};
static
int
min_ipdefmode
[]
=
{
0
},
max_ipdefmode
[]
=
{
1
};
...
@@ -102,9 +103,11 @@ static const ctl_table ax25_param_table[] = {
...
@@ -102,9 +103,11 @@ static const ctl_table ax25_param_table[] = {
void
ax25_register_sysctl
(
void
)
void
ax25_register_sysctl
(
void
)
{
{
unsigned
long
flags
;
ax25_dev
*
ax25_dev
;
ax25_dev
*
ax25_dev
;
int
n
,
k
;
int
n
,
k
;
spin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
for
(
ax25_table_size
=
sizeof
(
ctl_table
),
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
for
(
ax25_table_size
=
sizeof
(
ctl_table
),
ax25_dev
=
ax25_dev_list
;
ax25_dev
!=
NULL
;
ax25_dev
=
ax25_dev
->
next
)
ax25_table_size
+=
sizeof
(
ctl_table
);
ax25_table_size
+=
sizeof
(
ctl_table
);
...
@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
...
@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
while
(
n
--
)
while
(
n
--
)
kfree
(
ax25_table
[
n
].
child
);
kfree
(
ax25_table
[
n
].
child
);
kfree
(
ax25_table
);
kfree
(
ax25_table
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
return
;
return
;
}
}
memcpy
(
child
,
ax25_param_table
,
sizeof
(
ax25_param_table
));
memcpy
(
child
,
ax25_param_table
,
sizeof
(
ax25_param_table
));
...
@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
...
@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
n
++
;
n
++
;
}
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
ax25_dir_table
[
0
].
child
=
ax25_table
;
ax25_dir_table
[
0
].
child
=
ax25_table
;
...
...
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