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 @@
*
* Alan Cox (GW4PTS) 10/11/93
*/
#ifndef _AX25_H
#define _AX25_H
#include <linux/config.h>
#include <linux/ax25.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <asm/atomic.h>
#define AX25_T1CLAMPLO 1
#define AX25_T1CLAMPHI (30 * HZ)
...
...
@@ -147,10 +150,12 @@ typedef struct {
typedef
struct
ax25_route
{
struct
ax25_route
*
next
;
atomic_t
ref
;
ax25_address
callsign
;
struct
net_device
*
dev
;
ax25_digi
*
digipeat
;
char
ip_mode
;
struct
timer_list
timer
;
}
ax25_route
;
typedef
struct
{
...
...
@@ -197,7 +202,8 @@ typedef struct ax25_cb {
#define ax25_sk(__sk) ((ax25_cb *)(__sk)->protinfo)
/* 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_insert_socket
(
ax25_cb
*
);
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 *);
/* ax25_dev.c */
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_addr_ax25dev
(
ax25_address
*
);
extern
void
ax25_dev_device_up
(
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_get_info
(
char
*
,
char
**
,
off_t
,
int
);
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
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 @@
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/smp_lock.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <net/ax25.h>
...
...
@@ -134,13 +135,15 @@
#include <linux/netfilter.h>
#include <linux/sysctl.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <net/tcp.h>
#include <net/ip.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
;
...
...
@@ -173,25 +176,25 @@ static void ax25_remove_socket(ax25_cb *ax25)
ax25_cb
*
s
;
unsigned
long
flags
;
s
ave_flags
(
flags
);
cli
(
);
s
pin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
if
((
s
=
ax25_list
)
==
ax25
)
{
ax25_list
=
s
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
;
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25
)
{
s
->
next
=
ax25
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
;
}
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)
*/
static
void
ax25_kill_by_device
(
struct
net_device
*
dev
)
{
unsigned
long
flags
;
ax25_dev
*
ax25_dev
;
ax25_cb
*
s
;
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
return
;
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
ax25_dev
==
ax25_dev
)
{
s
->
ax25_dev
=
NULL
;
ax25_disconnect
(
s
,
ENETUNREACH
);
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
/*
* 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
;
...
...
@@ -247,62 +254,58 @@ void ax25_insert_socket(ax25_cb *ax25)
{
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
ax25
->
next
=
ax25_list
;
ax25_list
=
ax25
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
/*
* Find a socket that wants to accept the SABM we have just
* 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
;
ax25_cb
*
s
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
((
s
->
iamdigi
&&
!
digi
)
||
(
!
s
->
iamdigi
&&
digi
))
continue
;
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
(
s
->
ax25_dev
==
NULL
||
s
->
ax25_dev
->
dev
==
dev
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
->
sk
;
}
}
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
restore_flags
(
flags
);
return
NULL
;
}
/*
* 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
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
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
)
{
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
->
sk
;
}
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
NULL
;
}
...
...
@@ -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
* 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
;
unsigned
long
flags
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
if
(
s
->
sk
!=
NULL
&&
s
->
sk
->
type
!=
SOCK_SEQPACKET
)
continue
;
...
...
@@ -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
)
continue
;
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
s
;
}
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
NULL
;
}
...
...
@@ -352,17 +354,14 @@ struct sock *ax25_addr_match(ax25_address *addr)
unsigned
long
flags
;
ax25_cb
*
s
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
s
=
ax25_list
;
s
!=
NULL
;
s
=
s
->
next
)
{
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
;
}
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
NULL
;
}
...
...
@@ -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
*
interrupt users but doesn't worry about being called during work.
*
Once it is removed from the queue no interrupt or bottom half will
* touch it and we are (fairly 8-) ) safe.
* This is called from user mode and the timers. Thus it protects itself
*
against interrupt users but doesn't worry about being called during
*
work. Once it is removed from the queue no interrupt or bottom half
*
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
;
unsigned
long
flags
;
...
...
@@ -631,13 +630,14 @@ ax25_cb *ax25_create_cb(void)
* 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
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
net_device
*
dev
;
char
devname
[
IFNAMSIZ
];
int
opt
;
int
opt
,
res
=
0
;
if
(
level
!=
SOL_AX25
)
return
-
ENOPROTOOPT
;
...
...
@@ -648,98 +648,131 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op
if
(
get_user
(
opt
,
(
int
*
)
optval
))
return
-
EFAULT
;
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
switch
(
optname
)
{
case
AX25_WINDOW
:
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
if
(
opt
<
1
||
opt
>
7
)
return
-
EINVAL
;
if
(
opt
<
1
||
opt
>
7
)
{
res
=
-
EINVAL
;
break
;
}
}
else
{
if
(
opt
<
1
||
opt
>
63
)
return
-
EINVAL
;
if
(
opt
<
1
||
opt
>
63
)
{
res
=
-
EINVAL
;
break
;
}
}
ax25
->
window
=
opt
;
return
0
;
break
;
case
AX25_T1
:
if
(
opt
<
1
)
return
-
EINVAL
;
if
(
opt
<
1
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
rtt
=
(
opt
*
HZ
)
/
2
;
ax25
->
t1
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_T2
:
if
(
opt
<
1
)
return
-
EINVAL
;
if
(
opt
<
1
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
t2
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_N2
:
if
(
opt
<
1
||
opt
>
31
)
return
-
EINVAL
;
if
(
opt
<
1
||
opt
>
31
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
n2
=
opt
;
return
0
;
break
;
case
AX25_T3
:
if
(
opt
<
1
)
return
-
EINVAL
;
if
(
opt
<
1
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
t3
=
opt
*
HZ
;
return
0
;
break
;
case
AX25_IDLE
:
if
(
opt
<
0
)
return
-
EINVAL
;
if
(
opt
<
0
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
idle
=
opt
*
60
*
HZ
;
return
0
;
break
;
case
AX25_BACKOFF
:
if
(
opt
<
0
||
opt
>
2
)
return
-
EINVAL
;
if
(
opt
<
0
||
opt
>
2
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
backoff
=
opt
;
return
0
;
break
;
case
AX25_EXTSEQ
:
ax25
->
modulus
=
opt
?
AX25_EMODULUS
:
AX25_MODULUS
;
return
0
;
break
;
case
AX25_PIDINCL
:
ax25
->
pidincl
=
opt
?
1
:
0
;
return
0
;
break
;
case
AX25_IAMDIGI
:
ax25
->
iamdigi
=
opt
?
1
:
0
;
return
0
;
break
;
case
AX25_PACLEN
:
if
(
opt
<
16
||
opt
>
65535
)
return
-
EINVAL
;
if
(
opt
<
16
||
opt
>
65535
)
{
res
=
-
EINVAL
;
break
;
}
ax25
->
paclen
=
opt
;
return
0
;
break
;
case
SO_BINDTODEVICE
:
if
(
optlen
>
IFNAMSIZ
)
optlen
=
IFNAMSIZ
;
if
(
copy_from_user
(
devname
,
optval
,
optlen
))
return
-
EFAULT
;
if
(
optlen
>
IFNAMSIZ
)
optlen
=
IFNAMSIZ
;
if
(
copy_from_user
(
devname
,
optval
,
optlen
))
{
res
=
-
EFAULT
;
break
;
}
dev
=
dev_get_by_name
(
devname
);
if
(
dev
==
NULL
)
return
-
ENODEV
;
if
(
dev
==
NULL
)
{
res
=
-
ENODEV
;
break
;
}
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
(
sock
->
state
!=
SS_UNCONNECTED
||
sk
->
state
==
TCP_LISTEN
))
return
-
EADDRNOTAVAIL
;
(
sock
->
state
!=
SS_UNCONNECTED
||
sk
->
state
==
TCP_LISTEN
))
{
res
=
-
EADDRNOTAVAIL
;
break
;
}
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
dev
);
ax25_fillin_cb
(
ax25
,
ax25
->
ax25_dev
);
return
0
;
break
;
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
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
ax25_dev
*
ax25_dev
;
char
devname
[
IFNAMSIZ
];
void
*
valptr
;
...
...
@@ -758,6 +791,9 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
valptr
=
(
void
*
)
&
val
;
length
=
min_t
(
unsigned
int
,
maxlen
,
sizeof
(
int
));
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
switch
(
optname
)
{
case
AX25_WINDOW
:
val
=
ax25
->
window
;
...
...
@@ -819,8 +855,10 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op
break
;
default:
unlock_kernel
();
return
-
ENOPROTOOPT
;
}
unlock_kernel
();
if
(
put_user
(
length
,
optlen
))
return
-
EFAULT
;
...
...
@@ -832,11 +870,14 @@ static int ax25_listen(struct socket *sock, int backlog)
{
struct
sock
*
sk
=
sock
->
sk
;
lock_kernel
();
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
sk
->
state
!=
TCP_LISTEN
)
{
sk
->
max_ack_backlog
=
backlog
;
sk
->
state
=
TCP_LISTEN
;
unlock_kernel
();
return
0
;
}
unlock_kernel
();
return
-
EOPNOTSUPP
;
}
...
...
@@ -851,6 +892,7 @@ int ax25_create(struct socket *sock, int protocol)
if
(
protocol
==
0
||
protocol
==
PF_AX25
)
protocol
=
AX25_P_TEXT
;
break
;
case
SOCK_SEQPACKET
:
switch
(
protocol
)
{
case
0
:
...
...
@@ -883,6 +925,7 @@ int ax25_create(struct socket *sock, int protocol)
break
;
}
break
;
case
SOCK_RAW
:
break
;
default:
...
...
@@ -985,7 +1028,11 @@ static int ax25_release(struct socket *sock)
struct
sock
*
sk
=
sock
->
sk
;
ax25_cb
*
ax25
;
if
(
sk
==
NULL
)
return
0
;
lock_kernel
();
if
(
sk
==
NULL
)
{
unlock_kernel
();
return
0
;
}
ax25
=
ax25_sk
(
sk
);
...
...
@@ -1048,6 +1095,7 @@ static int ax25_release(struct socket *sock)
sock
->
sk
=
NULL
;
sk
->
socket
=
NULL
;
/* Not used, but we should do this */
unlock_kernel
();
return
0
;
}
...
...
@@ -1066,26 +1114,35 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
ax25_address
*
call
;
ax25_dev
*
ax25_dev
=
NULL
;
if
(
sk
->
zapped
==
0
)
lock_kernel
();
if
(
sk
->
zapped
==
0
)
{
unlock_kernel
();
return
-
EINVAL
;
}
if
(
addr_len
!=
sizeof
(
struct
sockaddr_ax25
)
&&
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
/* support for old structure may go away some time */
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
;
}
printk
(
KERN_WARNING
"ax25_bind(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
}
if
(
addr
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
if
(
addr
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
}
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
;
}
if
(
call
==
NULL
)
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)
if
(
addr_len
>
sizeof
(
struct
sockaddr_ax25
)
&&
addr
->
fsa_ax25
.
sax25_ndigis
==
1
)
{
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
;
}
}
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
;
}
}
if
(
ax25_dev
!=
NULL
)
ax25_fillin_cb
(
ax25
,
ax25_dev
);
...
...
@@ -1114,13 +1175,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
done:
ax25_insert_socket
(
ax25
);
sk
->
zapped
=
0
;
unlock_kernel
();
return
0
;
}
/*
* 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
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
);
...
...
@@ -1128,24 +1192,30 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_digi
*
digi
=
NULL
;
int
ct
=
0
,
err
;
lock_kernel
();
/* deal with restarts */
if
(
sock
->
state
==
SS_CONNECTING
)
{
switch
(
sk
->
state
)
{
case
TCP_SYN_SENT
:
/* still trying */
unlock_kernel
();
return
-
EINPROGRESS
;
case
TCP_ESTABLISHED
:
/* connection established */
unlock_kernel
();
sock
->
state
=
SS_CONNECTED
;
return
0
;
case
TCP_CLOSE
:
/* connection refused */
unlock_kernel
();
sock
->
state
=
SS_UNCONNECTED
;
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 */
}
sk
->
state
=
TCP_CLOSE
;
sock
->
state
=
SS_UNCONNECTED
;
...
...
@@ -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
))
{
/* support for old structure may go away some time */
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
;
}
printk
(
KERN_WARNING
"ax25_connect(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
}
if
(
fsa
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
if
(
fsa
->
fsa_ax25
.
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
}
if
(
ax25
->
digipeat
!=
NULL
)
{
kfree
(
ax25
->
digipeat
);
...
...
@@ -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
)
{
/* 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
;
}
if
((
digi
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_KERNEL
))
==
NULL
)
if
((
digi
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_KERNEL
))
==
NULL
)
{
unlock_kernel
();
return
-
ENOBUFS
;
}
digi
->
ndigi
=
fsa
->
fsa_ax25
.
sax25_ndigis
;
digi
->
lastrepeat
=
-
1
;
...
...
@@ -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_insert_socket
(
ax25
);
}
else
{
if
(
ax25
->
ax25_dev
==
NULL
)
if
(
ax25
->
ax25_dev
==
NULL
)
{
unlock_kernel
();
return
-
EHOSTUNREACH
;
}
}
if
(
sk
->
type
==
SOCK_SEQPACKET
&&
ax25_find_cb
(
&
ax25
->
source_addr
,
&
fsa
->
fsa_ax25
.
sax25_call
,
digi
,
ax25
->
ax25_dev
->
dev
))
{
if
(
digi
!=
NULL
)
kfree
(
digi
);
if
(
digi
!=
NULL
)
kfree
(
digi
);
unlock_kernel
();
return
-
EADDRINUSE
;
/* Already such a connection */
}
...
...
@@ -1236,6 +1318,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
{
sock
->
state
=
SS_CONNECTED
;
sk
->
state
=
TCP_ESTABLISHED
;
unlock_kernel
();
return
0
;
}
...
...
@@ -1252,8 +1335,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
#ifdef CONFIG_AX25_DAMA_SLAVE
case
AX25_PROTO_DAMA_SLAVE
:
ax25
->
modulus
=
AX25_MODULUS
;
ax25
->
window
=
ax25
->
ax25_dev
->
values
[
AX25_VALUES_WINDOW
];
ax25
->
window
=
ax25
->
ax25_dev
->
values
[
AX25_VALUES_WINDOW
];
if
(
ax25
->
ax25_dev
->
dama
.
slave
)
ax25_ds_establish_data_link
(
ax25
);
else
...
...
@@ -1267,30 +1349,38 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le
ax25_start_heartbeat
(
ax25
);
/* Now the loop */
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
if
(
sk
->
state
!=
TCP_ESTABLISHED
&&
(
flags
&
O_NONBLOCK
))
{
unlock_kernel
();
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 */
while
(
sk
->
state
==
TCP_SYN_SENT
)
{
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
{
sti
();
add_wait_queue
(
sk
->
sleep
,
&
wait
);
for
(;;)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
if
(
sk
->
state
!=
TCP_SYN_SENT
)
break
;
if
(
!
signal_pending
(
tsk
))
{
schedule
();
continue
;
}
return
-
ERESTARTSYS
;
}
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
sk
->
sleep
,
&
wait
);
}
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
/* Not in ABM, not in WAIT_UA -> failed */
sti
();
sock
->
state
=
SS_UNCONNECTED
;
return
sock_error
(
sk
);
/* Always set at this point */
}
sock
->
state
=
SS_CONNECTED
;
sti
();
unlock_kernel
();
return
0
;
}
...
...
@@ -1302,17 +1392,26 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
struct
sock
*
newsk
;
struct
sk_buff
*
skb
;
if
(
sock
->
state
!=
SS_UNCONNECTED
)
lock_kernel
();
if
(
sock
->
state
!=
SS_UNCONNECTED
)
{
unlock_kernel
();
return
-
EINVAL
;
}
if
((
sk
=
sock
->
sk
)
==
NULL
)
if
((
sk
=
sock
->
sk
)
==
NULL
)
{
unlock_kernel
();
return
-
EINVAL
;
}
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
if
(
sk
->
type
!=
SOCK_SEQPACKET
)
{
unlock_kernel
();
return
-
EOPNOTSUPP
;
}
if
(
sk
->
state
!=
TCP_LISTEN
)
if
(
sk
->
state
!=
TCP_LISTEN
)
{
unlock_kernel
();
return
-
EINVAL
;
}
/*
* 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)
*/
do
{
if
((
skb
=
skb_dequeue
(
&
sk
->
receive_queue
))
==
NULL
)
{
if
(
flags
&
O_NONBLOCK
)
if
(
flags
&
O_NONBLOCK
)
{
unlock_kernel
();
return
-
EWOULDBLOCK
;
}
interruptible_sleep_on
(
sk
->
sleep
);
if
(
signal_pending
(
current
))
if
(
signal_pending
(
current
))
{
unlock_kernel
();
return
-
ERESTARTSYS
;
}
}
}
while
(
skb
==
NULL
);
newsk
=
skb
->
sk
;
...
...
@@ -1339,20 +1442,28 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
sk
->
ack_backlog
--
;
newsock
->
sk
=
newsk
;
newsock
->
state
=
SS_CONNECTED
;
unlock_kernel
();
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
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
struct
sock
*
sk
;
ax25_cb
*
ax25
;
struct
full_sockaddr_ax25
*
fsa
=
(
struct
full_sockaddr_ax25
*
)
uaddr
;
unsigned
char
ndigi
,
i
;
lock_kernel
();
sk
=
sock
->
sk
;
ax25
=
ax25_sk
(
sk
);
if
(
peer
!=
0
)
{
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
unlock_kernel
();
return
-
ENOTCONN
;
}
fsa
->
fsa_ax25
.
sax25_family
=
AF_AX25
;
fsa
->
fsa_ax25
.
sax25_call
=
ax25
->
dest_addr
;
...
...
@@ -1377,13 +1488,16 @@ static int ax25_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
}
}
*
uaddr_len
=
sizeof
(
struct
full_sockaddr_ax25
);
unlock_kernel
();
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
;
ax25_cb
*
ax25
=
ax25_sk
(
sk
)
;
ax25_cb
*
ax25
;
struct
sockaddr_ax25
*
usax
=
(
struct
sockaddr_ax25
*
)
msg
->
msg_name
;
int
err
;
struct
sockaddr_ax25
sax
;
...
...
@@ -1395,23 +1509,34 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
int
lv
;
int
addr_len
=
msg
->
msg_namelen
;
if
(
msg
->
msg_flags
&
~
(
MSG_DONTWAIT
|
MSG_EOR
))
if
(
msg
->
msg_flags
&
~
(
MSG_DONTWAIT
|
MSG_EOR
))
{
return
-
EINVAL
;
}
if
(
sk
->
zapped
)
lock_kernel
();
ax25
=
ax25_sk
(
sk
);
if
(
sk
->
zapped
)
{
unlock_kernel
();
return
-
EADDRNOTAVAIL
;
}
if
(
sk
->
shutdown
&
SEND_SHUTDOWN
)
{
unlock_kernel
();
send_sig
(
SIGPIPE
,
current
,
0
);
return
-
EPIPE
;
}
if
(
ax25
->
ax25_dev
==
NULL
)
if
(
ax25
->
ax25_dev
==
NULL
)
{
unlock_kernel
();
return
-
ENETUNREACH
;
}
if
(
usax
!=
NULL
)
{
if
(
usax
->
sax25_family
!=
AF_AX25
)
if
(
usax
->
sax25_family
!=
AF_AX25
)
{
unlock_kernel
();
return
-
EINVAL
;
}
if
(
addr_len
==
sizeof
(
struct
sockaddr_ax25
))
{
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
else
if
(
addr_len
!=
sizeof
(
struct
full_sockaddr_ax25
))
{
/* support for old structure may go away some time */
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
;
}
printk
(
KERN_WARNING
"ax25_sendmsg(): %s uses old (6 digipeater) socket structure.
\n
"
,
current
->
comm
);
...
...
@@ -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
;
/* 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
;
}
dtmp
.
ndigi
=
usax
->
sax25_ndigis
;
...
...
@@ -1447,8 +1576,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
}
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
;
}
if
(
usax
->
sax25_ndigis
==
0
)
dp
=
NULL
;
else
...
...
@@ -1474,8 +1605,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
/* Assume the worst case */
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
;
}
skb_reserve
(
skb
,
size
-
len
);
...
...
@@ -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 */
if
(
sk
->
state
!=
TCP_ESTABLISHED
)
{
kfree_skb
(
skb
);
unlock_kernel
();
return
-
ENOTCONN
;
}
/* Shove it onto the queue and kick */
ax25_output
(
ax25
,
ax25
->
paclen
,
skb
);
unlock_kernel
();
return
len
;
}
else
{
...
...
@@ -1529,28 +1664,37 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
skb
->
dev
=
ax25
->
ax25_dev
->
dev
;
ax25_queue_xmit
(
skb
);
unlock_kernel
();
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
;
struct
sk_buff
*
skb
;
int
er
;
lock_kernel
();
sk
=
sock
->
sk
;
/*
* This works for seqpacket too. The receiver has ordered the
* 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
;
}
/* 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
;
}
if
(
!
ax25_sk
(
sk
)
->
pidincl
)
skb_pull
(
skb
,
1
);
/* Remove PID */
...
...
@@ -1590,6 +1734,7 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int f
}
skb_free_datagram
(
sk
,
skb
);
unlock_kernel
();
return
copied
;
}
...
...
@@ -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
)
{
struct
sock
*
sk
=
sock
->
sk
;
int
res
=
0
;
lock_kernel
();
switch
(
cmd
)
{
case
TIOCOUTQ
:
{
long
amount
;
amount
=
sk
->
sndbuf
-
atomic_read
(
&
sk
->
wmem_alloc
);
if
(
amount
<
0
)
amount
=
0
;
return
put_user
(
amount
,
(
int
*
)
arg
);
res
=
put_user
(
amount
,
(
int
*
)
arg
);
break
;
}
case
TIOCINQ
:
{
...
...
@@ -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 */
if
((
skb
=
skb_peek
(
&
sk
->
receive_queue
))
!=
NULL
)
amount
=
skb
->
len
;
return
put_user
(
amount
,
(
int
*
)
arg
);
res
=
put_user
(
amount
,
(
int
*
)
arg
);
break
;
}
case
SIOCGSTAMP
:
if
(
sk
!=
NULL
)
{
if
(
sk
->
stamp
.
tv_sec
==
0
)
return
-
ENOENT
;
return
copy_to_user
((
void
*
)
arg
,
&
sk
->
stamp
,
sizeof
(
struct
timeval
))
?
-
EFAULT
:
0
;
if
(
sk
->
stamp
.
tv_sec
==
0
)
{
res
=
-
ENOENT
;
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
SIOCAX25DELUID
:
/* Delete a uid from the uid/call map table */
case
SIOCAX25GETUID
:
{
struct
sockaddr_ax25
sax25
;
if
(
copy_from_user
(
&
sax25
,
(
void
*
)
arg
,
sizeof
(
sax25
)))
return
-
EFAULT
;
return
ax25_uid_ioctl
(
cmd
,
&
sax25
);
if
(
copy_from_user
(
&
sax25
,
(
void
*
)
arg
,
sizeof
(
sax25
)))
{
res
=
-
EFAULT
;
break
;
}
res
=
ax25_uid_ioctl
(
cmd
,
&
sax25
);
break
;
}
case
SIOCAX25NOUID
:
{
/* Set the default policy (default/bar) */
long
amount
;
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
if
(
get_user
(
amount
,
(
long
*
)
arg
))
return
-
EFAULT
;
if
(
amount
>
AX25_NOUID_BLOCK
)
return
-
EINVAL
;
if
(
!
capable
(
CAP_NET_ADMIN
))
{
res
=
-
EPERM
;
break
;
}
if
(
get_user
(
amount
,
(
long
*
)
arg
))
{
res
=
-
EFAULT
;
break
;
}
if
(
amount
>
AX25_NOUID_BLOCK
)
{
res
=
-
EINVAL
;
break
;
}
ax25_uid_policy
=
amount
;
return
0
;
res
=
0
;
break
;
}
case
SIOCADDRT
:
case
SIOCDELRT
:
case
SIOCAX25OPTRT
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
ax25_rt_ioctl
(
cmd
,
(
void
*
)
arg
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
res
=
-
EPERM
;
break
;
}
res
=
ax25_rt_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCAX25CTLCON
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
return
ax25_ctl_ioctl
(
cmd
,
(
void
*
)
arg
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
res
=
-
EPERM
;
break
;
}
res
=
ax25_ctl_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
case
SIOCAX25GETINFO
:
case
SIOCAX25GETINFOOLD
:
{
...
...
@@ -1697,23 +1866,33 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
warned
=
1
;
}
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct_depreciated
)))
return
-
EFAULT
;
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct_depreciated
)))
{
res
=
-
EFAULT
;
break
;
}
}
else
{
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct
)))
return
-
EINVAL
;
if
(
copy_to_user
((
void
*
)
arg
,
&
ax25_info
,
sizeof
(
struct
ax25_info_struct
)))
{
res
=
-
EINVAL
;
break
;
}
return
0
;
}
res
=
0
;
break
;
}
case
SIOCAX25ADDFWD
:
case
SIOCAX25DELFWD
:
{
struct
ax25_fwd_struct
ax25_fwd
;
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
if
(
copy_from_user
(
&
ax25_fwd
,
(
void
*
)
arg
,
sizeof
(
ax25_fwd
)))
return
-
EFAULT
;
return
ax25_fwd_ioctl
(
cmd
,
&
ax25_fwd
);
if
(
!
capable
(
CAP_NET_ADMIN
))
{
res
=
-
EPERM
;
break
;
}
if
(
copy_from_user
(
&
ax25_fwd
,
(
void
*
)
arg
,
sizeof
(
ax25_fwd
)))
{
res
=
-
EFAULT
;
break
;
}
res
=
ax25_fwd_ioctl
(
cmd
,
&
ax25_fwd
);
break
;
}
case
SIOCGIFADDR
:
...
...
@@ -1726,25 +1905,28 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case
SIOCSIFNETMASK
:
case
SIOCGIFMETRIC
:
case
SIOCSIFMETRIC
:
return
-
EINVAL
;
res
=
-
EINVAL
;
break
;
default:
return
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
res
=
dev_ioctl
(
cmd
,
(
void
*
)
arg
);
break
;
}
/*NOTREACHED*/
return
0
;
unlock_kernel
();
return
res
;
}
static
int
ax25_get_info
(
char
*
buffer
,
char
**
start
,
off_t
offset
,
int
length
)
{
unsigned
long
flags
;
ax25_cb
*
ax25
;
int
k
;
int
len
=
0
;
off_t
pos
=
0
;
off_t
begin
=
0
;
cli
(
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
/*
* New format:
...
...
@@ -1799,7 +1981,7 @@ static int ax25_get_info(char *buffer, char **start, off_t offset, int length)
break
;
}
s
ti
(
);
s
pin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
...
...
@@ -1814,7 +1996,6 @@ static struct net_proto_family ax25_family_ops = {
.
create
=
ax25_create
,
};
static
struct
proto_ops
SOCKOPS_WRAPPED
(
ax25_proto_ops
)
=
{
.
family
=
PF_AX25
,
.
release
=
ax25_release
,
...
...
@@ -1835,15 +2016,14 @@ static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = {
.
sendpage
=
sock_no_sendpage
,
}
;
#include <linux/smp_lock.h>
SOCKOPS_WRAP
(
ax25_proto
,
PF_AX25
);
/*
* Called by socket.c on kernel start up
*/
static
struct
packet_type
ax25_packet_type
=
{
.
type
=
__constant_htons
(
ETH_P_AX25
),
.
dev
=
NULL
,
/* All devices */
.
func
=
ax25_kiss_rcv
,
.
data
=
(
void
*
)
1
};
static
struct
notifier_block
ax25_dev_notifier
=
{
...
...
net/ax25/ax25_dev.c
View file @
0dfe6e55
...
...
@@ -27,6 +27,7 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
...
...
@@ -41,27 +42,37 @@
#include <linux/init.h>
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
;
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
)
if
(
ax25_dev
->
dev
==
dev
)
return
ax25_dev
;
if
(
ax25_dev
->
dev
==
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_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
)
if
(
ax25cmp
(
addr
,
(
ax25_address
*
)
ax25_dev
->
dev
->
dev_addr
)
==
0
)
return
ax25_dev
;
if
(
ax25cmp
(
addr
,
(
ax25_address
*
)
ax25_dev
->
dev
->
dev_addr
)
==
0
)
{
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)
ax25_dev
->
values
[
AX25_VALUES_PROTOCOL
]
=
AX25_DEF_PROTOCOL
;
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_list
=
ax25_dev
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
ax25_register_sysctl
();
}
...
...
@@ -118,7 +129,7 @@ void ax25_dev_device_down(struct net_device *dev)
ax25_unregister_sysctl
();
s
ave_flags
(
flags
);
cli
(
);
s
pin_lock_irqsave
(
&
ax25_dev_lock
,
flags
);
#ifdef CONFIG_AX25_DAMA_SLAVE
ax25_ds_del_timer
(
ax25_dev
);
...
...
@@ -133,7 +144,7 @@ void ax25_dev_device_down(struct net_device *dev)
if
((
s
=
ax25_dev_list
)
==
ax25_dev
)
{
ax25_dev_list
=
s
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
kfree
(
ax25_dev
);
ax25_register_sysctl
();
return
;
...
...
@@ -142,7 +153,7 @@ void ax25_dev_device_down(struct net_device *dev)
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25_dev
)
{
s
->
next
=
ax25_dev
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
kfree
(
ax25_dev
);
ax25_register_sysctl
();
return
;
...
...
@@ -150,8 +161,8 @@ void ax25_dev_device_down(struct net_device *dev)
s
=
s
->
next
;
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
restore_flags
(
flags
);
ax25_register_sysctl
();
}
...
...
@@ -202,12 +213,17 @@ struct net_device *ax25_fwd_dev(struct net_device *dev)
*/
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
)
{
s
=
ax25_dev
;
ax25_dev
=
ax25_dev
->
next
;
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
break
;
case
AX25_DM
:
if
(
pf
)
ax25_disconnect
(
ax25
,
ECONNREFUSED
);
if
(
pf
)
ax25_disconnect
(
ax25
,
ECONNREFUSED
);
break
;
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
;
}
...
...
net/ax25/ax25_ds_subr.c
View file @
0dfe6e55
...
...
@@ -31,6 +31,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
...
...
@@ -53,6 +54,7 @@ void ax25_ds_nr_error_recovery(ax25_cb *ax25)
*/
void
ax25_ds_enquiry_response
(
ax25_cb
*
ax25
)
{
unsigned
long
flags
;
ax25_cb
*
ax25o
;
/* Please note that neither DK4EGs nor DG2FEFs
...
...
@@ -93,6 +95,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
ax25_start_t3timer
(
ax25
);
ax25_ds_set_timer
(
ax25
->
ax25_dev
);
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
ax25o
=
ax25_list
;
ax25o
!=
NULL
;
ax25o
=
ax25o
->
next
)
{
if
(
ax25o
==
ax25
)
continue
;
...
...
@@ -118,6 +121,7 @@ void ax25_ds_enquiry_response(ax25_cb *ax25)
if
(
ax25o
->
state
!=
AX25_STATE_0
)
ax25_start_t3timer
(
ax25o
);
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
}
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
*/
static
int
ax25_check_dama_slave
(
ax25_dev
*
ax25_dev
)
{
unsigned
long
flags
;
ax25_cb
*
ax25
;
int
res
=
0
;
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
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
)
return
1
;
if
(
ax25
->
ax25_dev
==
ax25_dev
&&
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
)
&&
ax25
->
state
>
AX25_STATE_1
)
{
res
=
1
;
break
;
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
return
0
;
return
res
;
}
void
ax25_dev_dama_on
(
ax25_dev
*
ax25_dev
)
...
...
net/ax25/ax25_ds_timer.c
View file @
0dfe6e55
...
...
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/spinlock.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
...
...
@@ -58,7 +59,8 @@ static void ax25_ds_add_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
)
...
...
@@ -79,6 +81,7 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev)
static
void
ax25_ds_timeout
(
unsigned
long
arg
)
{
ax25_dev
*
ax25_dev
=
(
struct
ax25_dev
*
)
arg
;
unsigned
long
flags
;
ax25_cb
*
ax25
;
if
(
ax25_dev
==
NULL
||
!
ax25_dev
->
dama
.
slave
)
...
...
@@ -89,6 +92,7 @@ static void ax25_ds_timeout(unsigned long arg)
return
;
}
spin_lock_irqsave
(
&
ax25_list_lock
,
flags
);
for
(
ax25
=
ax25_list
;
ax25
!=
NULL
;
ax25
=
ax25
->
next
)
{
if
(
ax25
->
ax25_dev
!=
ax25_dev
||
!
(
ax25
->
condition
&
AX25_COND_DAMA_MODE
))
continue
;
...
...
@@ -96,6 +100,7 @@ static void ax25_ds_timeout(unsigned long arg)
ax25_send_control
(
ax25
,
AX25_DISC
,
AX25_POLLON
,
AX25_COMMAND
);
ax25_disconnect
(
ax25
,
ETIMEDOUT
);
}
spin_unlock_irqrestore
(
&
ax25_list_lock
,
flags
);
ax25_dev_dama_off
(
ax25_dev
);
}
...
...
@@ -178,7 +183,6 @@ void ax25_ds_idletimer_expiry(ax25_cb *ax25)
void
ax25_ds_t1_timeout
(
ax25_cb
*
ax25
)
{
switch
(
ax25
->
state
)
{
case
AX25_STATE_1
:
if
(
ax25
->
n2count
==
ax25
->
n2
)
{
if
(
ax25
->
modulus
==
AX25_MODULUS
)
{
...
...
net/ax25/ax25_iface.c
View file @
0dfe6e55
...
...
@@ -20,6 +20,7 @@
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
...
...
@@ -40,22 +41,25 @@ static struct protocol_struct {
unsigned
int
pid
;
int
(
*
func
)(
struct
sk_buff
*
,
ax25_cb
*
);
}
*
protocol_list
;
static
rwlock_t
protocol_list_lock
=
RW_LOCK_UNLOCKED
;
static
struct
linkfail_struct
{
struct
linkfail_struct
*
next
;
void
(
*
func
)(
ax25_cb
*
,
int
);
}
*
linkfail_list
;
static
spinlock_t
linkfail_lock
=
SPIN_LOCK_UNLOCKED
;
static
struct
listen_struct
{
struct
listen_struct
*
next
;
ax25_address
callsign
;
struct
net_device
*
dev
;
}
*
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
;
unsigned
long
flags
;
if
(
pid
==
AX25_P_TEXT
||
pid
==
AX25_P_SEGMENT
)
return
0
;
...
...
@@ -69,31 +73,28 @@ int ax25_protocol_register(unsigned int pid, int (*func)(struct sk_buff *, ax25_
protocol
->
pid
=
pid
;
protocol
->
func
=
func
;
save_flags
(
flags
);
cli
();
write_lock
(
&
protocol_list_lock
);
protocol
->
next
=
protocol_list
;
protocol_list
=
protocol
;
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
return
1
;
}
void
ax25_protocol_release
(
unsigned
int
pid
)
{
struct
protocol_struct
*
s
,
*
protocol
=
protocol_list
;
unsigned
long
flags
;
struct
protocol_struct
*
s
,
*
protocol
;
if
(
protocol
==
NULL
)
write_lock
(
&
protocol_list_lock
);
protocol
=
protocol_list
;
if
(
protocol
==
NULL
)
{
write_unlock
(
&
protocol_list_lock
);
return
;
save_flags
(
flags
);
cli
();
}
if
(
protocol
->
pid
==
pid
)
{
protocol_list
=
protocol
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
kfree
(
protocol
);
return
;
}
...
...
@@ -102,15 +103,14 @@ void ax25_protocol_release(unsigned int pid)
if
(
protocol
->
next
->
pid
==
pid
)
{
s
=
protocol
->
next
;
protocol
->
next
=
protocol
->
next
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
kfree
(
s
);
return
;
}
protocol
=
protocol
->
next
;
}
restore_flags
(
flags
);
write_unlock
(
&
protocol_list_lock
);
}
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
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
linkfail
->
next
=
linkfail_list
;
linkfail_list
=
linkfail
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
return
1
;
}
void
ax25_linkfail_release
(
void
(
*
func
)(
ax25_cb
*
,
int
))
{
struct
linkfail_struct
*
s
,
*
linkfail
=
linkfail_list
;
struct
linkfail_struct
*
s
,
*
linkfail
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
linkfail
=
linkfail_list
;
if
(
linkfail
==
NULL
)
return
;
save_flags
(
flags
);
cli
();
if
(
linkfail
->
func
==
func
)
{
linkfail_list
=
linkfail
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
kfree
(
linkfail
);
return
;
}
...
...
@@ -156,15 +152,14 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int))
if
(
linkfail
->
next
->
func
==
func
)
{
s
=
linkfail
->
next
;
linkfail
->
next
=
linkfail
->
next
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
kfree
(
s
);
return
;
}
linkfail
=
linkfail
->
next
;
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
}
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
->
dev
=
dev
;
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
listen_lock
,
flags
);
listen
->
next
=
listen_list
;
listen_list
=
listen
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
return
1
;
}
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
;
spin_lock_irqsave
(
&
listen_lock
,
flags
);
listen
=
listen_list
;
if
(
listen
==
NULL
)
return
;
save_flags
(
flags
);
cli
();
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
listen
->
dev
==
dev
)
{
listen_list
=
listen
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
kfree
(
listen
);
return
;
}
...
...
@@ -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
)
{
s
=
listen
->
next
;
listen
->
next
=
listen
->
next
->
next
;
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
kfree
(
s
);
return
;
}
listen
=
listen
->
next
;
}
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
}
int
(
*
ax25_protocol_function
(
unsigned
int
pid
))(
struct
sk_buff
*
,
ax25_cb
*
)
{
int
(
*
res
)(
struct
sk_buff
*
,
ax25_cb
*
)
=
NULL
;
struct
protocol_struct
*
protocol
;
read_lock
(
&
protocol_list_lock
);
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
if
(
protocol
->
pid
==
pid
)
return
protocol
->
func
;
if
(
protocol
->
pid
==
pid
)
{
res
=
protocol
->
func
;
break
;
}
read_unlock
(
&
protocol_list_lock
);
return
NULL
;
return
res
;
}
int
ax25_listen_mine
(
ax25_address
*
callsign
,
struct
net_device
*
dev
)
{
struct
listen_struct
*
listen
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
listen_lock
,
flags
);
for
(
listen
=
listen_list
;
listen
!=
NULL
;
listen
=
listen
->
next
)
if
(
ax25cmp
(
&
listen
->
callsign
,
callsign
)
==
0
&&
(
listen
->
dev
==
dev
||
listen
->
dev
==
NULL
))
return
1
;
spin_unlock_irqrestore
(
&
listen_lock
,
flags
);
return
0
;
}
...
...
@@ -250,19 +248,26 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
void
ax25_link_failed
(
ax25_cb
*
ax25
,
int
reason
)
{
struct
linkfail_struct
*
linkfail
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
linkfail_lock
,
flags
);
for
(
linkfail
=
linkfail_list
;
linkfail
!=
NULL
;
linkfail
=
linkfail
->
next
)
(
linkfail
->
func
)(
ax25
,
reason
);
spin_unlock_irqrestore
(
&
linkfail_lock
,
flags
);
}
int
ax25_protocol_is_registered
(
unsigned
int
pid
)
{
struct
protocol_struct
*
protocol
;
int
res
=
0
;
read_lock
(
&
protocol_list_lock
);
for
(
protocol
=
protocol_list
;
protocol
!=
NULL
;
protocol
=
protocol
->
next
)
if
(
protocol
->
pid
==
pid
)
return
1
;
if
(
protocol
->
pid
==
pid
)
{
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
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
*
sk
;
...
...
@@ -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
);
}
net/ax25/ax25_ip.c
View file @
0dfe6e55
...
...
@@ -112,8 +112,8 @@ int ax25_rebuild_header(struct sk_buff *skb)
unsigned
char
*
bp
=
skb
->
data
;
struct
net_device
*
dev
;
ax25_address
*
src
,
*
dst
;
ax25_route
*
route
;
ax25_dev
*
ax25_dev
;
ax25_route
_route
,
*
route
=
&
_route
;
dst
=
(
ax25_address
*
)(
bp
+
1
);
src
=
(
ax25_address
*
)(
bp
+
8
);
...
...
@@ -121,14 +121,15 @@ int ax25_rebuild_header(struct sk_buff *skb)
if
(
arp_find
(
bp
+
1
,
skb
))
return
1
;
route
=
ax25_rt_find_route
(
dst
,
NULL
);
route
=
ax25_rt_find_route
(
route
,
dst
,
NULL
);
dev
=
route
->
dev
;
if
(
dev
==
NULL
)
dev
=
skb
->
dev
;
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
return
1
;
if
((
ax25_dev
=
ax25_dev_ax25dev
(
dev
))
==
NULL
)
{
goto
put
;
}
if
(
bp
[
16
]
==
AX25_P_IP
)
{
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)
if
((
ourskb
=
skb_copy
(
skb
,
GFP_ATOMIC
))
==
NULL
)
{
kfree_skb
(
skb
);
return
1
;
goto
put
;
}
if
(
skb
->
sk
!=
NULL
)
...
...
@@ -170,7 +171,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_send_frame
(
ourskb
,
ax25_dev
->
values
[
AX25_VALUES_PACLEN
],
&
src_c
,
&
dst_c
,
route
->
digipeat
,
dev
);
return
1
;
goto
put
;
}
}
...
...
@@ -187,7 +188,7 @@ int ax25_rebuild_header(struct sk_buff *skb)
if
(
route
->
digipeat
!=
NULL
)
{
if
((
ourskb
=
ax25_rt_build_path
(
skb
,
src
,
dst
,
route
->
digipeat
))
==
NULL
)
{
kfree_skb
(
skb
);
return
1
;
goto
put
;
}
skb
=
ourskb
;
...
...
@@ -197,6 +198,9 @@ int ax25_rebuild_header(struct sk_buff *skb)
ax25_queue_xmit
(
skb
);
put:
ax25_put_route
(
route
);
return
1
;
}
...
...
net/ax25/ax25_out.c
View file @
0dfe6e55
...
...
@@ -44,6 +44,7 @@
#include <linux/timer.h>
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/spinlock.h>
#include <linux/net.h>
#include <net/ax25.h>
#include <linux/inet.h>
...
...
@@ -57,6 +58,8 @@
#include <linux/mm.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_dev
*
ax25_dev
;
...
...
@@ -155,11 +158,9 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
frontlen
=
skb_headroom
(
skb
);
/* Address space + CTRL */
while
(
skb
->
len
>
0
)
{
save_flags
(
flags
);
cli
();
spin_lock_irqsave
(
&
ax25_frag_lock
,
flags
);
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
"
);
return
;
}
...
...
@@ -167,7 +168,7 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb)
if
(
skb
->
sk
!=
NULL
)
skb_set_owner_w
(
skbn
,
skb
->
sk
);
restore_flags
(
flags
);
spin_unlock_irqrestore
(
&
ax25_frag_lock
,
flags
);
len
=
(
paclen
>
skb
->
len
)
?
skb
->
len
:
paclen
;
...
...
net/ax25/ax25_route.c
View file @
0dfe6e55
...
...
@@ -40,10 +40,10 @@
* Jonathan(G4KLX) Support for packet forwarding.
* Arnaldo C. Melo s/suser/capable/
*/
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/timer.h>
#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/sched.h>
...
...
@@ -56,6 +56,7 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/system.h>
...
...
@@ -65,8 +66,9 @@
#include <linux/init.h>
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
...
...
@@ -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
)
{
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
)
{
s
=
ax25_rt
;
ax25_rt
=
ax25_rt
->
next
;
...
...
@@ -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
*
s
,
*
t
,
*
ax25_rt
;
struct
ax25_routes_struct
route
;
struct
ax25_route_opt_struct
rt_option
;
ax25_route
*
ax25_rt
;
ax25_dev
*
ax25_dev
;
int
i
;
switch
(
cmd
)
{
case
SIOCADDRT
:
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
.
port_addr
))
==
NULL
)
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
->
port_addr
))
==
NULL
)
return
-
EINVAL
;
if
(
route
.
digi_count
>
AX25_MAX_DIGIS
)
if
(
route
->
digi_count
>
AX25_MAX_DIGIS
)
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
)
{
kfree
(
ax25_rt
->
digipeat
);
ax25_rt
->
digipeat
=
NULL
;
}
if
(
route
.
digi_count
!=
0
)
{
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
if
(
route
->
digi_count
!=
0
)
{
if
((
ax25_rt
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
write_unlock
(
&
ax25_route_lock
);
return
-
ENOMEM
;
}
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
ndigi
=
route
.
digi_count
;
for
(
i
=
0
;
i
<
route
.
digi_count
;
i
++
)
{
ax25_rt
->
digipeat
->
ndigi
=
route
->
digi_count
;
for
(
i
=
0
;
i
<
route
->
digi_count
;
i
++
)
{
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
;
}
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
;
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
->
digipeat
=
NULL
;
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
)
{
write_unlock
(
&
ax25_route_lock
);
kfree
(
ax25_rt
);
return
-
ENOMEM
;
}
ax25_rt
->
digipeat
->
lastrepeat
=
-
1
;
ax25_rt
->
digipeat
->
ndigi
=
route
.
digi_count
;
for
(
i
=
0
;
i
<
route
.
digi_count
;
i
++
)
{
ax25_rt
->
digipeat
->
ndigi
=
route
->
digi_count
;
for
(
i
=
0
;
i
<
route
->
digi_count
;
i
++
)
{
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_route_list
=
ax25_rt
;
restore_flags
(
flags
);
break
;
write_unlock
(
&
ax25_route_lock
);
case
SIOCDELRT
:
if
(
copy_from_user
(
&
route
,
arg
,
sizeof
(
route
)))
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
route
.
port_addr
))
==
NULL
)
return
0
;
}
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
;
write_lock
(
&
ax25_route_lock
);
ax25_rt
=
ax25_route_list
;
while
(
ax25_rt
!=
NULL
)
{
s
=
ax25_rt
;
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
)
{
ax25_route_list
=
s
->
next
;
if
(
s
->
digipeat
!=
NULL
)
kfree
(
s
->
digipeat
);
kfree
(
s
);
ax25_rt_destroy
(
s
);
}
else
{
for
(
t
=
ax25_route_list
;
t
!=
NULL
;
t
=
t
->
next
)
{
if
(
t
->
next
==
s
)
{
t
->
next
=
s
->
next
;
if
(
s
->
digipeat
!=
NULL
)
kfree
(
s
->
digipeat
);
kfree
(
s
);
ax25_rt_destroy
(
s
);
break
;
}
}
}
}
}
break
;
write_unlock
(
&
ax25_route_lock
)
;
case
SIOCAX25OPTRT
:
if
(
copy_from_user
(
&
rt_option
,
arg
,
sizeof
(
rt_option
)))
return
-
EFAULT
;
if
((
ax25_dev
=
ax25_addr_ax25dev
(
&
rt_option
.
port_addr
))
==
NULL
)
return
0
;
}
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
;
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
)
{
switch
(
rt_option
.
cmd
)
{
write_lock
(
&
ax25_route_lock
);
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
:
switch
(
rt_option
.
arg
)
{
switch
(
rt_option
->
arg
)
{
case
' '
:
case
'D'
:
case
'V'
:
ax25_rt
->
ip_mode
=
rt_option
.
arg
;
ax25_rt
->
ip_mode
=
rt_option
->
arg
;
break
;
default:
return
-
EINVAL
;
err
=
-
EINVAL
;
goto
out
;
}
break
;
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:
return
-
EINVAL
;
}
return
0
;
}
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
;
int
i
;
cli
(
);
read_lock
(
&
ax25_route_lock
);
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)
if
(
pos
>
offset
+
length
)
break
;
}
sti
();
read_unlock
(
&
ax25_route_lock
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
(
offset
-
begin
);
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
len
;
}
/*
* 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_def_rt
=
NULL
;
ax25_route
*
ax25_rt
;
read_lock
(
&
ax25_route_lock
);
/*
* Bind to the physical interface we heard them on, or the default
* route if none is found;
...
...
@@ -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
)
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)
{
ax25_route
*
ax25_rt
;
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
;
if
((
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
ax25_rt
->
dev
))
==
NULL
)
return
-
EHOSTUNREACH
;
if
((
ax25
->
ax25_dev
=
ax25_dev_ax25dev
(
ax25_rt
->
dev
))
==
NULL
)
{
err
=
-
EHOSTUNREACH
;
goto
put
;
}
if
((
call
=
ax25_findbyuid
(
current
->
euid
))
==
NULL
)
{
if
(
ax25_uid_policy
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
return
-
EPERM
;
if
(
ax25_uid_policy
&&
!
capable
(
CAP_NET_BIND_SERVICE
))
{
err
=
-
EPERM
;
goto
put
;
}
call
=
(
ax25_address
*
)
ax25
->
ax25_dev
->
dev
->
dev_addr
;
}
ax25
->
source_addr
=
*
call
;
if
(
ax25_rt
->
digipeat
!=
NULL
)
{
if
((
ax25
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
return
-
ENOMEM
;
if
((
ax25
->
digipeat
=
kmalloc
(
sizeof
(
ax25_digi
),
GFP_ATOMIC
))
==
NULL
)
{
err
=
-
ENOMEM
;
goto
put
;
}
memcpy
(
ax25
->
digipeat
,
ax25_rt
->
digipeat
,
sizeof
(
ax25_digi
));
ax25_adjust_path
(
addr
,
ax25
->
digipeat
);
}
...
...
@@ -380,31 +472,32 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
if
(
ax25
->
sk
!=
NULL
)
ax25
->
sk
->
zapped
=
0
;
put:
ax25_put_route
(
ax25_rt
);
return
0
;
}
/*
* dl1bke 960117: build digipeater path
* dl1bke 960301: use the default route if it exists
*/
ax25_route
*
ax25_rt_find_route
(
ax25_address
*
addr
,
struct
net_device
*
dev
)
ax25_route
*
ax25_rt_find_route
(
ax25_route
*
route
,
ax25_address
*
addr
,
struct
net_device
*
dev
)
{
static
ax25_route
route
;
ax25_route
*
ax25_rt
;
if
((
ax25_rt
=
ax25_find_route
(
addr
,
dev
))
==
NULL
)
{
route
.
next
=
NULL
;
route
.
callsign
=
*
addr
;
route
.
dev
=
dev
;
route
.
digipeat
=
NULL
;
route
.
ip_mode
=
' '
;
return
&
route
;
}
if
((
ax25_rt
=
ax25_get_route
(
addr
,
dev
)))
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
;
unsigned
char
*
bp
;
...
...
@@ -440,6 +533,7 @@ void __exit ax25_rt_free(void)
{
ax25_route
*
s
,
*
ax25_rt
=
ax25_route_list
;
write_unlock
(
&
ax25_route_lock
);
while
(
ax25_rt
!=
NULL
)
{
s
=
ax25_rt
;
ax25_rt
=
ax25_rt
->
next
;
...
...
@@ -449,4 +543,5 @@ void __exit ax25_rt_free(void)
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
case
AX25_DM
:
case
AX25_UA
:
if
(
pf
)
ax25_disconnect
(
ax25
,
0
);
if
(
pf
)
ax25_disconnect
(
ax25
,
0
);
break
;
case
AX25_I
:
...
...
@@ -397,7 +398,8 @@ static int ax25_std_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frame
}
ax25_frames_acked
(
ax25
,
nr
);
if
(
ax25
->
condition
&
AX25_COND_OWN_RX_BUSY
)
{
if
(
pf
)
ax25_std_enquiry_response
(
ax25
);
if
(
pf
)
ax25_std_enquiry_response
(
ax25
);
break
;
}
if
(
ns
==
ax25
->
vr
)
{
...
...
net/ax25/ax25_std_timer.c
View file @
0dfe6e55
...
...
@@ -47,7 +47,6 @@
void
ax25_std_heartbeat_expiry
(
ax25_cb
*
ax25
)
{
switch
(
ax25
->
state
)
{
case
AX25_STATE_0
:
/* Magic here: If we listen() and a new link dies before it
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 @@
#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
#include <linux/inet.h>
#include <linux/netdevice.h>
...
...
@@ -47,17 +48,23 @@
*/
static
ax25_uid_assoc
*
ax25_uid_list
;
static
rwlock_t
ax25_uid_lock
=
RW_LOCK_UNLOCKED
;
int
ax25_uid_policy
=
0
;
ax25_address
*
ax25_findbyuid
(
uid_t
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
)
{
if
(
ax25_uid
->
uid
==
uid
)
return
&
ax25_uid
->
call
;
if
(
ax25_uid
->
uid
==
uid
)
{
res
=
&
ax25_uid
->
call
;
break
;
}
}
read_unlock
(
&
ax25_uid_lock
);
return
NULL
;
}
...
...
@@ -65,15 +72,21 @@ ax25_address *ax25_findbyuid(uid_t uid)
int
ax25_uid_ioctl
(
int
cmd
,
struct
sockaddr_ax25
*
sax
)
{
ax25_uid_assoc
*
s
,
*
ax25_uid
;
unsigned
long
flag
s
;
unsigned
long
re
s
;
switch
(
cmd
)
{
case
SIOCAX25GETUID
:
res
=
-
ENOENT
;
read_lock
(
&
ax25_uid_lock
);
for
(
ax25_uid
=
ax25_uid_list
;
ax25_uid
!=
NULL
;
ax25_uid
=
ax25_uid
->
next
)
{
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
return
ax25_uid
->
uid
;
if
(
ax25cmp
(
&
sax
->
sax25_call
,
&
ax25_uid
->
call
)
==
0
)
{
res
=
ax25_uid
->
uid
;
break
;
}
return
-
ENOENT
;
}
read_unlock
(
&
ax25_uid_lock
);
return
res
;
case
SIOCAX25ADDUID
:
if
(
!
capable
(
CAP_NET_ADMIN
))
...
...
@@ -84,40 +97,48 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
return
-
EINVAL
;
if
((
ax25_uid
=
kmalloc
(
sizeof
(
*
ax25_uid
),
GFP_KERNEL
))
==
NULL
)
return
-
ENOMEM
;
ax25_uid
->
uid
=
sax
->
sax25_uid
;
ax25_uid
->
call
=
sax
->
sax25_call
;
save_flags
(
flags
);
cli
();
write_lock
(
&
ax25_uid_lock
);
ax25_uid
->
next
=
ax25_uid_list
;
ax25_uid_list
=
ax25_uid
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
return
0
;
case
SIOCAX25DELUID
:
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
write_lock
(
&
ax25_uid_lock
);
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
;
}
if
(
ax25_uid
==
NULL
)
}
if
(
ax25_uid
==
NULL
)
{
write_unlock
(
&
ax25_uid_lock
);
return
-
ENOENT
;
save_flags
(
flags
);
cli
();
}
if
((
s
=
ax25_uid_list
)
==
ax25_uid
)
{
ax25_uid_list
=
s
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
kfree
(
ax25_uid
);
return
0
;
}
while
(
s
!=
NULL
&&
s
->
next
!=
NULL
)
{
if
(
s
->
next
==
ax25_uid
)
{
s
->
next
=
ax25_uid
->
next
;
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
kfree
(
ax25_uid
);
return
0
;
}
s
=
s
->
next
;
}
restore_flags
(
flags
);
write_unlock
(
&
ax25_uid_lock
);
return
-
ENOENT
;
default:
...
...
@@ -134,8 +155,7 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
off_t
pos
=
0
;
off_t
begin
=
0
;
cli
();
read_lock
(
&
ax25_uid_lock
);
len
+=
sprintf
(
buffer
,
"Policy: %d
\n
"
,
ax25_uid_policy
);
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)
if
(
pos
>
offset
+
length
)
break
;
}
sti
();
read_unlock
(
&
ax25_uid_lock
);
*
start
=
buffer
+
(
offset
-
begin
);
len
-=
offset
-
begin
;
if
(
len
>
length
)
len
=
length
;
if
(
len
>
length
)
len
=
length
;
return
len
;
}
...
...
@@ -167,12 +187,16 @@ int ax25_uid_get_info(char *buffer, char **start, off_t offset, int length)
*/
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
)
{
s
=
ax25_uid
;
ax25_uid
=
ax25_uid
->
next
;
kfree
(
s
);
}
ax25_uid_list
=
NULL
;
write_unlock
(
&
ax25_uid_lock
);
}
net/ax25/sysctl_net_ax25.c
View file @
0dfe6e55
...
...
@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/mm.h>
#include <linux/sysctl.h>
#include <linux/spinlock.h>
#include <net/ax25.h>
static
int
min_ipdefmode
[]
=
{
0
},
max_ipdefmode
[]
=
{
1
};
...
...
@@ -102,9 +103,11 @@ static const ctl_table ax25_param_table[] = {
void
ax25_register_sysctl
(
void
)
{
unsigned
long
flags
;
ax25_dev
*
ax25_dev
;
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
)
ax25_table_size
+=
sizeof
(
ctl_table
);
...
...
@@ -119,6 +122,7 @@ void ax25_register_sysctl(void)
while
(
n
--
)
kfree
(
ax25_table
[
n
].
child
);
kfree
(
ax25_table
);
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
return
;
}
memcpy
(
child
,
ax25_param_table
,
sizeof
(
ax25_param_table
));
...
...
@@ -144,6 +148,7 @@ void ax25_register_sysctl(void)
n
++
;
}
spin_unlock_irqrestore
(
&
ax25_dev_lock
,
flags
);
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