2 * X.25 Packet Layer release 002
4 * This is ALPHA test software. This code may break your machine, randomly fail to work with new
5 * releases, misbehave and/or generally screw up. It might even work.
7 * This code REQUIRES 2.1.15 or higher
10 * This module is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
16 * X.25 001 Jonathan Naylor Started coding.
19 #include <linux/config.h>
20 #if defined(CONFIG_X25) || defined(CONFIG_X25_MODULE)
21 #include <linux/errno.h>
22 #include <linux/types.h>
23 #include <linux/socket.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/timer.h>
28 #include <linux/string.h>
29 #include <linux/sockios.h>
30 #include <linux/net.h>
31 #include <linux/inet.h>
32 #include <linux/netdevice.h>
34 #include <linux/if_arp.h>
35 #include <linux/skbuff.h>
37 #include <asm/segment.h>
38 #include <asm/system.h>
39 #include <asm/uaccess.h>
40 #include <linux/fcntl.h>
41 #include <linux/termios.h> /* For TIOCINQ/OUTQ */
43 #include <linux/interrupt.h>
44 #include <linux/notifier.h>
47 static struct x25_route
*x25_route_list
= NULL
;
52 static int x25_add_route(x25_address
*address
, unsigned int sigdigits
, struct net_device
*dev
)
54 struct x25_route
*x25_route
;
57 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
)
58 if (memcmp(&x25_route
->address
, address
, sigdigits
) == 0 && x25_route
->sigdigits
== sigdigits
)
61 if ((x25_route
= kmalloc(sizeof(*x25_route
), GFP_ATOMIC
)) == NULL
)
64 strcpy(x25_route
->address
.x25_addr
, "000000000000000");
65 memcpy(x25_route
->address
.x25_addr
, address
->x25_addr
, sigdigits
);
67 x25_route
->sigdigits
= sigdigits
;
70 save_flags(flags
); cli();
71 x25_route
->next
= x25_route_list
;
72 x25_route_list
= x25_route
;
78 static void x25_remove_route(struct x25_route
*x25_route
)
86 if ((s
= x25_route_list
) == x25_route
) {
87 x25_route_list
= x25_route
->next
;
93 while (s
!= NULL
&& s
->next
!= NULL
) {
94 if (s
->next
== x25_route
) {
95 s
->next
= x25_route
->next
;
104 restore_flags(flags
);
107 static int x25_del_route(x25_address
*address
, unsigned int sigdigits
, struct net_device
*dev
)
109 struct x25_route
*x25_route
;
111 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
) {
112 if (memcmp(&x25_route
->address
, address
, sigdigits
) == 0 && x25_route
->sigdigits
== sigdigits
&& x25_route
->dev
== dev
) {
113 x25_remove_route(x25_route
);
122 * A device has been removed, remove its routes.
124 void x25_route_device_down(struct net_device
*dev
)
126 struct x25_route
*route
, *x25_route
= x25_route_list
;
128 while (x25_route
!= NULL
) {
130 x25_route
= x25_route
->next
;
132 if (route
->dev
== dev
)
133 x25_remove_route(route
);
138 * Check that the device given is a valid X.25 interface that is "up".
140 struct net_device
*x25_dev_get(char *devname
)
142 struct net_device
*dev
;
144 if ((dev
= dev_get_by_name(devname
)) == NULL
)
147 if ((dev
->flags
& IFF_UP
) && (dev
->type
== ARPHRD_X25
148 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
149 || dev
->type
== ARPHRD_ETHER
160 * Find a device given an X.25 address.
162 struct net_device
*x25_get_route(x25_address
*addr
)
164 struct x25_route
*route
, *use
= NULL
;
166 for (route
= x25_route_list
; route
!= NULL
; route
= route
->next
) {
167 if (memcmp(&route
->address
, addr
, route
->sigdigits
) == 0) {
171 if (route
->sigdigits
> use
->sigdigits
)
177 return (use
!= NULL
) ? use
->dev
: NULL
;
181 * Handle the ioctls that control the routing functions.
183 int x25_route_ioctl(unsigned int cmd
, void *arg
)
185 struct x25_route_struct x25_route
;
186 struct net_device
*dev
;
192 if (copy_from_user(&x25_route
, arg
, sizeof(struct x25_route_struct
)))
194 if (x25_route
.sigdigits
< 0 || x25_route
.sigdigits
> 15)
196 if ((dev
= x25_dev_get(x25_route
.device
)) == NULL
)
198 err
= x25_add_route(&x25_route
.address
, x25_route
.sigdigits
, dev
);
203 if (copy_from_user(&x25_route
, arg
, sizeof(struct x25_route_struct
)))
205 if (x25_route
.sigdigits
< 0 || x25_route
.sigdigits
> 15)
207 if ((dev
= x25_dev_get(x25_route
.device
)) == NULL
)
209 err
= x25_del_route(&x25_route
.address
, x25_route
.sigdigits
, dev
);
220 int x25_routes_get_info(char *buffer
, char **start
, off_t offset
, int length
, int dummy
)
222 struct x25_route
*x25_route
;
229 len
+= sprintf(buffer
, "address digits device\n");
231 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
) {
232 len
+= sprintf(buffer
+ len
, "%-15s %-6d %-5s\n",
233 x25_route
->address
.x25_addr
,
234 x25_route
->sigdigits
,
235 (x25_route
->dev
!= NULL
) ? x25_route
->dev
->name
: "???");
244 if (pos
> offset
+ length
)
250 *start
= buffer
+ (offset
- begin
);
251 len
-= (offset
- begin
);
253 if (len
> length
) len
= length
;
261 * Release all memory associated with X.25 routing structures.
263 void x25_route_free(void)
265 struct x25_route
*route
, *x25_route
= x25_route_list
;
267 while (x25_route
!= NULL
) {
269 x25_route
= x25_route
->next
;
271 x25_remove_route(route
);