source: src/router/httpd/validate/webs.c @ 11163

Last change on this file since 11163 was 11163, checked in by BrainSlayer, 4 years ago

phase2 authentication support

File size: 82.9 KB
Line 
1#define VALIDSOURCE 1
2
3#ifdef WEBS
4#include <webs.h>
5#include <uemf.h>
6#include <ej.h>
7#else /* !WEBS */
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12#include <unistd.h>
13#include <limits.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <sys/socket.h>
17#include <netinet/in.h>
18#include <arpa/inet.h>
19#include <httpd.h>
20#include <errno.h>
21#endif /* WEBS */
22
23#include <proto/ethernet.h>
24#include <fcntl.h>
25#include <signal.h>
26#include <time.h>
27#include <sys/klog.h>
28#include <sys/wait.h>
29#include <cyutils.h>
30#include <support.h>
31#include <cy_conf.h>
32// #ifdef EZC_SUPPORT
33#include <ezc.h>
34// #endif
35#include <broadcom.h>
36#include <wlutils.h>
37#include <netdb.h>
38#include <utils.h>
39#include <stdarg.h>
40
41extern char *( *websGetVar ) ( webs_t wp, char *var, char *d );
42
43void wan_proto( webs_t wp )
44{
45    char *enable;
46    enable = websGetVar( wp, "wan_proto", NULL );
47    nvram_set( "wan_proto", enable );
48}
49
50#ifdef FILTER_DEBUG
51extern FILE *debout;
52
53#define D(a) fprintf(debout,"%s\n",a); fflush(debout);
54#else
55#define D(a)
56#endif
57
58void dhcpfwd( webs_t wp )
59{
60    char *enable;
61
62    enable = websGetVar( wp, "dhcpfwd_enable", NULL );
63    nvram_set( "dhcpfwd_enable", enable );
64
65}
66
67#ifdef HAVE_CCONTROL
68
69void execute( webs_t wp );
70
71{
72    char command[256];
73    char *var = websGetVar( wp, "command", "" );
74
75    sysprintf( "%s > /tmp/.result" );
76}
77
78#endif
79void clone_mac( webs_t wp )
80{
81    nvram_set( "clone_wan_mac", "1" );
82}
83
84/*
85 * Delete lease
86 */
87void delete_leases( webs_t wp )
88{
89    char *iface;
90    char *ip;
91    char *mac;
92
93    if( nvram_match( "lan_proto", "static" ) )
94        return;
95
96    if( nvram_match( "fon_enable", "1" )
97        || ( nvram_match( "chilli_nowifibridge", "1" )
98             && nvram_match( "chilli_enable", "1" ) ) )
99    {
100        iface = nvram_safe_get( "wl0_ifname" );
101    }
102    else
103    {
104        if( nvram_match( "chilli_enable", "1" ) )
105            iface = nvram_safe_get( "wl0_ifname" );
106        else
107            iface = nvram_safe_get( "lan_ifname" );
108    }
109
110    ip = websGetVar( wp, "ip_del", NULL );
111    mac = websGetVar( wp, "mac_del", NULL );
112
113    sysprintf( "dhcp_release %s %s %s", iface, ip, mac );
114}
115
116void save_wifi( webs_t wp )
117{
118    // fprintf (stderr, "save wifi\n");
119    char *var = websGetVar( wp, "wifi_display", NULL );
120
121    if( var )
122    {
123        nvram_set( "wifi_display", var );
124    }
125}
126
127void dhcp_renew( webs_t wp )
128{
129    killall( "igmprt", SIGTERM );
130    killall( "udhcpc", SIGUSR1 );
131}
132
133void dhcp_release( webs_t wp )
134{
135
136    killall( "igmprt", SIGTERM );
137    nvram_set( "wan_ipaddr", "0.0.0.0" );
138    nvram_set( "wan_netmask", "0.0.0.0" );
139    nvram_set( "wan_gateway", "0.0.0.0" );
140    nvram_set( "wan_get_dns", "" );
141    nvram_set( "wan_lease", "0" );
142
143    unlink( "/tmp/get_lease_time" );
144    unlink( "/tmp/lease_time" );
145
146}
147
148void stop_ppp( webs_t wp )
149{
150    unlink( "/tmp/ppp/log" );
151    unlink( "/tmp/ppp/link" );
152}
153
154void validate_filter_tod( webs_t wp )
155{
156    char buf[256] = "";
157    char tod_buf[20];
158    struct variable filter_tod_variables[] = {
159      {argv:ARGV( "20" )},
160      {argv:ARGV( "0", "1", "2" )},
161
162    }, *which;
163
164    char *day_all, *week0, *week1, *week2, *week3, *week4, *week5, *week6;
165    char *time_all, *start_hour, *start_min, *end_hour, *end_min;
166    int _start_hour, _start_min, _end_hour, _end_min;
167    char time[20];
168    int week[7];
169    int i, flag = -1, dash = 0;
170    char filter_tod[] = "filter_todXXX";
171    char filter_tod_buf[] = "filter_tod_bufXXX";
172
173    which = &filter_tod_variables[0];
174
175    day_all = websGetVar( wp, "day_all", "0" );
176    week0 = websGetVar( wp, "week0", "0" );
177    week1 = websGetVar( wp, "week1", "0" );
178    week2 = websGetVar( wp, "week2", "0" );
179    week3 = websGetVar( wp, "week3", "0" );
180    week4 = websGetVar( wp, "week4", "0" );
181    week5 = websGetVar( wp, "week5", "0" );
182    week6 = websGetVar( wp, "week6", "0" );
183    time_all = websGetVar( wp, "time_all", "0" );
184    start_hour = websGetVar( wp, "start_hour", "0" );
185    start_min = websGetVar( wp, "start_min", "0" );
186    // start_time = websGetVar (wp, "start_time", "0");
187    end_hour = websGetVar( wp, "end_hour", "0" );
188    end_min = websGetVar( wp, "end_min", "0" );
189    // end_time = websGetVar (wp, "end_time", "0");
190
191    // if(atoi(time_all) == 0)
192    // if(!start_hour || !start_min || !start_time || !end_hour || !end_min
193    // || !end_time)
194    // return 1;
195
196    if( atoi( day_all ) == 1 )
197    {
198        strcpy( time, "0-6" );
199        strcpy( tod_buf, "7" );
200    }
201    else
202    {
203        week[0] = atoi( week0 );
204        week[1] = atoi( week1 );
205        week[2] = atoi( week2 );
206        week[3] = atoi( week3 );
207        week[4] = atoi( week4 );
208        week[5] = atoi( week5 );
209        week[6] = atoi( week6 );
210        strcpy( time, "" );
211
212        for( i = 0; i < 7; i++ )
213        {
214            if( week[i] == 1 )
215            {
216                if( i == 6 )
217                {
218                    if( dash == 0 && flag == 1 )
219                        sprintf( time + strlen( time ), "%c", '-' );
220                    sprintf( time + strlen( time ), "%d", i );
221                }
222                else if( flag == 1 && dash == 0 )
223                {
224                    sprintf( time + strlen( time ), "%c", '-' );
225                    dash = 1;
226                }
227                else if( dash == 0 )
228                {
229                    sprintf( time + strlen( time ), "%d", i );
230                    flag = 1;
231                    dash = 0;
232                }
233            }
234            else
235            {
236                if( !strcmp( time, "" ) )
237                    continue;
238                if( dash == 1 )
239                    sprintf( time + strlen( time ), "%d", i - 1 );
240                if( flag != 0 )
241                    sprintf( time + strlen( time ), "%c", ',' );
242                flag = 0;
243                dash = 0;
244            }
245        }
246        if( time[strlen( time ) - 1] == ',' )
247            time[strlen( time ) - 1] = '\0';
248
249        snprintf( tod_buf, sizeof( tod_buf ), "%s %s %s %s %s %s %s", week0,
250                  week1, week2, week3, week4, week5, week6 );
251    }
252    if( atoi( time_all ) == 1 )
253    {
254        _start_hour = 0;
255        _start_min = 0;
256        _end_hour = 23;
257        _end_min = 59;
258    }
259    else
260    {
261        _start_hour = atoi( start_hour );
262        _start_min = atoi( start_min );
263        _end_hour = atoi( end_hour );
264        _end_min = atoi( end_min );
265    }
266
267    sprintf( buf, "%d:%d %d:%d %s", _start_hour, _start_min, _end_hour,
268             _end_min, time );
269    snprintf( filter_tod, sizeof( filter_tod ), "filter_tod%s",
270              nvram_safe_get( "filter_id" ) );
271    snprintf( filter_tod_buf, sizeof( filter_tod_buf ), "filter_tod_buf%s",
272              nvram_safe_get( "filter_id" ) );
273
274    nvram_set( filter_tod, buf );
275    nvram_set( filter_tod_buf, tod_buf );
276    D( "everything okay" );
277
278}
279
280void save_policy( webs_t wp )
281{
282    char *f_id, *f_name, *f_status, *f_status2;
283    char buf[256] = "";
284    char *value = websGetVar( wp, "action", "" );
285    struct variable filter_variables[] = {
286      {argv:ARGV( "1", "10" )},
287      {argv:ARGV( "0", "1", "2" )},
288      {argv:ARGV( "deny", "allow" )},
289
290    }, *which;
291    char filter_buf[] = "filter_ruleXXX";
292
293    D( "save policy" );
294    which = &filter_variables[0];
295    f_id = websGetVar( wp, "f_id", NULL );
296    f_name = websGetVar( wp, "f_name", NULL );
297    f_status = websGetVar( wp, "f_status", NULL );      // 0=>Disable /
298                                                        // 1,2=>Enable
299    f_status2 = websGetVar( wp, "f_status2", NULL );    // deny=>Deny /
300                                                        // allow=>Allow
301    if( !f_id || !f_name || !f_status || !f_status2 )
302    {
303        D( "invalid" );
304        return;
305    }
306    if( !valid_range( wp, f_id, &which[0] ) )
307    {
308        D( "invalid" );
309        return;
310    }
311    if( !valid_choice( wp, f_status, &which[1] ) )
312    {
313        D( "invalid" );
314        return;
315    }
316    if( !valid_choice( wp, f_status2, &which[2] ) )
317    {
318        D( "invalid" );
319        return;
320    }
321
322    validate_filter_tod( wp );
323
324    snprintf( filter_buf, sizeof( filter_buf ), "filter_rule%s",
325              nvram_safe_get( "filter_id" ) );
326
327    // Add $DENY to decide that users select Allow or Deny, if status is
328    // Disable // 2003/10/21
329    snprintf( buf, sizeof( buf ), "$STAT:%s$NAME:%s$DENY:%d$$", f_status,
330              f_name, !strcmp( f_status2, "deny" ) ? 1 : 0 );
331
332    nvram_set( filter_buf, buf );
333
334    addAction( "filters" );
335    if( !strcmp( value, "ApplyTake" ) )
336    {
337        nvram_commit(  );
338        service_restart(  );
339    }
340
341    D( "okay" );
342}
343
344void validate_filter_policy( webs_t wp, char *value, struct variable *v )
345{
346    char *f_id = websGetVar( wp, "f_id", NULL );
347
348    if( f_id )
349        nvram_set( "filter_id", f_id );
350    else
351        nvram_set( "filter_id", "1" );
352
353    save_policy( wp );
354}
355
356char *num_to_protocol( int num )
357{
358    switch ( num )
359    {
360        case 1:
361            return "icmp";
362        case 6:
363            return "tcp";
364        case 17:
365            return "udp";
366        case 23:
367            return "both";
368        case 99:
369            return "l7";
370        case 100:
371            return "p2p";
372        default:
373            return "unknown";
374    }
375}
376
377/*
378 * Format: 21:21:tcp:FTP(&nbsp;)500:1000:both:TEST1
379 */
380
381void validate_services_port( webs_t wp )
382{
383    char buf[8192] = "", services[8192] = "", *cur = buf, *svcs = NULL;
384    char *services_array = websGetVar( wp, "services_array0", NULL );
385
386    // char *services_length = websGetVar (wp, "services_length0", NULL);
387    char word[1025], *next;
388    char delim[] = "(&nbsp;)";
389    char var[32] = "";
390    int index = 0;
391
392    do
393    {
394        snprintf( var, 31, "services_array%d", index++ );
395        svcs = websGetVar( wp, var, NULL );
396        if( svcs )
397            strcat( services, svcs );
398
399    }
400    while( svcs );
401
402    services_array = services;
403
404    split( word, services_array, next, delim )
405    {
406        int from, to, proto;
407        char name[80];
408
409        if( sscanf( word, "%d:%d:%d:%s", &from, &to, &proto, name ) != 4 )
410            continue;
411
412        cur +=
413            snprintf( cur, buf + sizeof( buf ) - cur,
414                      "%s$NAME:%03d:%s$PROT:%03d:%s$PORT:%03d:%d:%d",
415                      cur == buf ? "" : "<&nbsp;>", strlen( name ), name,
416                      strlen( num_to_protocol( proto ) ),
417                      num_to_protocol( proto ),
418                      ( int )( get_int_len( from ) + get_int_len( to ) +
419                               strlen( ":" ) ), from, to );
420    }
421
422    // segment filter_services into <= 1024 byte lengths
423    cur = buf;
424    // fprintf (stderr, "cur=%s\n", cur);
425
426    memcpy( word, cur, 1024 );
427    word[1025] = 0;
428    nvram_set( "filter_services", word );
429    cur += 1024;
430
431    if( strlen( cur ) > 0 )
432    {
433        nvram_set( "filter_services_1", cur );
434    }
435
436    // nvram_set ("filter_services", cur);
437    D( "okay" );
438}
439
440void save_services_port( webs_t wp )
441{
442    validate_services_port( wp );
443    char *value = websGetVar( wp, "action", "" );
444
445    addAction( "index" );
446    if( !strcmp( value, "ApplyTake" ) )
447    {
448        nvram_commit(  );
449        service_restart(  );
450    }
451}
452
453void delete_policy( webs_t wp, int which )
454{
455    char filter_rule[] = "filter_ruleXXX";
456    char filter_tod[] = "filter_todXXX";
457    char filter_tod_buf[] = "filter_tod_bufXXX";
458    char filter_host[] = "filter_web_hostXXX";
459    char filter_url[] = "filter_web_urlXXX";
460    char filter_ip_grp[] = "filter_ip_grpXXX";
461    char filter_mac_grp[] = "filter_mac_grpXXX";
462    char filter_port_grp[] = "filter_port_grpXXX";
463    char filter_dport_grp[] = "filter_dport_grpXXX";
464
465    D( "delete policy" );
466
467    snprintf( filter_rule, sizeof( filter_rule ), "filter_rule%d", which );
468    snprintf( filter_tod, sizeof( filter_tod ), "filter_tod%d", which );
469    snprintf( filter_tod_buf, sizeof( filter_tod_buf ), "filter_tod_buf%d",
470              which );
471    snprintf( filter_host, sizeof( filter_host ), "filter_web_host%d",
472              which );
473    snprintf( filter_url, sizeof( filter_url ), "filter_web_url%d", which );
474    snprintf( filter_ip_grp, sizeof( filter_ip_grp ), "filter_ip_grp%d",
475              which );
476    snprintf( filter_mac_grp, sizeof( filter_mac_grp ), "filter_mac_grp%d",
477              which );
478    snprintf( filter_port_grp, sizeof( filter_port_grp ), "filter_port_grp%d",
479              which );
480    snprintf( filter_dport_grp, sizeof( filter_dport_grp ),
481              "filter_dport_grp%d", which );
482
483    nvram_set( filter_rule, "" );
484    nvram_set( filter_tod, "" );
485    nvram_set( filter_tod_buf, "" );
486    nvram_set( filter_host, "" );
487    nvram_set( filter_url, "" );
488    nvram_set( filter_ip_grp, "" );
489    nvram_set( filter_mac_grp, "" );
490    nvram_set( filter_port_grp, "" );
491    nvram_set( filter_dport_grp, "" );
492    D( "okay" );
493}
494
495void single_delete_policy( webs_t wp )
496{
497    addAction( "filters" );
498    char *id = nvram_safe_get( "filter_id" );
499
500    D( "single delete policy" );
501    delete_policy( wp, atoi( id ) );
502    D( "okay" );
503    return;
504}
505
506void summary_delete_policy( webs_t wp )
507{
508    addAction( "filters" );
509    int i;
510
511    D( "summary delete policy" );
512    for( i = 1; i <= 10; i++ )
513    {
514        char filter_sum[] = "sumXXX";
515        char *sum;
516
517        snprintf( filter_sum, sizeof( filter_sum ), "sum%d", i );
518        sum = websGetVar( wp, filter_sum, NULL );
519        if( sum )
520            delete_policy( wp, i );
521    }
522    D( "okay" );
523}
524
525void addDeletion( char *word )
526{
527    char *oldarg = nvram_get( "action_service_arg1" );
528
529    if( oldarg && strlen( oldarg ) > 0 )
530    {
531        char *newarg = malloc( strlen( oldarg ) + strlen( word ) + 2 );
532
533        sprintf( newarg, "%s %s", oldarg, word );
534        nvram_set( "action_service_arg1", newarg );
535        free( newarg );
536    }
537    else
538        nvram_set( "action_service_arg1", word );
539}
540
541void delete_static_route( webs_t wp )
542{
543    addAction( "routing" );
544    char *buf = malloc( 1000 );
545    char *buf_name = malloc( 1000 );
546
547    memset( buf, 0, 1000 );
548    memset( buf_name, 0, 1000 );
549    char *cur = buf;
550    char *cur_name = buf_name;
551    static char word[256], *next;
552    static char word_name[256], *next_name;
553    char *page = websGetVar( wp, "route_page", NULL );
554    char *value = websGetVar( wp, "action", "" );
555    int i = 0;
556    char *performance = nvram_safe_get( "static_route" );
557    char *performance2 = nvram_safe_get( "static_route_name" );
558
559    foreach( word, performance, next )
560    {
561        if( i == atoi( page ) )
562        {
563            addDeletion( word );
564            i++;
565            continue;
566        }
567
568        cur += snprintf( cur, buf + 1000 - cur, "%s%s",
569                         cur == buf ? "" : " ", word );
570
571        i++;
572    }
573
574    i = 0;
575    foreach( word_name, performance2, next_name )
576    {
577        if( i == atoi( page ) )
578        {
579            i++;
580            continue;
581        }
582        cur_name +=
583            snprintf( cur_name, buf_name + 1000 - cur_name, "%s%s",
584                      cur_name == buf_name ? "" : " ", word_name );
585
586        i++;
587    }
588
589    nvram_set( "static_route", buf );
590    nvram_set( "static_route_name", buf_name );
591    free( buf_name );
592    free( buf );
593    if( !strcmp( value, "ApplyTake" ) )
594    {
595        nvram_commit(  );
596        service_restart(  );
597    }
598    return;
599}
600extern void gen_key( char *genstr, int weptype );
601
602extern unsigned char key128[4][13];
603extern unsigned char key64[4][5];
604
605void generate_wep_key( webs_t wp )
606{
607    int i;
608    char buf[256];
609    char *prefix, *passphrase, *bit, *tx;
610
611#ifdef HAVE_MADWIFI
612    prefix = websGetVar( wp, "security_varname", "ath0" );
613#else
614    prefix = websGetVar( wp, "security_varname", "wl" );
615#endif
616    char var[80];
617
618    sprintf( var, "%s_wep_bit", prefix );
619    bit = websGetVar( wp, var, NULL );
620    if( bit != NULL )
621        nvram_set( "wl_wep_bit", bit );
622    sprintf( var, "%s_passphrase", prefix );
623    passphrase = websGetVar( wp, var, NULL );
624    sprintf( var, "%s_key", prefix );
625    tx = websGetVar( wp, var, NULL );
626    cprintf( "gen wep key: bits = %s\n", bit );
627    if( !prefix || !bit || !passphrase || !tx )
628        return;
629
630    gen_key( passphrase, atoi( bit ) );
631
632    nvram_set( "generate_key", "1" );
633
634    if( atoi( bit ) == 64 )
635    {
636        char key1[27] = "";
637        char key2[27] = "";
638        char key3[27] = "";
639        char key4[27] = "";
640
641        for( i = 0; i < 5; i++ )
642            sprintf( key1 + ( i << 1 ), "%02X", key64[0][i] );
643        for( i = 0; i < 5; i++ )
644            sprintf( key2 + ( i << 1 ), "%02X", key64[1][i] );
645        for( i = 0; i < 5; i++ )
646            sprintf( key3 + ( i << 1 ), "%02X", key64[2][i] );
647        for( i = 0; i < 5; i++ )
648            sprintf( key4 + ( i << 1 ), "%02X", key64[3][i] );
649
650        snprintf( buf, sizeof( buf ), "%s:%s:%s:%s:%s:%s", passphrase, key1,
651                  key2, key3, key4, tx );
652        // nvram_set("wl_wep_gen_64",buf);
653        cprintf( "buf = %s\n", buf );
654        sprintf( var, "%s_wep_gen", prefix );
655
656        nvram_set( var, buf );
657    }
658    else if( atoi( bit ) == 128 )
659    {
660        char key1[27] = "";
661        char key2[27] = "";
662        char key3[27] = "";
663        char key4[27] = "";
664
665        for( i = 0; i < 13; i++ )
666            sprintf( key1 + ( i << 1 ), "%02X", key128[0][i] );
667        key1[26] = 0;
668
669        for( i = 0; i < 13; i++ )
670            sprintf( key2 + ( i << 1 ), "%02X", key128[1][i] );
671        key2[26] = 0;
672
673        for( i = 0; i < 13; i++ )
674            sprintf( key3 + ( i << 1 ), "%02X", key128[2][i] );
675        key3[26] = 0;
676
677        for( i = 0; i < 13; i++ )
678            sprintf( key4 + ( i << 1 ), "%02X", key128[3][i] );
679        key4[26] = 0;
680        // cprintf("passphrase[%s]\n", passphrase);
681        // filter_name(passphrase, new_passphrase, sizeof(new_passphrase),
682        // SET);
683        // cprintf("new_passphrase[%s]\n", new_passphrase);
684        cprintf( "key1 = %s\n", key1 );
685        cprintf( "key2 = %s\n", key2 );
686        cprintf( "key3 = %s\n", key3 );
687        cprintf( "key4 = %s\n", key4 );
688
689        snprintf( buf, sizeof( buf ), "%s:%s:%s:%s:%s:%s", passphrase, key1,
690                  key2, key3, key4, tx );
691        cprintf( "buf = %s\n", buf );
692        // nvram_set("wl_wep_gen_128",buf);
693        sprintf( var, "%s_wep_gen", prefix );
694        nvram_set( var, buf );
695    }
696
697    return;
698}
699
700#ifndef HAVE_MSSID
701
702void set_security( webs_t wp )
703{
704    char *var = websGetVar( wp, "security_varname", "security_mode" );
705
706    nvram_set( var, websGetVar( wp, var, "disabled" ) );
707}
708#endif
709
710void copytonv( webs_t wp, const char *fmt, ... )
711{
712    char varbuf[64];
713    va_list args;
714
715    va_start( args, ( char * )fmt );
716    vsnprintf( varbuf, sizeof( varbuf ), fmt, args );
717    va_end( args );
718
719    char *wl = websGetVar( wp, varbuf, NULL );
720
721    if( wl )
722        nvram_set( varbuf, wl );
723}
724
725extern int get_merge_ipaddr( webs_t wp, char *name, char *ipaddr );
726
727#ifdef HAVE_MSSID
728
729static void save_secprefix( webs_t wp, char *prefix )
730{
731    char n[80];
732    char radius[80];
733    char p2[80];
734
735    strcpy( p2, prefix );
736    if( contains( prefix, '.' ) )
737        rep( p2, '.', 'X' );    // replace invalid characters for sub ifs
738
739#ifdef HAVE_WPA_SUPPLICANT
740
741/*_8021xtype
742_8021xuser
743_8021xpasswd
744_8021xca
745_8021xpem
746_8021xprv
747*/
748    copytonv( wp, "%s_8021xtype", prefix );
749    copytonv( wp, "%s_tls8021xuser", prefix );
750    copytonv( wp, "%s_tls8021xpasswd", prefix );
751    copytonv( wp, "%s_tls8021xphase2", prefix );
752    copytonv( wp, "%s_tls8021xca", prefix );
753    copytonv( wp, "%s_tls8021xpem", prefix );
754    copytonv( wp, "%s_tls8021xprv", prefix );
755    copytonv( wp, "%s_peap8021xuser", prefix );
756    copytonv( wp, "%s_peap8021xpasswd", prefix );
757    copytonv( wp, "%s_peap8021xphase2", prefix );
758    copytonv( wp, "%s_peap8021xca", prefix );
759    copytonv( wp, "%s_ttls8021xuser", prefix );
760    copytonv( wp, "%s_ttls8021xpasswd", prefix );
761    copytonv( wp, "%s_ttls8021xphase2", prefix );
762    copytonv( wp, "%s_ttls8021xca", prefix );
763    copytonv( wp, "%s_leap8021xuser", prefix );
764    copytonv( wp, "%s_leap8021xpasswd", prefix );
765    copytonv( wp, "%s_leap8021xphase2", prefix );
766
767#endif
768
769    copytonv( wp, "%s_crypto", prefix );
770    copytonv( wp, "%s_wpa_psk", prefix );
771    copytonv( wp, "%s_wpa_gtk_rekey", prefix );
772    sprintf( n, "%s_radius_ipaddr", prefix );
773    if( get_merge_ipaddr( wp, n, radius ) )
774        nvram_set( n, radius );
775    copytonv( wp, "%s_radius_port", prefix );
776    copytonv( wp, "%s_radius_key", prefix );
777#ifdef HAVE_MADWIFI
778    copytonv( wp, "%s_acct", prefix );
779    sprintf( n, "%s_acct_ipaddr", prefix );
780    if( get_merge_ipaddr( wp, n, radius ) )
781        nvram_set( n, radius );
782    copytonv( wp, "%s_acct_port", prefix );
783    copytonv( wp, "%s_acct_key", prefix );
784#endif
785
786    copytonv( wp, "%s_radmactype", prefix );
787    sprintf( n, "%s_key1", prefix );
788    char *key1 = websGetVar( wp, n, "" );
789
790    copytonv( wp, n );
791    sprintf( n, "%s_key2", prefix );
792    char *key2 = websGetVar( wp, n, "" );
793
794    copytonv( wp, n );
795    sprintf( n, "%s_key3", prefix );
796    char *key3 = websGetVar( wp, n, "" );
797
798    copytonv( wp, n );
799    sprintf( n, "%s_key4", prefix );
800    char *key4 = websGetVar( wp, n, "" );
801
802    copytonv( wp, n );
803    sprintf( n, "%s_passphrase", prefix );
804    char *pass = websGetVar( wp, n, "" );
805
806    copytonv( wp, n );
807    sprintf( n, "%s_key", prefix );
808    char *tx = websGetVar( wp, n, "" );
809
810    copytonv( wp, n );
811    sprintf( n, "%s_wep_bit", prefix );
812    copytonv( wp, n );
813    char buf[128];
814
815    snprintf( buf, sizeof( buf ), "%s:%s:%s:%s:%s:%s", pass,
816              key1, key2, key3, key4, tx );
817    sprintf( n, "%s_wep_buf", prefix );
818    nvram_set( n, buf );
819
820    sprintf( n, "%s_security_mode", p2 );
821    char n2[80];
822
823    sprintf( n2, "%s_akm", prefix );
824    char *v = websGetVar( wp, n, NULL );
825
826    if( v )
827    {
828        char auth[32];
829        char wep[32];
830
831        sprintf( auth, "%s_auth_mode", prefix );
832        sprintf( wep, "%s_wep", prefix );
833        if( !strcmp( v, "wep" ) )
834        {
835            nvram_set( auth, "none" );
836            nvram_set( wep, "enabled" );
837        }
838        else if( !strcmp( v, "radius" ) )
839        {
840            nvram_set( auth, "radius" );
841            nvram_set( wep, "enabled" );
842        }
843        else
844        {
845            nvram_set( auth, "none" );
846            nvram_set( wep, "disabled" );
847        }
848        nvram_set( n2, v );
849    }
850
851    copytonv( wp, n );
852
853}
854
855static int security_save_prefix( webs_t wp, char *prefix )
856{
857
858    save_secprefix( wp, prefix );
859    char *next;
860    char var[80];
861    char *vifs = nvram_nget( "%s_vifs", prefix );
862
863    if( vifs == NULL )
864        return 0;
865    foreach( var, vifs, next )
866    {
867        save_secprefix( wp, var );
868    }
869    // nvram_commit ();
870    return 0;
871}
872
873void security_save( webs_t wp )
874{
875    char *value = websGetVar( wp, "action", "" );
876
877    addAction( "wireless_2" );
878#ifdef HAVE_MADWIFI
879    int dc = getdevicecount(  );
880    int i;
881
882    for( i = 0; i < dc; i++ )
883    {
884        char b[16];
885
886        sprintf( b, "ath%d", i );
887        security_save_prefix( wp, b );
888    }
889#else
890    int dc = get_wl_instances(  );
891    int i;
892
893    for( i = 0; i < dc; i++ )
894    {
895        char b[16];
896
897        sprintf( b, "wl%d", i );
898        security_save_prefix( wp, b );
899    }
900#endif
901    if( !strcmp( value, "ApplyTake" ) )
902    {
903        nvram_commit(  );
904        service_restart(  );
905    }
906}
907
908#endif
909
910extern struct wl_client_mac *wl_client_macs;
911
912void add_active_mac( webs_t wp )
913{
914    char buf[1000] = "", *cur = buf;
915    int i, count = 0;
916
917    nvram_set( "wl_active_add_mac", "1" );
918
919    for( i = 0; i < MAX_LEASES; i++ )
920    {
921        char active_mac[] = "onXXX";
922        char *index = NULL;
923
924        snprintf( active_mac, sizeof( active_mac ), "%s%d", "on", i );
925        index = websGetVar( wp, active_mac, NULL );
926        if( !index )
927            continue;
928
929        count++;
930
931        cur += snprintf( cur, buf + sizeof( buf ) - cur, "%s%s",
932                         cur == buf ? "" : " ",
933                         wl_client_macs[atoi( index )].hwaddr );
934    }
935    for( i = 0; i < MAX_LEASES; i++ )
936    {
937        char active_mac[] = "offXXX";
938        char *index;
939
940        snprintf( active_mac, sizeof( active_mac ), "%s%d", "off", i );
941        index = websGetVar( wp, active_mac, NULL );
942        if( !index )
943            continue;
944
945        count++;
946        cur += snprintf( cur, buf + sizeof( buf ) - cur, "%s%s",
947                         cur == buf ? "" : " ",
948                         wl_client_macs[atoi( index )].hwaddr );
949    }
950    nvram_set( "wl_active_mac", buf );
951    nvram_set( "wl0_active_mac", buf );
952}
953
954void removeLineBreak( char *startup )
955{
956    int i = 0;
957    int c = 0;
958
959    for( i = 0; i < strlen( startup ); i++ )
960    {
961        if( startup[i] == '\r' )
962            continue;
963        startup[c++] = startup[i];
964    }
965    startup[c++] = 0;
966
967}
968
969void ping_startup( webs_t wp )
970{
971    char *startup = websGetVar( wp, "ping_ip", NULL );
972
973    // filter Windows <cr>ud
974    removeLineBreak( startup );
975
976    nvram_set( "rc_startup", startup );
977    nvram_commit(  );
978    nvram2file( "rc_startup", "/tmp/.rc_startup" );
979    chmod( "/tmp/.rc_startup", 0700 );
980
981    return;
982
983}
984
985void ping_shutdown( webs_t wp )
986{
987    char *shutdown = websGetVar( wp, "ping_ip", NULL );
988
989    // filter Windows <cr>ud
990    removeLineBreak( shutdown );
991
992    nvram_set( "rc_shutdown", shutdown );
993    nvram_commit(  );
994    nvram2file( "rc_shutdown", "/tmp/.rc_shutdown" );
995    chmod( "/tmp/.rc_shutdown", 0700 );
996
997    return;
998
999}
1000
1001void ping_firewall( webs_t wp )
1002{
1003    char *firewall = websGetVar( wp, "ping_ip", NULL );
1004
1005    // filter Windows <cr>ud
1006    removeLineBreak( firewall );
1007    nvram_set( "rc_firewall", firewall );
1008    nvram_commit(  );
1009    nvram2file( "rc_firewall", "/tmp/.rc_firewall" );
1010    chmod( "/tmp/.rc_firewall", 0700 );
1011
1012    return;
1013}
1014
1015void ping_custom( webs_t wp )
1016{
1017    char *custom = websGetVar( wp, "ping_ip", NULL );
1018
1019    // filter Windows <cr>ud
1020    unlink( "/tmp/custom.sh" );
1021    removeLineBreak( custom );
1022    nvram_set( "rc_custom", custom );
1023    nvram_commit(  );
1024    if( nvram_invmatch( "rc_custom", "" ) )
1025    {
1026        nvram2file( "rc_custom", "/tmp/custom.sh" );
1027        chmod( "/tmp/custom.sh", 0700 );
1028    }
1029
1030    return;
1031}
1032
1033void ping_wol( webs_t wp )
1034{
1035    char *wol_type = websGetVar( wp, "wol_type", NULL );
1036
1037    unlink( PING_TMP );
1038
1039    if( !wol_type || !strcmp( wol_type, "" ) )
1040        return;
1041
1042    if( !strcmp( wol_type, "update" ) )
1043    {
1044        char *wol_hosts = websGetVar( wp, "wol_hosts", NULL );
1045
1046        if( !wol_hosts || !strcmp( wol_hosts, "" ) )
1047            return;
1048
1049        nvram_set( "wol_hosts", wol_hosts );
1050        nvram_set( "wol_cmd", "" );
1051        return;
1052    }
1053
1054    char *manual_wol_mac = websGetVar( wp, "manual_wol_mac", NULL );
1055    char *manual_wol_network = websGetVar( wp, "manual_wol_network", NULL );
1056    char *manual_wol_port = websGetVar( wp, "manual_wol_port", NULL );
1057
1058    if( !strcmp( wol_type, "manual" ) )
1059    {
1060        nvram_set( "manual_wol_mac", manual_wol_mac );
1061        nvram_set( "manual_wol_network", manual_wol_network );
1062        nvram_set( "manual_wol_port", manual_wol_port );
1063    }
1064
1065    char wol_cmd[256] = { 0 };
1066    snprintf( wol_cmd, sizeof( wol_cmd ), "/usr/sbin/wol -v -i %s -p %s %s",
1067              manual_wol_network, manual_wol_port, manual_wol_mac );
1068    nvram_set( "wol_cmd", wol_cmd );
1069
1070    // use Wol.asp as a debugging console
1071#ifdef HAVE_REGISTER
1072if (!isregistered_real())
1073    return;
1074#endif
1075    sysprintf( "%s > %s 2>&1 &", wol_cmd, PING_TMP );
1076
1077}
1078
1079void diag_ping_start( webs_t wp )
1080{
1081    char *ip = websGetVar( wp, "ping_ip", NULL );
1082
1083    if( !ip || !strcmp( ip, "" ) )
1084        return;
1085
1086    unlink( PING_TMP );
1087    nvram_set( "ping_ip", ip );
1088
1089    setenv( "PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1 );
1090#ifdef HAVE_REGISTER
1091if (!isregistered_real())
1092    return;
1093#endif
1094    sysprintf( "alias ping=\'ping -c 3\'; eval \"%s\" > %s 2>&1 &", ip,
1095               PING_TMP );
1096
1097    return;
1098}
1099
1100void diag_ping_stop( webs_t wp )
1101{
1102    killall( "ping", SIGKILL );
1103}
1104
1105void diag_ping_clear( webs_t wp )
1106{
1107    unlink( PING_TMP );
1108}
1109
1110void save_wds( webs_t wp )
1111{
1112    char *wds_enable_val, wds_enable_var[32] = { 0 };
1113    int h = 0;
1114    char *interface = websGetVar( wp, "interface", NULL );
1115
1116    for( h = 1; h <= MAX_WDS_DEVS; h++ )
1117    {
1118        sprintf( wds_enable_var, "%s_wds%d_enable", interface, h );
1119        wds_enable_val = websGetVar( wp, wds_enable_var, NULL );
1120        nvram_set( wds_enable_var, wds_enable_val );
1121    }
1122    sprintf( wds_enable_var, "%s_br1_enable", interface );
1123    wds_enable_val = websGetVar( wp, wds_enable_var, NULL );
1124    nvram_set( wds_enable_var, wds_enable_val );
1125
1126    sprintf( wds_enable_var, "%s_br1_nat", interface );
1127    wds_enable_val = websGetVar( wp, wds_enable_var, NULL );
1128    nvram_set( wds_enable_var, wds_enable_val );
1129
1130    return;
1131
1132}
1133
1134int get_svc( char *svc, char *protocol, char *ports )
1135{
1136    char word[1024], *next;
1137    char delim[] = "<&nbsp;>";
1138    char services[8192];
1139
1140    // services = nvram_safe_get("filter_services");
1141    memset( services, 0, 8192 );
1142    get_filter_services( services );
1143
1144    split( word, services, next, delim )
1145    {
1146        int len = 0;
1147        char *name, *prot, *port;
1148        int from = 0, to = 0;
1149
1150        if( ( name = strstr( word, "$NAME:" ) ) == NULL ||
1151            ( prot = strstr( word, "$PROT:" ) ) == NULL ||
1152            ( port = strstr( word, "$PORT:" ) ) == NULL )
1153            continue;
1154
1155        /*
1156         * $NAME
1157         */
1158        if( sscanf( name, "$NAME:%3d:", &len ) != 1 )
1159            return -1;
1160
1161        strncpy( name, name + sizeof( "$NAME:nnn:" ) - 1, len );
1162        name[len] = '\0';
1163
1164        if( strcasecmp( svc, name ) )
1165            continue;
1166
1167        /*
1168         * $PROT
1169         */
1170        if( sscanf( prot, "$PROT:%3d:", &len ) != 1 )
1171            return -1;
1172
1173        strncpy( protocol, prot + sizeof( "$PROT:nnn:" ) - 1, len );
1174        protocol[len] = '\0';
1175
1176        /*
1177         * $PORT
1178         */
1179        if( sscanf( port, "$PORT:%3d:", &len ) != 1 )
1180            return -1;
1181
1182        strncpy( ports, port + sizeof( "$PORT:nnn:" ) - 1, len );
1183        ports[len] = '\0';
1184
1185        if( sscanf( ports, "%d:%d", &from, &to ) != 2 )
1186            return -1;
1187
1188        if( strcasecmp( svc, name ) == 0 )
1189            return 0;
1190    }
1191
1192    return -1;
1193}
1194
1195void qos_add_svc( webs_t wp )
1196{
1197    char *var = websGetVar( wp, "wshaper_enable", NULL );
1198
1199    if( var != NULL )
1200        nvram_set( "wshaper_enable", var );
1201
1202    char protocol[100] = { 0 }, ports[100] =
1203    {
1204    0};
1205    char *add_svc = websGetVar( wp, "add_svc", NULL );
1206    char *svqos_svcs = nvram_safe_get( "svqos_svcs" );
1207    char new_svcs[4096] = { 0 };
1208    int i = 0;
1209
1210    memset( new_svcs, 0, sizeof( new_svcs ) );
1211
1212    if( get_svc( add_svc, protocol, ports ) )
1213        return;
1214
1215    if( strcmp( protocol, "l7" ) == 0 )
1216    {
1217        int slen = strlen( add_svc );
1218
1219        for( i = 0; i < slen; i++ )
1220            add_svc[i] = tolower( add_svc[i] );
1221    }
1222
1223    /*
1224     * if this service exists, return an error
1225     */
1226    if( strstr( svqos_svcs, add_svc ) )
1227        return;
1228
1229    if( strlen( svqos_svcs ) > 0 )
1230        snprintf( new_svcs, 4095, "%s %s %s %s 30 |", svqos_svcs, add_svc,
1231                  protocol, ports );
1232    else
1233        snprintf( new_svcs, 4095, "%s %s %s 30 |", add_svc, protocol, ports );
1234
1235    if( strlen( new_svcs ) >= sizeof( new_svcs ) )
1236        return;
1237
1238    nvram_set( "svqos_svcs", new_svcs );
1239    nvram_commit(  );
1240}
1241
1242void qos_add_ip( webs_t wp )
1243{
1244    char *var = websGetVar( wp, "wshaper_enable", NULL );
1245
1246    if( var != NULL )
1247        nvram_set( "wshaper_enable", var );
1248
1249    char *add_ip0 = websGetVar( wp, "svqos_ipaddr0", NULL );
1250    char *add_ip1 = websGetVar( wp, "svqos_ipaddr1", NULL );
1251    char *add_ip2 = websGetVar( wp, "svqos_ipaddr2", NULL );
1252    char *add_ip3 = websGetVar( wp, "svqos_ipaddr3", NULL );
1253    char *add_nm = websGetVar( wp, "svqos_netmask", NULL );
1254    char add_ip[19] = { 0 };
1255    char *svqos_ips = nvram_safe_get( "svqos_ips" );
1256    char new_ip[4096] = { 0 };
1257
1258    memset( new_ip, 0, sizeof( new_ip ) );
1259
1260    snprintf( add_ip, 19, "%s.%s.%s.%s/%s", add_ip0, add_ip1, add_ip2,
1261              add_ip3, add_nm );
1262
1263    /*
1264     * if this ip exists, return an error
1265     */
1266    if( strstr( svqos_ips, add_ip ) )
1267        return;
1268#ifdef HAVE_AQOS
1269    snprintf( new_ip, 4095, "%s %s 100 100 |", svqos_ips, add_ip );
1270#else
1271    snprintf( new_ip, 4095, "%s %s 30 |", svqos_ips, add_ip );
1272#endif
1273    if( strlen( new_ip ) >= sizeof( new_ip ) )
1274        return;
1275
1276    nvram_set( "svqos_ips", new_ip );
1277    nvram_commit(  );
1278
1279}
1280
1281void qos_add_mac( webs_t wp )
1282{
1283    char *var = websGetVar( wp, "wshaper_enable", NULL );
1284
1285    if( var != NULL )
1286        nvram_set( "wshaper_enable", var );
1287
1288    char *add_mac0 = websGetVar( wp, "svqos_hwaddr0", NULL );
1289    char *add_mac1 = websGetVar( wp, "svqos_hwaddr1", NULL );
1290    char *add_mac2 = websGetVar( wp, "svqos_hwaddr2", NULL );
1291    char *add_mac3 = websGetVar( wp, "svqos_hwaddr3", NULL );
1292    char *add_mac4 = websGetVar( wp, "svqos_hwaddr4", NULL );
1293    char *add_mac5 = websGetVar( wp, "svqos_hwaddr5", NULL );
1294    char add_mac[19] = { 0 };
1295    char *svqos_macs = nvram_safe_get( "svqos_macs" );
1296    char new_mac[4096] = { 0 };
1297
1298    memset( new_mac, 0, sizeof( new_mac ) );
1299
1300    snprintf( add_mac, 18, "%s:%s:%s:%s:%s:%s", add_mac0, add_mac1, add_mac2,
1301              add_mac3, add_mac4, add_mac5 );
1302
1303    /*
1304     * if this mac exists, return an error
1305     */
1306    if( strstr( svqos_macs, add_mac ) )
1307        return;
1308#ifdef HAVE_AQOS
1309    snprintf( new_mac, 4095, "%s %s 100 100 user |", svqos_macs, add_mac );
1310#else
1311    snprintf( new_mac, 4095, "%s %s 30 |", svqos_macs, add_mac );
1312#endif
1313    if( strlen( new_mac ) >= sizeof( new_mac ) )
1314        return;
1315
1316    nvram_set( "svqos_macs", new_mac );
1317    nvram_commit(  );
1318
1319}
1320
1321void qos_save( webs_t wp )
1322{
1323    char *value = websGetVar( wp, "action", "" );
1324    char svqos_var[4096] = { 0 };
1325    char field[32] = { 0 };
1326    char *name, *data, *level, *level2, *delete;
1327    int no_svcs = atoi( websGetVar( wp, "svqos_nosvcs", NULL ) );
1328    int no_ips = atoi( websGetVar( wp, "svqos_noips", NULL ) );
1329    int no_macs = atoi( websGetVar( wp, "svqos_nomacs", NULL ) );
1330    int i = 0, j = 0;
1331
1332    /*
1333     * reused wshaper fields - see src/router/rc/wshaper.c
1334     */
1335    snprintf( field, 31, "wshaper_enable" );
1336    data = websGetVar( wp, field, NULL );
1337    nvram_set( "wshaper_enable", data );
1338
1339    if( strcmp( data, "0" ) == 0 )
1340    {
1341        addAction( "qos" );
1342        if( !strcmp( value, "ApplyTake" ) )
1343        {
1344            nvram_commit(  );
1345            service_restart(  );
1346        }
1347        return;
1348    }
1349
1350    snprintf( field, 31, "enable_game" );
1351    data = websGetVar( wp, field, NULL );
1352    nvram_set( "enable_game", data );
1353
1354    snprintf( field, 31, "default_uplevel" );
1355    data = websGetVar( wp, field, NULL );
1356    nvram_set( "default_uplevel", data );
1357
1358    snprintf( field, 31, "default_downlevel" );
1359    data = websGetVar( wp, field, NULL );
1360    nvram_set( "default_downlevel", data );
1361
1362    snprintf( field, 31, "wshaper_downlink" );
1363    data = websGetVar( wp, field, NULL );
1364    nvram_set( "wshaper_downlink", data );
1365
1366    snprintf( field, 31, "wshaper_uplink" );
1367    data = websGetVar( wp, field, NULL );
1368    nvram_set( "wshaper_uplink", data );
1369
1370    snprintf( field, 31, "wshaper_dev" );
1371    data = websGetVar( wp, field, NULL );
1372    nvram_set( "wshaper_dev", data );
1373
1374    snprintf( field, 31, "qos_type" );
1375    data = websGetVar( wp, field, NULL );
1376    nvram_set( "qos_type", data );
1377
1378    // nvram_commit ();
1379
1380    memset( svqos_var, 0, sizeof( svqos_var ) );
1381
1382    /*
1383     * services priorities
1384     */
1385    for( i = 0; i < no_svcs; i++ )
1386    {
1387        char protocol[100], ports[100];
1388
1389        memset( protocol, 0, 100 );
1390        memset( ports, 0, 10 );
1391
1392        snprintf( field, 31, "svqos_svcdel%d", i );
1393        delete = websGetVar( wp, field, NULL );
1394
1395        if( delete && strlen( delete ) > 0 )
1396            continue;
1397
1398        snprintf( field, 31, "svqos_svcname%d", i );
1399        name = websGetVar( wp, field, NULL );
1400
1401        snprintf( field, 31, "svqos_svcprio%d", i );
1402        level = websGetVar( wp, field, NULL );
1403
1404        if( get_svc( name, protocol, ports ) )
1405            continue;
1406
1407        if( strcmp( protocol, "l7" ) == 0 )
1408        {
1409            int slen = strlen( name );
1410
1411            for( j = 0; j < slen; j++ )
1412                name[j] = tolower( name[j] );
1413        }
1414
1415        if( strlen( svqos_var ) > 0 )
1416            sprintf( svqos_var, "%s %s %s %s %s |", svqos_var, name, protocol,
1417                     ports, level );
1418        else
1419            sprintf( svqos_var, "%s %s %s %s |", name, protocol, ports,
1420                     level );
1421
1422    }
1423
1424    if( strlen( svqos_var ) <= sizeof( svqos_var ) )
1425        nvram_set( "svqos_svcs", svqos_var );
1426    // nvram_commit ();
1427    memset( svqos_var, 0, sizeof( svqos_var ) );
1428
1429    /*
1430     * IP priorities
1431     */
1432    for( i = 0; i < no_ips; i++ )
1433    {
1434
1435        snprintf( field, 31, "svqos_ipdel%d", i );
1436        delete = websGetVar( wp, field, NULL );
1437
1438        if( delete && strlen( delete ) > 0 )
1439            continue;
1440
1441        snprintf( field, 31, "svqos_ip%d", i );
1442        data = websGetVar( wp, field, NULL );
1443
1444#ifndef HAVE_AQOS
1445        snprintf( field, 31, "svqos_ipprio%d", i );
1446        level = websGetVar( wp, field, NULL );
1447        if( strlen( svqos_var ) > 0 )
1448            sprintf( svqos_var, "%s %s %s |", svqos_var, data, level );
1449        else
1450            sprintf( svqos_var, "%s %s |", data, level );
1451#else
1452        snprintf( field, 31, "svqos_ipup%d", i );
1453        level = websGetVar( wp, field, NULL );
1454        snprintf( field, 31, "svqos_ipdown%d", i );
1455        level2 = websGetVar( wp, field, NULL );
1456        if( strlen( svqos_var ) > 0 )
1457            sprintf( svqos_var, "%s %s %s %s |", svqos_var, data, level,
1458                     level2 );
1459        else
1460            sprintf( svqos_var, "%s %s %s |", data, level, level2 );
1461
1462#endif
1463
1464    }
1465
1466    if( strlen( svqos_var ) <= sizeof( svqos_var ) )
1467        nvram_set( "svqos_ips", svqos_var );
1468    // nvram_commit ();
1469    memset( svqos_var, 0, sizeof( svqos_var ) );
1470
1471    /*
1472     * MAC priorities
1473     */
1474    for( i = 0; i < no_macs; i++ )
1475    {
1476        snprintf( field, 31, "svqos_macdel%d", i );
1477        delete = websGetVar( wp, field, NULL );
1478
1479        if( delete && strlen( delete ) > 0 )
1480            continue;
1481
1482        snprintf( field, 31, "svqos_mac%d", i );
1483        data = websGetVar( wp, field, NULL );
1484
1485#ifndef HAVE_AQOS
1486        snprintf( field, 31, "svqos_macprio%d", i );
1487        level = websGetVar( wp, field, NULL );
1488
1489        if( strlen( svqos_var ) > 0 )
1490            sprintf( svqos_var, "%s %s %s |", svqos_var, data, level );
1491        else
1492            sprintf( svqos_var, "%s %s |", data, level );
1493#else
1494        snprintf( field, 31, "svqos_macup%d", i );
1495        level = websGetVar( wp, field, NULL );
1496        snprintf( field, 31, "svqos_macdown%d", i );
1497        level2 = websGetVar( wp, field, NULL );
1498
1499        if( strlen( svqos_var ) > 0 )
1500            sprintf( svqos_var, "%s %s %s %s user |", svqos_var, data, level,
1501                     level2 );
1502        else
1503            sprintf( svqos_var, "%s %s %s user |", data, level, level2 );
1504#endif
1505
1506    }
1507
1508    if( strlen( svqos_var ) <= sizeof( svqos_var ) )
1509        nvram_set( "svqos_macs", svqos_var );
1510    // nvram_commit ();
1511
1512    /*
1513     * adm6996 LAN port priorities
1514     */
1515    nvram_set( "svqos_port1prio", websGetVar( wp, "svqos_port1prio", NULL ) );
1516    nvram_set( "svqos_port2prio", websGetVar( wp, "svqos_port2prio", NULL ) );
1517    nvram_set( "svqos_port3prio", websGetVar( wp, "svqos_port3prio", NULL ) );
1518    nvram_set( "svqos_port4prio", websGetVar( wp, "svqos_port4prio", NULL ) );
1519
1520    nvram_set( "svqos_port1bw", websGetVar( wp, "svqos_port1bw", NULL ) );
1521    nvram_set( "svqos_port2bw", websGetVar( wp, "svqos_port2bw", NULL ) );
1522    nvram_set( "svqos_port3bw", websGetVar( wp, "svqos_port3bw", NULL ) );
1523    nvram_set( "svqos_port4bw", websGetVar( wp, "svqos_port4bw", NULL ) );
1524
1525    addAction( "qos" );
1526    if( !strcmp( value, "ApplyTake" ) )
1527    {
1528        nvram_commit(  );
1529        service_restart(  );
1530    }
1531
1532}
1533void macro_add( char *a )
1534{
1535    cprintf( "adding %s\n", a );
1536
1537    char *count;
1538    int c;
1539    char buf[20];
1540
1541    count = nvram_safe_get( a );
1542    cprintf( "count = %s\n", count );
1543    if( count != NULL && strlen( count ) > 0 )
1544    {
1545        c = atoi( count );
1546        if( c > -1 )
1547        {
1548            c++;
1549            sprintf( buf, "%d", c );
1550            cprintf( "set %s to %s\n", a, buf );
1551            nvram_set( a, buf );
1552        }
1553    }
1554    return;
1555}
1556
1557void macro_rem( char *a, char *nv )
1558{
1559    char *count;
1560    int c, i, cnt;
1561    char buf[20];
1562    char *buffer, *b;
1563
1564    cnt = 0;
1565    count = nvram_safe_get( a );
1566    if( count != NULL && strlen( count ) > 0 )
1567    {
1568        c = atoi( count );
1569        if( c > 0 )
1570        {
1571            c--;
1572            sprintf( buf, "%d", c );
1573            nvram_set( a, buf );
1574            buffer = nvram_safe_get( nv );
1575            if( buffer != NULL )
1576            {
1577                int slen = strlen( buffer );
1578
1579                b = malloc( slen + 1 );
1580
1581                for( i = 0; i < slen; i++ )
1582                {
1583                    if( buffer[i] == ' ' )
1584                        cnt++;
1585                    if( cnt == c )
1586                        break;
1587                    b[i] = buffer[i];
1588                }
1589                b[i] = 0;
1590                nvram_set( nv, b );
1591            }
1592
1593        }
1594    }
1595    return;
1596}
1597
1598void forward_remove( webs_t wp )
1599{
1600    macro_rem( "forward_entries", "forward_port" );
1601}
1602
1603void forward_add( webs_t wp )
1604{
1605    macro_add( "forward_entries" );
1606}
1607
1608void lease_remove( webs_t wp )
1609{
1610    macro_rem( "static_leasenum", "static_leases" );
1611}
1612
1613void lease_add( webs_t wp )
1614{
1615    macro_add( "static_leasenum" );
1616}
1617
1618#ifdef HAVE_PPPOESERVER
1619void chap_user_add( webs_t wp )
1620{
1621    char *var = websGetVar( wp, "pppoeserver_enabled", NULL );
1622
1623    if( var != NULL )
1624        nvram_set( "pppoeserver_enabled", var );
1625    macro_add( "pppoeserver_chapsnum" );
1626}
1627
1628void chap_user_remove( webs_t wp )
1629{
1630    char *var = websGetVar( wp, "pppoeserver_enabled", NULL );
1631
1632    if( var != NULL )
1633        nvram_set( "pppoeserver_enabled", var );
1634    macro_rem( "pppoeserver_chapsnum", "pppoeserver_chaps" );
1635}
1636#endif
1637
1638#ifdef HAVE_MILKFISH
1639void milkfish_user_add( webs_t wp )
1640{
1641    macro_add( "milkfish_ddsubscribersnum" );
1642}
1643
1644void milkfish_user_remove( webs_t wp )
1645{
1646    macro_rem( "milkfish_ddsubscribersnum", "milkfish_ddsubscribers" );
1647}
1648
1649void milkfish_alias_add( webs_t wp )
1650{
1651    macro_add( "milkfish_ddaliasesnum" );
1652}
1653
1654void milkfish_alias_remove( webs_t wp )
1655{
1656    macro_rem( "milkfish_ddaliasesnum", "milkfish_ddaliases" );
1657}
1658#endif
1659
1660void forwardspec_remove( webs_t wp )
1661{
1662    macro_rem( "forwardspec_entries", "forward_spec" );
1663}
1664
1665void forwardspec_add( webs_t wp )
1666{
1667    macro_add( "forwardspec_entries" );
1668}
1669
1670void trigger_remove( webs_t wp )
1671{
1672    macro_rem( "trigger_entries", "port_trigger" );
1673}
1674
1675void trigger_add( webs_t wp )
1676{
1677    macro_add( "trigger_entries" );
1678}
1679
1680int get_vifcount( char *prefix )
1681{
1682    char *next;
1683    char var[80];
1684    char wif[16];
1685
1686    sprintf( wif, "%s_vifs", prefix );
1687    char *vifs = nvram_safe_get( wif );
1688
1689    if( vifs == NULL )
1690        return 0;
1691    int count = 0;
1692
1693    foreach( var, vifs, next )
1694    {
1695        count++;
1696    }
1697    return count;
1698}
1699
1700void add_vifs_single( char *prefix, int device )
1701{
1702    int count = get_vifcount( prefix );
1703
1704    if( count == 16 )
1705        return;
1706    char vif[16];
1707
1708    sprintf( vif, "%s_vifs", prefix );
1709    char *vifs = nvram_safe_get( vif );
1710
1711    if( vifs == NULL )
1712        return;
1713    char *n = ( char * )malloc( strlen( vifs ) + 8 );
1714    char v[80];
1715    char v2[80];
1716
1717#ifdef HAVE_MADWIFI
1718    // char *cou[] = { "a", "b", "c", "d", "e", "f" };
1719    sprintf( v, "ath%d.%d", device, count + 1 );
1720#else
1721    sprintf( v, "wl%d.%d", device, count + 1 );
1722#endif
1723    if( strlen( vifs ) == 0 )
1724        sprintf( n, "%s", v );
1725    else
1726        sprintf( n, "%s %s", vifs, v );
1727    sprintf( v2, "%s_closed", v );
1728    nvram_set( v2, "0" );
1729    sprintf( v2, "%s_mode", v );
1730    nvram_set( v2, "ap" );
1731
1732    sprintf( v2, "%s_ap_isolate", v );
1733    nvram_set( v2, "0" );
1734    sprintf( v2, "%s_ssid", v );
1735#ifdef HAVE_MAKSAT
1736    nvram_set( v2, "maksat_vap" );
1737#elif defined(HAVE_TRIMAX)
1738    nvram_set( v2, "trimax_vap" );
1739#else
1740    nvram_set( v2, "dd-wrt_vap" );
1741#endif
1742    sprintf( v2, "%s_vifs", prefix );
1743    nvram_set( v2, n );
1744    sprintf( v2, "%s_bridged", v );
1745    nvram_set( v2, "1" );
1746    sprintf( v2, "%s_ipaddr", v );
1747    nvram_set( v2, "0.0.0.0" );
1748    sprintf( v2, "%s_netmask", v );
1749    nvram_set( v2, "0.0.0.0" );
1750
1751    sprintf( v2, "%s_gtk_rekey", v );
1752    nvram_set( v2, "3600" );
1753
1754    sprintf( v2, "%s_radius_port", v );
1755    nvram_set( v2, "1812" );
1756
1757    sprintf( v2, "%s_radius_ipaddr", v );
1758    nvram_set( v2, "0.0.0.0" );
1759
1760    // nvram_commit ();
1761    free( n );
1762}
1763
1764void add_vifs( webs_t wp )
1765{
1766    char *prefix = websGetVar( wp, "iface", NULL );
1767
1768    if( prefix == NULL )
1769        return;
1770    int devcount = prefix[strlen( prefix ) - 1] - '0';
1771
1772    add_vifs_single( prefix, devcount );
1773}
1774
1775void remove_vifs_single( char *prefix )
1776{
1777    char wif[16];
1778
1779    sprintf( wif, "%s_vifs", prefix );
1780    int o = -1;
1781    char *vifs = nvram_safe_get( wif );
1782    char copy[128];
1783
1784    strcpy( copy, vifs );
1785    int i;
1786    int slen = strlen( copy );
1787
1788    for( i = 0; i < slen; i++ )
1789    {
1790        if( copy[i] == 0x20 )
1791            o = i;
1792    }
1793    if( o == -1 )
1794    {
1795        nvram_set( wif, "" );
1796    }
1797    else
1798    {
1799        copy[o] = 0;
1800        nvram_set( wif, copy );
1801    }
1802    // nvram_commit ();
1803}
1804
1805void remove_vifs( webs_t wp )
1806{
1807    char *prefix = websGetVar( wp, "iface", NULL );
1808
1809    remove_vifs_single( prefix );
1810}
1811
1812#ifdef HAVE_BONDING
1813void add_bond( webs_t wp )
1814{
1815    static char word[256];
1816    char *next, *wordlist;
1817    int count = 0;
1818    int realcount = atoi( nvram_safe_get( "bonding_count" ) );
1819
1820    if( realcount == 0 )
1821    {
1822        wordlist = nvram_safe_get( "bondings" );
1823        foreach( word, wordlist, next )
1824        {
1825            count++;
1826        }
1827        realcount = count;
1828    }
1829    realcount++;
1830    char var[32];
1831
1832    sprintf( var, "%d", realcount );
1833    nvram_set( "bonding_count", var );
1834    nvram_commit(  );
1835    return;
1836}
1837
1838void del_bond( webs_t wp )
1839{
1840    static char word[256];
1841    int realcount = 0;
1842    char *next, *wordlist, *newwordlist;
1843    char *val = websGetVar( wp, "del_value", NULL );
1844
1845    if( val == NULL )
1846        return;
1847    int todel = atoi( val );
1848
1849    wordlist = nvram_safe_get( "bondings" );
1850    newwordlist = ( char * )malloc( strlen( wordlist ) );
1851    memset( newwordlist, 0, strlen( wordlist ) );
1852    int count = 0;
1853
1854    foreach( word, wordlist, next )
1855    {
1856        if( count != todel )
1857        {
1858            strcat( newwordlist, word );
1859            strcat( newwordlist, " " );
1860        }
1861        count++;
1862    }
1863
1864    char var[32];
1865
1866    realcount = atoi( nvram_safe_get( "bonding_count" ) ) - 1;
1867    sprintf( var, "%d", realcount );
1868    nvram_set( "bonding_count", var );
1869    nvram_set( "bondings", newwordlist );
1870    nvram_commit(  );
1871    free( newwordlist );
1872
1873    return;
1874}
1875#endif
1876
1877#ifdef HAVE_OLSRD
1878void add_olsrd( webs_t wp )
1879{
1880    char *ifname = websGetVar( wp, "olsrd_ifname", NULL );
1881
1882    if( ifname == NULL )
1883        return;
1884    char *wordlist = nvram_safe_get( "olsrd_interfaces" );
1885    char *addition = ">5.0>90.0>2.0>270.0>15.0>90.0>15.0>90.0";
1886    char *newadd =
1887        ( char * )malloc( strlen( wordlist ) + strlen( addition ) +
1888                          strlen( ifname ) + 2 );
1889    if( strlen( wordlist ) > 0 )
1890    {
1891        strcpy( newadd, wordlist );
1892        strcat( newadd, " " );
1893        strcat( newadd, ifname );
1894    }
1895    else
1896    {
1897        strcpy( newadd, ifname );
1898    }
1899    strcat( newadd, addition );
1900    nvram_set( "olsrd_interfaces", newadd );
1901    nvram_commit(  );
1902    free( newadd );
1903    return;
1904}
1905
1906void del_olsrd( webs_t wp )
1907{
1908    char *del = websGetVar( wp, "olsrd_delcount", NULL );
1909
1910    if( del == NULL )
1911        return;
1912    int d = atoi( del );
1913    char *wordlist = nvram_safe_get( "olsrd_interfaces" );
1914    char *newlist = ( char * )malloc( strlen( wordlist ) + 1 );
1915
1916    memset( newlist, 0, strlen( wordlist ) );
1917    char *next;
1918    char word[128];
1919    int count = 0;
1920
1921    foreach( word, wordlist, next )
1922    {
1923        if( count != d )
1924            sprintf( newlist, "%s %s", newlist, word );
1925        count++;
1926    }
1927    nvram_set( "olsrd_interfaces", newlist );
1928    nvram_commit(  );
1929    free( newlist );
1930    return;
1931}
1932
1933void save_olsrd( webs_t wp )
1934{
1935    char *wordlist = nvram_safe_get( "olsrd_interfaces" );
1936    char *newlist = ( char * )malloc( strlen( wordlist ) + 512 );
1937
1938    memset( newlist, 0, strlen( wordlist ) + 512 );
1939    char *next;
1940    char word[64];
1941
1942    foreach( word, wordlist, next )
1943    {
1944        char *interface = word;
1945        char *dummy = interface;
1946
1947        strsep( &dummy, ">" );
1948        char valuename[32];
1949
1950        sprintf( valuename, "%s_hellointerval", interface );
1951        char *hellointerval = websGetVar( wp, valuename, "0" );
1952
1953        sprintf( valuename, "%s_hellovaliditytime", interface );
1954        char *hellovaliditytime = websGetVar( wp, valuename, "0" );
1955
1956        sprintf( valuename, "%s_tcinterval", interface );
1957        char *tcinterval = websGetVar( wp, valuename, "0" );
1958
1959        sprintf( valuename, "%s_tcvaliditytime", interface );
1960        char *tcvaliditytime = websGetVar( wp, valuename, "0" );
1961
1962        sprintf( valuename, "%s_midinterval", interface );
1963        char *midinterval = websGetVar( wp, valuename, "0" );
1964
1965        sprintf( valuename, "%s_midvaliditytime", interface );
1966        char *midvaliditytime = websGetVar( wp, valuename, "0" );
1967
1968        sprintf( valuename, "%s_hnainterval", interface );
1969        char *hnainterval = websGetVar( wp, valuename, "0" );
1970
1971        sprintf( valuename, "%s_hnavaliditytime", interface );
1972        char *hnavaliditytime = websGetVar( wp, valuename, "0" );
1973
1974        sprintf( newlist, "%s %s>%s>%s>%s>%s>%s>%s>%s>%s", newlist, interface,
1975                 hellointerval, hellovaliditytime, tcinterval, tcvaliditytime,
1976                 midinterval, midvaliditytime, hnainterval, hnavaliditytime );
1977    }
1978    nvram_set( "olsrd_interfaces", newlist );
1979    nvram_commit(  );
1980    free( newlist );
1981    return;
1982}
1983#endif
1984
1985#ifdef HAVE_VLANTAGGING
1986
1987void save_networking( webs_t wp )
1988{
1989    char *value = websGetVar( wp, "action", "" );
1990    int vlancount = atoi( nvram_safe_get( "vlan_tagcount" ) );
1991    int bridgescount = atoi( nvram_safe_get( "bridges_count" ) );
1992    int bridgesifcount = atoi( nvram_safe_get( "bridgesif_count" ) );
1993    int mdhcpd_count = atoi( nvram_safe_get( "mdhcpd_count" ) );
1994
1995#ifdef HAVE_BONDING
1996    int bondcount = atoi( nvram_safe_get( "bonding_count" ) );
1997#endif
1998    int i;
1999
2000    // save vlan stuff
2001    char buffer[1024];
2002
2003    memset( buffer, 0, 1024 );
2004    for( i = 0; i < vlancount; i++ )
2005    {
2006        char *ifname, *tag;
2007        char var[32];
2008
2009        sprintf( var, "vlanifname%d", i );
2010        ifname = websGetVar( wp, var, NULL );
2011        if( !ifname )
2012            return;
2013        sprintf( var, "vlantag%d", i );
2014        tag = websGetVar( wp, var, NULL );
2015        if( !tag )
2016            return;
2017        strcat( buffer, ifname );
2018        strcat( buffer, ">" );
2019        strcat( buffer, tag );
2020        if( i < vlancount - 1 )
2021            strcat( buffer, " " );
2022    }
2023    nvram_set( "vlan_tags", buffer );
2024    // save bonds
2025    memset( buffer, 0, 1024 );
2026#ifdef HAVE_BONDING
2027    char *bondingnumber = websGetVar( wp, "bonding_number", NULL );
2028
2029    if( bondingnumber )
2030        nvram_set( "bonding_number", bondingnumber );
2031    char *bondingtype = websGetVar( wp, "bonding_type", NULL );
2032
2033    if( bondingtype )
2034        nvram_set( "bonding_type", bondingtype );
2035    for( i = 0; i < bondcount; i++ )
2036    {
2037        char *ifname, *tag;
2038        char var[32];
2039
2040        sprintf( var, "bondingifname%d", i );
2041        ifname = websGetVar( wp, var, NULL );
2042        if( !ifname )
2043            return;
2044        sprintf( var, "bondingattach%d", i );
2045        tag = websGetVar( wp, var, NULL );
2046        if( !tag )
2047            return;
2048        strcat( buffer, ifname );
2049        strcat( buffer, ">" );
2050        strcat( buffer, tag );
2051        if( i < bondcount - 1 )
2052            strcat( buffer, " " );
2053    }
2054    nvram_set( "bondings", buffer );
2055    memset( buffer, 0, 1024 );
2056#endif
2057
2058    // save bridges
2059
2060    for( i = 0; i < bridgescount; i++ )
2061    {
2062        char *ifname, *tag, *prio,*mtu;
2063        char var[32];
2064        char ipaddr[32];
2065        char netmask[32];
2066        char n[32];
2067
2068        memset( ipaddr, 0, 32 );
2069        memset( netmask, 0, 32 );
2070        sprintf( var, "bridgename%d", i );
2071        ifname = websGetVar( wp, var, NULL );
2072        if( !ifname )
2073            return;
2074        sprintf( var, "bridgestp%d", i );
2075        tag = websGetVar( wp, var, NULL );
2076        if( !tag )
2077            return;
2078        sprintf( var, "bridgeprio%d", i );
2079        prio = websGetVar( wp, var, NULL );
2080        if( !prio )
2081            prio = "32768";
2082        if( strlen( prio ) == 0 )
2083            prio = "32768";
2084
2085        sprintf( var, "bridgemtu%d", i );
2086        mtu = websGetVar( wp, var, NULL );
2087        if( !mtu )
2088            mtu = "1500";
2089        if( strlen( prio ) == 0 )
2090            mtu = "1500";
2091
2092
2093        sprintf( n, "%s_ipaddr", ifname );
2094        if( get_merge_ipaddr( wp, n, ipaddr ) )
2095            nvram_set( n, ipaddr );
2096        sprintf( n, "%s_netmask", ifname );
2097        if( get_merge_ipaddr( wp, n, netmask ) )
2098            nvram_set( n, netmask );
2099
2100        strcat( buffer, ifname );
2101        strcat( buffer, ">" );
2102        if( !strcmp( tag, "On" ) )
2103            strcat( buffer, "On" );
2104        else
2105            strcat( buffer, "Off" );
2106        strcat( buffer, ">" );
2107        strcat( buffer, prio );
2108        strcat( buffer, ">" );
2109        strcat( buffer, mtu );
2110        if( i < bridgescount - 1 )
2111            strcat( buffer, " " );
2112    }
2113    nvram_set( "bridges", buffer );
2114    // save bridge assignment
2115    memset( buffer, 0, 1024 );
2116    for( i = 0; i < bridgesifcount; i++ )
2117    {
2118        char *ifname, *tag, *prio;
2119        char var[32];
2120
2121        sprintf( var, "bridge%d", i );
2122        ifname = websGetVar( wp, var, NULL );
2123        if( !ifname )
2124            return;
2125        sprintf( var, "bridgeif%d", i );
2126        tag = websGetVar( wp, var, NULL );
2127        if( !tag )
2128            return;
2129        sprintf( var, "bridgeifprio%d", i );
2130        prio = websGetVar( wp, var, NULL );
2131        if( !prio )
2132            prio = "128";
2133        if( strlen( prio ) == 0 )
2134            prio = "128";
2135        strcat( buffer, ifname );
2136        strcat( buffer, ">" );
2137        strcat( buffer, tag );
2138        strcat( buffer, ">" );
2139        strcat( buffer, prio );
2140        if( i < bridgesifcount - 1 )
2141            strcat( buffer, " " );
2142    }
2143    nvram_set( "bridgesif", buffer );
2144#ifdef HAVE_MDHCP
2145    // save multipe dhcp-servers
2146    memset( buffer, 0, 1024 );
2147    // if (!interface || !start || !dhcpon || !max || !leasetime)
2148    for( i = 0; i < mdhcpd_count; i++ )
2149    {
2150        char *mdhcpinterface, *mdhcpon, *mdhcpstart, *mdhcpmax,
2151            *mdhcpleasetime;
2152        char var[32];
2153
2154        sprintf( var, "mdhcpifname%d", i );
2155        mdhcpinterface = websGetVar( wp, var, NULL );
2156        if( !mdhcpinterface )
2157            return;
2158
2159        sprintf( var, "mdhcpon%d", i );
2160        mdhcpon = websGetVar( wp, var, NULL );
2161        if( !mdhcpon )
2162            return;
2163
2164        sprintf( var, "mdhcpstart%d", i );
2165        mdhcpstart = websGetVar( wp, var, NULL );
2166        if( !mdhcpstart )
2167            return;
2168
2169        sprintf( var, "mdhcpmax%d", i );
2170        mdhcpmax = websGetVar( wp, var, NULL );
2171        if( !mdhcpmax )
2172            return;
2173
2174        sprintf( var, "mdhcpleasetime%d", i );
2175        mdhcpleasetime = websGetVar( wp, var, NULL );
2176        if( !mdhcpleasetime )
2177            return;
2178
2179        strcat( buffer, mdhcpinterface );
2180        strcat( buffer, ">" );
2181        strcat( buffer, mdhcpon );
2182        strcat( buffer, ">" );
2183        strcat( buffer, mdhcpstart );
2184        strcat( buffer, ">" );
2185        strcat( buffer, mdhcpmax );
2186        strcat( buffer, ">" );
2187        strcat( buffer, mdhcpleasetime );
2188        if( i < mdhcpd_count - 1 )
2189            strcat( buffer, " " );
2190    }
2191    nvram_set( "mdhcpd", buffer );
2192#endif
2193#ifdef HAVE_PORTSETUP
2194    validate_portsetup( wp, NULL, NULL );
2195#endif
2196
2197    addAction( "index" );
2198    if( !strcmp( value, "ApplyTake" ) )
2199    {
2200        nvram_commit(  );
2201        service_restart(  );
2202    }
2203}
2204
2205void add_vlan( webs_t wp )
2206{
2207    static char word[256];
2208    char *next, *wordlist;
2209    int count = 0;
2210    int realcount = atoi( nvram_safe_get( "vlan_tagcount" ) );
2211
2212    if( realcount == 0 )
2213    {
2214        wordlist = nvram_safe_get( "vlan_tags" );
2215        foreach( word, wordlist, next )
2216        {
2217            count++;
2218        }
2219        realcount = count;
2220    }
2221    realcount++;
2222    char var[32];
2223
2224    sprintf( var, "%d", realcount );
2225    nvram_set( "vlan_tagcount", var );
2226    nvram_commit(  );
2227    return;
2228}
2229
2230void del_vlan( webs_t wp )
2231{
2232    static char word[256];
2233    int realcount = 0;
2234    char *next, *wordlist, *newwordlist;
2235    char *val = websGetVar( wp, "del_value", NULL );
2236
2237    if( val == NULL )
2238        return;
2239    int todel = atoi( val );
2240
2241    wordlist = nvram_safe_get( "vlan_tags" );
2242    newwordlist = ( char * )malloc( strlen( wordlist ) );
2243    memset( newwordlist, 0, strlen( wordlist ) );
2244    int count = 0;
2245
2246    foreach( word, wordlist, next )
2247    {
2248        if( count != todel )
2249        {
2250            strcat( newwordlist, word );
2251            strcat( newwordlist, " " );
2252        }
2253        else
2254        {
2255            char *port = word;
2256            char *tag = strsep( &port, ">" );
2257
2258            if( !tag || !port )
2259                break;
2260            char names[32];
2261
2262            sprintf( names, "%s.%s", tag, port );
2263            eval( "ifconfig", names, "down" );
2264            eval( "vconfig", "rem", names );
2265        }
2266        count++;
2267    }
2268
2269    char var[32];
2270
2271    realcount = atoi( nvram_safe_get( "vlan_tagcount" ) ) - 1;
2272    sprintf( var, "%d", realcount );
2273    nvram_set( "vlan_tagcount", var );
2274    nvram_set( "vlan_tags", newwordlist );
2275    nvram_commit(  );
2276    free( newwordlist );
2277
2278    return;
2279}
2280
2281void add_mdhcp( webs_t wp )
2282{
2283    static char word[256];
2284    char *next, *wordlist;
2285    int count = 0;
2286    int realcount = atoi( nvram_safe_get( "mdhcpd_count" ) );
2287
2288    if( realcount == 0 )
2289    {
2290        wordlist = nvram_safe_get( "mdhcpd" );
2291        foreach( word, wordlist, next )
2292        {
2293            count++;
2294        }
2295        realcount = count;
2296    }
2297    realcount++;
2298    char var[32];
2299
2300    sprintf( var, "%d", realcount );
2301    nvram_set( "mdhcpd_count", var );
2302    nvram_commit(  );
2303    return;
2304}
2305
2306void del_mdhcp( webs_t wp )
2307{
2308    static char word[256];
2309    int realcount = 0;
2310    char *next, *wordlist, *newwordlist;
2311    char *val = websGetVar( wp, "del_value", NULL );
2312
2313    if( val == NULL )
2314        return;
2315    int todel = atoi( val );
2316
2317    wordlist = nvram_safe_get( "mdhcpd" );
2318    newwordlist = ( char * )malloc( strlen( wordlist ) );
2319    memset( newwordlist, 0, strlen( wordlist ) );
2320    int count = 0;
2321
2322    foreach( word, wordlist, next )
2323    {
2324        if( count != todel )
2325        {
2326            strcat( newwordlist, word );
2327            strcat( newwordlist, " " );
2328        }
2329        count++;
2330    }
2331
2332    char var[32];
2333
2334    realcount = atoi( nvram_safe_get( "mdhcpd_count" ) ) - 1;
2335    sprintf( var, "%d", realcount );
2336    nvram_set( "mdhcpd_count", var );
2337    nvram_set( "mdhcpd", newwordlist );
2338    nvram_commit(  );
2339    free( newwordlist );
2340
2341    return;
2342}
2343
2344void del_bridge( webs_t wp )
2345{
2346    static char word[256];
2347    int realcount = 0;
2348    char *next, *wordlist, *newwordlist;
2349    char *val = websGetVar( wp, "del_value", NULL );
2350
2351    if( val == NULL )
2352        return;
2353    int todel = atoi( val );
2354
2355    wordlist = nvram_safe_get( "bridges" );
2356    newwordlist = ( char * )malloc( strlen( wordlist ) );
2357    memset( newwordlist, 0, strlen( wordlist ) );
2358    int count = 0;
2359
2360    foreach( word, wordlist, next )
2361    {
2362        if( count != todel )
2363        {
2364            strcat( newwordlist, word );
2365            strcat( newwordlist, " " );
2366        }
2367        else
2368        {
2369            char *port = word;
2370            char *tag = strsep( &port, ">" );
2371            char *prio = port;
2372
2373            strsep( &prio, ">" );
2374            if( !tag || !port )
2375                continue;
2376            eval( "ifconfig", tag, "down" );
2377            eval( "brctl", "delbr", tag );
2378        }
2379        count++;
2380    }
2381
2382    realcount = atoi( nvram_safe_get( "bridges_count" ) ) - 1;
2383    char var[32];
2384
2385    sprintf( var, "%d", realcount );
2386    nvram_set( "bridges_count", var );
2387    nvram_set( "bridges", newwordlist );
2388    nvram_commit(  );
2389    free( newwordlist );
2390
2391    return;
2392}
2393
2394void add_bridge( webs_t wp )
2395{
2396    static char word[256];
2397    char *next, *wordlist;
2398    int count = 0;
2399    int realcount = atoi( nvram_safe_get( "bridges_count" ) );
2400
2401    if( realcount == 0 )
2402    {
2403        wordlist = nvram_safe_get( "bridges" );
2404        foreach( word, wordlist, next )
2405        {
2406            count++;
2407        }
2408        realcount = count;
2409    }
2410    realcount++;
2411    char var[32];
2412
2413    sprintf( var, "%d", realcount );
2414    nvram_set( "bridges_count", var );
2415    nvram_commit(  );
2416    return;
2417}
2418
2419void del_bridgeif( webs_t wp )
2420{
2421    static char word[256];
2422    int realcount = 0;
2423    char *next, *wordlist, *newwordlist;
2424    char *val = websGetVar( wp, "del_value", NULL );
2425
2426    if( val == NULL )
2427        return;
2428    int todel = atoi( val );
2429
2430    wordlist = nvram_safe_get( "bridgesif" );
2431    newwordlist = ( char * )malloc( strlen( wordlist ) );
2432    memset( newwordlist, 0, strlen( wordlist ) );
2433    int count = 0;
2434
2435    foreach( word, wordlist, next )
2436    {
2437        if( count != todel )
2438        {
2439            strcat( newwordlist, word );
2440            strcat( newwordlist, " " );
2441        }
2442        count++;
2443    }
2444
2445    char var[32];
2446
2447    realcount = atoi( nvram_safe_get( "bridgesif_count" ) ) - 1;
2448    sprintf( var, "%d", realcount );
2449    nvram_set( "bridgesif_count", var );
2450    nvram_set( "bridgesif", newwordlist );
2451    nvram_commit(  );
2452    free( newwordlist );
2453
2454    return;
2455}
2456
2457void add_bridgeif( webs_t wp )
2458{
2459
2460    static char word[256];
2461    char *next, *wordlist;
2462    int count = 0;
2463    int realcount = atoi( nvram_safe_get( "bridgesif_count" ) );
2464
2465    if( realcount == 0 )
2466    {
2467        wordlist = nvram_safe_get( "bridgesif" );
2468        foreach( word, wordlist, next )
2469        {
2470            count++;
2471        }
2472        realcount = count;
2473    }
2474    realcount++;
2475    char var[32];
2476
2477    sprintf( var, "%d", realcount );
2478    nvram_set( "bridgesif_count", var );
2479    nvram_commit(  );
2480    return;
2481}
2482
2483#endif
2484
2485static void save_prefix( webs_t wp, char *prefix )
2486{
2487    char n[80];
2488#ifdef HAVE_MADWIFI
2489    char sifs[80];
2490    char turbo[80];
2491    char chanbw[80];
2492    char preamble[80];
2493    int cbwchanged = 0;
2494#endif
2495    sprintf( n, "%s_ssid", prefix );
2496    copytonv( wp, n );
2497    if( !strcmp( prefix, "wl0" ) || !strcmp( prefix, "wl1" ) )
2498    {
2499        char *wl = websGetVar( wp, n, NULL );
2500
2501        cprintf( "copy value %s which is [%s] to nvram\n", n, wl );
2502        if( wl && !strcmp( prefix, "wl0" ) )
2503            nvram_set( "wl_ssid", wl );
2504        else
2505            nvram_set( "wl1_ssid", wl );
2506    }
2507    copytonv( wp, "%s_distance", prefix );
2508#ifdef HAVE_MADWIFI
2509    {
2510        sprintf( n, "%s_txpwrdbm", prefix );
2511        char *sl = websGetVar( wp, n, NULL );
2512
2513        if( sl )
2514        {
2515            int txpower = atoi( sl ) - wifi_gettxpoweroffset( prefix );
2516
2517            if( txpower < 1 )
2518                txpower = 1;
2519            sprintf( turbo, "%d", txpower );
2520            nvram_set( n, turbo );
2521        }
2522    }
2523    copytonv( wp, "%s_antgain", prefix );
2524    copytonv( wp, "ath_regulatory" );
2525    sprintf( n, "%s_scanlist", prefix );
2526    {
2527        char *sl = websGetVar( wp, n, NULL );
2528
2529        if( sl )
2530        {
2531            char *slc = ( char * )malloc( strlen( sl ) + 1 );
2532
2533            strcpy( slc, sl );
2534            int i, sllen = strlen( slc );
2535
2536            for( i = 0; i < sllen; i++ )
2537            {
2538                if( slc[i] == ';' )
2539                    slc[i] = ' ';
2540                if( slc[i] == ',' )
2541                    slc[i] = ' ';
2542            }
2543            nvram_set( n, slc );
2544        }
2545    }
2546#ifdef HAVE_MAKSAT
2547    copytonv( wp, "ath_specialmode" );
2548#endif
2549    copytonv( wp, "%s_regdomain", prefix );
2550
2551    copytonv( wp, "%s_rts", prefix );
2552    if( nvram_nmatch( "1", "%s_rts", prefix ) )
2553    {
2554        sprintf( turbo, "%s_rtsvalue", prefix );
2555        char *tw = websGetVar( wp, turbo, NULL );
2556        if( tw )
2557        {
2558            if( atoi( tw ) < 1 )
2559                tw = "1";
2560            if( atoi( tw ) > 2346 )
2561                tw = "2346";
2562            nvram_nset( tw, "%s_rtsvalue", prefix );
2563        }
2564    }
2565    copytonv( wp, "%s_protmode", prefix );
2566    copytonv( wp, "%s_minrate", prefix );
2567    copytonv( wp, "%s_maxrate", prefix );
2568    copytonv( wp, "%s_xr", prefix );
2569    copytonv( wp, "%s_outdoor", prefix );
2570//    copytonv( wp, "%s_compression", prefix ); // Atheros SuperG header
2571                                                // compression
2572    copytonv( wp, "%s_ff", prefix );    // ff = 0, Atheros SuperG fast
2573                                        // framing disabled, 1 fast framing
2574                                        // enabled
2575    copytonv( wp, "%s_diversity", prefix );
2576    copytonv( wp, "%s_preamble", prefix );
2577    copytonv( wp, "%s_wmm", prefix );
2578    copytonv( wp, "%s_txantenna", prefix );
2579    copytonv( wp, "%s_rxantenna", prefix );
2580    copytonv( wp, "%s_intmit", prefix );
2581    copytonv( wp, "%s_csma", prefix );
2582    copytonv( wp, "%s_noise_immunity", prefix );
2583    copytonv( wp, "%s_ofdm_weak_det", prefix );
2584
2585    copytonv( wp, "%s_chanshift", prefix );
2586    copytonv( wp, "%s_doth", prefix );
2587    copytonv( wp, "%s_maxassoc", prefix);
2588
2589    sprintf( chanbw, "%s_channelbw", prefix );
2590    char *cbw = websGetVar( wp, chanbw, NULL );
2591
2592    if( cbw && !nvram_match( chanbw, cbw ) )
2593    {
2594        cbwchanged = 1;
2595    }
2596    if( cbw )
2597        nvram_set( chanbw, cbw );
2598
2599    copytonv( wp, "%s_xr", prefix );
2600    copytonv( wp, "%s_sifstime", prefix );
2601    copytonv( wp, "%s_preambletime", prefix );
2602    copytonv( wp, "%s_mtikie", prefix );
2603
2604#endif
2605    copytonv( wp, "%s_closed", prefix );
2606
2607#ifndef HAVE_MADWIFI
2608    char *ifname = "wl0";
2609
2610#ifndef HAVE_RT2880
2611
2612    if( !strcmp( prefix, "wl0" ) )
2613        ifname = get_wl_instance_name( 0 );
2614    else if( !strcmp( prefix, "wl1" ) )
2615        ifname = get_wl_instance_name( 1 );
2616    else
2617        ifname = prefix;
2618#else
2619    ifname = getRADev(prefix);
2620#endif
2621    copytonv( wp, "%s_multicast", ifname );
2622    copytonv( wp, "%s_bridged", ifname );
2623
2624    char addr[32];
2625
2626    sprintf( n, "%s_ipaddr", ifname );
2627    if( get_merge_ipaddr( wp, n, addr ) )
2628        nvram_set( n, addr );
2629
2630    sprintf( n, "%s_netmask", ifname );
2631    if( get_merge_ipaddr( wp, n, addr ) )
2632        nvram_set( n, addr );
2633#else
2634
2635    copytonv( wp, "%s_multicast", prefix );
2636    copytonv( wp, "%s_bridged", prefix );
2637    char addr[32];
2638
2639    sprintf( n, "%s_ipaddr", prefix );
2640    if( get_merge_ipaddr( wp, n, addr ) )
2641        nvram_set( n, addr );
2642
2643    sprintf( n, "%s_netmask", prefix );
2644    if( get_merge_ipaddr( wp, n, addr ) )
2645        nvram_set( n, addr );
2646
2647    copytonv( wp, "%s_duallink", prefix );
2648    sprintf( n, "%s_duallink_parent", prefix );
2649    if( get_merge_ipaddr( wp, n, addr ) )
2650        nvram_set( n, addr );
2651
2652#endif
2653
2654    copytonv( wp, "%s_ap_isolate", prefix );
2655    sprintf( n, "%s_mode", prefix );
2656    if (nvram_match(n,"sta"))
2657        {
2658        char *wl = websGetVar( wp, n, NULL );
2659        if (wl)
2660        if (!strcmp(wl,"ap") || !strcmp(wl,"wdsap") || !strcmp(wl,"infra") || !strcmp(wl,"wdssta"))
2661            {
2662            nvram_set("wan_proto","disabled");
2663            }
2664        }
2665    copytonv( wp, n );
2666    if( !strcmp( prefix, "wl0" ) || !strcmp( prefix, "wl1" ) )
2667    {
2668        char *wl = websGetVar( wp, n, NULL );
2669
2670        cprintf( "copy value %s which is [%s] to nvram\n", n, wl );
2671        if( wl && !strcmp( prefix, "wl0" ) )
2672            nvram_set( "wl_mode", wl );
2673#ifndef HAVE_MADWIFI
2674        if( strcmp( wl, "ap" ) && strcmp( wl, "apsta" )
2675            && strcmp( wl, "apstawet" ) )
2676        {
2677            nvram_nset( "", "%s_vifs", prefix );
2678        }
2679#endif
2680    }
2681    int chanchanged = 0;
2682#ifdef HAVE_RT2880
2683    copytonv( wp, "%s_greenfield", prefix );
2684#endif
2685
2686#ifndef HAVE_MADWIFI
2687    if( !strcmp( prefix, "wl0" ) || !strcmp( prefix, "wl1" ) )
2688#endif
2689    {
2690
2691        sprintf( n, "%s_net_mode", prefix );
2692        if( !nvram_match( n, websGetVar( wp, n, "" ) ) )
2693        {
2694            chanchanged = 1;
2695            copytonv( wp, n );
2696            if( !strcmp( prefix, "wl0" ) )
2697                convert_wl_gmode( nvram_safe_get( n ), "wl" );
2698            else
2699                convert_wl_gmode( nvram_safe_get( n ), prefix );
2700        }
2701    }
2702#ifdef HAVE_MADWIFI
2703    if( cbwchanged || chanchanged)
2704    {
2705        if( nvram_match( chanbw, "40" ) )
2706        {
2707            nvram_set( sifs, "8" );
2708            nvram_set( preamble, "14" );
2709        }
2710        else if( nvram_match( chanbw, "5" ) )
2711        {
2712            nvram_set( sifs, "64" );
2713            nvram_set( preamble, "80" );
2714        }
2715        else if( nvram_match( chanbw, "10" ) )
2716        {
2717            nvram_set( sifs, "32" );
2718            nvram_set( preamble, "40" );
2719        }
2720        else
2721        {
2722            nvram_set( sifs, "16" );
2723            nvram_set( preamble, "20" );
2724        }
2725
2726    }
2727#endif
2728    copytonv( wp, "%s_nbw", prefix );
2729    copytonv( wp, "%s_nctrlsb", prefix );
2730
2731    sprintf( n, "%s_channel", prefix );
2732    if( !strcmp( prefix, "wl0" ) || !strcmp( prefix, "wl1" ) )
2733    {
2734        char *wl = websGetVar( wp, n, NULL );
2735
2736        cprintf( "copy value %s which is [%s] to nvram\n", n, wl );
2737        if( wl && !strcmp( prefix, "wl0" ) )
2738            nvram_set( "wl_channel", wl );
2739        else if (wl)
2740            nvram_set( "wl1_channel", wl );
2741    }
2742    copytonv( wp, n );
2743
2744    sprintf( n, "%s_wchannel", prefix );
2745    if( !strcmp( prefix, "wl0" ) || !strcmp( prefix, "wl1" ) )
2746    {
2747        char *wl = websGetVar( wp, n, NULL );
2748
2749        cprintf( "copy value %s which is [%s] to nvram\n", n, wl );
2750        if( wl && !strcmp( prefix, "wl0" ) )
2751            nvram_set( "wl_wchannel", wl );
2752        else if (wl)
2753            nvram_set( "wl1_wchannel", wl );
2754
2755    }
2756
2757    copytonv( wp, n );
2758
2759}
2760
2761void wireless_save( webs_t wp )
2762{
2763    char *value = websGetVar( wp, "action", "" );
2764
2765    addAction( "wireless" );
2766#ifdef HAVE_MSSID
2767    char *next;
2768    char var[80];
2769
2770#ifndef HAVE_MADWIFI
2771    int c = get_wl_instances(  );
2772    int i;
2773
2774    for( i = 0; i < c; i++ )
2775    {
2776        char buf[16];
2777
2778        sprintf( buf, "wl%d", i );
2779        save_prefix( wp, buf );
2780        char *vifs = nvram_nget( "wl%d_vifs", i );
2781#else
2782    int c = getdevicecount(  );
2783    int i;
2784
2785    for( i = 0; i < c; i++ )
2786    {
2787        char buf[16];
2788
2789        sprintf( buf, "ath%d", i );
2790        save_prefix( wp, buf );
2791        char *vifs = nvram_nget( "ath%d_vifs", i );
2792
2793#endif
2794        if( vifs == NULL )
2795            return;
2796        foreach( var, vifs, next )
2797        {
2798            save_prefix( wp, var );
2799        }
2800    }
2801    // nvram_commit ();
2802#endif
2803    if( !strcmp( value, "ApplyTake" ) )
2804    {
2805        nvram_commit(  );
2806        service_restart(  );
2807    }
2808}
2809
2810#ifdef HAVE_WIVIZ
2811void set_wiviz( webs_t wp )
2812{
2813
2814    char *hopdwell = websGetVar( wp, "hopdwell", NULL );
2815    char *hopseq = websGetVar( wp, "hopseq", NULL );
2816    FILE *fp = fopen( "/tmp/wiviz2-cfg", "wb" );
2817
2818    if( strstr( hopseq, "," ) )
2819        fprintf( fp, "channelsel=hop&" );
2820    else
2821        fprintf( fp, "channelsel=%s&", hopseq );
2822
2823    fprintf( fp, "hopdwell=%s&hopseq=%s\n", hopdwell, hopseq );
2824
2825    nvram_set( "hopdwell", hopdwell );
2826    nvram_set( "hopseq", hopseq );
2827
2828    fclose( fp );
2829    killall( "wiviz", SIGUSR2 );
2830
2831}
2832#endif
2833
2834void ttraff_erase( webs_t wp )
2835{
2836        char line[2048];
2837        char *name = NULL;
2838        system2( "nvram show | grep traff- > /tmp/.ttraff" );   
2839        FILE *fp = fopen( "/tmp/.ttraff", "r" );
2840        if( fp == NULL )
2841        {
2842          return;
2843        }
2844        while( fgets( line, sizeof( line ), fp ) != NULL )
2845        {
2846                if (startswith (line, "traff-"))
2847            {
2848                 name = strtok (line, "=");
2849                 if (strlen (name) == 13)  //only unset ttraf-XX-XXXX
2850                 {
2851                   nvram_unset (name);
2852             }
2853            }
2854        }
2855        nvram_commit ( );
2856        unlink( "/tmp/.ttraff" );
2857}
2858
2859void changepass( webs_t wp )
2860{
2861    char *value = websGetVar( wp, "http_username", NULL );
2862    char *pass = websGetVar( wp, "http_passwd", NULL );
2863
2864    if( value && pass && strcmp( value, TMP_PASSWD )
2865        && valid_name( wp, value, NULL ) )
2866    {
2867        nvram_set( "http_username", zencrypt( value ) );
2868
2869        system2( "/sbin/setpasswd" );
2870    }
2871
2872    if( pass && value && strcmp( pass, TMP_PASSWD )
2873        && valid_name( wp, pass, NULL ) )
2874    {
2875        nvram_set( "http_passwd", zencrypt( pass ) );
2876
2877        system2( "/sbin/setpasswd" );
2878    }
2879    nvram_commit(  );
2880}
2881
2882#ifdef HAVE_CHILLILOCAL
2883
2884void user_remove( webs_t wp )
2885{
2886    macro_rem( "fon_usernames", "fon_userlist" );
2887}
2888
2889void user_add( webs_t wp )
2890{
2891    macro_add( "fon_usernames" );
2892    // validate_userlist(wp);
2893}
2894#endif
2895
2896#ifdef HAVE_RADLOCAL
2897
2898void raduser_add( webs_t wp )
2899{
2900    int radcount = 0;
2901    char *radc = nvram_get( "iradius_count" );
2902
2903    if( radc != NULL )
2904        radcount = atoi( radc );
2905    radcount++;
2906    char count[16];
2907
2908    sprintf( count, "%d", radcount );
2909    nvram_set( "iradius_count", count );
2910}
2911#endif
2912
2913#ifdef HAVE_MILKFISH
2914void milkfish_sip_message( webs_t wp )
2915{
2916    char *message = websGetVar( wp, "sip_message", NULL );
2917    char *dest = websGetVar( wp, "sip_message_dest", NULL );
2918    int i;
2919    FILE *fp = fopen( "/tmp/sipmessage", "wb" );
2920
2921    if( fp == NULL )
2922        return;
2923    char *host_key = message;
2924
2925    i = 0;
2926    do
2927    {
2928        if( host_key[i] != 0x0D )
2929            fprintf( fp, "%c", host_key[i] );
2930    }
2931    while( host_key[++i] );
2932    putc( 0xa, fp );
2933    fclose( fp );
2934    eval( "milkfish_services", "simpledd", dest );
2935    return;
2936}
2937#endif
2938
2939#ifndef HAVE_MSSID
2940
2941void set_security( webs_t wp )
2942{
2943    char *var = websGetVar( wp, "security_varname", "security_mode" );
2944
2945    nvram_set( var, websGetVar( wp, var, "disabled" ) );
2946}
2947#else
2948void set_security( webs_t wp )
2949{
2950    char *var = websGetVar( wp, "security_varname", "security_mode" );
2951
2952    cprintf( "set security to %s\n", var );
2953    cprintf( "security var = %s\n", websGetVar( wp, var, "disabled" ) );
2954    char *var2 = websGetVar( wp, var, "disabled" );
2955
2956    // rep(var,'X','.');
2957    nvram_set( var, var2 );
2958}
2959#endif
2960typedef struct sha1_ctx_t
2961{
2962    uint32_t count[2];
2963    uint32_t hash[5];
2964    uint32_t wbuf[16];
2965} sha1_ctx_t;
2966
2967#define SHA1_BLOCK_SIZE  64
2968#define SHA1_DIGEST_SIZE 20
2969#define SHA1_HASH_SIZE   SHA1_DIGEST_SIZE
2970#define SHA2_GOOD        0
2971#define SHA2_BAD         1
2972
2973#define rotl32(x,n)      (((x) << n) | ((x) >> (32 - n)))
2974
2975#define SHA1_MASK        (SHA1_BLOCK_SIZE - 1)
2976
2977/*
2978 * reverse byte order in 32-bit words
2979 */
2980#define ch(x,y,z)        ((z) ^ ((x) & ((y) ^ (z))))
2981#define parity(x,y,z)    ((x) ^ (y) ^ (z))
2982#define maj(x,y,z)       (((x) & (y)) | ((z) & ((x) | (y))))
2983
2984/*
2985 * A normal version as set out in the FIPS. This version uses
2986 */
2987/*
2988 * partial loop unrolling and is optimised for the Pentium 4
2989 */
2990#define rnd(f,k) \
2991        do { \
2992                t = a; a = rotl32(a,5) + f(b,c,d) + e + k + w[i]; \
2993                e = d; d = c; c = rotl32(b, 30); b = t; \
2994        } while (0)
2995
2996static void sha1_compile( sha1_ctx_t * ctx )
2997{
2998    uint32_t w[80], i, a, b, c, d, e, t;
2999
3000    /*
3001     * note that words are compiled from the buffer into 32-bit
3002     */
3003    /*
3004     * words in big-endian order so an order reversal is needed
3005     */
3006    /*
3007     * here on little endian machines
3008     */
3009    for( i = 0; i < SHA1_BLOCK_SIZE / 4; ++i )
3010        w[i] = htonl( ctx->wbuf[i] );
3011
3012    for( i = SHA1_BLOCK_SIZE / 4; i < 80; ++i )
3013        w[i] = rotl32( w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1 );
3014
3015    a = ctx->hash[0];
3016    b = ctx->hash[1];
3017    c = ctx->hash[2];
3018    d = ctx->hash[3];
3019    e = ctx->hash[4];
3020
3021    for( i = 0; i < 20; ++i )
3022    {
3023        rnd( ch, 0x5a827999 );
3024    }
3025
3026    for( i = 20; i < 40; ++i )
3027    {
3028        rnd( parity, 0x6ed9eba1 );
3029    }
3030
3031    for( i = 40; i < 60; ++i )
3032    {
3033        rnd( maj, 0x8f1bbcdc );
3034    }
3035
3036    for( i = 60; i < 80; ++i )
3037    {
3038        rnd( parity, 0xca62c1d6 );
3039    }
3040
3041    ctx->hash[0] += a;
3042    ctx->hash[1] += b;
3043    ctx->hash[2] += c;
3044    ctx->hash[3] += d;
3045    ctx->hash[4] += e;
3046}
3047
3048void sha1_begin( sha1_ctx_t * ctx )
3049{
3050    ctx->count[0] = ctx->count[1] = 0;
3051    ctx->hash[0] = 0x67452301;
3052    ctx->hash[1] = 0xefcdab89;
3053    ctx->hash[2] = 0x98badcfe;
3054    ctx->hash[3] = 0x10325476;
3055    ctx->hash[4] = 0xc3d2e1f0;
3056}
3057
3058/*
3059 * SHA1 hash data in an array of bytes into hash buffer and call the
3060 */
3061/*
3062 * hash_compile function as required. 
3063 */
3064void sha1_hash( const void *data, size_t length, sha1_ctx_t * ctx )
3065{
3066    uint32_t pos = ( uint32_t ) ( ctx->count[0] & SHA1_MASK );
3067    uint32_t freeb = SHA1_BLOCK_SIZE - pos;
3068    const unsigned char *sp = data;
3069
3070    if( ( ctx->count[0] += length ) < length )
3071        ++( ctx->count[1] );
3072
3073    while( length >= freeb )
3074    {                           /* tranfer whole blocks while possible */
3075        memcpy( ( ( unsigned char * )ctx->wbuf ) + pos, sp, freeb );
3076        sp += freeb;
3077        length -= freeb;
3078        freeb = SHA1_BLOCK_SIZE;
3079        pos = 0;
3080        sha1_compile( ctx );
3081    }
3082
3083    memcpy( ( ( unsigned char * )ctx->wbuf ) + pos, sp, length );
3084}
3085
3086void *sha1_end( void *resbuf, sha1_ctx_t * ctx )
3087{
3088    /*
3089     * SHA1 Final padding and digest calculation
3090     */
3091#if BB_BIG_ENDIAN
3092    static uint32_t mask[4] =
3093        { 0x00000000, 0xff000000, 0xffff0000, 0xffffff00 };
3094    static uint32_t bits[4] =
3095        { 0x80000000, 0x00800000, 0x00008000, 0x00000080 };
3096#else
3097    static uint32_t mask[4] =
3098        { 0x00000000, 0x000000ff, 0x0000ffff, 0x00ffffff };
3099    static uint32_t bits[4] =
3100        { 0x00000080, 0x00008000, 0x00800000, 0x80000000 };
3101#endif
3102
3103    uint8_t *hval = resbuf;
3104    uint32_t i, cnt = ( uint32_t ) ( ctx->count[0] & SHA1_MASK );
3105
3106    /*
3107     * mask out the rest of any partial 32-bit word and then set
3108     */
3109    /*
3110     * the next byte to 0x80. On big-endian machines any bytes in
3111     */
3112    /*
3113     * the buffer will be at the top end of 32 bit words, on little
3114     */
3115    /*
3116     * endian machines they will be at the bottom. Hence the AND
3117     */
3118    /*
3119     * and OR masks above are reversed for little endian systems
3120     */
3121    ctx->wbuf[cnt >> 2] =
3122        ( ctx->wbuf[cnt >> 2] & mask[cnt & 3] ) | bits[cnt & 3];
3123
3124    /*
3125     * we need 9 or more empty positions, one for the padding byte
3126     */
3127    /*
3128     * (above) and eight for the length count.  If there is not
3129     */
3130    /*
3131     * enough space pad and empty the buffer
3132     */
3133    if( cnt > SHA1_BLOCK_SIZE - 9 )
3134    {
3135        if( cnt < 60 )
3136            ctx->wbuf[15] = 0;
3137        sha1_compile( ctx );
3138        cnt = 0;
3139    }
3140    else                        /* compute a word index for the empty buffer
3141                                 * positions */
3142        cnt = ( cnt >> 2 ) + 1;
3143
3144    while( cnt < 14 )           /* and zero pad all but last two positions */
3145        ctx->wbuf[cnt++] = 0;
3146
3147    /*
3148     * assemble the eight byte counter in the buffer in big-endian
3149     */
3150    /*
3151     * format
3152     */
3153
3154    ctx->wbuf[14] = htonl( ( ctx->count[1] << 3 ) | ( ctx->count[0] >> 29 ) );
3155    ctx->wbuf[15] = htonl( ctx->count[0] << 3 );
3156
3157    sha1_compile( ctx );
3158
3159    /*
3160     * extract the hash value as bytes in case the hash buffer is
3161     */
3162    /*
3163     * misaligned for 32-bit words
3164     */
3165
3166    for( i = 0; i < SHA1_DIGEST_SIZE; ++i )
3167        hval[i] = ( unsigned char )( ctx->hash[i >> 2] >> 8 * ( ~i & 3 ) );
3168
3169    return resbuf;
3170}
3171
3172void
3173base64_encode( const unsigned char *in, size_t inlen,
3174               unsigned char *out, size_t outlen )
3175{
3176    static const char b64str[64] =
3177        "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3178
3179    while( inlen && outlen )
3180    {
3181        *out++ = b64str[( in[0] >> 2 ) & 0x3f];
3182        if( !--outlen )
3183            break;
3184        *out++ =
3185            b64str[( ( in[0] << 4 ) + ( --inlen ? in[1] >> 4 : 0 ) ) & 0x3f];
3186        if( !--outlen )
3187            break;
3188        *out++ =
3189            ( inlen
3190              ? b64str[( ( in[1] << 2 ) + ( --inlen ? in[2] >> 6 : 0 ) ) &
3191                       0x3f] : '=' );
3192        if( !--outlen )
3193            break;
3194        *out++ = inlen ? b64str[in[2] & 0x3f] : '=';
3195        if( !--outlen )
3196            break;
3197        if( inlen )
3198            inlen--;
3199        if( inlen )
3200            in += 3;
3201    }
3202
3203    if( outlen )
3204        *out = '\0';
3205}
3206
3207char *request_freedns( char *user, char *password )
3208{
3209    unsigned char final[32];
3210    char un[128];
3211
3212    unlink( "/tmp/.hash" );
3213    sprintf( un, "%s|%s", user, password );
3214    sha1_ctx_t context;
3215
3216    sha1_begin( &context );
3217    sha1_hash( un, strlen( un ), &context );
3218    sha1_end( final, &context );
3219    char request[128] = { 0 };
3220    int i;
3221
3222    for( i = 0; i < 20; i++ )
3223        sprintf( request, "%s%02x", request, final[i] );
3224    system2( "rm -f /tmp/.hash" );
3225    sysprintf
3226        ( "wget \"http://freedns.afraid.org/api/?action=getdyndns&sha=%s\" -O /tmp/.hash",
3227          request );
3228    FILE *in = fopen( "/tmp/.hash", "rb" );
3229
3230    if( in == NULL )
3231        return NULL;
3232    while( getc( in ) != '?' && feof( in ) == 0 );
3233    i = 0;
3234    char *hash = malloc( 64 );
3235
3236    if( feof( in ) )
3237    {
3238        free( hash );
3239        return NULL;
3240    }
3241    for( i = 0; i < 36; i++ )
3242        hash[i] = getc( in );
3243    fclose( in );
3244    hash[i++] = 0;
3245    return hash;
3246}
3247
3248void ddns_save_value( webs_t wp )
3249{
3250    char *enable, *username, *passwd, *hostname, *dyndnstype, *wildcard,
3251        *custom, *conf, *url, *force;
3252    struct variable ddns_variables[] = {
3253      {argv:ARGV( "0", "1", "2", "3", "4", "5", "6",
3254              "7",
3255              "8" )},
3256      {argv:ARGV( "30" )},
3257    }, *which;
3258    char _username[] = "ddns_username_X";
3259    char _passwd[] = "ddns_passwd_X";
3260    char _hostname[] = "ddns_hostname_X";
3261    char _dyndnstype[] = "ddns_dyndnstype_X";
3262    char _wildcard[] = "ddns_wildcard_X";
3263    char _custom[] = "ddns_custom_X";
3264    char _conf[] = "ddns_conf";
3265    char _url[] = "ddns_url";
3266    char _force[] = "ddns_force";
3267
3268    which = &ddns_variables[0];
3269
3270    enable = websGetVar( wp, "ddns_enable", NULL );
3271    if( !enable && !valid_choice( wp, enable, &which[0] ) )
3272    {
3273        return;
3274    }
3275    int gethash = 0;
3276
3277    if( atoi( enable ) == 0 )
3278    {
3279        // Disable
3280        nvram_set( "ddns_enable", enable );
3281        return;
3282    }
3283    else if( atoi( enable ) == 1 )
3284    {
3285        // dyndns
3286        snprintf( _username, sizeof( _username ), "%s", "ddns_username" );
3287        snprintf( _passwd, sizeof( _passwd ), "%s", "ddns_passwd" );
3288        snprintf( _hostname, sizeof( _hostname ), "%s", "ddns_hostname" );
3289        snprintf( _dyndnstype, sizeof( _dyndnstype ), "%s",
3290                  "ddns_dyndnstype" );
3291        snprintf( _wildcard, sizeof( _wildcard ), "%s", "ddns_wildcard" );
3292    }
3293    else if( atoi( enable ) == 2 )
3294    {
3295        // afraid
3296        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3297                  enable );
3298        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3299        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3300                  enable );
3301        gethash = 1;
3302    }
3303    else if( atoi( enable ) == 3 )
3304    {
3305        // zoneedit
3306        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3307                  enable );
3308        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3309        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3310                  enable );
3311    }
3312    else if( atoi( enable ) == 4 )
3313    {
3314        // no-ip
3315        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3316                  enable );
3317        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3318        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3319                  enable );
3320    }
3321    else if( atoi( enable ) == 5 )
3322    {
3323        // custom
3324        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3325                  enable );
3326        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3327        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3328                  enable );
3329        snprintf( _custom, sizeof( _custom ), "ddns_custom_%s", enable );
3330        snprintf( _conf, sizeof( _conf ), "%s", "ddns_conf" );
3331        snprintf( _url, sizeof( _url ), "%s", "ddns_url" );
3332    }
3333    else if( atoi( enable ) == 6 )
3334    {
3335        // 3322 dynamic : added botho 30/07/06
3336        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3337                  enable );
3338        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3339        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3340                  enable );
3341        snprintf( _dyndnstype, sizeof( _dyndnstype ), "ddns_dyndnstype_%s",
3342                  enable );
3343        snprintf( _wildcard, sizeof( _wildcard ), "ddns_wildcard_%s",
3344                  enable );
3345    }
3346    else if( atoi( enable ) == 7 )
3347    {
3348        // easydns
3349        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3350                  enable );
3351        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3352        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3353                  enable );
3354        snprintf( _wildcard, sizeof( _wildcard ), "ddns_wildcard_%s",
3355                  enable );
3356    }
3357    else if( atoi( enable ) == 8 )
3358    {
3359        // tzo
3360        snprintf( _username, sizeof( _username ), "ddns_username_%s",
3361                  enable );
3362        snprintf( _passwd, sizeof( _passwd ), "ddns_passwd_%s", enable );
3363        snprintf( _hostname, sizeof( _hostname ), "ddns_hostname_%s",
3364                  enable );
3365    }
3366
3367    username = websGetVar( wp, _username, NULL );
3368    passwd = websGetVar( wp, _passwd, NULL );
3369    hostname = websGetVar( wp, _hostname, NULL );
3370    dyndnstype = websGetVar( wp, _dyndnstype, NULL );
3371    wildcard = websGetVar( wp, _wildcard, NULL );
3372    custom = websGetVar( wp, _custom, NULL );
3373    conf = websGetVar( wp, _conf, NULL );
3374    url = websGetVar( wp, _url, NULL );
3375    force = websGetVar( wp, _force, NULL );
3376
3377    if( !username || !passwd || !hostname || !force )
3378    {
3379        return;
3380    }
3381
3382    nvram_set( "ddns_enable", enable );
3383    nvram_set( _username, username );
3384    if( strcmp( passwd, TMP_PASSWD ) )
3385    {
3386        nvram_set( _passwd, passwd );
3387    }
3388    if( gethash && !contains( hostname, ',' ) )
3389    {
3390        char hostn[128];
3391        char *hash = request_freedns( username, nvram_safe_get( _passwd ) );
3392
3393        if( hash )
3394        {
3395            sprintf( hostn, "%s,%s", hostname, hash );
3396            nvram_set( _hostname, hostn );
3397            free( hash );
3398        }
3399        else
3400        {
3401            nvram_set( _hostname, "User/Password wrong" );
3402        }
3403    }
3404    else
3405        nvram_set( _hostname, hostname );
3406    nvram_set( _dyndnstype, dyndnstype );
3407    nvram_set( _wildcard, wildcard );
3408    nvram_set( _custom, custom );
3409    nvram_set( _conf, conf );
3410    nvram_set( _url, url );
3411    nvram_set( _force, force );
3412
3413}
3414
3415void ddns_update_value( webs_t wp )
3416{
3417
3418}
3419void port_vlan_table_save( webs_t wp )
3420{
3421    int port = 0, vlan = 0, vlans[21], i;
3422    char portid[32], portvlan[64], *portval, buff[32], *c, *next,
3423        br0vlans[64], br1vlans[64], br2vlans[64];
3424
3425    strcpy( portvlan, "" );
3426
3427    for( vlan = 0; vlan < 21; vlan++ )
3428        vlans[vlan] = 0;
3429
3430    vlans[16] = 1;
3431
3432    for( port = 0; port < 5; port++ )
3433    {
3434        for( vlan = 0; vlan < 21; vlan++ )
3435        {
3436            snprintf( portid, 31, "port%dvlan%d", port, vlan );
3437            portval = websGetVar( wp, portid, "" );
3438
3439            if( vlan < 17 || vlan > 20 )
3440                i = ( strcmp( portval, "on" ) == 0 );
3441            else
3442                i = ( strcmp( portval, "on" ) != 0 );
3443
3444            if( i )
3445            {
3446                if( strlen( portvlan ) > 0 )
3447                    strcat( portvlan, " " );
3448
3449                snprintf( buff, 4, "%d", vlan );
3450                strcat( portvlan, buff );
3451                vlans[vlan] = 1;
3452            }
3453        }
3454
3455        snprintf( portid, 31, "port%dvlans", port );
3456        nvram_set( portid, portvlan );
3457        strcpy( portvlan, "" );
3458    }
3459
3460    /*
3461     * done with ports 0-4, now set up #5 automaticly
3462     */
3463    /*
3464     * if a VLAN is used, it also gets assigned to port #5
3465     */
3466    for( vlan = 0; vlan < 17; vlan++ )
3467    {
3468        if( vlans[vlan] )
3469        {
3470            if( strlen( portvlan ) > 0 )
3471                strcat( portvlan, " " );
3472
3473            snprintf( buff, 4, "%d", vlan );
3474            strcat( portvlan, buff );
3475        }
3476    }
3477
3478    nvram_set( "port5vlans", portvlan );
3479
3480    strcpy( br0vlans, "" );
3481    c = nvram_safe_get( "lan_ifnames" );
3482    if( c )
3483    {
3484        foreach( portid, c, next )
3485        {
3486            if( !( strncmp( portid, "vlan", 4 ) == 0 )
3487                && !( strncmp( portid, "eth1", 4 ) == 0 ) )
3488            {
3489                if( strlen( br0vlans ) > 0 )
3490                    strcat( br0vlans, " " );
3491                strcat( br0vlans, portid );
3492            }
3493        }
3494    }
3495
3496    strcpy( br1vlans, "" );
3497    c = nvram_safe_get( "ub1_ifnames" );
3498    if( c )
3499    {
3500        foreach( portid, c, next )
3501        {
3502            if( !( strncmp( portid, "vlan", 4 ) == 0 )
3503                && !( strncmp( portid, "eth1", 4 ) == 0 ) )
3504            {
3505                if( strlen( br1vlans ) > 0 )
3506                    strcat( br1vlans, " " );
3507                strcat( br1vlans, portid );
3508            }
3509        }
3510    }
3511
3512    strcpy( br2vlans, "" );
3513    c = nvram_safe_get( "ub2_ifnames" );
3514    if( c )
3515    {
3516        foreach( portid, c, next )
3517        {
3518            if( !( strncmp( portid, "vlan", 4 ) == 0 )
3519                && !( strncmp( portid, "eth1", 4 ) == 0 ) )
3520            {
3521                if( strlen( br2vlans ) > 0 )
3522                    strcat( br2vlans, " " );
3523                strcat( br2vlans, portid );
3524            }
3525        }
3526    }
3527
3528    for( i = 0; i < 16; i++ )
3529    {
3530        snprintf( buff, 31, "vlan%d", i );
3531        portval = websGetVar( wp, buff, "" );
3532
3533        switch ( atoi( portval ) )
3534        {
3535            case 0:
3536                if( strlen( br0vlans ) > 0 )
3537                    strcat( br0vlans, " " );
3538                strcat( br0vlans, buff );
3539                break;
3540            case 1:
3541                if( strlen( br1vlans ) > 0 )
3542                    strcat( br1vlans, " " );
3543                strcat( br1vlans, buff );
3544                break;
3545            case 2:
3546                if( strlen( br2vlans ) > 0 )
3547                    strcat( br2vlans, " " );
3548                strcat( br2vlans, buff );
3549                break;
3550        }
3551    }
3552
3553    strcpy( buff, "" );
3554
3555    switch ( atoi( websGetVar( wp, "wireless", "" ) ) )
3556    {
3557        case 0:
3558            if( strlen( br0vlans ) > 0 )
3559                strcat( br0vlans, " " );
3560            strcat( br0vlans, get_wdev(  ) );
3561            break;
3562        case 1:
3563            if( strlen( br1vlans ) > 0 )
3564                strcat( br1vlans, " " );
3565            strcat( br1vlans, get_wdev(  ) );
3566            break;
3567        case 2:
3568            if( strlen( br2vlans ) > 0 )
3569                strcat( br2vlans, " " );
3570            strcat( br2vlans, get_wdev(  ) );
3571            break;
3572    }
3573
3574    snprintf( buff, 3, "%s", websGetVar( wp, "trunking", "" ) );
3575
3576    nvram_set( "lan_ifnames", br0vlans );
3577    // nvram_set("ub1_ifnames", br1vlans);
3578    // nvram_set("ub2_ifnames", br2vlans);
3579    nvram_set( "trunking", buff );
3580    nvram_set( "vlans", "1" );
3581
3582    nvram_commit(  );
3583
3584}
3585
3586static void save_macmode_if( webs_t wp, char *ifname )
3587{
3588
3589    char macmode[32];
3590    char macmode1[32];
3591
3592    sprintf( macmode, "%s_macmode", ifname );
3593    sprintf( macmode1, "%s_macmode1", ifname );
3594    rep( macmode1, '.', 'X' );
3595    char *wl_macmode1, *wl_macmode;
3596
3597    wl_macmode = websGetVar( wp, macmode, NULL );
3598    wl_macmode1 = websGetVar( wp, macmode1, NULL );
3599
3600    if( !wl_macmode1 )
3601        return;
3602
3603    if( !strcmp( wl_macmode1, "disabled" ) )
3604    {
3605        nvram_set( macmode1, "disabled" );
3606        nvram_set( macmode, "disabled" );
3607    }
3608    else if( !strcmp( wl_macmode1, "other" ) )
3609    {
3610        if( !wl_macmode )
3611            nvram_set( macmode, "deny" );
3612        else
3613            nvram_set( macmode, wl_macmode );
3614        nvram_set( macmode1, "other" );
3615    }
3616}
3617
3618void save_macmode( webs_t wp )
3619{
3620#ifndef HAVE_MADWIFI
3621    int c = get_wl_instances(  );
3622    char devs[32];
3623    int i;
3624
3625    for( i = 0; i < c; i++ )
3626    {
3627        sprintf( devs, "wl%d", i );
3628        save_macmode_if( wp, devs );
3629    }
3630#else
3631    int c = getdevicecount(  );
3632    char devs[32];
3633    int i;
3634
3635    for( i = 0; i < c; i++ )
3636    {
3637        sprintf( devs, "ath%d", i );
3638        save_macmode_if( wp, devs );
3639        char vif[32];
3640
3641        sprintf( vif, "%s_vifs", devs );
3642        char var[80], *next;
3643        char *vifs = nvram_safe_get( vif );
3644
3645        if( vifs != NULL )
3646            foreach( var, vifs, next )
3647        {
3648            save_macmode_if( wp, var );
3649        }
3650    }
3651
3652#endif
3653    return;
3654
3655}
3656
3657// handle UPnP.asp requests / added 10
3658void tf_upnp( webs_t wp )
3659{
3660    char *v;
3661    char s[64];
3662
3663    if( ( ( v = websGetVar( wp, "remove", NULL ) ) != NULL ) && ( *v ) )
3664    {
3665        if( strcmp( v, "all" ) == 0 )
3666        {
3667            nvram_set( "upnp_clear", "1" );
3668        }
3669        else
3670        {
3671            sprintf( s, "forward_port%s", v );
3672            nvram_unset( s );
3673        }
3674    }
3675    // firewall + upnp service is restarted after this
3676}
Note: See TracBrowser for help on using the repository browser.