Merge branch 'tomato-ND-usbmod-base' into tomato-ND-USBmod
[tomato.git] / release / src / router / httpd / tomato.c
blob85cfd17d14c86f8afb09b8e98353e0f39c763235
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2008 Jonathan Zarate
6 */
8 #include "tomato.h"
10 #include <sys/sysinfo.h>
11 #include <sys/stat.h>
12 #include <arpa/inet.h>
13 #include <time.h>
16 // #define DEBUG_NOEXECSERVICE
17 // #define DEBUG_NVRAMSET(k, v) cprintf("nvram set %s=%s\n", k, v);
18 #define DEBUG_NVRAMSET(k, v) do { } while(0);
21 char *post_buf = NULL;
22 int rboot = 0;
23 extern int post;
25 void asp_resmsg(int argc, char **argv);
28 static void wo_tomato(char *url);
29 static void wo_update(char *url);
30 static void wo_service(char *url);
31 static void wo_logout(char *url);
32 static void wo_shutdown(char *url);
33 static void wo_nvcommit(char *url);
36 // ----------------------------------------------------------------------------
39 void exec_service(const char *action)
41 int i;
43 _dprintf("exec_service: %s\n", action);
45 i = 10;
46 while ((!nvram_match("action_service", "")) && (i-- > 0)) {
47 _dprintf("%s: waiting before %d\n", __FUNCTION__, i);
48 sleep(1);
51 nvram_set("action_service", action);
52 kill(1, SIGUSR1);
54 i = 3;
55 while ((nvram_match("action_service", (char *)action)) && (i-- > 0)) {
56 _dprintf("%s: waiting after %d\n", __FUNCTION__, i);
57 sleep(1);
61 if (atoi(webcgi_safeget("_service_wait", ""))) {
62 i = 10;
63 while ((nvram_match("action_service", (char *)action)) && (i-- > 0)) {
64 _dprintf("%s: waiting after %d\n", __FUNCTION__, i);
65 sleep(1);
71 void wi_generic_noid(char *url, int len, char *boundary)
73 if (post == 1) {
74 if (len >= (32 * 1024)) {
75 syslog(LOG_WARNING, "POST length exceeded maximum allowed");
76 exit(1);
79 if (!post_buf) free(post_buf);
80 if ((post_buf = malloc(len + 1)) == NULL) {
81 // syslog(LOG_CRIT, "Unable to allocate post buffer");
82 exit(1);
85 if (web_read_x(post_buf, len) != len) {
86 exit(1);
88 post_buf[len] = 0;
89 _dprintf("post_buf=%s\n", post_buf);
90 webcgi_init(post_buf);
94 void wi_generic(char *url, int len, char *boundary)
96 wi_generic_noid(url, len, boundary);
97 check_id();
100 // !!TB - CGI Support
101 void wi_cgi_bin(char *url, int len, char *boundary)
103 if (!post_buf) free(post_buf);
104 post_buf = NULL;
106 if (post) {
107 if (len >= (32 * 1024)) {
108 syslog(LOG_WARNING, "POST length exceeded maximum allowed");
109 exit(1);
112 if (len > 0) {
113 if ((post_buf = malloc(len + 1)) == NULL) {
114 exit(1);
116 if (web_read_x(post_buf, len) != len) {
117 exit(1);
119 post_buf[len] = 0;
124 static void wo_cgi_bin(char *url)
126 char webExecFile[] = "/tmp/.webexecXXXXXX";
127 char webQueryFile[] = "/tmp/.webqueryXXXXXX";
128 char webASPFile[] = "/tmp/.weboutXXXXXX";
130 FILE *f;
132 mktemp(webExecFile);
133 if (post_buf) mktemp(webQueryFile);
135 if ((f = fopen(webExecFile, "wb")) != NULL) {
136 fprintf(f, "#!/bin/sh\nexport REQUEST_METHOD=\"%s\"\n", post ? "POST" : "GET");
137 if (post_buf)
138 fprintf(f, "./%s <%s\n", url, webQueryFile);
139 else
140 fprintf(f, "./%s\n", url);
141 fclose(f);
143 else {
144 exit(1);
147 if (post_buf) {
148 if ((f = fopen(webQueryFile, "wb")) != NULL) {
149 fprintf(f, "%s\n", post_buf);
150 fclose(f);
151 free(post_buf);
152 post_buf = NULL;
154 else {
155 unlink(webExecFile);
156 exit(1);
160 chmod(webExecFile, 0700);
162 char cmd[128];
163 mktemp(webASPFile);
164 sprintf(cmd, "%s >%s", webExecFile, webASPFile);
165 system(cmd);
166 unlink(webQueryFile);
167 unlink(webExecFile);
168 wo_asp(webASPFile);
169 unlink(webASPFile);
172 static void wo_blank(char *url)
174 web_puts("\n\n\n\n");
177 static void wo_favicon(char *url)
179 if (nvram_match("web_favicon", "1")) {
180 send_header(200, NULL, "image/vnd.microsoft.icon", 0);
181 do_file(url);
183 else {
184 send_error(404, NULL, NULL);
188 static void wo_cfe(char *url)
190 do_file("/dev/mtd/0ro");
193 static void wo_nvram(char *url)
195 web_pipecmd("nvram show", WOF_NONE);
198 static void wo_iptables(char *url)
200 web_pipecmd("iptables -nvL; iptables -t nat -nvL; iptables -t mangle -nvL", WOF_NONE);
204 static void wo_spin(char *url)
206 char s[64];
208 strlcpy(s, nvram_safe_get("web_css"), sizeof(s));
209 strlcat(s, "_spin.gif", sizeof(s));
210 if (f_exists(s)) do_file(s);
211 else do_file("_spin.gif");
215 void common_redirect(void)
217 if (atoi(webcgi_safeget("_ajax", ""))) {
218 send_header(200, NULL, mime_html, 0);
219 web_puts("OK");
221 else {
222 redirect(webcgi_safeget("_redirect", "/"));
226 // ----------------------------------------------------------------------------
228 const struct mime_handler mime_handlers[] = {
229 { "update.cgi", mime_javascript, 0, wi_generic, wo_update, 1 },
230 { "tomato.cgi", NULL, 0, wi_generic, wo_tomato, 1 },
232 { "debug.js", mime_javascript, 5, wi_generic_noid, wo_blank, 1 }, // while debugging
233 { "cfe/*.bin", mime_binary, 0, wi_generic, wo_cfe, 1 },
234 { "nvram/*.txt", mime_binary, 0, wi_generic, wo_nvram, 1 },
235 { "ipt/*.txt", mime_binary, 0, wi_generic, wo_iptables, 1 },
237 { "cfg/*.cfg", NULL, 0, wi_generic, wo_backup, 1 },
238 { "cfg/restore.cgi", mime_html, 0, wi_restore, wo_restore, 1 },
239 { "cfg/defaults.cgi", NULL, 0, wi_generic, wo_defaults, 1 },
241 { "bwm/*.gz", NULL, 0, wi_generic, wo_bwmbackup, 1 },
242 { "bwm/restore.cgi", NULL, 0, wi_bwmrestore, wo_bwmrestore, 1 },
244 { "logs/view.cgi", NULL, 0, wi_generic, wo_viewlog, 1 },
245 { "logs/*.txt", NULL, 0, wi_generic, wo_syslog, 1 },
247 { "logout.asp", NULL, 0, wi_generic, wo_asp, 1 },
248 { "clearcookies.asp", NULL, 0, wi_generic, wo_asp, 1 },
250 // { "spin.gif", NULL, 0, wi_generic_noid, wo_spin, 1 },
252 { "**.asp", NULL, 0, wi_generic_noid, wo_asp, 1 },
253 { "**.css", "text/css", 2, wi_generic_noid, do_file, 1 },
254 { "**.htm", mime_html, 2, wi_generic_noid, do_file, 1 },
255 { "**.gif", "image/gif", 5, wi_generic_noid, do_file, 1 },
256 { "**.jpg", "image/jpeg", 5, wi_generic_noid, do_file, 1 },
257 { "**.png", "image/png", 5, wi_generic_noid, do_file, 1 },
258 { "**.js", mime_javascript, 2, wi_generic_noid, do_file, 1 },
259 { "**.jsx", mime_javascript, 0, wi_generic, wo_asp, 1 },
260 { "**.svg", "image/svg+xml", 2, wi_generic_noid, do_file, 1 },
261 { "**.txt", mime_plain, 2, wi_generic_noid, do_file, 1 },
262 { "**.bin", mime_binary, 0, wi_generic_noid, do_file, 1 },
263 { "**.bino", mime_octetstream, 0, wi_generic_noid, do_file, 1 },
264 { "favicon.ico", NULL, 5, wi_generic_noid, wo_favicon, 1 },
266 // !!TB - CGI Support, enable downloading archives
267 { "**/cgi-bin/**|**.sh", NULL, 0, wi_cgi_bin, wo_cgi_bin, 1 },
268 { "**.tar|**.gz", mime_binary, 0, wi_generic_noid, do_file, 1 },
270 { "dhcpc.cgi", NULL, 0, wi_generic, wo_dhcpc, 1 },
271 { "dhcpd.cgi", mime_javascript, 0, wi_generic, wo_dhcpd, 1 },
272 { "nvcommit.cgi", NULL, 0, wi_generic, wo_nvcommit, 1 },
273 { "ping.cgi", mime_javascript, 0, wi_generic, wo_ping, 1 },
274 { "trace.cgi", mime_javascript, 0, wi_generic, wo_trace, 1 },
275 { "upgrade.cgi", mime_html, 0, wi_upgrade, wo_flash, 1 },
276 { "upnp.cgi", NULL, 0, wi_generic, wo_upnp, 1 },
277 { "wakeup.cgi", NULL, 0, wi_generic, wo_wakeup, 1 },
278 { "wlmnoise.cgi", mime_html, 0, wi_generic, wo_wlmnoise, 1 },
279 { "wlradio.cgi", NULL, 0, wi_generic, wo_wlradio, 1 },
280 { "resolve.cgi", mime_javascript, 0, wi_generic, wo_resolve, 1 },
281 { "expct.cgi", mime_html, 0, wi_generic, wo_expct, 1 },
282 { "service.cgi", NULL, 0, wi_generic, wo_service, 1 },
283 { "logout.cgi", NULL, 0, wi_generic, wo_logout, 0 },
284 { "shutdown.cgi", mime_html, 0, wi_generic, wo_shutdown, 1 },
286 { "usbcmd.cgi", mime_javascript, 0, wi_generic, wo_usbcommand, 1 }, //!!TB - USB
287 #if TOMATO_SL
288 { "usb.cgi", NULL, 0, wi_generic, wo_usb, 1 },
289 { "umount.cgi", NULL, 0, wi_generic, wo_umount, 1 },
290 #endif
291 #ifdef BLACKHOLE
292 { "blackhole.cgi", NULL, 0, wi_blackhole, NULL, 1 },
293 #endif
294 // { "test", mime_html, 0, wi_generic, wo_test, 1 },
295 { NULL, NULL, 0, NULL, NULL, 1 }
298 const aspapi_t aspapi[] = {
299 { "activeroutes", asp_activeroutes },
300 { "arplist", asp_arplist },
301 { "bandwidth", asp_bandwidth },
302 { "build_time", asp_build_time },
303 { "cgi_get", asp_cgi_get },
304 { "compmac", asp_compmac },
305 { "ctcount", asp_ctcount },
306 { "ctdump", asp_ctdump },
307 { "ddnsx", asp_ddnsx },
308 { "devlist", asp_devlist },
309 { "dhcpc_time", asp_dhcpc_time },
310 { "dns", asp_dns },
311 { "ident", asp_ident },
312 { "lanip", asp_lanip },
313 { "layer7", asp_layer7 },
314 { "link_uptime", asp_link_uptime },
315 { "lipp", asp_lipp },
316 { "netdev", asp_netdev },
317 { "notice", asp_notice },
318 { "nv", asp_nv },
319 { "nvram", asp_nvram },
320 { "nvramseq", asp_nvramseq },
321 { "psup", asp_psup },
322 { "qrate", asp_qrate },
323 { "resmsg", asp_resmsg },
324 { "rrule", asp_rrule },
325 { "statfs", asp_statfs },
326 { "sysinfo", asp_sysinfo },
327 { "time", asp_time },
328 { "upnpinfo", asp_upnpinfo },
329 { "version", asp_version },
330 { "wanstatus", asp_wanstatus },
331 { "wanup", asp_wanup },
332 { "wlchannel", asp_wlchannel },
333 { "wlclient", asp_wlclient },
334 { "wlcrssi", asp_wlcrssi },
335 { "wlnoise", asp_wlnoise },
336 { "wlradio", asp_wlradio },
337 { "wlscan", asp_wlscan },
338 #if TOMATO_SL
339 { "sharelist", asp_sharelist },
340 #endif
341 { "usbdevices", asp_usbdevices }, //!!TB - USB Support
342 { "wlchannels", asp_wlchannels }, //!!TB
343 { NULL, NULL }
346 // -----------------------------------------------------------------------------
348 const char *resmsg_get(void)
350 return webcgi_safeget("resmsg", "");
353 void resmsg_set(const char *msg)
355 webcgi_set("resmsg", strdup(msg)); // m ok
358 int resmsg_fread(const char *fname)
360 char s[256];
361 char *p;
363 f_read_string(fname, s, sizeof(s));
364 if ((p = strchr(s, '\n')) != NULL) *p = 0;
365 if (s[0]) {
366 resmsg_set(s);
367 return 1;
369 return 0;
372 void asp_resmsg(int argc, char **argv)
374 char *p;
376 if ((p = js_string(webcgi_safeget("resmsg", (argc > 0) ? argv[0] : ""))) == NULL) return;
377 web_printf("\nresmsg='%s';\n", p);
378 free(p);
381 // ----------------------------------------------------------------------------
383 // verification... simple sanity checks. UI should verify all fields.
385 // todo: move and re-use for filtering - zzz
387 typedef union {
388 int i;
389 long l;
390 const char *s;
391 } nvset_varg_t;
393 typedef struct {
394 const char *name;
395 enum {
396 VT_NONE, // no checking
397 VT_LENGTH, // check length of string
398 VT_TEXT, // strip \r, check length of string
399 VT_RANGE, // expect an integer, check range
400 VT_IP, // expect an ip address
401 VT_MAC, // expect a mac address
402 VT_TEMP // no checks, no commit
403 } vtype;
404 nvset_varg_t va;
405 nvset_varg_t vb;
406 } nvset_t;
409 #define V_NONE VT_NONE, { }, { }
410 #define V_01 VT_RANGE, { .l = 0 }, { .l = 1 }
411 #define V_PORT VT_RANGE, { .l = 2 }, { .l = 65535 }
412 #define V_ONOFF VT_LENGTH, { .i = 2 }, { .i = 3 }
413 #define V_WORD VT_LENGTH, { .i = 1 }, { .i = 16 }
414 #define V_LENGTH(min, max) VT_LENGTH, { .i = min }, { .i = max }
415 #define V_TEXT(min, max) VT_TEXT, { .i = min }, { .i = max }
416 #define V_RANGE(min, max) VT_RANGE, { .l = min }, { .l = max }
417 #define V_IP VT_IP, { }, { }
418 #define V_OCTET VT_RANGE, { .l = 0 }, { .l = 255 }
419 #define V_NUM VT_RANGE, { .l = 0 }, { .l = 0x7FFFFFFF }
420 #define V_TEMP VT_TEMP, { }, { }
422 static const nvset_t nvset_list[] = {
424 // basic-ident
425 { "router_name", V_LENGTH(0, 32) },
426 { "wan_hostname", V_LENGTH(0, 32) },
427 { "wan_domain", V_LENGTH(0, 32) },
429 // basic-time
430 { "tm_tz", V_LENGTH(1, 64) }, // PST8PDT
431 { "tm_sel", V_LENGTH(1, 64) }, // PST8PDT
432 { "tm_dst", V_01 },
433 { "ntp_updates", V_RANGE(-1, 24) },
434 { "ntp_tdod", V_01 },
435 { "ntp_server", V_LENGTH(1, 150) }, // x y z
436 { "ntp_kiss", V_LENGTH(0, 255) },
438 // basic-static
439 { "dhcpd_static", V_LENGTH(0, 53*101) }, // 53 (max chars per entry) x 100 entries
441 // basic-ddns
442 { "ddnsx0", V_LENGTH(0, 2048) },
443 { "ddnsx1", V_LENGTH(0, 2048) },
444 { "ddnsx0_cache", V_LENGTH(0, 1) }, // only to clear
445 { "ddnsx1_cache", V_LENGTH(0, 1) },
446 { "ddnsx_ip", V_LENGTH(0, 32) },
448 // basic-network
449 // WAN
450 { "wan_proto", V_LENGTH(1, 16) }, // disabled, dhcp, static, pppoe, pptp, l2tp
451 { "wan_ipaddr", V_IP },
452 { "wan_netmask", V_IP },
453 { "wan_gateway", V_IP },
454 { "hb_server_ip", V_LENGTH(0, 32) },
455 { "l2tp_server_ip", V_IP },
456 { "pptp_server_ip", V_IP },
457 { "ppp_username", V_LENGTH(0, 50) },
458 { "ppp_passwd", V_LENGTH(0, 50) },
459 { "ppp_service", V_LENGTH(0, 50) },
460 { "ppp_demand", V_01 },
461 { "ppp_idletime", V_RANGE(0, 1440) },
462 { "ppp_redialperiod", V_RANGE(1, 86400) },
463 { "mtu_enable", V_01 },
464 { "wan_mtu", V_RANGE(576, 1500) },
466 // LAN
467 { "lan_ipaddr", V_IP },
468 { "lan_netmask", V_IP },
469 { "lan_gateway", V_IP },
470 { "wan_dns", V_LENGTH(0, 50) }, // ip ip ip
471 { "lan_proto", V_WORD }, // static, dhcp
472 { "dhcp_start", V_RANGE(1, 254) }, // remove !
473 { "dhcp_num", V_RANGE(1, 255) }, // remove !
474 { "dhcpd_startip", V_IP },
475 { "dhcpd_endip", V_IP },
476 { "dhcp_lease", V_RANGE(1, 10080) },
477 { "wan_wins", V_IP },
479 // wireless
480 { "wl_radio", V_01 },
481 { "wl_mode", V_LENGTH(2, 3) }, // ap, sta, wet, wds
482 { "wl_net_mode", V_LENGTH(5, 8) }, // disabled, mixed, b-only, g-only, bg-mixed, n-only [speedbooster]
483 { "wl_ssid", V_LENGTH(1, 32) },
484 { "wl_closed", V_01 },
485 { "wl_channel", V_RANGE(1, 14) },
486 #if TOMATO_N
487 // ! update
488 #endif
490 { "security_mode2", V_LENGTH(1, 32) }, // disabled, radius, wep, wpa_personal, wpa_enterprise, wpa2_personal, wpa2_enterprise
491 { "wl_radius_ipaddr", V_IP },
492 { "wl_radius_port", V_PORT },
493 { "wl_radius_key", V_LENGTH(1, 64) },
494 { "wl_wep_bit", V_RANGE(64, 128) }, // 64 or 128
495 { "wl_passphrase", V_LENGTH(0, 20) },
496 { "wl_key", V_RANGE(1, 4) },
497 { "wl_key1", V_LENGTH(0, 26) },
498 { "wl_key2", V_LENGTH(0, 26) },
499 { "wl_key3", V_LENGTH(0, 26) },
500 { "wl_key4", V_LENGTH(0, 26) },
501 { "wl_crypto", V_LENGTH(3, 8) }, // tkip, aes, tkip+aes
502 { "wl_wpa_psk", V_LENGTH(8, 64) },
503 { "wl_wpa_gtk_rekey", V_RANGE(60, 7200) },
505 { "wl_lazywds", V_01 },
506 { "wl_wds", V_LENGTH(0, 180) }, // mac mac mac (x 10)
508 { "security_mode", V_LENGTH(1, 32) }, // disabled, radius, wpa, psk,wep, wpa2, psk2, wpa wpa2, psk psk2
509 { "wds_enable", V_01 },
510 { "wl_gmode", V_RANGE(-1, 6) },
511 { "wl_wep", V_LENGTH(1, 32) }, // off, on, restricted,tkip,aes,tkip+aes
512 { "wl_akm", V_LENGTH(0, 32) }, // wpa, wpa2, psk, psk2, wpa wpa2, psk psk2, ""
513 { "wl_auth_mode", V_LENGTH(4, 6) }, // none, radius
515 #if TOMATO_N
516 { "wl_nmode", V_NONE },
517 { "wl_nreqd", V_NONE },
518 #endif
520 // basic-wfilter
521 { "wl_macmode", V_NONE }, // allow, deny, disabled
522 { "wl_maclist", V_LENGTH(0, 18*101) }, // 18 x 100 (11:22:33:44:55:66 ...)
523 { "macnames", V_LENGTH(0, 62*101) }, // 62 (12+1+48+1) x 50 (112233445566<..>) todo: re-use -- zzz
525 // advanced-ctnf
526 { "ct_max", V_RANGE(128, 10240) },
527 { "ct_tcp_timeout", V_LENGTH(20, 70) },
528 { "ct_udp_timeout", V_LENGTH(5, 15) },
529 { "nf_ttl", V_RANGE(-10, 10) },
530 { "nf_l7in", V_01 },
531 { "nf_rtsp", V_01 },
532 { "nf_pptp", V_01 },
533 { "nf_h323", V_01 },
534 { "nf_ftp", V_01 },
536 // advanced-dhcpdns
537 { "dhcpd_slt", V_RANGE(-1, 43200) }, // -1=infinite, 0=follow normal lease time, >=1 custom
538 { "dhcpd_dmdns", V_01 },
539 { "dhcpd_lmax", V_NUM },
540 { "dns_addget", V_01 },
541 { "dns_intcpt", V_01 },
542 { "dhcpc_minpkt", V_01 },
543 { "dnsmasq_custom", V_TEXT(0, 2048) },
544 // { "dnsmasq_norw", V_01 },
546 // advanced-firewall // todo: moveme
547 { "block_wan", V_01 },
548 { "multicast_pass", V_01 },
549 { "block_loopback", V_01 },
550 { "nf_loopback", V_NUM },
551 { "ne_syncookies", V_01 },
552 { "ne_snat", V_01 },
554 // advanced-misc
555 { "wait_time", V_RANGE(3, 20) },
556 { "wan_speed", V_RANGE(0, 4) },
558 // advanced-mac
559 { "mac_wan", V_LENGTH(0, 17) },
560 { "mac_wl", V_LENGTH(0, 17) },
562 // advanced-routing
563 { "routes_static", V_LENGTH(0, 2048) },
564 { "lan_stp", V_RANGE(0, 1) },
565 { "wk_mode", V_LENGTH(1, 32) }, // gateway, router
566 { "dr_setting", V_RANGE(0, 3) },
567 { "dr_lan_tx", V_LENGTH(0, 32) },
568 { "dr_lan_rx", V_LENGTH(0, 32) },
569 { "dr_wan_tx", V_LENGTH(0, 32) },
570 { "dr_wan_rx", V_LENGTH(0, 32) },
572 // advanced-wireless
573 { "wl_country", V_LENGTH(0, 64) }, // !!TB - Country code
574 { "wl_country_code", V_LENGTH(0, 4) }, // !!TB - Country code
575 { "wl_afterburner", V_LENGTH(2, 4) }, // off, on, auto
576 { "wl_auth", V_01 },
577 { "wl_rateset", V_LENGTH(2, 7) }, // all, default, 12
578 { "wl_rate", V_RANGE(0, 54 * 1000 * 1000) },
579 { "wl_mrate", V_RANGE(0, 54 * 1000 * 1000) },
580 { "wl_gmode_protection",V_LENGTH(3, 4) }, // off, auto
581 { "wl_frameburst", V_ONOFF }, // off, on
582 { "wl_bcn", V_RANGE(1, 65535) },
583 { "wl_dtim", V_RANGE(1, 255) },
584 { "wl_frag", V_RANGE(256, 2346) },
585 { "wl_rts", V_RANGE(0, 2347) },
586 { "wl_ap_isolate", V_01 },
587 { "wl_plcphdr", V_LENGTH(4, 5) }, // long, short
588 { "wl_antdiv", V_RANGE(0, 3) },
589 { "wl_txant", V_RANGE(0, 3) },
590 { "wl_txpwr", V_RANGE(0, 255) },
591 { "wl_wme", V_ONOFF }, // off, on
592 { "wl_wme_no_ack", V_ONOFF }, // off, on
593 { "wl_maxassoc", V_RANGE(0, 255) },
594 { "wl_distance", V_LENGTH(0, 5) }, // "", 1-99999
595 { "wlx_hpamp", V_01 },
596 { "wlx_hperx", V_01 },
597 { "wl_reg_mode", V_LENGTH(1, 3) }, // !!TB - Regulatory: off, h, d
599 #if TOMATO_N
600 { "wl_nmode_protection",V_WORD, }, // off, auto
601 { "wl_nmcsidx", V_RANGE(-2, 15), }, // -2 - 15
602 #endif
605 // advanced-watchdog
606 { "wd_en", V_01 },
607 { "wd_atp0", V_LENGTH(1, 48) },
608 { "wd_atp1", V_LENGTH(0, 48) },
609 { "wd_atp2", V_LENGTH(0, 48) },
610 { "wd_atp3", V_LENGTH(0, 48) },
611 { "wd_atp4", V_LENGTH(0, 48) },
612 { "wd_mxr", V_NUM },
613 { "wd_rdy", V_NUM },
614 { "wd_cki", V_NUM },
615 { "wd_fdm", V_NUM },
616 { "wd_aof", V_NUM },
619 // forward-dmz
620 { "dmz_enable", V_01 },
621 { "dmz_ipaddr", V_LENGTH(0, 15) },
622 { "dmz_sip", V_LENGTH(0, 32) },
624 // forward-upnp
625 { "upnp_enable", V_01 },
626 { "upnp_mnp", V_01 },
627 // { "upnp_config", V_01 },
628 { "upnp_ssdp_interval", V_RANGE(10, 9999) },
629 { "upnp_max_age", V_RANGE(5, 9999) },
631 //!!TB - miniupnpd
632 { "upnp_nat_pmp_enable", V_01 },
633 { "upnp_clean_ruleset_enable", V_01 },
634 { "upnp_secure_mode", V_01 },
635 { "upnp_clean_ruleset_interval",V_RANGE(60, 65535) },
636 { "upnp_clean_ruleset_threshold",V_RANGE(0, 9999) },
637 { "upnp_port", V_RANGE(0, 65535) },
638 { "upnp_bitrate_up", V_RANGE(10, 100000000) },
639 { "upnp_bitrate_down", V_RANGE(10, 100000000) },
640 { "upnp_min_port_int", V_PORT },
641 { "upnp_max_port_int", V_PORT },
642 { "upnp_min_port_ext", V_PORT },
643 { "upnp_max_port_ext", V_PORT },
645 // forward-basic
646 { "portforward", V_LENGTH(0, 4096) },
648 // forward-triggered
649 { "trigforward", V_LENGTH(0, 4096) },
652 // access restriction
653 { "rruleN", V_RANGE(0, 49) },
654 // { "rrule##", V_LENGTH(0, 2048) }, // in save_variables()
656 // admin-access
657 { "http_enable", V_01 },
658 { "https_enable", V_01 },
659 { "https_crt_save", V_01 },
660 { "https_crt_cn", V_LENGTH(0, 64) },
661 { "https_crt_gen", V_TEMP },
662 { "remote_management", V_01 },
663 { "remote_mgt_https", V_01 },
664 { "http_lanport", V_PORT },
665 { "https_lanport", V_PORT },
666 { "web_wl_filter", V_01 },
667 { "web_favicon", V_01 },
668 { "web_css", V_LENGTH(1, 32) },
669 { "http_wanport", V_PORT },
670 { "telnetd_eas", V_01 },
671 { "telnetd_port", V_PORT },
672 { "sshd_eas", V_01 },
673 { "sshd_pass", V_01 },
674 { "sshd_port", V_PORT },
675 { "sshd_remote", V_01 },
676 { "sshd_forwarding", V_01 },
677 { "sshd_rport", V_PORT },
678 { "sshd_authkeys", V_TEXT(0, 4096) },
679 { "rmgt_sip", V_LENGTH(0, 32) },
681 // admin-bwm
682 { "rstats_enable", V_01 },
683 { "rstats_path", V_LENGTH(0, 48) },
684 { "rstats_stime", V_RANGE(1, 168) },
685 { "rstats_offset", V_RANGE(1, 31) },
686 { "rstats_exclude", V_LENGTH(0, 64) },
687 { "rstats_sshut", V_01 },
688 { "rstats_bak", V_01 },
690 // admin-buttons
691 { "sesx_led", V_RANGE(0, 255) }, // amber, white, aoss
692 { "sesx_b0", V_RANGE(0, 4) }, // 0-4: toggle wireless, reboot, shutdown, script
693 { "sesx_b1", V_RANGE(0, 4) }, // "
694 { "sesx_b2", V_RANGE(0, 4) }, // "
695 { "sesx_b3", V_RANGE(0, 4) }, // "
696 { "sesx_script", V_TEXT(0, 1024) }, //
698 // admin-debug
699 { "debug_nocommit", V_01 },
700 { "debug_cprintf", V_01 },
701 { "debug_cprintf_file", V_01 },
702 // { "debug_keepfiles", V_01 },
703 { "debug_ddns", V_01 },
704 { "debug_norestart", V_TEXT(0, 128) },
705 { "console_loglevel", V_RANGE(1, 8) },
706 { "t_cafree", V_01 },
707 { "t_hidelr", V_01 },
709 // admin-sched
710 { "sch_rboot", V_TEXT(0, 64) },
711 { "sch_rcon", V_TEXT(0, 64) },
712 { "sch_c1", V_TEXT(0, 64) },
713 { "sch_c1_cmd", V_TEXT(0, 2048) },
714 { "sch_c2", V_TEXT(0, 64) },
715 { "sch_c2_cmd", V_TEXT(0, 2048) },
716 { "sch_c3", V_TEXT(0, 64) },
717 { "sch_c3_cmd", V_TEXT(0, 2048) },
719 // admin-scripts
720 { "script_init", V_TEXT(0, 4096) },
721 { "script_shut", V_TEXT(0, 4096) },
722 { "script_fire", V_TEXT(0, 8192) },
723 { "script_wanup", V_TEXT(0, 4096) },
725 // admin-log
726 { "log_remote", V_01 },
727 { "log_remoteip", V_IP },
728 { "log_remoteport", V_PORT },
729 { "log_file", V_01 },
730 { "log_limit", V_RANGE(0, 2400) },
731 { "log_in", V_RANGE(0, 3) },
732 { "log_out", V_RANGE(0, 3) },
733 { "log_mark", V_RANGE(0, 1440) },
734 { "log_events", V_TEXT(0, 32) }, // "acre,crond,ntp"
736 // admin-cifs
737 { "cifs1", V_LENGTH(5, 384) },
738 { "cifs2", V_LENGTH(5, 384) },
740 // admin-jffs2
741 { "jffs2_on", V_01 },
742 { "jffs2_exec", V_LENGTH(0, 64) },
743 { "jffs2_format", V_01 },
745 // nas-usb - !!TB
746 { "usb_enable", V_01 },
747 { "usb_uhci", V_01 },
748 { "usb_ohci", V_01 },
749 { "usb_usb2", V_01 },
750 { "usb_storage", V_01 },
751 { "usb_printer", V_01 },
752 { "usb_printer_bidirect", V_01 },
753 { "usb_fs_ext3", V_01 },
754 { "usb_fs_fat", V_01 },
755 { "usb_automount", V_01 },
756 { "script_usbhotplug", V_TEXT(0, 2048) },
757 { "script_usbmount", V_TEXT(0, 2048) },
758 { "script_usbumount", V_TEXT(0, 2048) },
760 // nas-ftp - !!TB
761 #ifdef TCONFIG_FTP
762 { "ftp_enable", V_RANGE(0, 2) },
763 { "ftp_super", V_01 },
764 { "ftp_anonymous", V_RANGE(0, 3) },
765 { "ftp_dirlist", V_RANGE(0, 2) },
766 { "ftp_port", V_PORT },
767 { "ftp_max", V_RANGE(0, 12) },
768 { "ftp_ipmax", V_RANGE(0, 12) },
769 { "ftp_staytimeout", V_RANGE(0, 65535) },
770 { "ftp_rate", V_RANGE(0, 99999) },
771 { "ftp_anonrate", V_RANGE(0, 99999) },
772 { "ftp_anonroot", V_LENGTH(0, 256) },
773 { "ftp_pubroot", V_LENGTH(0, 256) },
774 { "ftp_pvtroot", V_LENGTH(0, 256) },
775 { "ftp_users", V_LENGTH(0, 4096) },
776 { "ftp_custom", V_TEXT(0, 2048) },
777 { "log_ftp", V_01 },
778 #endif
780 #ifdef TCONFIG_SAMBASRV
781 // nas-samba - !!TB
782 { "smbd_enable", V_RANGE(0, 2) },
783 { "smbd_wgroup", V_LENGTH(0, 20) },
784 { "smbd_cpage", V_LENGTH(0, 4) },
785 { "smbd_cset", V_LENGTH(0, 20) },
786 { "smbd_loglevel", V_RANGE(0, 100) },
787 { "smbd_custom", V_TEXT(0, 2048) },
788 { "smbd_autoshare", V_RANGE(0, 3) },
789 { "smbd_shares", V_LENGTH(0, 4096) },
790 { "smbd_user", V_LENGTH(0, 50) },
791 { "smbd_passwd", V_LENGTH(0, 50) },
792 #endif
794 // qos
795 { "qos_enable", V_01 },
796 { "qos_ack", V_01 },
797 { "qos_syn", V_01 },
798 { "qos_fin", V_01 },
799 { "qos_rst", V_01 },
800 { "qos_icmp", V_01 },
801 { "qos_reset", V_01 },
802 { "qos_obw", V_RANGE(10, 999999) },
803 { "qos_ibw", V_RANGE(10, 999999) },
804 { "qos_orules", V_LENGTH(0, 4096) },
805 { "qos_default", V_RANGE(0, 9) },
806 { "qos_pfifo", V_01 }, // !!TB
807 { "qos_irates", V_LENGTH(0, 128) },
808 { "qos_orates", V_LENGTH(0, 128) },
810 { "ne_vegas", V_01 },
811 { "ne_valpha", V_NUM },
812 { "ne_vbeta", V_NUM },
813 { "ne_vgamma", V_NUM },
817 ppp_static 0/1
818 ppp_static_ip IP
819 wl_enable 0/1
820 wl_wds_timeout
821 wl_maxassoc 1-256
822 wl_phytype a,b,g
823 wl_net_reauth
824 wl_preauth
825 wl_wme_ap_bk
826 wl_wme_ap_be
827 wl_wme_ap_vi
828 wl_wme_ap_vo
829 wl_wme_sta_bk
830 wl_wme_sta_be
831 wl_wme_sta_vi
832 wl_wme_sta_vo
834 port_priority_1 0-2
835 port_flow_control_1 0,1
836 port_rate_limit_1 0-8
837 port_priority_2 0-2
838 port_flow_control_2 0,1
839 port_rate_limit_2 0-8
840 port_priority_3 0-2
841 port_flow_control_3 0,1
842 port_rate_limit_3 0-8
843 port_priority_4 0-2
844 port_flow_control_4 0,1
845 port_rate_limit_4 0-8
846 wl_ap_ip
847 wl_ap_ssid
850 { NULL }
853 static int save_variables(int write)
855 const nvset_t *v;
856 char *p, *e;
857 int n;
858 long l;
859 unsigned u[6];
860 int ok;
861 char s[256];
862 int dirty;
863 static const char *msgf = "The field \"%s\" is invalid. Please report this problem.";
865 dirty = 0;
866 for (v = nvset_list; v->name; ++v) {
867 // _dprintf("[%s] %p\n", v->name, webcgi_get((char*)v->name));
868 if ((p = webcgi_get((char*)v->name)) == NULL) continue;
869 ok = 1;
870 switch (v->vtype) {
871 case VT_TEXT:
872 p = unix_string(p); // NOTE: p = malloc'd
873 // drop
874 case VT_LENGTH:
875 n = strlen(p);
876 if ((n < v->va.i) || (n > v->vb.i)) ok = 0;
877 break;
878 case VT_RANGE:
879 l = strtol(p, &e, 10);
880 if ((p == e) || (*e) || (l < v->va.l) || (l > v->vb.l)) ok = 0;
881 break;
882 case VT_IP:
883 if ((sscanf(p, "%3u.%3u.%3u.%3u", &u[0], &u[1], &u[2], &u[3]) != 4) ||
884 (u[0] > 255) || (u[1] > 255) || (u[2] > 255) || (u[3] > 255)) ok = 0;
885 break;
886 case VT_MAC:
887 if ((sscanf(p, "%2x:%2x:%2x:%2x:%2x:%2x", &u[0], &u[1], &u[2], &u[3], &u[4], &u[5]) != 6) ||
888 (u[0] > 255) || (u[1] > 255) || (u[2] > 255) || (u[3] > 255) || (u[4] > 255) || (u[5] > 255)) ok = 0;
889 break;
890 default:
891 // shutup gcc
892 break;
894 if (!ok) {
895 if (v->vtype == VT_TEXT) free(p);
897 sprintf(s, msgf, v->name);
898 resmsg_set(s);
899 return 0;
901 if (write) {
902 if (!nvram_match((char *)v->name, p)) {
903 if (v->vtype != VT_TEMP) dirty = 1;
904 nvram_set(v->name, p);
907 if (v->vtype == VT_TEXT) free(p);
911 // special cases
913 char *p1, *p2;
914 if (((p1 = webcgi_get("set_password_1")) != NULL) && (strcmp(p1, "**********") != 0)) {
915 if (((p2 = webcgi_get("set_password_2")) != NULL) && (strcmp(p1, p2) == 0)) {
916 if ((write) && (!nvram_match("http_passwd", p1))) {
917 dirty = 1;
918 nvram_set("http_passwd", p1);
921 else {
922 sprintf(s, msgf, "password");
923 resmsg_set(s);
924 return 0;
928 for (n = 0; n < 50; ++n) {
929 sprintf(s, "rrule%d", n);
930 if ((p = webcgi_get(s)) != NULL) {
931 if (strlen(p) > 2048) {
932 sprintf(s, msgf, s);
933 resmsg_set(s);
934 return 0;
936 if ((write) && (!nvram_match(s, p))) {
937 dirty = 1;
938 nvram_set(s, p);
943 return (write) ? dirty : 1;
946 static void wo_tomato(char *url)
948 char *v;
949 int i;
950 int ajax;
951 int nvset;
952 const char *red;
953 int commit;
955 // _dprintf("tomato.cgi\n");
957 red = webcgi_safeget("_redirect", "");
958 if (!*red) send_header(200, NULL, mime_html, 0);
960 commit = atoi(webcgi_safeget("_commit", "1"));
961 ajax = atoi(webcgi_safeget("_ajax", "0"));
963 nvset = atoi(webcgi_safeget("_nvset", "1"));
964 if (nvset) {
965 if (!save_variables(0)) {
966 if (ajax) {
967 web_printf("@msg:%s", resmsg_get());
969 else {
970 parse_asp("error.asp");
972 return;
974 commit = save_variables(1) && commit;
976 resmsg_set("Settings saved.");
979 rboot = atoi(webcgi_safeget("_reboot", "0"));
980 if (rboot) {
981 parse_asp("reboot.asp");
983 else {
984 if (ajax) {
985 web_printf("@msg:%s", resmsg_get());
987 else if (atoi(webcgi_safeget("_moveip", "0"))) {
988 parse_asp("saved-moved.asp");
990 else if (!*red) {
991 parse_asp("saved.asp");
995 if (commit) {
996 _dprintf("commit from tomato.cgi\n");
997 if (!nvram_match("debug_nocommit", "1")) {
998 nvram_commit();
1002 if ((v = webcgi_get("_service")) != NULL) {
1003 if (!*red) {
1004 if (ajax) web_printf(" Some services are being restarted...");
1005 web_close();
1007 sleep(1);
1009 if (*v == '*') {
1010 kill(1, SIGHUP);
1012 else if (*v != 0) {
1013 exec_service(v);
1017 for (i = atoi(webcgi_safeget("_sleep", "0")); i > 0; --i) sleep(1);
1019 if (*red) redirect(red);
1021 if (rboot) {
1022 web_close();
1023 sleep(1);
1024 kill(1, SIGTERM);
1029 // ----------------------------------------------------------------------------
1032 static void wo_update(char *url)
1034 const aspapi_t *api;
1035 const char *name;
1036 int argc;
1037 char *argv[16];
1038 char s[32];
1040 if ((name = webcgi_get("exec")) != NULL) {
1041 for (api = aspapi; api->name; ++api) {
1042 if (strcmp(api->name, name) == 0) {
1043 for (argc = 0; argc < 16; ++argc) {
1044 sprintf(s, "arg%d", argc);
1045 if ((argv[argc] = (char *)webcgi_get(s)) == NULL) break;
1047 api->exec(argc, argv);
1048 break;
1054 static void wo_service(char *url)
1056 int n;
1058 exec_service(webcgi_safeget("_service", ""));
1060 if ((n = atoi(webcgi_safeget("_sleep", "2"))) <= 0) n = 2;
1061 sleep(n);
1063 common_redirect();
1069 static void wo_login(char *url)
1071 const char *u;
1072 const char *p;
1074 u = webcgi_safeget("user", "");
1075 p = webcgi_safeget("pass", "");
1077 if ((*u) && (*p)) {
1078 if ((strcmp(u, "root") == 0) || (strcmp(u, "admin") == 0)) {
1079 if (strcmp(p, nvram_safe_get("http_password")) == 0) {
1080 nvram_set("web_logout", "0");
1081 common_redirect();
1082 return;
1087 web_printf("<form action='login'><input type='text' name='user'><input type='text' name='pass'></form>");
1091 #if 0
1092 void gen_sessnum(void)
1094 char s[256];
1096 sprintf(s, "%llx", (unsigned long long)time(NULL) * rand());
1097 nvram_set("web_sess", s);
1099 #endif
1101 static void wo_logout(char *url)
1103 char s[256];
1105 // doesn't work with all browsers...
1107 if (((user_agent) && (strstr(user_agent, "Opera") != NULL))) {
1108 sprintf(s, "%llx", (unsigned long long)time(NULL) * rand());
1109 send_authenticate(s);
1111 else {
1112 send_authenticate(NULL);
1115 #if 0
1116 gen_sessnum();
1117 #endif
1120 #if 0
1121 char *c;
1122 char *p;
1124 p = nvram_safe_get("web_out");
1125 c = inet_ntoa(clientsai.sin_addr);
1126 if ((c != NULL) && (!find_word(p, c))) {
1127 while (strlen(p) > 128) {
1128 p = strchr(p, ',');
1129 if (!p) break;
1130 ++p;
1132 if ((p) && (*p)) {
1133 sprintf(s, "%s,%s", p, c);
1134 nvram_set("web_out", s);
1136 else {
1137 nvram_set("web_out", c);
1139 nvram_unset("web_outx");
1141 #endif
1144 static void wo_shutdown(char *url)
1146 parse_asp("shutdown.asp");
1147 web_close();
1148 sleep(1);
1150 kill(1, SIGQUIT);
1153 static void wo_nvcommit(char *url)
1155 parse_asp("saved.asp");
1156 web_close();
1157 nvram_commit();