allow coexistance of N build and AC build.
[tomato.git] / release / src / router / shared / nvparse.c
blob4b9df3a64e54efcf329b03a39fcedc437c425ec1
1 /*
2 * Routines for managing persistent storage of port mappings, etc.
4 * Copyright (C) 2012, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 * $Id: nvparse.c 374496 2012-12-13 08:59:12Z $
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <sys/types.h>
29 #include <netinet/in.h>
30 #include <arpa/inet.h>
31 #include <assert.h>
33 #include <typedefs.h>
34 #include <netconf.h>
35 #include <bcmnvram.h>
36 #include <shutils.h>
37 #include <nvparse.h>
38 #include <bcmconfig.h>
40 char *
41 safe_snprintf(char *str, int *len, const char *fmt, ...)
43 va_list ap;
44 int n;
46 va_start(ap, fmt);
47 n = vsnprintf(str, *len, fmt, ap);
48 va_end(ap);
50 if (n > 0) {
51 str += n;
52 *len -= n;
53 } else if (n < 0) {
54 *len = 0;
57 return str;
60 #ifdef __CONFIG_NAT__
61 #if !defined(AUTOFW_PORT_DEPRECATED)
62 bool
63 valid_autofw_port(const netconf_app_t *app)
65 /* Check outbound protocol */
66 if (app->match.ipproto != IPPROTO_TCP && app->match.ipproto != IPPROTO_UDP)
67 return FALSE;
69 /* Check outbound port range */
70 if (ntohs(app->match.dst.ports[0]) > ntohs(app->match.dst.ports[1]))
71 return FALSE;
73 /* Check related protocol */
74 if (app->proto != IPPROTO_TCP && app->proto != IPPROTO_UDP)
75 return FALSE;
77 /* Check related destination port range */
78 if (ntohs(app->dport[0]) > ntohs(app->dport[1]))
79 return FALSE;
81 /* Check mapped destination port range */
82 if (ntohs(app->to[0]) > ntohs(app->to[1]))
83 return FALSE;
85 /* Check port range size */
86 if ((ntohs(app->dport[1]) - ntohs(app->dport[0])) !=
87 (ntohs(app->to[1]) - ntohs(app->to[0])))
88 return FALSE;
90 return TRUE;
93 bool
94 get_autofw_port(int which, netconf_app_t *app)
96 char name[] = "autofw_portXXXXXXXXXX", value[1000];
97 char *out_proto, *out_start, *out_end, *in_proto, *in_start, *in_end, *to_start, *to_end;
98 char *enable, *desc;
100 memset(app, 0, sizeof(netconf_app_t));
102 /* Parse out_proto:out_start-out_end,in_proto:in_start-in_end>to_start-to_end,enable,desc */
103 snprintf(name, sizeof(name), "autofw_port%d", which);
104 if (!nvram_invmatch(name, ""))
105 return FALSE;
106 strncpy(value, nvram_get(name), sizeof(value));
108 /* Check for outbound port specification */
109 out_start = value;
110 out_proto = strsep(&out_start, ":");
111 if (!out_start)
112 return FALSE;
114 /* Check for related protocol specification */
115 in_proto = out_start;
116 out_start = strsep(&in_proto, ",");
117 if (!in_proto)
118 return FALSE;
120 /* Check for related destination port specification */
121 in_start = in_proto;
122 in_proto = strsep(&in_start, ":");
123 if (!in_start)
124 return FALSE;
126 /* Check for mapped destination port specification */
127 to_start = in_start;
128 in_start = strsep(&to_start, ">");
129 if (!to_start)
130 return FALSE;
132 /* Check for enable specification */
133 enable = to_start;
134 to_end = strsep(&enable, ",");
135 if (!enable)
136 return FALSE;
138 /* Check for description specification (optional) */
139 desc = enable;
140 enable = strsep(&desc, ",");
142 /* Check for outbound port range (optional) */
143 out_end = out_start;
144 out_start = strsep(&out_end, "-");
145 if (!out_end)
146 out_end = out_start;
148 /* Check for related destination port range (optional) */
149 in_end = in_start;
150 in_start = strsep(&in_end, "-");
151 if (!in_end)
152 in_end = in_start;
154 /* Check for mapped destination port range (optional) */
155 to_end = to_start;
156 to_start = strsep(&to_end, "-");
157 if (!to_end)
158 to_end = to_start;
160 /* Parse outbound protocol */
161 if (!strncasecmp(out_proto, "tcp", 3))
162 app->match.ipproto = IPPROTO_TCP;
163 else if (!strncasecmp(out_proto, "udp", 3))
164 app->match.ipproto = IPPROTO_UDP;
165 else
166 return FALSE;
168 /* Parse outbound port range */
169 app->match.dst.ports[0] = htons(atoi(out_start));
170 app->match.dst.ports[1] = htons(atoi(out_end));
172 /* Parse related protocol */
173 if (!strncasecmp(in_proto, "tcp", 3))
174 app->proto = IPPROTO_TCP;
175 else if (!strncasecmp(in_proto, "udp", 3))
176 app->proto = IPPROTO_UDP;
177 else
178 return FALSE;
180 /* Parse related destination port range */
181 app->dport[0] = htons(atoi(in_start));
182 app->dport[1] = htons(atoi(in_end));
184 /* Parse mapped destination port range */
185 app->to[0] = htons(atoi(to_start));
186 app->to[1] = htons(atoi(to_end));
188 /* Parse enable */
189 if (!strncasecmp(enable, "off", 3))
190 app->match.flags = NETCONF_DISABLED;
192 /* Parse description */
193 if (desc)
194 strncpy(app->desc, desc, sizeof(app->desc));
196 /* Set interface name (match packets entering LAN interface) */
197 strncpy(app->match.in.name, nvram_safe_get("lan_ifname"), IFNAMSIZ);
199 /* Set LAN source port range (match packets from any source port) */
200 app->match.src.ports[1] = htons(0xffff);
202 /* Set target (application specific port forward) */
203 app->target = NETCONF_APP;
205 return valid_autofw_port(app);
208 bool
209 set_autofw_port(int which, const netconf_app_t *app)
211 char name[] = "autofw_portXXXXXXXXXX", value[1000], *cur = value;
212 int len;
214 if (!valid_autofw_port(app))
215 return FALSE;
217 /* Set out_proto:out_start-out_end,in_proto:in_start-in_end>to_start-to_end,enable,desc */
218 snprintf(name, sizeof(name), "autofw_port%d", which);
219 len = sizeof(value);
221 /* Set outbound protocol */
222 if (app->match.ipproto == IPPROTO_TCP)
223 cur = safe_snprintf(cur, &len, "tcp");
224 else if (app->match.ipproto == IPPROTO_UDP)
225 cur = safe_snprintf(cur, &len, "udp");
227 /* Set outbound port */
228 cur = safe_snprintf(cur, &len, ":");
229 cur = safe_snprintf(cur, &len, "%d", ntohs(app->match.dst.ports[0]));
230 cur = safe_snprintf(cur, &len, "-");
231 cur = safe_snprintf(cur, &len, "%d", ntohs(app->match.dst.ports[1]));
233 /* Set related protocol */
234 cur = safe_snprintf(cur, &len, ",");
235 if (app->proto == IPPROTO_TCP)
236 cur = safe_snprintf(cur, &len, "tcp");
237 else if (app->proto == IPPROTO_UDP)
238 cur = safe_snprintf(cur, &len, "udp");
240 /* Set related destination port range */
241 cur = safe_snprintf(cur, &len, ":");
242 cur = safe_snprintf(cur, &len, "%d", ntohs(app->dport[0]));
243 cur = safe_snprintf(cur, &len, "-");
244 cur = safe_snprintf(cur, &len, "%d", ntohs(app->dport[1]));
246 /* Set mapped destination port range */
247 cur = safe_snprintf(cur, &len, ">");
248 cur = safe_snprintf(cur, &len, "%d", ntohs(app->to[0]));
249 cur = safe_snprintf(cur, &len, "-");
250 cur = safe_snprintf(cur, &len, "%d", ntohs(app->to[1]));
252 /* Set enable */
253 cur = safe_snprintf(cur, &len, ",");
254 if (app->match.flags & NETCONF_DISABLED)
255 cur = safe_snprintf(cur, &len, "off");
256 else
257 cur = safe_snprintf(cur, &len, "on");
259 /* Set description */
260 if (*app->desc) {
261 cur = safe_snprintf(cur, &len, ",");
262 cur = safe_snprintf(cur, &len, app->desc);
265 /* Do it */
266 if (nvram_set(name, value))
267 return FALSE;
269 return TRUE;
272 bool
273 del_autofw_port(int which)
275 char name[] = "autofw_portXXXXXXXXXX";
277 snprintf(name, sizeof(name), "autofw_port%d", which);
278 return (nvram_unset(name) == 0) ? TRUE : FALSE;
280 #endif /* !AUTOFW_PORT_DEPRECATED */
282 bool
283 valid_forward_port(const netconf_nat_t *nat)
285 /* Check WAN destination port range */
286 if (ntohs(nat->match.dst.ports[0]) > ntohs(nat->match.dst.ports[1]))
287 return FALSE;
289 /* Check protocol */
290 if (nat->match.ipproto != IPPROTO_TCP && nat->match.ipproto != IPPROTO_UDP)
291 return FALSE;
293 /* Check LAN IP address */
294 if (nat->ipaddr.s_addr == htonl(0))
295 return FALSE;
297 /* Check LAN destination port range */
298 if (ntohs(nat->ports[0]) > ntohs(nat->ports[1]))
299 return FALSE;
301 /* Check port range size */
302 if ((ntohs(nat->match.dst.ports[1]) - ntohs(nat->match.dst.ports[0])) !=
303 (ntohs(nat->ports[1]) - ntohs(nat->ports[0])))
304 return FALSE;
306 return TRUE;
309 bool
310 get_forward_port(int which, netconf_nat_t *nat)
312 char name[] = "forward_portXXXXXXXXXX", value[1000];
313 char *wan_port0, *wan_port1, *lan_ipaddr, *lan_port0, *lan_port1, *proto;
314 char *enable, *desc;
316 memset(nat, 0, sizeof(netconf_nat_t));
318 /* Parse wan_port0-wan_port1>lan_ipaddr:lan_port0-lan_port1[:,]proto[:,]enable[:,]desc */
319 snprintf(name, sizeof(name), "forward_port%d", which);
320 if (!nvram_invmatch(name, ""))
321 return FALSE;
322 strncpy(value, nvram_get(name), sizeof(value));
324 /* Check for LAN IP address specification */
325 lan_ipaddr = value;
326 wan_port0 = strsep(&lan_ipaddr, ">");
327 if (!lan_ipaddr)
328 return FALSE;
330 /* Check for LAN destination port specification */
331 lan_port0 = lan_ipaddr;
332 lan_ipaddr = strsep(&lan_port0, ":");
333 if (!lan_port0)
334 return FALSE;
336 /* Check for protocol specification */
337 proto = lan_port0;
338 lan_port0 = strsep(&proto, ":,");
339 if (!proto)
340 return FALSE;
342 /* Check for enable specification */
343 enable = proto;
344 proto = strsep(&enable, ":,");
345 if (!enable)
346 return FALSE;
348 /* Check for description specification (optional) */
349 desc = enable;
350 enable = strsep(&desc, ":,");
352 /* Check for WAN destination port range (optional) */
353 wan_port1 = wan_port0;
354 wan_port0 = strsep(&wan_port1, "-");
355 if (!wan_port1)
356 wan_port1 = wan_port0;
358 /* Check for LAN destination port range (optional) */
359 lan_port1 = lan_port0;
360 lan_port0 = strsep(&lan_port1, "-");
361 if (!lan_port1)
362 lan_port1 = lan_port0;
364 /* Parse WAN destination port range */
365 nat->match.dst.ports[0] = htons(atoi(wan_port0));
366 nat->match.dst.ports[1] = htons(atoi(wan_port1));
368 /* Parse LAN IP address */
369 (void) inet_aton(lan_ipaddr, &nat->ipaddr);
371 /* Parse LAN destination port range */
372 nat->ports[0] = htons(atoi(lan_port0));
373 nat->ports[1] = htons(atoi(lan_port1));
375 /* Parse protocol */
376 if (!strncasecmp(proto, "tcp", 3))
377 nat->match.ipproto = IPPROTO_TCP;
378 else if (!strncasecmp(proto, "udp", 3))
379 nat->match.ipproto = IPPROTO_UDP;
380 else
381 return FALSE;
383 /* Parse enable */
384 if (!strncasecmp(enable, "off", 3))
385 nat->match.flags = NETCONF_DISABLED;
387 /* Parse description */
388 if (desc)
389 strncpy(nat->desc, desc, sizeof(nat->desc));
390 /* Set WAN source port range (match packets from any source port) */
391 nat->match.src.ports[1] = htons(0xffff);
393 /* Set target (DNAT) */
394 nat->target = NETCONF_DNAT;
396 return valid_forward_port(nat);
399 bool
400 set_forward_port(int which, const netconf_nat_t *nat)
402 char name[] = "forward_portXXXXXXXXXX", value[1000], *cur = value;
403 int len;
405 if (!valid_forward_port(nat))
406 return FALSE;
408 /* Set wan_port0-wan_port1>lan_ipaddr:lan_port0-lan_port1,proto,enable,desc */
409 snprintf(name, sizeof(name), "forward_port%d", which);
410 len = sizeof(value);
412 /* Set WAN destination port range */
413 cur = safe_snprintf(cur, &len, "%d", ntohs(nat->match.dst.ports[0]));
414 cur = safe_snprintf(cur, &len, "-");
415 cur = safe_snprintf(cur, &len, "%d", ntohs(nat->match.dst.ports[1]));
417 /* Set LAN IP address */
418 cur = safe_snprintf(cur, &len, ">");
419 cur = safe_snprintf(cur, &len, inet_ntoa(nat->ipaddr));
421 /* Set LAN destination port range */
422 cur = safe_snprintf(cur, &len, ":");
423 cur = safe_snprintf(cur, &len, "%d", ntohs(nat->ports[0]));
424 cur = safe_snprintf(cur, &len, "-");
425 cur = safe_snprintf(cur, &len, "%d", ntohs(nat->ports[1]));
427 /* Set protocol */
428 cur = safe_snprintf(cur, &len, ",");
429 if (nat->match.ipproto == IPPROTO_TCP)
430 cur = safe_snprintf(cur, &len, "tcp");
431 else if (nat->match.ipproto == IPPROTO_UDP)
432 cur = safe_snprintf(cur, &len, "udp");
434 /* Set enable */
435 cur = safe_snprintf(cur, &len, ",");
436 if (nat->match.flags & NETCONF_DISABLED)
437 cur = safe_snprintf(cur, &len, "off");
438 else
439 cur = safe_snprintf(cur, &len, "on");
441 /* Set description */
442 if (*nat->desc) {
443 cur = safe_snprintf(cur, &len, ",");
444 cur = safe_snprintf(cur, &len, nat->desc);
447 /* Do it */
448 if (nvram_set(name, value))
449 return FALSE;
451 return TRUE;
454 bool
455 del_forward_port(int which)
457 char name[] = "forward_portXXXXXXXXXX";
459 snprintf(name, sizeof(name), "forward_port%d", which);
460 return (nvram_unset(name) == 0) ? TRUE : FALSE;
463 static void
464 convert_forward_proto(const char *name, int ipproto)
466 char var[1000], *next;
467 char *wan_port0, *wan_port1, *lan_ipaddr, *lan_port0, *lan_port1;
468 netconf_nat_t nat, unused;
469 bool valid;
470 int i;
472 foreach(var, nvram_safe_get(name), next) {
473 /* Parse wan_port0-wan_port1>lan_ipaddr:lan_port0-lan_port1 */
474 lan_ipaddr = var;
475 wan_port0 = strsep(&lan_ipaddr, ">");
476 if (!lan_ipaddr)
477 continue;
478 lan_port0 = lan_ipaddr;
479 lan_ipaddr = strsep(&lan_port0, ":");
480 if (!lan_port0)
481 continue;
482 wan_port1 = wan_port0;
483 wan_port0 = strsep(&wan_port1, "-");
484 if (!wan_port1)
485 wan_port1 = wan_port0;
486 lan_port1 = lan_port0;
487 lan_port0 = strsep(&lan_port1, "-");
488 if (!lan_port1)
489 lan_port1 = lan_port0;
491 /* Set up parameters */
492 memset(&nat, 0, sizeof(netconf_nat_t));
493 nat.match.ipproto = ipproto;
494 nat.match.dst.ports[0] = htons(atoi(wan_port0));
495 nat.match.dst.ports[1] = htons(atoi(wan_port1));
496 (void) inet_aton(lan_ipaddr, &nat.ipaddr);
497 nat.ports[0] = htons(atoi(lan_port0));
498 nat.ports[1] = htons(atoi(lan_port1));
500 /* Replace an unused or invalid entry */
501 for (i = 0; get_forward_port(i, &unused); i++);
502 valid = set_forward_port(i, &nat);
503 assert(valid);
506 nvram_unset(name);
509 bool
510 valid_filter_client(const netconf_filter_t *start, const netconf_filter_t *end)
512 /* Check address range */
513 if (start->match.src.netmask.s_addr) {
514 if (start->match.src.netmask.s_addr != htonl(0xffffffff) ||
515 start->match.src.netmask.s_addr != end->match.src.netmask.s_addr)
516 return FALSE;
517 if (ntohl(start->match.src.ipaddr.s_addr) > ntohl(end->match.src.ipaddr.s_addr))
518 return FALSE;
521 /* Check destination port range */
522 if (ntohs(start->match.dst.ports[0]) > ntohs(start->match.dst.ports[1]) ||
523 start->match.dst.ports[0] != end->match.dst.ports[0] ||
524 start->match.dst.ports[1] != end->match.dst.ports[1])
525 return FALSE;
527 /* Check protocol */
528 if ((start->match.ipproto != IPPROTO_TCP && start->match.ipproto != IPPROTO_UDP) ||
529 start->match.ipproto != end->match.ipproto)
530 return FALSE;
532 /* Check day range */
533 if (start->match.days[0] < 0 || start->match.days[0] > 6 ||
534 start->match.days[1] < 0 || start->match.days[1] > 6 ||
535 start->match.days[0] != end->match.days[0] ||
536 start->match.days[1] != end->match.days[1])
537 return FALSE;
539 /* Check time range */
540 if (start->match.secs[0] < 0 || start->match.secs[0] >= (24*60*60) ||
541 start->match.secs[1] < 0 || start->match.secs[1] >= (24*60*60) ||
542 start->match.secs[0] != end->match.secs[0] ||
543 start->match.secs[1] != end->match.secs[1])
544 return FALSE;
546 return TRUE;
549 bool
550 get_filter_client(int which, netconf_filter_t *start, netconf_filter_t *end)
552 char name[] = "filter_clientXXXXXXXXXX", value[1000];
553 char *lan_ipaddr0, *lan_ipaddr1, *lan_port0, *lan_port1, *proto;
554 char *day_start, *day_end, *sec_start, *sec_end;
555 char *enable, *desc;
557 memset(start, 0, sizeof(netconf_filter_t));
558 memset(end, 0, sizeof(netconf_filter_t));
560 /* Parse
561 * [lan_ipaddr0-lan_ipaddr1|*]:lan_port0-lan_port1,proto,day_start-day_end,
562 * sec_start-sec_end,enable,desc
564 snprintf(name, sizeof(name), "filter_client%d", which);
565 if (!nvram_invmatch(name, ""))
566 return FALSE;
567 strncpy(value, nvram_get(name), sizeof(value));
569 /* Check for port specification */
570 lan_port0 = value;
571 lan_ipaddr0 = strsep(&lan_port0, ":");
572 if (!lan_port0)
573 return FALSE;
575 /* Check for protocol specification */
576 proto = lan_port0;
577 lan_port0 = strsep(&proto, ",");
578 if (!proto)
579 return FALSE;
581 /* Check for day specification */
582 day_start = proto;
583 proto = strsep(&day_start, ",");
584 if (!day_start)
585 return FALSE;
587 /* Check for time specification */
588 sec_start = day_start;
589 day_start = strsep(&sec_start, ",");
590 if (!sec_start)
591 return FALSE;
593 /* Check for enable specification */
594 enable = sec_start;
595 sec_start = strsep(&enable, ",");
596 if (!enable)
597 return FALSE;
599 /* Check for description specification (optional) */
600 desc = enable;
601 enable = strsep(&desc, ",");
603 /* Check for address range (optional) */
604 lan_ipaddr1 = lan_ipaddr0;
605 lan_ipaddr0 = strsep(&lan_ipaddr1, "-");
606 if (!lan_ipaddr1)
607 lan_ipaddr1 = lan_ipaddr0;
609 /* Check for port range (optional) */
610 lan_port1 = lan_port0;
611 lan_port0 = strsep(&lan_port1, "-");
612 if (!lan_port1)
613 lan_port1 = lan_port0;
615 /* Check for day range (optional) */
616 day_end = day_start;
617 day_start = strsep(&day_end, "-");
618 if (!day_end)
619 day_end = day_start;
621 /* Check for time range (optional) */
622 sec_end = sec_start;
623 sec_start = strsep(&sec_end, "-");
624 if (!sec_end)
625 sec_end = sec_start;
627 /* Parse address range */
628 if (*lan_ipaddr0 == '*') {
629 /* Match any IP address */
630 start->match.src.ipaddr.s_addr = end->match.src.ipaddr.s_addr = htonl(0);
631 start->match.src.netmask.s_addr = end->match.src.netmask.s_addr = htonl(0);
632 } else {
633 /* Match a range of IP addresses */
634 inet_aton(lan_ipaddr0, &start->match.src.ipaddr);
635 inet_aton(lan_ipaddr1, &end->match.src.ipaddr);
636 start->match.src.netmask.s_addr = end->match.src.netmask.s_addr = htonl(0xffffffff);
639 /* Parse destination port range */
640 start->match.dst.ports[0] = end->match.dst.ports[0] = htons(atoi(lan_port0));
641 start->match.dst.ports[1] = end->match.dst.ports[1] = htons(atoi(lan_port1));
643 /* Parse protocol */
644 if (!strncasecmp(proto, "tcp", 3))
645 start->match.ipproto = end->match.ipproto = IPPROTO_TCP;
646 else if (!strncasecmp(proto, "udp", 3))
647 start->match.ipproto = end->match.ipproto = IPPROTO_UDP;
648 else
649 return FALSE;
651 /* Parse day range */
652 start->match.days[0] = end->match.days[0] = atoi(day_start);
653 start->match.days[1] = end->match.days[1] = atoi(day_end);
655 /* Parse time range */
656 start->match.secs[0] = end->match.secs[0] = atoi(sec_start);
657 start->match.secs[1] = end->match.secs[1] = atoi(sec_end);
659 /* Parse enable */
660 if (!strncasecmp(enable, "off", 3))
661 start->match.flags = end->match.flags = NETCONF_DISABLED;
663 /* Parse description */
664 if (desc) {
665 strncpy(start->desc, desc, sizeof(start->desc));
666 strncpy(end->desc, desc, sizeof(end->desc));
669 /* Set interface name (match packets entering LAN interface) */
670 strncpy(start->match.in.name, nvram_safe_get("lan_ifname"), IFNAMSIZ);
672 /* Set source port range (match packets from any source port) */
673 start->match.src.ports[1] = end->match.src.ports[1] = htons(0xffff);
675 /* Set default target (drop) */
676 start->target = NETCONF_DROP;
678 return valid_filter_client(start, end);
681 bool
682 set_filter_client(int which, const netconf_filter_t *start, const netconf_filter_t *end)
684 char name[] = "filter_clientXXXXXXXXXX", value[1000], *cur = value;
685 int len;
687 if (!valid_filter_client(start, end))
688 return FALSE;
690 /* Set
691 * [lan_ipaddr0-lan_ipaddr1|*]:lan_port0-lan_port1,proto,day_start-day_end,
692 * sec_start-sec_end,enable,desc
694 snprintf(name, sizeof(name), "filter_client%d", which);
695 len = sizeof(value);
697 /* Set address range */
698 if (start->match.src.ipaddr.s_addr == htonl(0) &&
699 end->match.src.ipaddr.s_addr == htonl(0) &&
700 start->match.src.netmask.s_addr == htonl(0) &&
701 end->match.src.netmask.s_addr == htonl(0))
702 cur = safe_snprintf(cur, &len, "*");
703 else {
704 cur = safe_snprintf(cur, &len, inet_ntoa(start->match.src.ipaddr));
705 cur = safe_snprintf(cur, &len, "-");
706 cur = safe_snprintf(cur, &len, inet_ntoa(end->match.src.ipaddr));
709 /* Set port range */
710 cur = safe_snprintf(cur, &len, ":");
711 cur = safe_snprintf(cur, &len, "%d", ntohs(start->match.dst.ports[0]));
712 cur = safe_snprintf(cur, &len, "-");
713 cur = safe_snprintf(cur, &len, "%d", ntohs(start->match.dst.ports[1]));
715 /* Set protocol */
716 cur = safe_snprintf(cur, &len, ",");
717 if (start->match.ipproto == IPPROTO_TCP)
718 cur = safe_snprintf(cur, &len, "tcp");
719 else if (start->match.ipproto == IPPROTO_UDP)
720 cur = safe_snprintf(cur, &len, "udp");
722 /* Set day range */
723 cur = safe_snprintf(cur, &len, ",");
724 cur = safe_snprintf(cur, &len, "%d", start->match.days[0]);
725 cur = safe_snprintf(cur, &len, "-");
726 cur = safe_snprintf(cur, &len, "%d", start->match.days[1]);
728 /* Set time range */
729 cur = safe_snprintf(cur, &len, ",");
730 cur = safe_snprintf(cur, &len, "%d", start->match.secs[0]);
731 cur = safe_snprintf(cur, &len, "-");
732 cur = safe_snprintf(cur, &len, "%d", start->match.secs[1]);
734 /* Set enable */
735 cur = safe_snprintf(cur, &len, ",");
736 if (start->match.flags & NETCONF_DISABLED)
737 cur = safe_snprintf(cur, &len, "off");
738 else
739 cur = safe_snprintf(cur, &len, "on");
741 /* Set description */
742 if (*start->desc) {
743 cur = safe_snprintf(cur, &len, ",");
744 cur = safe_snprintf(cur, &len, start->desc);
747 /* Do it */
748 if (nvram_set(name, value))
749 return FALSE;
751 return TRUE;
754 bool
755 del_filter_client(int which)
757 char name[] = "filter_clientXXXXXXXXXX";
759 snprintf(name, sizeof(name), "filter_client%d", which);
760 return (nvram_unset(name) == 0) ? TRUE : FALSE;
763 #ifdef __CONFIG_URLFILTER__
764 bool
765 valid_filter_url(const netconf_urlfilter_t *start, const netconf_urlfilter_t *end)
767 /* Check address range */
768 if (start->match.src.netmask.s_addr) {
769 if (start->match.src.netmask.s_addr != htonl(0xffffffff) ||
770 start->match.src.netmask.s_addr != end->match.src.netmask.s_addr)
771 return FALSE;
772 if (ntohl(start->match.src.ipaddr.s_addr) > ntohl(end->match.src.ipaddr.s_addr))
773 return FALSE;
776 return TRUE;
779 bool
780 get_filter_url(int which, netconf_urlfilter_t *start, netconf_urlfilter_t *end)
782 char name[] = "filter_urlXXXXXXXXXX", value[1000];
783 char *lan_ipaddr0, *lan_ipaddr1;
784 char *url, *enable, *desc;
786 memset(start, 0, sizeof(netconf_urlfilter_t));
787 memset(end, 0, sizeof(netconf_urlfilter_t));
789 /* Parse
790 * [lan_ipaddr0-lan_ipaddr1|*]:url,enable,desc
792 snprintf(name, sizeof(name), "filter_url%d", which);
793 if (!nvram_invmatch(name, ""))
794 return FALSE;
795 strncpy(value, nvram_get(name), sizeof(value));
797 /* Check for URL */
798 url = value;
799 lan_ipaddr0 = strsep(&url, ":");
800 if (!url)
801 return FALSE;
803 /* Check for enable specification */
804 enable = url;
805 url = strsep(&enable, ",");
806 if (!enable)
807 return FALSE;
809 /* Check for description specification (optional) */
810 desc = enable;
811 enable = strsep(&desc, ",");
813 /* Check for address range (optional) */
814 lan_ipaddr1 = lan_ipaddr0;
815 lan_ipaddr0 = strsep(&lan_ipaddr1, "-");
816 if (!lan_ipaddr1)
817 lan_ipaddr1 = lan_ipaddr0;
819 /* Parse address range */
820 if (*lan_ipaddr0 == '*') {
821 /* Match any IP address */
822 start->match.src.ipaddr.s_addr = end->match.src.ipaddr.s_addr = htonl(0);
823 start->match.src.netmask.s_addr = end->match.src.netmask.s_addr = htonl(0);
824 } else {
825 /* Match a range of IP addresses */
826 inet_aton(lan_ipaddr0, &start->match.src.ipaddr);
827 inet_aton(lan_ipaddr1, &end->match.src.ipaddr);
828 start->match.src.netmask.s_addr = end->match.src.netmask.s_addr = htonl(0xffffffff);
831 /* Parse enable */
832 if (!strncasecmp(enable, "off", 3))
833 start->match.flags = end->match.flags = NETCONF_DISABLED;
835 /* Parse description */
836 if (url) {
837 strncpy(start->url, url, sizeof(start->url));
838 strncpy(end->url, url, sizeof(end->url));
841 /* Parse description */
842 if (desc) {
843 strncpy(start->desc, desc, sizeof(start->desc));
844 strncpy(end->desc, desc, sizeof(end->desc));
847 /* Set interface name (match packets entering LAN interface) */
848 strncpy(start->match.in.name, nvram_safe_get("lan_ifname"), IFNAMSIZ);
850 /* Set default target (drop) */
851 start->target = NETCONF_DROP;
853 return valid_filter_url(start, end);
856 bool
857 set_filter_url(int which, const netconf_urlfilter_t *start, const netconf_urlfilter_t *end)
859 char name[] = "filter_urlXXXXXXXXXX", value[1000], *cur = value;
860 int len;
862 if (!valid_filter_url(start, end))
863 return FALSE;
865 /* Set
866 * [lan_ipaddr0-lan_ipaddr1|*]:url,enable
868 snprintf(name, sizeof(name), "filter_url%d", which);
869 len = sizeof(value);
871 /* Set address range */
872 if (start->match.src.ipaddr.s_addr == htonl(0) &&
873 end->match.src.ipaddr.s_addr == htonl(0) &&
874 start->match.src.netmask.s_addr == htonl(0) &&
875 end->match.src.netmask.s_addr == htonl(0))
876 cur = safe_snprintf(cur, &len, "*");
877 else {
878 cur = safe_snprintf(cur, &len, inet_ntoa(start->match.src.ipaddr));
879 cur = safe_snprintf(cur, &len, "-");
880 cur = safe_snprintf(cur, &len, inet_ntoa(end->match.src.ipaddr));
883 /* Set URL */
884 cur = safe_snprintf(cur, &len, ":");
885 cur = safe_snprintf(cur, &len, "%s", start->url);
887 /* Set enable */
888 cur = safe_snprintf(cur, &len, ",");
889 if (start->match.flags & NETCONF_DISABLED)
890 cur = safe_snprintf(cur, &len, "off");
891 else
892 cur = safe_snprintf(cur, &len, "on");
894 /* Set description */
895 if (*start->desc) {
896 cur = safe_snprintf(cur, &len, ",");
897 cur = safe_snprintf(cur, &len, start->desc);
900 /* Do it */
901 if (nvram_set(name, value))
902 return FALSE;
904 return TRUE;
907 bool
908 del_filter_url(int which)
910 char name[] = "filter_urlXXXXXXXXXX";
912 snprintf(name, sizeof(name), "filter_url%d", which);
913 return (nvram_unset(name) == 0) ? TRUE : FALSE;
915 #endif /* __CONFIG_URLFILTER__ */
916 #endif /* __CONFIG_NAT__ */
918 #ifdef TRAFFIC_MGMT
920 * Parser for traffic management filter settings, convert string to binary structure
921 * string format: proto,sr_port,dst_port,mac_adr,priority,favored,enable
923 bool
924 get_trf_mgmt_port(char *prefix, int which, netconf_trmgmt_t *trm)
926 char name[] = "tmXXXXXXXXXXXXXX", value[128];
927 char *proto;
928 char *enable;
929 char *sport, *dport, *macaddr, *prio, *flags;
931 memset(trm, 0, sizeof(netconf_trmgmt_t));
933 snprintf(name, sizeof(name), "%stm%d", prefix, which);
934 if (!nvram_invmatch(name, ""))
935 return FALSE;
936 strncpy(value, nvram_get(name), sizeof(value));
938 /* Parse protocol */
939 sport = value;
940 proto = strsep(&sport, ",");
941 if (!sport)
942 return FALSE;
943 trm->match.ipproto = atoi(proto);
946 /* Parse source port */
947 dport = sport;
948 sport = strsep(&dport, ",");
949 if (!dport)
950 return FALSE;
951 trm->match.src.ports[0] = htons(atoi(sport));
953 /* Parse destination port */
954 macaddr = dport;
955 dport = strsep(&macaddr, ",");
956 if (!macaddr)
957 return FALSE;
958 trm->match.dst.ports[0] = htons(atoi(dport));
960 /* Parse MAC address */
961 prio = macaddr;
962 macaddr = strsep(&prio, ",");
963 if (!prio)
964 return FALSE;
965 if (trm->match.ipproto == IPPROTO_IP) {
966 ether_atoe((const char *)macaddr, (unsigned char *)&trm->match.mac);
969 /* Parse priority */
970 flags = prio;
971 prio = strsep(&flags, ",");
972 if (!flags)
973 return FALSE;
974 trm->prio = atoi(prio);
976 /* Parse favored */
977 enable = flags;
978 flags = strsep(&enable, ",");
979 if (!enable)
980 return FALSE;
981 trm->favored = atoi(flags);
983 /* Parse enable */
984 if (*enable == '0')
985 trm->match.flags = NETCONF_DISABLED;
987 return TRUE;
991 * Parser for traffic management filter settings, convert binary structure to string
992 * string format: proto,sr_port,dst_port,mac_adr,priority,favored,enable
994 bool
995 set_trf_mgmt_port(char *prefix, int which, const netconf_trmgmt_t *trm)
997 char name[] = "tmXXXXXXXXXXXXXX", value[128], *cur = value;
998 int len;
999 char eastr[40];
1001 /* Set proto,sport,dport,mac,prio,flags,enable */
1002 snprintf(name, sizeof(name), "%stm%d", prefix, which);
1003 len = sizeof(value);
1005 /* Set protocol */
1006 cur = safe_snprintf(cur, &len, "%d", trm->match.ipproto);
1007 cur = safe_snprintf(cur, &len, ",");
1010 /* Set Mac Address */
1011 if (trm->match.ipproto == IPPROTO_IP) {
1012 cur = safe_snprintf(cur, &len, ",,");
1013 cur = safe_snprintf(cur, &len, ether_etoa((unsigned char *)&trm->match.mac, eastr));
1014 cur = safe_snprintf(cur, &len, ",");
1015 } else {
1016 /* Set Source Port */
1017 cur = safe_snprintf(cur, &len, "%d", ntohs(trm->match.src.ports[0]));
1018 cur = safe_snprintf(cur, &len, ",");
1020 /* Set Destination Port */
1021 cur = safe_snprintf(cur, &len, "%d", ntohs(trm->match.dst.ports[0]));
1022 cur = safe_snprintf(cur, &len, ",,");
1025 /* Set Priority */
1026 cur = safe_snprintf(cur, &len, "%d", trm->prio);
1027 cur = safe_snprintf(cur, &len, ",");
1029 /* Set Favored */
1030 cur = safe_snprintf(cur, &len, "%d", trm->favored);
1031 cur = safe_snprintf(cur, &len, ",");
1033 /* Set enable */
1034 if (trm->match.flags & NETCONF_DISABLED)
1035 cur = safe_snprintf(cur, &len, "0");
1036 else
1037 cur = safe_snprintf(cur, &len, "1");
1039 /* Do it */
1040 if (nvram_set(name, value))
1041 return FALSE;
1043 return TRUE;
1046 bool
1047 del_trf_mgmt_port(char *prefix, int which)
1049 char name[] = "tmXXXXXXXXXXXXXX";
1051 snprintf(name, sizeof(name), "%stm%d", prefix, which);
1052 return (nvram_unset(name) == 0) ? TRUE : FALSE;
1054 #endif /* TRAFFIC_MGMT */
1057 * wl_wds<N> is authentication protocol dependant.
1058 * when auth is "psk":
1059 * wl_wds<N>=mac,role,crypto,auth,ssid,passphrase
1061 bool
1062 get_wds_wsec(int unit, int which, char *mac, char *role,
1063 char *crypto, char *auth, ...)
1065 char name[] = "wlXXXXXXX_wdsXXXXXXX", value[1000], *next;
1067 snprintf(name, sizeof(name), "wl%d_wds%d", unit, which);
1068 strncpy(value, nvram_safe_get(name), sizeof(value));
1069 next = value;
1071 /* separate mac */
1072 strcpy(mac, strsep(&next, ","));
1073 if (!next)
1074 return FALSE;
1076 /* separate role */
1077 strcpy(role, strsep(&next, ","));
1078 if (!next)
1079 return FALSE;
1081 /* separate crypto */
1082 strcpy(crypto, strsep(&next, ","));
1083 if (!next)
1084 return FALSE;
1086 /* separate auth */
1087 strcpy(auth, strsep(&next, ","));
1088 if (!next)
1089 return FALSE;
1091 if (!strcmp(auth, "psk")) {
1092 va_list va;
1094 va_start(va, auth);
1096 /* separate ssid */
1097 strcpy(va_arg(va, char *), strsep(&next, ","));
1098 if (!next)
1099 goto fail;
1101 /* separate passphrase */
1102 strcpy(va_arg(va, char *), next);
1104 va_end(va);
1105 return TRUE;
1106 fail:
1107 va_end(va);
1108 return FALSE;
1111 return FALSE;
1114 bool
1115 set_wds_wsec(int unit, int which, char *mac, char *role,
1116 char *crypto, char *auth, ...)
1118 char name[] = "wlXXXXXXX_wdsXXXXXXX", value[10000];
1120 snprintf(name, sizeof(name), "wl%d_wds%d", unit, which);
1121 snprintf(value, sizeof(value), "%s,%s,%s,%s",
1122 mac, role, crypto, auth);
1124 if (!strcmp(auth, "psk")) {
1125 int offset;
1126 char *str1, *str2;
1127 va_list va;
1129 va_start(va, auth);
1130 offset = strlen(value);
1131 str1 = va_arg(va, char *);
1132 str2 = va_arg(va, char *);
1134 snprintf(&value[offset], sizeof(value) - offset, ",%s,%s", str1, str2);
1135 va_end(va);
1137 if (nvram_set(name, value))
1138 return FALSE;
1140 return TRUE;
1143 return FALSE;
1146 bool
1147 del_wds_wsec(int unit, int which)
1149 char name[] = "wlXXXXXXX_wdsXXXXXXX";
1151 snprintf(name, sizeof(name), "wl%d_wds%d", unit, which);
1153 nvram_unset(name);
1155 return TRUE;
1158 #ifdef __CONFIG_NAT__
1159 static void
1160 convert_filter_ip(void)
1162 char var[1000], *next;
1163 char *lan_ipaddr0, *lan_ipaddr1;
1164 netconf_filter_t start, end, unused;
1165 bool valid;
1166 int i;
1168 foreach(var, nvram_safe_get("filter_ip"), next) {
1169 /* Parse lan_ipaddr0-lan_ipaddr1 */
1170 lan_ipaddr1 = var;
1171 lan_ipaddr0 = strsep(&lan_ipaddr1, "-");
1172 if (!lan_ipaddr0 || !lan_ipaddr1)
1173 continue;
1175 /* Set up parameters */
1176 memset(&start, 0, sizeof(netconf_filter_t));
1177 (void) inet_aton(lan_ipaddr0, &start.match.src.ipaddr);
1178 start.match.src.netmask.s_addr = htonl(0xffffffff);
1179 start.match.dst.ports[1] = htons(0xffff);
1180 memcpy(&end, &start, sizeof(netconf_filter_t));
1181 (void) inet_aton(lan_ipaddr1, &end.match.src.ipaddr);
1183 /* Replace an unused or invalid entry */
1184 start.match.ipproto = end.match.ipproto = IPPROTO_TCP;
1185 for (i = 0; get_filter_client(i, &unused, &unused); i++);
1186 valid = set_filter_client(i, &start, &end);
1187 assert(valid);
1189 /* Replace an unused or invalid entry */
1190 start.match.ipproto = end.match.ipproto = IPPROTO_UDP;
1191 for (; get_filter_client(i, &unused, &unused); i++);
1192 valid = set_filter_client(i, &start, &end);
1193 assert(valid);
1196 nvram_unset("filter_ip");
1199 static void
1200 convert_filter_proto(const char *name, int ipproto)
1202 char var[1000], *next;
1203 char *lan_ipaddr, *lan_port0, *lan_port1;
1204 netconf_filter_t start, end, unused;
1205 bool valid;
1206 int i;
1208 foreach(var, nvram_safe_get(name), next) {
1209 /* Parse [lan_ipaddr|*]:lan_port0-lan_port1 */
1210 lan_port0 = var;
1211 lan_ipaddr = strsep(&lan_port0, ":");
1212 if (!lan_ipaddr || !lan_port0)
1213 continue;
1214 lan_port1 = lan_port0;
1215 lan_port0 = strsep(&lan_port1, "-");
1216 if (!lan_port0 || !lan_port1)
1217 continue;
1219 /* Set up parameters */
1220 memset(&start, 0, sizeof(netconf_filter_t));
1221 (void) inet_aton(lan_ipaddr, &start.match.src.ipaddr);
1222 start.match.src.netmask.s_addr = htonl(0xffffffff);
1223 start.match.ipproto = ipproto;
1224 start.match.dst.ports[0] = htons(atoi(lan_port0));
1225 start.match.dst.ports[1] = htons(atoi(lan_port1));
1226 memcpy(&end, &start, sizeof(netconf_filter_t));
1228 /* Replace an unused or invalid entry */
1229 for (i = 0; get_filter_client(i, &unused, &unused); i++);
1230 valid = set_filter_client(i, &start, &end);
1231 assert(valid);
1234 nvram_unset(name);
1237 static void
1238 convert_filter_port(void)
1240 char name[1000], *value, *colon;
1241 netconf_filter_t start, end, unused;
1242 bool valid;
1243 int i, j;
1245 /* Maximum number of filter_port entries was 6 */
1246 for (i = 1; i <= 6; i++) {
1247 snprintf(name, sizeof(name), "filter_port%d", i);
1248 if (!(value = nvram_get(name)) || !*value)
1249 goto fail;
1251 memset(&start, 0, sizeof(netconf_filter_t));
1252 memset(&end, 0, sizeof(netconf_filter_t));
1254 /* Only the last bytes of IP addresses were stored in NVRAM */
1255 (void) inet_aton(nvram_safe_get("lan_ipaddr"), &start.match.src.ipaddr);
1256 (void) inet_aton(nvram_safe_get("lan_ipaddr"), &end.match.src.ipaddr);
1258 /* id (unused) */
1259 if (!(colon = strchr(value, ':')))
1260 goto fail;
1261 value = colon + 1;
1263 /* active */
1264 if (!(colon = strchr(value, ':')))
1265 goto fail;
1266 if (!strtoul(value, NULL, 0))
1267 start.match.flags = end.match.flags = NETCONF_DISABLED;
1268 value = colon + 1;
1270 /* flags (unused) */
1271 if (!(colon = strchr(value, ':')))
1272 goto fail;
1273 value = colon + 1;
1275 /* from_ip */
1276 if (!(colon = strchr(value, ':')))
1277 goto fail;
1278 start.match.src.ipaddr.s_addr = htonl((ntohl(start.match.src.ipaddr.s_addr) & ~0xff)
1279 | strtoul(value, NULL, 0));
1280 value = colon + 1;
1282 /* to_ip */
1283 if (!(colon = strchr(value, ':')))
1284 goto fail;
1285 end.match.src.ipaddr.s_addr = htonl((ntohl(end.match.src.ipaddr.s_addr) & ~0xff) |
1286 strtoul(value, NULL, 0));
1287 value = colon + 1;
1289 /* from_port */
1290 if (!(colon = strchr(value, ':')))
1291 goto fail;
1292 start.match.dst.ports[0] = end.match.dst.ports[0] = htons(strtoul(value, NULL, 0));
1293 value = colon + 1;
1295 /* to_port */
1296 if (!(colon = strchr(value, ':')))
1297 goto fail;
1298 start.match.dst.ports[1] = end.match.dst.ports[1] = htons(strtoul(value, NULL, 0));
1299 value = colon + 1;
1301 /* protocol */
1302 if (!(colon = strchr(value, ':')))
1303 goto fail;
1304 start.match.ipproto = end.match.ipproto = strtoul(value, NULL, 0);
1305 value = colon + 1;
1307 /* always */
1308 if (!(colon = strchr(value, ':')))
1309 goto fail;
1310 if (strtoul(value, NULL, 0))
1311 goto done;
1312 value = colon + 1;
1314 /* from_day_of_week */
1315 if (!(colon = strchr(value, ':')))
1316 goto fail;
1317 start.match.days[0] = end.match.days[0] = strtoul(value, NULL, 0);
1318 value = colon + 1;
1320 /* to_day_of_week */
1321 if (!(colon = strchr(value, ':')))
1322 goto fail;
1323 start.match.days[1] = end.match.days[1] = strtoul(value, NULL, 0);
1324 value = colon + 1;
1326 /* from_time_of_day */
1327 if (!(colon = strchr(value, ':')))
1328 goto fail;
1329 start.match.secs[0] = end.match.secs[0] = strtoul(value, NULL, 0);
1330 value = colon + 1;
1332 /* to_time_of_day */
1333 start.match.secs[1] = end.match.secs[1] = strtoul(value, NULL, 0);
1335 done:
1336 /* Replace an unused or invalid entry */
1337 for (j = 0; get_filter_client(j, &unused, &unused); j++);
1338 valid = set_filter_client(j, &start, &end);
1339 assert(valid);
1341 fail:
1342 nvram_unset(name);
1345 nvram_unset("filter_port");
1347 #endif /* __CONFIG_NAT__ */
1349 static void
1350 convert_maclist(char *prefix)
1352 char mac[1000], maclist[1000], macmode[1000];
1353 char *value;
1355 snprintf(mac, sizeof(mac), "%s_mac", prefix);
1356 snprintf(maclist, sizeof(maclist), "%s_maclist", prefix);
1357 snprintf(macmode, sizeof(maclist), "%s_macmode", prefix);
1359 if ((value = nvram_get(mac))) {
1360 nvram_set(maclist, value);
1361 /* An empty *_mac used to imply *_macmode=disabled */
1362 if (!*value)
1363 nvram_set(macmode, "disabled");
1364 nvram_unset(mac);
1368 #ifdef __CONFIG_NAT__
1369 #if !defined(AUTOFW_PORT_DEPRECATED)
1370 static void
1371 convert_autofw_port(void)
1373 char name[] = "autofw_portXXXXXXXXXX", value[1000];
1374 char *out_proto, *out_start, *out_end, *in_proto, *in_start, *in_end, *to_start, *to_end;
1375 char *enable, *desc;
1376 netconf_app_t app;
1377 bool valid;
1378 int i;
1380 /* Maximum number of autofw_port entries was 10 */
1381 for (i = 0; i < 10; i++) {
1382 memset(&app, 0, sizeof(netconf_app_t));
1384 /* Parse out_proto:out_port,in_proto:in_start-in_end>to_start-to_end,enable,desc */
1385 snprintf(name, sizeof(name), "autofw_port%d", i);
1386 if (!nvram_invmatch(name, ""))
1387 goto fail;
1388 strncpy(value, nvram_get(name), sizeof(value));
1390 /* Check for outbound port specification */
1391 out_start = value;
1392 out_proto = strsep(&out_start, ":");
1393 if (!out_start)
1394 goto fail;
1396 /* Check for related protocol specification */
1397 in_proto = out_start;
1398 out_start = strsep(&in_proto, ",");
1399 if (!in_proto)
1400 goto fail;
1402 /* Check for related destination port specification */
1403 in_start = in_proto;
1404 in_proto = strsep(&in_start, ":");
1405 if (!in_start)
1406 goto fail;
1408 /* Check for mapped destination port specification */
1409 to_start = in_start;
1410 in_start = strsep(&to_start, ">");
1411 if (!to_start)
1412 goto fail;
1414 /* Check for enable specification */
1415 enable = to_start;
1416 to_end = strsep(&enable, ",");
1417 if (!enable)
1418 goto fail;
1420 /* Check for description specification (optional) */
1421 desc = enable;
1422 enable = strsep(&desc, ",");
1424 /* Check for outbound port range (new format) */
1425 out_end = out_start;
1426 out_start = strsep(&out_end, "-");
1427 if (!out_end)
1428 out_end = out_start;
1429 /* !new format already! */
1430 else
1431 continue;
1433 /* Check for related destination port range (optional) */
1434 in_end = in_start;
1435 in_start = strsep(&in_end, "-");
1436 if (!in_end)
1437 in_end = in_start;
1439 /* Check for mapped destination port range (optional) */
1440 to_end = to_start;
1441 to_start = strsep(&to_end, "-");
1442 if (!to_end)
1443 to_end = to_start;
1445 /* Parse outbound protocol */
1446 if (!strncasecmp(out_proto, "tcp", 3))
1447 app.match.ipproto = IPPROTO_TCP;
1448 else if (!strncasecmp(out_proto, "udp", 3))
1449 app.match.ipproto = IPPROTO_UDP;
1450 else
1451 goto fail;
1453 /* Parse outbound port */
1454 app.match.dst.ports[0] = htons(atoi(out_start));
1455 app.match.dst.ports[1] = htons(atoi(out_end));
1457 /* Parse related protocol */
1458 if (!strncasecmp(in_proto, "tcp", 3))
1459 app.proto = IPPROTO_TCP;
1460 else if (!strncasecmp(in_proto, "udp", 3))
1461 app.proto = IPPROTO_UDP;
1462 else
1463 goto fail;
1465 /* Parse related destination port range */
1466 app.dport[0] = htons(atoi(in_start));
1467 app.dport[1] = htons(atoi(in_end));
1469 /* Parse mapped destination port range */
1470 app.to[0] = htons(atoi(to_start));
1471 app.to[1] = htons(atoi(to_end));
1473 /* Parse enable */
1474 if (!strncasecmp(enable, "off", 3))
1475 app.match.flags = NETCONF_DISABLED;
1477 /* Parse description */
1478 if (desc)
1479 strncpy(app.desc, desc, sizeof(app.desc));
1481 /* Set interface name (match packets entering LAN interface) */
1482 strncpy(app.match.in.name, nvram_safe_get("lan_ifname"), IFNAMSIZ);
1484 /* Set LAN source port range (match packets from any source port) */
1485 app.match.src.ports[1] = htons(0xffff);
1487 /* Set target (application specific port forward) */
1488 app.target = NETCONF_APP;
1490 /* Replace an unused or invalid entry */
1491 valid = set_autofw_port(i, &app);
1492 assert(valid);
1494 /* Next filter */
1495 continue;
1497 fail:
1498 nvram_unset(name);
1501 #endif /* !AUTOFW_PORT_DEPRECATED */
1503 static void
1504 convert_pppoe(void)
1506 char *old[] = {
1507 "pppoe_ifname", /* PPPoE enslaved interface */
1508 "pppoe_username", /* PPP username */
1509 "pppoe_passwd", /* PPP password */
1510 "pppoe_idletime", /* Dial on demand max idle time (seconds) */
1511 "pppoe_keepalive", /* Restore link automatically */
1512 "pppoe_demand", /* Dial on demand */
1513 "pppoe_mru", /* Negotiate MRU to this value */
1514 "pppoe_mtu", /* Negotiate MTU to the smaller of this value or the peer MRU */
1515 "pppoe_service", /* PPPoE service name */
1516 "pppoe_ac", /* PPPoE access concentrator name */
1517 NULL
1519 char new[] = "wan_pppoe_XXXXXXXXXXXXXXXXXX";
1520 char *value;
1521 int i;
1522 for (i = 0; old[i] != NULL; i ++) {
1523 if ((value = nvram_get(old[i]))) {
1524 snprintf(new, sizeof(new), "wan_%s", old[i]);
1525 nvram_set(new, value);
1526 nvram_unset(old[i]);
1530 #endif /* __CONFIG_NAT__ */
1532 static void
1533 convert_static_route(void)
1535 char word[80], *next;
1536 char *ipaddr, *netmask, *gateway, *metric, *ifname;
1537 char lan_route[1000] = "";
1538 char *lan_cur = lan_route;
1539 #ifdef __CONFIG_NAT__
1540 char wan_route[1000] = "";
1541 char *wan_cur = wan_route;
1542 #endif /* __CONFIG_NAT__ */
1544 foreach(word, nvram_safe_get("static_route"), next) {
1545 netmask = word;
1546 ipaddr = strsep(&netmask, ":");
1547 if (!ipaddr || !netmask)
1548 continue;
1549 gateway = netmask;
1550 netmask = strsep(&gateway, ":");
1551 if (!netmask || !gateway)
1552 continue;
1553 metric = gateway;
1554 gateway = strsep(&metric, ":");
1555 if (!gateway || !metric)
1556 continue;
1557 ifname = metric;
1558 metric = strsep(&ifname, ":");
1559 if (!metric || !ifname)
1560 continue;
1562 if (strcmp(ifname, "lan") == 0) {
1563 lan_cur += snprintf(lan_cur, lan_route + sizeof(lan_route) - lan_cur,
1564 "%s%s:%s:%s:%s",
1565 lan_cur == lan_route ? "" : " ", ipaddr, netmask,
1566 gateway, metric);
1568 #ifdef __CONFIG_NAT__
1569 else if (strcmp(ifname, "wan") == 0) {
1570 wan_cur += snprintf(wan_cur, wan_route + sizeof(wan_route) - wan_cur,
1571 "%s%s:%s:%s:%s",
1572 wan_cur == wan_route ? "" : " ", ipaddr, netmask, gateway, metric);
1574 #endif /* __CONFIG_NAT__ */
1575 /* what to do? */
1576 else {}
1579 if (lan_cur != lan_route)
1580 nvram_set("lan_route", lan_route);
1582 #ifdef __CONFIG_NAT__
1583 if (wan_cur != wan_route)
1584 nvram_set("wan_route", wan_route);
1585 #endif /* __CONFIG_NAT__ */
1587 nvram_unset("static_route");
1591 * convert wl_wep - separate WEP encryption from WPA cryptos:
1592 * wep|on|restricted|off -> enabled|disabled
1593 * tkip|ase|tkip+aes -> wl_crypto
1594 * combine wl_auth_mode and wl_auth:
1595 * wl_auth 0|1 -> wl_auth_mode open|shared (when wl_auth_mode is disabled)
1597 static void
1598 convert_wsec(void)
1600 char prefix[] = "wlXXXXXXXXXX_", tmp[64], *wep;
1601 int i;
1603 for (i = 0; i < MAX_NVPARSE; i ++) {
1604 sprintf(prefix, "wl%d_", i);
1605 wep = nvram_get(strcat_r(prefix, "wep", tmp));
1606 if (!wep)
1607 continue;
1608 /* 3.60.xx */
1609 /* convert wep, restricted, or on to enabled */
1610 if (!strcmp(wep, "wep") || !strcmp(wep, "restricted") ||
1611 !strcmp(wep, "on"))
1612 nvram_set(strcat_r(prefix, "wep", tmp), "enabled");
1613 /* split wep and wpa to wl_wep and wl_crypto */
1614 else if (!strcmp(wep, "tkip") || !strcmp(wep, "aes") ||
1615 !strcmp(wep, "tkip+aes")) {
1616 nvram_set(strcat_r(prefix, "crypto", tmp), wep);
1617 nvram_set(strcat_r(prefix, "wep", tmp), "disabled");
1619 /* treat everything else as disabled */
1620 else if (strcmp(wep, "enabled"))
1621 nvram_set(strcat_r(prefix, "wep", tmp), "disabled");
1622 /* combine 802.11 open/shared authentication mode with WPA to wl_auth_mode */
1623 if (nvram_match(strcat_r(prefix, "auth_mode", tmp), "disabled")) {
1624 if (nvram_match(strcat_r(prefix, "auth", tmp), "1"))
1625 nvram_set(strcat_r(prefix, "auth_mode", tmp), "shared");
1626 else
1627 nvram_set(strcat_r(prefix, "auth_mode", tmp), "open");
1629 /* 3.80.xx
1631 * check only if the wl_auth_mode is set to "shared"
1632 * wl_auth_carries a default value of "0"
1634 /* split 802.11 auth from wl_auth_mode */
1635 if (nvram_match(strcat_r(prefix, "auth_mode", tmp), "shared"))
1636 nvram_set(strcat_r(prefix, "auth", tmp), "1");
1637 /* split wpa akm from wl_auth_mode */
1638 if (nvram_match(strcat_r(prefix, "auth_mode", tmp), "wpa"))
1639 nvram_set(strcat_r(prefix, "akm", tmp), "wpa");
1640 else if (nvram_match(strcat_r(prefix, "auth_mode", tmp), "psk"))
1641 nvram_set(strcat_r(prefix, "akm", tmp), "psk");
1642 /* preserve radius only in wl_auth_mode */
1643 if (nvram_invmatch(strcat_r(prefix, "auth_mode", tmp), "radius"))
1644 nvram_set(strcat_r(prefix, "auth_mode", tmp), "none");
1648 void
1649 convert_deprecated(void)
1651 #ifdef __CONFIG_NAT__
1652 /* forward_tcp and forward_udp were space separated lists of port forwards */
1653 convert_forward_proto("forward_tcp", IPPROTO_TCP);
1654 convert_forward_proto("forward_udp", IPPROTO_UDP);
1656 /* filter_ip was a space separated list of IP address ranges */
1657 convert_filter_ip();
1659 /* filter_tcp and filter_udp were space separated lists of IP address and TCP port ranges */
1660 convert_filter_proto("filter_tcp", IPPROTO_TCP);
1661 convert_filter_proto("filter_udp", IPPROTO_UDP);
1663 /* filter_port was a short-lived implementation of filter_client */
1664 convert_filter_port();
1665 #endif /* __CONFIG_NAT__ */
1667 convert_maclist("filter");
1668 convert_maclist("wl");
1670 #ifdef __CONFIG_NAT__
1671 /* pppoe_ifname used to save the underlying WAN interface name */
1672 if (nvram_invmatch("pppoe_ifname", "") && nvram_match("wan_proto", "pppoe"))
1673 nvram_set("wan_ifname", nvram_get("pppoe_ifname"));
1674 nvram_unset("pppoe_ifname");
1676 #if !defined(AUTOFW_PORT_DEPRECATED)
1677 /* autofw_port were single destination port and now support a port range */
1678 convert_autofw_port();
1679 #endif
1680 /* pppoe_XXXXXXXX are now wan_pppoe_XXXXXXXX */
1681 convert_pppoe();
1682 #endif /* __CONFIG_NAT__ */
1684 /* static_route used to save routes for LAN and WAN and is now between lan_route and
1685 * wan_route
1687 convert_static_route();
1689 /* convert wl_wep and combine wl_auth_mode and wl_auth */
1690 convert_wsec();