x25_route.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  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. #include <linux/config.h>
  19. #include <linux/errno.h>
  20. #include <linux/types.h>
  21. #include <linux/socket.h>
  22. #include <linux/in.h>
  23. #include <linux/kernel.h>
  24. #include <linux/sched.h>
  25. #include <linux/timer.h>
  26. #include <linux/string.h>
  27. #include <linux/sockios.h>
  28. #include <linux/net.h>
  29. #include <linux/inet.h>
  30. #include <linux/netdevice.h>
  31. #include <net/arp.h>
  32. #include <linux/if_arp.h>
  33. #include <linux/skbuff.h>
  34. #include <net/sock.h>
  35. #include <asm/segment.h>
  36. #include <asm/system.h>
  37. #include <asm/uaccess.h>
  38. #include <linux/fcntl.h>
  39. #include <linux/termios.h> /* For TIOCINQ/OUTQ */
  40. #include <linux/mm.h>
  41. #include <linux/interrupt.h>
  42. #include <linux/notifier.h>
  43. #include <linux/init.h>
  44. #include <net/x25.h>
  45. static struct x25_route *x25_route_list /* = NULL initially */;
  46. /*
  47.  * Add a new route.
  48.  */
  49. static int x25_add_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
  50. {
  51. struct x25_route *x25_route;
  52. unsigned long flags;
  53. for (x25_route = x25_route_list; x25_route != NULL; x25_route = x25_route->next)
  54. if (memcmp(&x25_route->address, address, sigdigits) == 0 && x25_route->sigdigits == sigdigits)
  55. return -EINVAL;
  56. if ((x25_route = kmalloc(sizeof(*x25_route), GFP_ATOMIC)) == NULL)
  57. return -ENOMEM;
  58. strcpy(x25_route->address.x25_addr, "000000000000000");
  59. memcpy(x25_route->address.x25_addr, address->x25_addr, sigdigits);
  60. x25_route->sigdigits = sigdigits;
  61. x25_route->dev       = dev;
  62. save_flags(flags); cli();
  63. x25_route->next = x25_route_list;
  64. x25_route_list  = x25_route;
  65. restore_flags(flags);
  66. return 0;
  67. }
  68. static void x25_remove_route(struct x25_route *x25_route)
  69. {
  70. struct x25_route *s;
  71. unsigned long flags;
  72. save_flags(flags);
  73. cli();
  74. if ((s = x25_route_list) == x25_route) {
  75. x25_route_list = x25_route->next;
  76. restore_flags(flags);
  77. kfree(x25_route);
  78. return;
  79. }
  80. while (s != NULL && s->next != NULL) {
  81. if (s->next == x25_route) {
  82. s->next = x25_route->next;
  83. restore_flags(flags);
  84. kfree(x25_route);
  85. return;
  86. }
  87. s = s->next;
  88. }
  89. restore_flags(flags);
  90. }
  91. static int x25_del_route(x25_address *address, unsigned int sigdigits, struct net_device *dev)
  92. {
  93. struct x25_route *x25_route;
  94. for (x25_route = x25_route_list; x25_route != NULL; x25_route = x25_route->next) {
  95. if (memcmp(&x25_route->address, address, sigdigits) == 0 && x25_route->sigdigits == sigdigits && x25_route->dev == dev) {
  96. x25_remove_route(x25_route);
  97. return 0;
  98. }
  99. }
  100. return -EINVAL;
  101. }
  102. /*
  103.  * A device has been removed, remove its routes.
  104.  */
  105. void x25_route_device_down(struct net_device *dev)
  106. {
  107. struct x25_route *route, *x25_route = x25_route_list;
  108. while (x25_route != NULL) {
  109. route     = x25_route;
  110. x25_route = x25_route->next;
  111. if (route->dev == dev)
  112. x25_remove_route(route);
  113. }
  114. }
  115. /*
  116.  * Check that the device given is a valid X.25 interface that is "up".
  117.  */
  118. struct net_device *x25_dev_get(char *devname)
  119. {
  120. struct net_device *dev;
  121. if ((dev = dev_get_by_name(devname)) == NULL)
  122. return NULL;
  123. if ((dev->flags & IFF_UP) && (dev->type == ARPHRD_X25
  124. #if defined(CONFIG_LLC) || defined(CONFIG_LLC_MODULE)
  125.    || dev->type == ARPHRD_ETHER
  126. #endif
  127.    ))
  128. return dev;
  129. dev_put(dev);
  130. return NULL;
  131. }
  132. /*
  133.  * Find a device given an X.25 address.
  134.  */
  135. struct net_device *x25_get_route(x25_address *addr)
  136. {
  137. struct x25_route *route, *use = NULL;
  138. for (route = x25_route_list; route != NULL; route = route->next) {
  139. if (memcmp(&route->address, addr, route->sigdigits) == 0) {
  140. if (use == NULL) {
  141. use = route;
  142. } else {
  143. if (route->sigdigits > use->sigdigits)
  144. use = route;
  145. }
  146. }
  147. }
  148. return (use != NULL) ? use->dev : NULL;
  149. }
  150. /*
  151.  * Handle the ioctls that control the routing functions.
  152.  */
  153. int x25_route_ioctl(unsigned int cmd, void *arg)
  154. {
  155. struct x25_route_struct x25_route;
  156. struct net_device *dev;
  157. int err;
  158. switch (cmd) {
  159. case SIOCADDRT:
  160. if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
  161. return -EFAULT;
  162. if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
  163. return -EINVAL;
  164. if ((dev = x25_dev_get(x25_route.device)) == NULL)
  165. return -EINVAL;
  166. err = x25_add_route(&x25_route.address, x25_route.sigdigits, dev);
  167. dev_put(dev);
  168. return err;
  169. case SIOCDELRT:
  170. if (copy_from_user(&x25_route, arg, sizeof(struct x25_route_struct)))
  171. return -EFAULT;
  172. if (x25_route.sigdigits < 0 || x25_route.sigdigits > 15)
  173. return -EINVAL;
  174. if ((dev = x25_dev_get(x25_route.device)) == NULL)
  175. return -EINVAL;
  176. err = x25_del_route(&x25_route.address, x25_route.sigdigits, dev);
  177. dev_put(dev);
  178. return err;
  179. default:
  180. return -EINVAL;
  181. }
  182. return 0;
  183. }
  184. int x25_routes_get_info(char *buffer, char **start, off_t offset, int length)
  185. {
  186. struct x25_route *x25_route;
  187. int len     = 0;
  188. off_t pos   = 0;
  189. off_t begin = 0;
  190. cli();
  191. len += sprintf(buffer, "address          digits  devicen");
  192. for (x25_route = x25_route_list; x25_route != NULL; x25_route = x25_route->next) {
  193. len += sprintf(buffer + len, "%-15s  %-6d  %-5sn",
  194. x25_route->address.x25_addr,
  195. x25_route->sigdigits,
  196. (x25_route->dev != NULL) ? x25_route->dev->name : "???");
  197. pos = begin + len;
  198. if (pos < offset) {
  199. len   = 0;
  200. begin = pos;
  201. }
  202. if (pos > offset + length)
  203. break;
  204. }
  205. sti();
  206. *start = buffer + (offset - begin);
  207. len   -= (offset - begin);
  208. if (len > length) len = length;
  209. return len;
  210. /*
  211.  * Release all memory associated with X.25 routing structures.
  212.  */
  213. void __exit x25_route_free(void)
  214. {
  215. struct x25_route *route, *x25_route = x25_route_list;
  216. while (x25_route != NULL) {
  217. route     = x25_route;
  218. x25_route = x25_route->next;
  219. x25_remove_route(route);
  220. }
  221. }