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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * DECnet       An implementation of the DECnet protocol suite for the LINUX
  3.  *              operating system.  DECnet is implemented using the  BSD Socket
  4.  *              interface as the means of communication with the user level.
  5.  *
  6.  *              DECnet sysctl support functions
  7.  *
  8.  * Author:      Steve Whitehouse <SteveW@ACM.org>
  9.  *
  10.  *
  11.  * Changes:
  12.  *
  13.  */
  14. #include <linux/config.h>
  15. #include <linux/mm.h>
  16. #include <linux/sysctl.h>
  17. #include <linux/fs.h>
  18. #include <linux/netdevice.h>
  19. #include <linux/string.h>
  20. #include <net/neighbour.h>
  21. #include <net/dst.h>
  22. #include <asm/uaccess.h>
  23. #include <net/dn.h>
  24. #include <net/dn_dev.h>
  25. #include <net/dn_route.h>
  26. int decnet_debug_level;
  27. int decnet_time_wait = 30;
  28. int decnet_dn_count = 1;
  29. int decnet_di_count = 3;
  30. int decnet_dr_count = 3;
  31. int decnet_log_martians = 1;
  32. int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
  33. #ifdef CONFIG_SYSCTL
  34. extern int decnet_dst_gc_interval;
  35. static int min_decnet_time_wait[] = { 5 };
  36. static int max_decnet_time_wait[] = { 600 };
  37. static int min_state_count[] = { 1 };
  38. static int max_state_count[] = { NSP_MAXRXTSHIFT };
  39. static int min_decnet_dst_gc_interval[] = { 1 };
  40. static int max_decnet_dst_gc_interval[] = { 60 };
  41. static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
  42. static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
  43. static char node_name[7] = "???";
  44. static struct ctl_table_header *dn_table_header = NULL;
  45. /*
  46.  * ctype.h :-)
  47.  */
  48. #define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
  49. #define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
  50. #define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
  51. #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
  52. #define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
  53. static void strip_it(char *str)
  54. {
  55. for(;;) {
  56. switch(*str) {
  57. case ' ':
  58. case 'n':
  59. case 'r':
  60. case ':':
  61. *str = 0;
  62. case 0:
  63. return;
  64. }
  65. str++;
  66. }
  67. }
  68. /*
  69.  * Simple routine to parse an ascii DECnet address
  70.  * into a network order address.
  71.  */
  72. static int parse_addr(dn_address *addr, char *str)
  73. {
  74. dn_address area, node;
  75. while(*str && !ISNUM(*str)) str++;
  76. if (*str == 0)
  77. return -1;
  78. area = (*str++ - '0');
  79. if (ISNUM(*str)) {
  80. area *= 10;
  81. area += (*str++ - '0');
  82. }
  83. if (*str++ != '.')
  84. return -1;
  85. if (!ISNUM(*str))
  86. return -1;
  87. node = *str++ - '0';
  88. if (ISNUM(*str)) {
  89. node *= 10;
  90. node += (*str++ - '0');
  91. }
  92. if (ISNUM(*str)) {
  93. node *= 10;
  94. node += (*str++ - '0');
  95. }
  96. if (ISNUM(*str)) {
  97. node *= 10;
  98. node += (*str++ - '0');
  99. }
  100. if ((node > 1023) || (area > 63))
  101. return -1;
  102. if (INVALID_END_CHAR(*str))
  103. return -1;
  104. *addr = dn_htons((area << 10) | node);
  105. return 0;
  106. }
  107. static int dn_node_address_strategy(ctl_table *table, int *name, int nlen,
  108. void *oldval, size_t *oldlenp,
  109. void *newval, size_t newlen,
  110. void **context)
  111. {
  112. size_t len;
  113. dn_address addr;
  114. if (oldval && oldlenp) {
  115. if (get_user(len, oldlenp))
  116. return -EFAULT;
  117. if (len) {
  118. if (len != sizeof(unsigned short))
  119. return -EINVAL;
  120. if (put_user(decnet_address, (unsigned short *)oldval))
  121. return -EFAULT;
  122. }
  123. }
  124. if (newval && newlen) {
  125. if (newlen != sizeof(unsigned short))
  126. return -EINVAL;
  127. if (get_user(addr, (unsigned short *)newval))
  128. return -EFAULT;
  129. dn_dev_devices_off();
  130. decnet_address = addr;
  131. dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
  132. dn_dev_devices_on();
  133. }
  134. return 0;
  135. }
  136. static int dn_node_address_handler(ctl_table *table, int write, 
  137. struct file *filp,
  138. void *buffer, size_t *lenp)
  139. {
  140. char addr[DN_ASCBUF_LEN];
  141. size_t len;
  142. dn_address dnaddr;
  143. if (!*lenp || (filp->f_pos && !write)) {
  144. *lenp = 0;
  145. return 0;
  146. }
  147. if (write) {
  148. int len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
  149. if (copy_from_user(addr, buffer, len))
  150. return -EFAULT;
  151. addr[len] = 0;
  152. strip_it(addr);
  153. if (parse_addr(&dnaddr, addr))
  154. return -EINVAL;
  155. dn_dev_devices_off();
  156. decnet_address = dnaddr;
  157. dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address));
  158. dn_dev_devices_on();
  159. filp->f_pos += len;
  160. return 0;
  161. }
  162. dn_addr2asc(dn_ntohs(decnet_address), addr);
  163. len = strlen(addr);
  164. addr[len++] = 'n';
  165. if (len > *lenp) len = *lenp;
  166. if (copy_to_user(buffer, addr, len))
  167. return -EFAULT;
  168. *lenp = len;
  169. filp->f_pos += len;
  170. return 0;
  171. }
  172. static int dn_def_dev_strategy(ctl_table *table, int *name, int nlen,
  173. void *oldval, size_t *oldlenp,
  174. void *newval, size_t newlen,
  175. void **context)
  176. {
  177. size_t len;
  178. struct net_device *dev = decnet_default_device;
  179. char devname[17];
  180. size_t namel;
  181. devname[0] = 0;
  182. if (oldval && oldlenp) {
  183. if (get_user(len, oldlenp))
  184. return -EFAULT;
  185. if (len) {
  186. if (dev)
  187. strcpy(devname, dev->name);
  188. namel = strlen(devname) + 1;
  189. if (len > namel) len = namel;
  190. if (copy_to_user(oldval, devname, len))
  191. return -EFAULT;
  192. if (put_user(len, oldlenp))
  193. return -EFAULT;
  194. }
  195. }
  196. if (newval && newlen) {
  197. if (newlen > 16)
  198. return -E2BIG;
  199. if (copy_from_user(devname, newval, newlen))
  200. return -EFAULT;
  201. devname[newlen] = 0;
  202. if ((dev = __dev_get_by_name(devname)) == NULL)
  203. return -ENODEV;
  204. if (dev->dn_ptr == NULL)
  205. return -ENODEV;
  206. decnet_default_device = dev;
  207. }
  208. return 0;
  209. }
  210. static int dn_def_dev_handler(ctl_table *table, int write, 
  211. struct file * filp,
  212. void *buffer, size_t *lenp)
  213. {
  214. size_t len;
  215. struct net_device *dev = decnet_default_device;
  216. char devname[17];
  217. if (!*lenp || (filp->f_pos && !write)) {
  218. *lenp = 0;
  219. return 0;
  220. }
  221. if (write) {
  222. if (*lenp > 16)
  223. return -E2BIG;
  224. if (copy_from_user(devname, buffer, *lenp))
  225. return -EFAULT;
  226. devname[*lenp] = 0;
  227. strip_it(devname);
  228. if ((dev = __dev_get_by_name(devname)) == NULL)
  229. return -ENODEV;
  230. if (dev->dn_ptr == NULL)
  231. return -ENODEV;
  232. decnet_default_device = dev;
  233. filp->f_pos += *lenp;
  234. return 0;
  235. }
  236. if (dev == NULL) {
  237. *lenp = 0;
  238. return 0;
  239. }
  240. strcpy(devname, dev->name);
  241. len = strlen(devname);
  242. devname[len++] = 'n';
  243. if (len > *lenp) len = *lenp;
  244. if (copy_to_user(buffer, devname, len))
  245. return -EFAULT;
  246. *lenp = len;
  247. filp->f_pos += len;
  248. return 0;
  249. }
  250. static ctl_table dn_table[] = {
  251. {NET_DECNET_NODE_ADDRESS, "node_address", NULL, 7, 0644, NULL,
  252. dn_node_address_handler, dn_node_address_strategy, NULL,
  253. NULL, NULL},
  254. {NET_DECNET_NODE_NAME, "node_name", node_name, 7, 0644, NULL,
  255. &proc_dostring, &sysctl_string, NULL, NULL, NULL},
  256. {NET_DECNET_DEFAULT_DEVICE, "default_device", NULL, 16, 0644, NULL,
  257. dn_def_dev_handler, dn_def_dev_strategy, NULL, NULL, NULL},
  258. {NET_DECNET_TIME_WAIT, "time_wait", &decnet_time_wait,
  259. sizeof(int), 0644,
  260. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  261. &min_decnet_time_wait, &max_decnet_time_wait},
  262. {NET_DECNET_DN_COUNT, "dn_count", &decnet_dn_count,
  263. sizeof(int), 0644,
  264. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  265. &min_state_count, &max_state_count},
  266. {NET_DECNET_DI_COUNT, "di_count", &decnet_di_count,
  267. sizeof(int), 0644,
  268. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  269. &min_state_count, &max_state_count},
  270. {NET_DECNET_DR_COUNT, "dr_count", &decnet_dr_count,
  271. sizeof(int), 0644,
  272. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  273. &min_state_count, &max_state_count},
  274. {NET_DECNET_DST_GC_INTERVAL, "dst_gc_interval", &decnet_dst_gc_interval,
  275. sizeof(int), 0644,
  276. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  277. &min_decnet_dst_gc_interval, &max_decnet_dst_gc_interval},
  278. {NET_DECNET_NO_FC_MAX_CWND, "no_fc_max_cwnd", &decnet_no_fc_max_cwnd,
  279. sizeof(int), 0644,
  280. NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL,
  281. &min_decnet_no_fc_max_cwnd, &max_decnet_no_fc_max_cwnd},
  282. {NET_DECNET_DEBUG_LEVEL, "debug", &decnet_debug_level, 
  283. sizeof(int), 0644, 
  284. NULL, &proc_dointvec, &sysctl_intvec, NULL,
  285. NULL, NULL},
  286. {0}
  287. };
  288. static ctl_table dn_dir_table[] = {
  289. {NET_DECNET, "decnet", NULL, 0, 0555, dn_table},
  290. {0}
  291. };
  292. static ctl_table dn_root_table[] = {
  293. {CTL_NET, "net", NULL, 0, 0555, dn_dir_table},
  294. {0}
  295. };
  296. void dn_register_sysctl(void)
  297. {
  298. dn_table_header = register_sysctl_table(dn_root_table, 1);
  299. }
  300. void dn_unregister_sysctl(void)
  301. {
  302. unregister_sysctl_table(dn_table_header);
  303. }
  304. #else  /* CONFIG_SYSCTL */
  305. void dn_unregister_sysctl(void)
  306. {
  307. }
  308. void dn_register_sysctl(void)
  309. {
  310. }
  311. #endif