Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
net
x25
x25_route.c
Go to the documentation of this file.
1
/*
2
* X.25 Packet Layer release 002
3
*
4
* This is ALPHA test software. This code may break your machine,
5
* randomly fail to work with new releases, misbehave and/or generally
6
* screw up. It might even work.
7
*
8
* This code REQUIRES 2.1.15 or higher
9
*
10
* This module:
11
* This module is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU General Public License
13
* as published by the Free Software Foundation; either version
14
* 2 of the License, or (at your option) any later version.
15
*
16
* History
17
* X.25 001 Jonathan Naylor Started coding.
18
*/
19
20
#include <linux/if_arp.h>
21
#include <
linux/init.h
>
22
#include <linux/slab.h>
23
#include <
net/x25.h
>
24
25
LIST_HEAD
(x25_route_list);
26
DEFINE_RWLOCK
(x25_route_list_lock);
27
28
/*
29
* Add a new route.
30
*/
31
static
int
x25_add_route(
struct
x25_address
*
address
,
unsigned
int
sigdigits,
32
struct
net_device
*
dev
)
33
{
34
struct
x25_route
*rt;
35
struct
list_head
*
entry
;
36
int
rc
= -
EINVAL
;
37
38
write_lock_bh
(&x25_route_list_lock);
39
40
list_for_each
(entry, &x25_route_list) {
41
rt =
list_entry
(entry,
struct
x25_route
,
node
);
42
43
if
(!
memcmp
(&rt->
address
, address, sigdigits) &&
44
rt->
sigdigits
== sigdigits)
45
goto
out
;
46
}
47
48
rt =
kmalloc
(
sizeof
(*rt),
GFP_ATOMIC
);
49
rc = -
ENOMEM
;
50
if
(!rt)
51
goto
out
;
52
53
strcpy
(rt->
address
.x25_addr,
"000000000000000"
);
54
memcpy
(rt->
address
.x25_addr, address->
x25_addr
, sigdigits);
55
56
rt->
sigdigits
= sigdigits;
57
rt->
dev
=
dev
;
58
atomic_set
(&rt->
refcnt
, 1);
59
60
list_add(&rt->
node
, &x25_route_list);
61
rc = 0;
62
out
:
63
write_unlock_bh
(&x25_route_list_lock);
64
return
rc
;
65
}
66
74
static
void
__x25_remove_route(
struct
x25_route
*rt)
75
{
76
if
(rt->
node
.next) {
77
list_del
(&rt->
node
);
78
x25_route_put(rt);
79
}
80
}
81
82
static
int
x25_del_route(
struct
x25_address
*address,
unsigned
int
sigdigits,
83
struct
net_device
*dev)
84
{
85
struct
x25_route
*rt;
86
struct
list_head
*
entry
;
87
int
rc = -
EINVAL
;
88
89
write_lock_bh
(&x25_route_list_lock);
90
91
list_for_each
(entry, &x25_route_list) {
92
rt =
list_entry
(entry,
struct
x25_route
,
node
);
93
94
if
(!
memcmp
(&rt->
address
, address, sigdigits) &&
95
rt->
sigdigits
== sigdigits && rt->
dev
== dev) {
96
__x25_remove_route(rt);
97
rc = 0;
98
break
;
99
}
100
}
101
102
write_unlock_bh
(&x25_route_list_lock);
103
return
rc
;
104
}
105
106
/*
107
* A device has been removed, remove its routes.
108
*/
109
void
x25_route_device_down
(
struct
net_device
*dev)
110
{
111
struct
x25_route
*rt;
112
struct
list_head
*
entry
, *
tmp
;
113
114
write_lock_bh
(&
x25_route_list_lock
);
115
116
list_for_each_safe
(entry, tmp, &
x25_route_list
) {
117
rt =
list_entry
(entry,
struct
x25_route
,
node
);
118
119
if
(rt->
dev
== dev)
120
__x25_remove_route(rt);
121
}
122
write_unlock_bh
(&
x25_route_list_lock
);
123
124
/* Remove any related forwarding */
125
x25_clear_forward_by_dev
(dev);
126
}
127
128
/*
129
* Check that the device given is a valid X.25 interface that is "up".
130
*/
131
struct
net_device
*
x25_dev_get
(
char
*devname)
132
{
133
struct
net_device
*dev =
dev_get_by_name
(&
init_net
, devname);
134
135
if
(dev &&
136
(!(dev->
flags
&
IFF_UP
) || (dev->
type
!=
ARPHRD_X25
137
#
if
IS_ENABLED
(CONFIG_LLC)
138
&& dev->
type
!=
ARPHRD_ETHER
139
#
endif
140
))){
141
dev_put(dev);
142
dev =
NULL
;
143
}
144
145
return
dev
;
146
}
147
154
struct
x25_route
*
x25_get_route
(
struct
x25_address
*
addr
)
155
{
156
struct
x25_route
*rt, *use =
NULL
;
157
struct
list_head
*
entry
;
158
159
read_lock_bh
(&
x25_route_list_lock
);
160
161
list_for_each
(entry, &
x25_route_list
) {
162
rt =
list_entry
(entry,
struct
x25_route
,
node
);
163
164
if
(!
memcmp
(&rt->
address
, addr, rt->
sigdigits
)) {
165
if
(!use)
166
use = rt;
167
else
if
(rt->
sigdigits
> use->
sigdigits
)
168
use = rt;
169
}
170
}
171
172
if
(use)
173
x25_route_hold(use);
174
175
read_unlock_bh
(&
x25_route_list_lock
);
176
return
use;
177
}
178
179
/*
180
* Handle the ioctls that control the routing functions.
181
*/
182
int
x25_route_ioctl
(
unsigned
int
cmd
,
void
__user *
arg
)
183
{
184
struct
x25_route_struct
rt;
185
struct
net_device
*
dev
;
186
int
rc = -
EINVAL
;
187
188
if
(cmd !=
SIOCADDRT
&& cmd !=
SIOCDELRT
)
189
goto
out
;
190
191
rc = -
EFAULT
;
192
if
(
copy_from_user
(&rt, arg,
sizeof
(rt)))
193
goto
out
;
194
195
rc = -
EINVAL
;
196
if
(rt.
sigdigits
> 15)
197
goto
out
;
198
199
dev =
x25_dev_get
(rt.
device
);
200
if
(!dev)
201
goto
out
;
202
203
if
(cmd ==
SIOCADDRT
)
204
rc = x25_add_route(&rt.
address
, rt.
sigdigits
, dev);
205
else
206
rc = x25_del_route(&rt.
address
, rt.
sigdigits
, dev);
207
dev_put(dev);
208
out
:
209
return
rc
;
210
}
211
212
/*
213
* Release all memory associated with X.25 routing structures.
214
*/
215
void
__exit
x25_route_free
(
void
)
216
{
217
struct
x25_route
*rt;
218
struct
list_head
*
entry
, *
tmp
;
219
220
write_lock_bh
(&
x25_route_list_lock
);
221
list_for_each_safe
(entry, tmp, &
x25_route_list
) {
222
rt =
list_entry
(entry,
struct
x25_route
,
node
);
223
__x25_remove_route(rt);
224
}
225
write_unlock_bh
(&
x25_route_list_lock
);
226
}
Generated on Thu Jan 10 2013 15:02:38 for Linux Kernel by
1.8.2