Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.15-rc4 480 lines 9.3 kB view raw
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 * Steve Whitehouse - C99 changes and default device handling 13 * 14 */ 15#include <linux/config.h> 16#include <linux/mm.h> 17#include <linux/sysctl.h> 18#include <linux/fs.h> 19#include <linux/netdevice.h> 20#include <linux/string.h> 21#include <net/neighbour.h> 22#include <net/dst.h> 23#include <net/flow.h> 24 25#include <asm/uaccess.h> 26 27#include <net/dn.h> 28#include <net/dn_dev.h> 29#include <net/dn_route.h> 30 31 32int decnet_debug_level; 33int decnet_time_wait = 30; 34int decnet_dn_count = 1; 35int decnet_di_count = 3; 36int decnet_dr_count = 3; 37int decnet_log_martians = 1; 38int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW; 39 40#ifdef CONFIG_SYSCTL 41extern int decnet_dst_gc_interval; 42static int min_decnet_time_wait[] = { 5 }; 43static int max_decnet_time_wait[] = { 600 }; 44static int min_state_count[] = { 1 }; 45static int max_state_count[] = { NSP_MAXRXTSHIFT }; 46static int min_decnet_dst_gc_interval[] = { 1 }; 47static int max_decnet_dst_gc_interval[] = { 60 }; 48static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW }; 49static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW }; 50static char node_name[7] = "???"; 51 52static struct ctl_table_header *dn_table_header = NULL; 53 54/* 55 * ctype.h :-) 56 */ 57#define ISNUM(x) (((x) >= '0') && ((x) <= '9')) 58#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z')) 59#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z')) 60#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x)) 61#define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x)) 62 63static void strip_it(char *str) 64{ 65 for(;;) { 66 switch(*str) { 67 case ' ': 68 case '\n': 69 case '\r': 70 case ':': 71 *str = 0; 72 case 0: 73 return; 74 } 75 str++; 76 } 77} 78 79/* 80 * Simple routine to parse an ascii DECnet address 81 * into a network order address. 82 */ 83static int parse_addr(dn_address *addr, char *str) 84{ 85 dn_address area, node; 86 87 while(*str && !ISNUM(*str)) str++; 88 89 if (*str == 0) 90 return -1; 91 92 area = (*str++ - '0'); 93 if (ISNUM(*str)) { 94 area *= 10; 95 area += (*str++ - '0'); 96 } 97 98 if (*str++ != '.') 99 return -1; 100 101 if (!ISNUM(*str)) 102 return -1; 103 104 node = *str++ - '0'; 105 if (ISNUM(*str)) { 106 node *= 10; 107 node += (*str++ - '0'); 108 } 109 if (ISNUM(*str)) { 110 node *= 10; 111 node += (*str++ - '0'); 112 } 113 if (ISNUM(*str)) { 114 node *= 10; 115 node += (*str++ - '0'); 116 } 117 118 if ((node > 1023) || (area > 63)) 119 return -1; 120 121 if (INVALID_END_CHAR(*str)) 122 return -1; 123 124 *addr = dn_htons((area << 10) | node); 125 126 return 0; 127} 128 129 130static int dn_node_address_strategy(ctl_table *table, int __user *name, int nlen, 131 void __user *oldval, size_t __user *oldlenp, 132 void __user *newval, size_t newlen, 133 void **context) 134{ 135 size_t len; 136 dn_address addr; 137 138 if (oldval && oldlenp) { 139 if (get_user(len, oldlenp)) 140 return -EFAULT; 141 if (len) { 142 if (len != sizeof(unsigned short)) 143 return -EINVAL; 144 if (put_user(decnet_address, (unsigned short __user *)oldval)) 145 return -EFAULT; 146 } 147 } 148 if (newval && newlen) { 149 if (newlen != sizeof(unsigned short)) 150 return -EINVAL; 151 if (get_user(addr, (unsigned short __user *)newval)) 152 return -EFAULT; 153 154 dn_dev_devices_off(); 155 156 decnet_address = addr; 157 158 dn_dev_devices_on(); 159 } 160 return 0; 161} 162 163static int dn_node_address_handler(ctl_table *table, int write, 164 struct file *filp, 165 void __user *buffer, 166 size_t *lenp, loff_t *ppos) 167{ 168 char addr[DN_ASCBUF_LEN]; 169 size_t len; 170 dn_address dnaddr; 171 172 if (!*lenp || (*ppos && !write)) { 173 *lenp = 0; 174 return 0; 175 } 176 177 if (write) { 178 int len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1); 179 180 if (copy_from_user(addr, buffer, len)) 181 return -EFAULT; 182 183 addr[len] = 0; 184 strip_it(addr); 185 186 if (parse_addr(&dnaddr, addr)) 187 return -EINVAL; 188 189 dn_dev_devices_off(); 190 191 decnet_address = dnaddr; 192 193 dn_dev_devices_on(); 194 195 *ppos += len; 196 197 return 0; 198 } 199 200 dn_addr2asc(dn_ntohs(decnet_address), addr); 201 len = strlen(addr); 202 addr[len++] = '\n'; 203 204 if (len > *lenp) len = *lenp; 205 206 if (copy_to_user(buffer, addr, len)) 207 return -EFAULT; 208 209 *lenp = len; 210 *ppos += len; 211 212 return 0; 213} 214 215 216static int dn_def_dev_strategy(ctl_table *table, int __user *name, int nlen, 217 void __user *oldval, size_t __user *oldlenp, 218 void __user *newval, size_t newlen, 219 void **context) 220{ 221 size_t len; 222 struct net_device *dev; 223 char devname[17]; 224 size_t namel; 225 int rv = 0; 226 227 devname[0] = 0; 228 229 if (oldval && oldlenp) { 230 if (get_user(len, oldlenp)) 231 return -EFAULT; 232 if (len) { 233 dev = dn_dev_get_default(); 234 if (dev) { 235 strcpy(devname, dev->name); 236 dev_put(dev); 237 } 238 239 namel = strlen(devname) + 1; 240 if (len > namel) len = namel; 241 242 if (copy_to_user(oldval, devname, len)) 243 return -EFAULT; 244 245 if (put_user(len, oldlenp)) 246 return -EFAULT; 247 } 248 } 249 250 if (newval && newlen) { 251 if (newlen > 16) 252 return -E2BIG; 253 254 if (copy_from_user(devname, newval, newlen)) 255 return -EFAULT; 256 257 devname[newlen] = 0; 258 259 dev = dev_get_by_name(devname); 260 if (dev == NULL) 261 return -ENODEV; 262 263 rv = -ENODEV; 264 if (dev->dn_ptr != NULL) { 265 rv = dn_dev_set_default(dev, 1); 266 if (rv) 267 dev_put(dev); 268 } 269 } 270 271 return rv; 272} 273 274 275static int dn_def_dev_handler(ctl_table *table, int write, 276 struct file * filp, 277 void __user *buffer, 278 size_t *lenp, loff_t *ppos) 279{ 280 size_t len; 281 struct net_device *dev; 282 char devname[17]; 283 284 if (!*lenp || (*ppos && !write)) { 285 *lenp = 0; 286 return 0; 287 } 288 289 if (write) { 290 if (*lenp > 16) 291 return -E2BIG; 292 293 if (copy_from_user(devname, buffer, *lenp)) 294 return -EFAULT; 295 296 devname[*lenp] = 0; 297 strip_it(devname); 298 299 dev = dev_get_by_name(devname); 300 if (dev == NULL) 301 return -ENODEV; 302 303 if (dev->dn_ptr == NULL) { 304 dev_put(dev); 305 return -ENODEV; 306 } 307 308 if (dn_dev_set_default(dev, 1)) { 309 dev_put(dev); 310 return -ENODEV; 311 } 312 *ppos += *lenp; 313 314 return 0; 315 } 316 317 dev = dn_dev_get_default(); 318 if (dev == NULL) { 319 *lenp = 0; 320 return 0; 321 } 322 323 strcpy(devname, dev->name); 324 dev_put(dev); 325 len = strlen(devname); 326 devname[len++] = '\n'; 327 328 if (len > *lenp) len = *lenp; 329 330 if (copy_to_user(buffer, devname, len)) 331 return -EFAULT; 332 333 *lenp = len; 334 *ppos += len; 335 336 return 0; 337} 338 339static ctl_table dn_table[] = { 340 { 341 .ctl_name = NET_DECNET_NODE_ADDRESS, 342 .procname = "node_address", 343 .maxlen = 7, 344 .mode = 0644, 345 .proc_handler = dn_node_address_handler, 346 .strategy = dn_node_address_strategy, 347 }, 348 { 349 .ctl_name = NET_DECNET_NODE_NAME, 350 .procname = "node_name", 351 .data = node_name, 352 .maxlen = 7, 353 .mode = 0644, 354 .proc_handler = &proc_dostring, 355 .strategy = &sysctl_string, 356 }, 357 { 358 .ctl_name = NET_DECNET_DEFAULT_DEVICE, 359 .procname = "default_device", 360 .maxlen = 16, 361 .mode = 0644, 362 .proc_handler = dn_def_dev_handler, 363 .strategy = dn_def_dev_strategy, 364 }, 365 { 366 .ctl_name = NET_DECNET_TIME_WAIT, 367 .procname = "time_wait", 368 .data = &decnet_time_wait, 369 .maxlen = sizeof(int), 370 .mode = 0644, 371 .proc_handler = &proc_dointvec_minmax, 372 .strategy = &sysctl_intvec, 373 .extra1 = &min_decnet_time_wait, 374 .extra2 = &max_decnet_time_wait 375 }, 376 { 377 .ctl_name = NET_DECNET_DN_COUNT, 378 .procname = "dn_count", 379 .data = &decnet_dn_count, 380 .maxlen = sizeof(int), 381 .mode = 0644, 382 .proc_handler = &proc_dointvec_minmax, 383 .strategy = &sysctl_intvec, 384 .extra1 = &min_state_count, 385 .extra2 = &max_state_count 386 }, 387 { 388 .ctl_name = NET_DECNET_DI_COUNT, 389 .procname = "di_count", 390 .data = &decnet_di_count, 391 .maxlen = sizeof(int), 392 .mode = 0644, 393 .proc_handler = &proc_dointvec_minmax, 394 .strategy = &sysctl_intvec, 395 .extra1 = &min_state_count, 396 .extra2 = &max_state_count 397 }, 398 { 399 .ctl_name = NET_DECNET_DR_COUNT, 400 .procname = "dr_count", 401 .data = &decnet_dr_count, 402 .maxlen = sizeof(int), 403 .mode = 0644, 404 .proc_handler = &proc_dointvec_minmax, 405 .strategy = &sysctl_intvec, 406 .extra1 = &min_state_count, 407 .extra2 = &max_state_count 408 }, 409 { 410 .ctl_name = NET_DECNET_DST_GC_INTERVAL, 411 .procname = "dst_gc_interval", 412 .data = &decnet_dst_gc_interval, 413 .maxlen = sizeof(int), 414 .mode = 0644, 415 .proc_handler = &proc_dointvec_minmax, 416 .strategy = &sysctl_intvec, 417 .extra1 = &min_decnet_dst_gc_interval, 418 .extra2 = &max_decnet_dst_gc_interval 419 }, 420 { 421 .ctl_name = NET_DECNET_NO_FC_MAX_CWND, 422 .procname = "no_fc_max_cwnd", 423 .data = &decnet_no_fc_max_cwnd, 424 .maxlen = sizeof(int), 425 .mode = 0644, 426 .proc_handler = &proc_dointvec_minmax, 427 .strategy = &sysctl_intvec, 428 .extra1 = &min_decnet_no_fc_max_cwnd, 429 .extra2 = &max_decnet_no_fc_max_cwnd 430 }, 431 { 432 .ctl_name = NET_DECNET_DEBUG_LEVEL, 433 .procname = "debug", 434 .data = &decnet_debug_level, 435 .maxlen = sizeof(int), 436 .mode = 0644, 437 .proc_handler = &proc_dointvec, 438 .strategy = &sysctl_intvec, 439 }, 440 {0} 441}; 442 443static ctl_table dn_dir_table[] = { 444 { 445 .ctl_name = NET_DECNET, 446 .procname = "decnet", 447 .mode = 0555, 448 .child = dn_table}, 449 {0} 450}; 451 452static ctl_table dn_root_table[] = { 453 { 454 .ctl_name = CTL_NET, 455 .procname = "net", 456 .mode = 0555, 457 .child = dn_dir_table 458 }, 459 {0} 460}; 461 462void dn_register_sysctl(void) 463{ 464 dn_table_header = register_sysctl_table(dn_root_table, 1); 465} 466 467void dn_unregister_sysctl(void) 468{ 469 unregister_sysctl_table(dn_table_header); 470} 471 472#else /* CONFIG_SYSCTL */ 473void dn_unregister_sysctl(void) 474{ 475} 476void dn_register_sysctl(void) 477{ 478} 479 480#endif