~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/x25/x25_route.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      X.25 Packet Layer release 002
  3  *
  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. 
  6  *
  7  *      This code REQUIRES 2.1.15 or higher
  8  *
  9  *      This module:
 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.
 14  *
 15  *      History
 16  *      X.25 001        Jonathan Naylor Started coding.
 17  */
 18 
 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>
 24 #include <linux/in.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>
 33 #include <net/arp.h>
 34 #include <linux/if_arp.h>
 35 #include <linux/skbuff.h>
 36 #include <net/sock.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 */
 42 #include <linux/mm.h>
 43 #include <linux/interrupt.h>
 44 #include <linux/notifier.h>
 45 #include <net/x25.h>
 46 
 47 static struct x25_route *x25_route_list = NULL;
 48 
 49 /*
 50  *      Add a new route.
 51  */
 52 static int x25_add_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
 53 {
 54         struct x25_route *x25_route;
 55         unsigned long flags;
 56 
 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)
 59                         return -EINVAL;
 60 
 61         if ((x25_route = kmalloc(sizeof(*x25_route), GFP_ATOMIC)) == NULL)
 62                 return -ENOMEM;
 63 
 64         strcpy(x25_route->address.x25_addr, "000000000000000");
 65         memcpy(x25_route->address.x25_addr, address->x25_addr, sigdigits);
 66 
 67         x25_route->sigdigits = sigdigits;
 68         x25_route->dev       = dev;
 69 
 70         save_flags(flags); cli();
 71         x25_route->next = x25_route_list;
 72         x25_route_list  = x25_route;
 73         restore_flags(flags);
 74 
 75         return 0;
 76 }
 77 
 78 static void x25_remove_route(struct x25_route *x25_route)
 79 {
 80         struct x25_route *s;
 81         unsigned long flags;
 82 
 83         save_flags(flags);
 84         cli();
 85 
 86         if ((s = x25_route_list) == x25_route) {
 87                 x25_route_list = x25_route->next;
 88                 restore_flags(flags);
 89                 kfree(x25_route);
 90                 return;
 91         }
 92 
 93         while (s != NULL && s->next != NULL) {
 94                 if (s->next == x25_route) {
 95                         s->next = x25_route->next;
 96                         restore_flags(flags);
 97                         kfree(x25_route);
 98                         return;
 99                 }
100 
101                 s = s->next;
102         }
103 
104         restore_flags(flags);
105 }
106 
107 static int x25_del_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
108 {
109         struct x25_route *x25_route;
110 
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);
114                         return 0;
115                 }
116         }
117 
118         return -EINVAL;
119 }
120 
121 /*
122  *      A device has been removed, remove its routes.
123  */
124 void x25_route_device_down(struct net_device *dev)
125 {
126         struct x25_route *route, *x25_route = x25_route_list;
127 
128         while (x25_route != NULL) {
129                 route     = x25_route;
130                 x25_route = x25_route->next;
131 
132                 if (route->dev == dev)
133                         x25_remove_route(route);
134         }
135 }
136 
137 /*
138  *      Check that the device given is a valid X.25 interface that is "up".
139  */
140 struct net_device *x25_dev_get(char *devname)
141 {
142         struct net_device *dev;
143 
144         if ((dev = dev_get_by_name(devname)) == NULL)
145                 return NULL;
146 
147         if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25
148 #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
149            || dev->type == ARPHRD_ETHER
150 #endif
151            ))
152                 return dev;
153 
154         dev_put(dev);
155 
156         return NULL;
157 }
158 
159 /*
160  *      Find a device given an X.25 address.
161  */
162 struct net_device *x25_get_route(x25_address *addr)
163 {
164         struct x25_route *route, *use = NULL;
165 
166         for (route = x25_route_list; route != NULL; route = route->next) {
167                 if (memcmp(&route->address, addr, route->sigdigits) == 0) {
168                         if (use == NULL) {
169                                 use = route;
170                         } else {
171                                 if (route->sigdigits > use->sigdigits)
172                                         use = route;
173                         }
174                 }
175         }
176 
177         return (use != NULL) ? use->dev : NULL;
178 }
179 
180 /*
181  *      Handle the ioctls that control the routing functions.
182  */
183 int x25_route_ioctl(unsigned int cmd, void *arg)
184 {
185         struct x25_route_struct x25_route;
186         struct net_device *dev;
187         int err;
188 
189         switch (cmd) {
190 
191                 case SIOCADDRT:
192                         if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
193                                 return -EFAULT;
194                         if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
195                                 return -EINVAL;
196                         if ((dev = x25_dev_get(x25_route.device)) == NULL)
197                                 return -EINVAL;
198                         err = x25_add_route(&x25_route.address, x25_route.sigdigits, dev);
199                         dev_put(dev);
200                         return err;
201 
202                 case SIOCDELRT:
203                         if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
204                                 return -EFAULT;
205                         if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
206                                 return -EINVAL;
207                         if ((dev = x25_dev_get(x25_route.device)) == NULL)
208                                 return -EINVAL;
209                         err = x25_del_route(&x25_route.address, x25_route.sigdigits, dev);
210                         dev_put(dev);
211                         return err;
212 
213                 default:
214                         return -EINVAL;
215         }
216 
217         return 0;
218 }
219 
220 int x25_routes_get_info(char *buffer, char **start, off_t offset, int length)
221 {
222         struct x25_route *x25_route;
223         int len     = 0;
224         off_t pos   = 0;
225         off_t begin = 0;
226 
227         cli();
228 
229         len += sprintf(buffer, "address          digits  device\n");
230 
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 : "???");
236 
237                 pos = begin + len;
238 
239                 if (pos < offset) {
240                         len   = 0;
241                         begin = pos;
242                 }
243 
244                 if (pos > offset + length)
245                         break;
246         }
247 
248         sti();
249 
250         *start = buffer + (offset - begin);
251         len   -= (offset - begin);
252 
253         if (len > length) len = length;
254 
255         return len;
256 } 
257 
258 #ifdef MODULE
259 
260 /*
261  *      Release all memory associated with X.25 routing structures.
262  */
263 void x25_route_free(void)
264 {
265         struct x25_route *route, *x25_route = x25_route_list;
266 
267         while (x25_route != NULL) {
268                 route     = x25_route;
269                 x25_route = x25_route->next;
270 
271                 x25_remove_route(route);
272         }
273 }
274 
275 #endif
276 
277 #endif
278 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.