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

Configure Feed

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

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