0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #include <linux/mm.h>
0018 #include <linux/sysctl.h>
0019 #include <linux/fs.h>
0020 #include <linux/netdevice.h>
0021 #include <linux/string.h>
0022 #include <net/neighbour.h>
0023 #include <net/dst.h>
0024 #include <net/flow.h>
0025
0026 #include <linux/uaccess.h>
0027
0028 #include <net/dn.h>
0029 #include <net/dn_dev.h>
0030 #include <net/dn_route.h>
0031
0032
0033 int decnet_debug_level;
0034 int decnet_time_wait = 30;
0035 int decnet_dn_count = 1;
0036 int decnet_di_count = 3;
0037 int decnet_dr_count = 3;
0038 int decnet_log_martians = 1;
0039 int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
0040
0041
0042 long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
0043 int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
0044 int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
0045
0046 #ifdef CONFIG_SYSCTL
0047 extern int decnet_dst_gc_interval;
0048 static int min_decnet_time_wait[] = { 5 };
0049 static int max_decnet_time_wait[] = { 600 };
0050 static int min_state_count[] = { 1 };
0051 static int max_state_count[] = { NSP_MAXRXTSHIFT };
0052 static int min_decnet_dst_gc_interval[] = { 1 };
0053 static int max_decnet_dst_gc_interval[] = { 60 };
0054 static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
0055 static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
0056 static char node_name[7] = "???";
0057
0058 static struct ctl_table_header *dn_table_header = NULL;
0059
0060
0061
0062
0063 #define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
0064 #define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
0065 #define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
0066 #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
0067 #define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
0068
0069 static void strip_it(char *str)
0070 {
0071 for(;;) {
0072 switch (*str) {
0073 case ' ':
0074 case '\n':
0075 case '\r':
0076 case ':':
0077 *str = 0;
0078 fallthrough;
0079 case 0:
0080 return;
0081 }
0082 str++;
0083 }
0084 }
0085
0086
0087
0088
0089
0090 static int parse_addr(__le16 *addr, char *str)
0091 {
0092 __u16 area, node;
0093
0094 while(*str && !ISNUM(*str)) str++;
0095
0096 if (*str == 0)
0097 return -1;
0098
0099 area = (*str++ - '0');
0100 if (ISNUM(*str)) {
0101 area *= 10;
0102 area += (*str++ - '0');
0103 }
0104
0105 if (*str++ != '.')
0106 return -1;
0107
0108 if (!ISNUM(*str))
0109 return -1;
0110
0111 node = *str++ - '0';
0112 if (ISNUM(*str)) {
0113 node *= 10;
0114 node += (*str++ - '0');
0115 }
0116 if (ISNUM(*str)) {
0117 node *= 10;
0118 node += (*str++ - '0');
0119 }
0120 if (ISNUM(*str)) {
0121 node *= 10;
0122 node += (*str++ - '0');
0123 }
0124
0125 if ((node > 1023) || (area > 63))
0126 return -1;
0127
0128 if (INVALID_END_CHAR(*str))
0129 return -1;
0130
0131 *addr = cpu_to_le16((area << 10) | node);
0132
0133 return 0;
0134 }
0135
0136 static int dn_node_address_handler(struct ctl_table *table, int write,
0137 void *buffer, size_t *lenp, loff_t *ppos)
0138 {
0139 char addr[DN_ASCBUF_LEN];
0140 size_t len;
0141 __le16 dnaddr;
0142
0143 if (!*lenp || (*ppos && !write)) {
0144 *lenp = 0;
0145 return 0;
0146 }
0147
0148 if (write) {
0149 len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
0150 memcpy(addr, buffer, len);
0151 addr[len] = 0;
0152 strip_it(addr);
0153
0154 if (parse_addr(&dnaddr, addr))
0155 return -EINVAL;
0156
0157 dn_dev_devices_off();
0158
0159 decnet_address = dnaddr;
0160
0161 dn_dev_devices_on();
0162
0163 *ppos += len;
0164
0165 return 0;
0166 }
0167
0168 dn_addr2asc(le16_to_cpu(decnet_address), addr);
0169 len = strlen(addr);
0170 addr[len++] = '\n';
0171
0172 if (len > *lenp)
0173 len = *lenp;
0174 memcpy(buffer, addr, len);
0175 *lenp = len;
0176 *ppos += len;
0177
0178 return 0;
0179 }
0180
0181 static int dn_def_dev_handler(struct ctl_table *table, int write,
0182 void *buffer, size_t *lenp, loff_t *ppos)
0183 {
0184 size_t len;
0185 struct net_device *dev;
0186 char devname[17];
0187
0188 if (!*lenp || (*ppos && !write)) {
0189 *lenp = 0;
0190 return 0;
0191 }
0192
0193 if (write) {
0194 if (*lenp > 16)
0195 return -E2BIG;
0196
0197 memcpy(devname, buffer, *lenp);
0198 devname[*lenp] = 0;
0199 strip_it(devname);
0200
0201 dev = dev_get_by_name(&init_net, devname);
0202 if (dev == NULL)
0203 return -ENODEV;
0204
0205 if (dev->dn_ptr == NULL) {
0206 dev_put(dev);
0207 return -ENODEV;
0208 }
0209
0210 if (dn_dev_set_default(dev, 1)) {
0211 dev_put(dev);
0212 return -ENODEV;
0213 }
0214 *ppos += *lenp;
0215
0216 return 0;
0217 }
0218
0219 dev = dn_dev_get_default();
0220 if (dev == NULL) {
0221 *lenp = 0;
0222 return 0;
0223 }
0224
0225 strcpy(devname, dev->name);
0226 dev_put(dev);
0227 len = strlen(devname);
0228 devname[len++] = '\n';
0229
0230 if (len > *lenp) len = *lenp;
0231
0232 memcpy(buffer, devname, len);
0233 *lenp = len;
0234 *ppos += len;
0235
0236 return 0;
0237 }
0238
0239 static struct ctl_table dn_table[] = {
0240 {
0241 .procname = "node_address",
0242 .maxlen = 7,
0243 .mode = 0644,
0244 .proc_handler = dn_node_address_handler,
0245 },
0246 {
0247 .procname = "node_name",
0248 .data = node_name,
0249 .maxlen = 7,
0250 .mode = 0644,
0251 .proc_handler = proc_dostring,
0252 },
0253 {
0254 .procname = "default_device",
0255 .maxlen = 16,
0256 .mode = 0644,
0257 .proc_handler = dn_def_dev_handler,
0258 },
0259 {
0260 .procname = "time_wait",
0261 .data = &decnet_time_wait,
0262 .maxlen = sizeof(int),
0263 .mode = 0644,
0264 .proc_handler = proc_dointvec_minmax,
0265 .extra1 = &min_decnet_time_wait,
0266 .extra2 = &max_decnet_time_wait
0267 },
0268 {
0269 .procname = "dn_count",
0270 .data = &decnet_dn_count,
0271 .maxlen = sizeof(int),
0272 .mode = 0644,
0273 .proc_handler = proc_dointvec_minmax,
0274 .extra1 = &min_state_count,
0275 .extra2 = &max_state_count
0276 },
0277 {
0278 .procname = "di_count",
0279 .data = &decnet_di_count,
0280 .maxlen = sizeof(int),
0281 .mode = 0644,
0282 .proc_handler = proc_dointvec_minmax,
0283 .extra1 = &min_state_count,
0284 .extra2 = &max_state_count
0285 },
0286 {
0287 .procname = "dr_count",
0288 .data = &decnet_dr_count,
0289 .maxlen = sizeof(int),
0290 .mode = 0644,
0291 .proc_handler = proc_dointvec_minmax,
0292 .extra1 = &min_state_count,
0293 .extra2 = &max_state_count
0294 },
0295 {
0296 .procname = "dst_gc_interval",
0297 .data = &decnet_dst_gc_interval,
0298 .maxlen = sizeof(int),
0299 .mode = 0644,
0300 .proc_handler = proc_dointvec_minmax,
0301 .extra1 = &min_decnet_dst_gc_interval,
0302 .extra2 = &max_decnet_dst_gc_interval
0303 },
0304 {
0305 .procname = "no_fc_max_cwnd",
0306 .data = &decnet_no_fc_max_cwnd,
0307 .maxlen = sizeof(int),
0308 .mode = 0644,
0309 .proc_handler = proc_dointvec_minmax,
0310 .extra1 = &min_decnet_no_fc_max_cwnd,
0311 .extra2 = &max_decnet_no_fc_max_cwnd
0312 },
0313 {
0314 .procname = "decnet_mem",
0315 .data = &sysctl_decnet_mem,
0316 .maxlen = sizeof(sysctl_decnet_mem),
0317 .mode = 0644,
0318 .proc_handler = proc_doulongvec_minmax
0319 },
0320 {
0321 .procname = "decnet_rmem",
0322 .data = &sysctl_decnet_rmem,
0323 .maxlen = sizeof(sysctl_decnet_rmem),
0324 .mode = 0644,
0325 .proc_handler = proc_dointvec,
0326 },
0327 {
0328 .procname = "decnet_wmem",
0329 .data = &sysctl_decnet_wmem,
0330 .maxlen = sizeof(sysctl_decnet_wmem),
0331 .mode = 0644,
0332 .proc_handler = proc_dointvec,
0333 },
0334 {
0335 .procname = "debug",
0336 .data = &decnet_debug_level,
0337 .maxlen = sizeof(int),
0338 .mode = 0644,
0339 .proc_handler = proc_dointvec,
0340 },
0341 { }
0342 };
0343
0344 void dn_register_sysctl(void)
0345 {
0346 dn_table_header = register_net_sysctl(&init_net, "net/decnet", dn_table);
0347 }
0348
0349 void dn_unregister_sysctl(void)
0350 {
0351 unregister_net_sysctl_table(dn_table_header);
0352 }
0353
0354 #else
0355 void dn_unregister_sysctl(void)
0356 {
0357 }
0358 void dn_register_sysctl(void)
0359 {
0360 }
0361
0362 #endif