2 * X.25 Packet Layer release 001
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>
45 #include <linux/firewall.h>
48 static struct x25_route
*x25_route_list
= NULL
;
53 static int x25_add_route(x25_address
*address
, unsigned int sigdigits
, struct device
*dev
)
55 struct x25_route
*x25_route
;
58 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
)
59 if (memcmp(&x25_route
->address
, address
, sigdigits
) == 0 && x25_route
->sigdigits
== sigdigits
)
62 if ((x25_route
= kmalloc(sizeof(*x25_route
), GFP_ATOMIC
)) == NULL
)
65 strcpy(x25_route
->address
.x25_addr
, "000000000000000");
66 memcpy(x25_route
->address
.x25_addr
, address
->x25_addr
, sigdigits
);
68 x25_route
->sigdigits
= sigdigits
;
71 save_flags(flags
); cli();
72 x25_route
->next
= x25_route_list
;
73 x25_route_list
= x25_route
;
79 static void x25_remove_route(struct x25_route
*x25_route
)
87 if ((s
= x25_route_list
) == x25_route
) {
88 x25_route_list
= x25_route
->next
;
94 while (s
!= NULL
&& s
->next
!= NULL
) {
95 if (s
->next
== x25_route
) {
96 s
->next
= x25_route
->next
;
105 restore_flags(flags
);
108 static int x25_del_route(x25_address
*address
, unsigned int sigdigits
, struct device
*dev
)
110 struct x25_route
*x25_route
;
112 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
) {
113 if (memcmp(&x25_route
->address
, address
, sigdigits
) == 0 && x25_route
->sigdigits
== sigdigits
&& x25_route
->dev
== dev
) {
114 x25_remove_route(x25_route
);
123 * A device has been removed, remove its routes.
125 void x25_route_device_down(struct device
*dev
)
127 struct x25_route
*route
, *x25_route
= x25_route_list
;
129 while (x25_route
!= NULL
) {
131 x25_route
= x25_route
->next
;
133 if (route
->dev
== dev
)
134 x25_remove_route(route
);
139 * Check that the device given is a valid X.25 interface that is "up".
141 struct device
*x25_dev_get(char *devname
)
145 if ((dev
= dev_get(devname
)) == NULL
)
148 if ((dev
->flags
& IFF_UP
) && (dev
->type
== ARPHRD_X25
149 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
150 || dev
->type
== ARPHRD_ETHER
159 * Find a device given an X.25 address.
161 struct device
*x25_get_route(x25_address
*addr
)
163 struct x25_route
*route
, *use
= NULL
;
165 for (route
= x25_route_list
; route
!= NULL
; route
= route
->next
) {
166 if (memcmp(&route
->address
, addr
, route
->sigdigits
) == 0) {
170 if (route
->sigdigits
> use
->sigdigits
)
176 return (use
!= NULL
) ? use
->dev
: NULL
;
180 * Handle the ioctls that control the routing functions.
182 int x25_route_ioctl(unsigned int cmd
, void *arg
)
184 struct x25_route_struct x25_route
;
191 if ((err
= verify_area(VERIFY_READ
, arg
, sizeof(struct x25_route_struct
))) != 0)
193 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 return x25_add_route(&x25_route
.address
, x25_route
.sigdigits
, dev
);
201 if ((err
= verify_area(VERIFY_READ
, arg
, sizeof(struct x25_route_struct
))) != 0)
203 copy_from_user(&x25_route
, arg
, sizeof(struct x25_route_struct
));
204 if (x25_route
.sigdigits
< 0 || x25_route
.sigdigits
> 15)
206 if ((dev
= x25_dev_get(x25_route
.device
)) == NULL
)
208 return x25_del_route(&x25_route
.address
, x25_route
.sigdigits
, dev
);
217 int x25_routes_get_info(char *buffer
, char **start
, off_t offset
, int length
, int dummy
)
219 struct x25_route
*x25_route
;
226 len
+= sprintf(buffer
, "address digits device\n");
228 for (x25_route
= x25_route_list
; x25_route
!= NULL
; x25_route
= x25_route
->next
) {
229 len
+= sprintf(buffer
+ len
, "%-15s %-6d %-5s\n",
230 x25_route
->address
.x25_addr
, x25_route
->sigdigits
,
231 (x25_route
->dev
!= NULL
) ? x25_route
->dev
->name
: "???");
240 if (pos
> offset
+ length
)
246 *start
= buffer
+ (offset
- begin
);
247 len
-= (offset
- begin
);
249 if (len
> length
) len
= length
;
257 * Release all memory associated with X.25 routing structures.
259 void x25_route_free(void)
261 struct x25_route
*route
, *x25_route
= x25_route_list
;
263 while (x25_route
!= NULL
) {
265 x25_route
= x25_route
->next
;
267 x25_remove_route(route
);