4G/LTE - add watchdog and more
[tomato.git] / release / src / router / httpd / misc.c
bloba9c44ac8d70cbdfff7232e848ec533e849d977a3
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
8 #include "tomato.h"
10 #include <ctype.h>
11 #include <sys/sysinfo.h>
12 #include <sys/stat.h>
13 #include <sys/ioctl.h>
14 #include <net/if.h>
15 #include <fcntl.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <sys/types.h>
20 #include <dirent.h>
21 #include <time.h>
22 #include <sys/statfs.h>
23 #include <netdb.h>
24 #include <net/route.h>
26 #ifdef TCONFIG_IPV6
27 #include <ifaddrs.h>
28 #endif
30 #include <wlioctl.h>
31 #include <wlutils.h>
33 // to javascript-safe string
34 char *js_string(const char *s)
36 unsigned char c;
37 char *buffer;
38 char *b;
40 if ((buffer = malloc((strlen(s) * 4) + 1)) != NULL) {
41 b = buffer;
42 while ((c = *s++) != 0) {
43 if ((c == '"') || (c == '\'') || (c == '\\') || (!isprint(c))) {
44 b += sprintf(b, "\\x%02x", c);
46 else {
47 *b++ = c;
50 *b = 0;
52 return buffer;
55 // to html-safe string
56 char *html_string(const char *s)
58 unsigned char c;
59 char *buffer;
60 char *b;
62 if ((buffer = malloc((strlen(s) * 6) + 1)) != NULL) {
63 b = buffer;
64 while ((c = *s++) != 0) {
65 if ((c == '&') || (c == '<') || (c == '>') || (c == '"') || (c == '\'') || (!isprint(c))) {
66 b += sprintf(b, "&#%d;", c);
68 else {
69 *b++ = c;
72 *b = 0;
74 return buffer;
77 // removes \r
78 char *unix_string(const char *s)
80 char *buffer;
81 char *b;
82 char c;
84 if ((buffer = malloc(strlen(s) + 1)) != NULL) {
85 b = buffer;
86 while ((c = *s++) != 0)
87 if (c != '\r') *b++ = c;
88 *b = 0;
90 return buffer;
93 // # days, ##:##:##
94 char *reltime(char *buf, time_t t)
96 int days;
97 int m;
99 if (t < 0) t = 0;
100 days = t / 86400;
101 m = t / 60;
102 sprintf(buf, "%d day%s, %02d:%02d:%02d", days, ((days==1) ? "" : "s"), ((m / 60) % 24), (m % 60), (int)(t % 60));
103 return buf;
106 int get_client_info(char *mac, char *ifname)
108 FILE *f;
109 char s[256];
110 #ifdef TCONFIG_IPV6
111 char ip[INET6_ADDRSTRLEN];
112 #else
113 char ip[INET_ADDRSTRLEN];
114 #endif
117 # ip neigh show fe80:0:0::201:02ff:fe03:0405
118 fe80::201:2ff:fe3:405 dev br0 lladdr 00:01:02:03:04:05 REACHABLE
120 if (clientsai.ss_family == AF_INET) {
121 inet_ntop(clientsai.ss_family, &(((struct sockaddr_in*)&clientsai)->sin_addr), ip, sizeof(ip));
122 sprintf(s, "ip neigh show %s", ip);
124 #ifdef TCONFIG_IPV6
125 else if (clientsai.ss_family == AF_INET6) {
126 inet_ntop(clientsai.ss_family, &(((struct sockaddr_in6*)&clientsai)->sin6_addr), ip, sizeof(ip));
127 if (IN6_IS_ADDR_V4MAPPED( &(((struct sockaddr_in6*)&clientsai)->sin6_addr) ))
128 sprintf(s, "ip neigh show %s", ip + 7); // chop off the ::ffff: to get the ipv4 bit
129 else
130 sprintf(s, "ip neigh show %s", ip);
132 #endif
134 if ((f = popen(s, "r")) != NULL) {
135 while (fgets(s, sizeof(s), f)) {
136 if (sscanf(s, "%*s dev %16s lladdr %17s %*s", ifname, mac) == 2) {
137 pclose(f);
138 return 1;
141 pclose(f);
143 return 0;
147 // <% lanip(mode); %>
148 // <mode>
149 // 1 return first 3 octets (192.168.1)
150 // 2 return last octet (1)
151 // else return full (192.168.1.1)
153 void asp_lanip(int argc, char **argv)
155 char *nv, *p;
156 char s[64];
157 char mode;
159 mode = argc ? *argv[0] : 0;
161 if ((nv = nvram_get("lan_ipaddr")) != NULL) {
162 strcpy(s, nv);
163 if ((p = strrchr(s, '.')) != NULL) {
164 *p = 0;
165 web_puts((mode == '1') ? s : (mode == '2') ? (p + 1) : nv);
170 void asp_lipp(int argc, char **argv)
172 char *one = "1";
173 asp_lanip(1, &one);
176 // <% psup(process); %>
177 // returns 1 if process is running
179 void asp_psup(int argc, char **argv)
181 if (argc == 1) web_printf("%d", pidof(argv[0]) > 0);
184 void wo_vpn_status(char *url)
186 #ifdef TCONFIG_OPENVPN
187 char buf[256];
188 char *type;
189 char *str;
190 int num;
191 FILE *fp;
193 type = 0;
194 if ( (str = webcgi_get("server")) )
195 type = "server";
196 else if ( (str = webcgi_get("client")) )
197 type = "client";
199 num = str? atoi(str): 0;
200 if ( type && num > 0 )
202 // Trigger OpenVPN to update the status file
203 snprintf(&buf[0], sizeof(buf), "vpn%s%d", type, num);
204 killall(&buf[0], SIGUSR2);
206 // Give it a chance to update the file
207 sleep(1);
209 // Read the status file and repeat it verbatim to the caller
210 snprintf(&buf[0], sizeof(buf), "/etc/openvpn/%s%d/status", type, num);
211 fp = fopen(&buf[0], "r");
212 if( fp != NULL )
214 while (fgets(&buf[0], sizeof(buf), fp) != NULL)
215 web_puts(&buf[0]);
216 fclose(fp);
219 #endif
223 # cat /proc/meminfo
224 total: used: free: shared: buffers: cached:
225 Mem: 14872576 12877824 1994752 0 1236992 4837376
226 Swap: 0 0 0
227 MemTotal: 14524 kB
228 MemFree: 1948 kB
229 MemShared: 0 kB
230 Buffers: 1208 kB
231 Cached: 4724 kB
232 SwapCached: 0 kB
233 Active: 4364 kB
234 Inactive: 2952 kB
235 HighTotal: 0 kB
236 HighFree: 0 kB
237 LowTotal: 14524 kB
238 LowFree: 1948 kB
239 SwapTotal: 0 kB
240 SwapFree: 0 kB
244 typedef struct {
245 unsigned long total;
246 unsigned long free;
247 unsigned long shared;
248 unsigned long buffers;
249 unsigned long cached;
250 unsigned long swaptotal;
251 unsigned long swapfree;
252 unsigned long maxfreeram;
253 } meminfo_t;
255 static int get_memory(meminfo_t *m)
257 FILE *f;
258 char s[128];
259 int ok = 0;
261 memset(m, 0, sizeof(*m));
262 if ((f = fopen("/proc/meminfo", "r")) != NULL) {
263 while (fgets(s, sizeof(s), f)) {
264 #ifdef LINUX26
265 if (strncmp(s, "MemTotal:", 9) == 0) {
266 m->total = strtoul(s + 12, NULL, 10) * 1024;
267 ++ok;
269 else if (strncmp(s, "MemFree:", 8) == 0) {
270 m->free = strtoul(s + 12, NULL, 10) * 1024;
271 ++ok;
273 else if (strncmp(s, "Buffers:", 8) == 0) {
274 m->buffers = strtoul(s + 12, NULL, 10) * 1024;
275 ++ok;
277 else if (strncmp(s, "Cached:", 7) == 0) {
278 m->cached = strtoul(s + 12, NULL, 10) * 1024;
279 ++ok;
281 #else
282 if (strncmp(s, "Mem:", 4) == 0) {
283 if (sscanf(s + 6, "%ld %*d %ld %ld %ld %ld", &m->total, &m->free, &m->shared, &m->buffers, &m->cached) == 5)
284 ++ok;
286 #endif
287 else if (strncmp(s, "SwapTotal:", 10) == 0) {
288 m->swaptotal = strtoul(s + 12, NULL, 10) * 1024;
289 ++ok;
291 else if (strncmp(s, "SwapFree:", 9) == 0) {
292 m->swapfree = strtoul(s + 11, NULL, 10) * 1024;
293 ++ok;
294 #ifndef LINUX26
295 break;
296 #endif
299 fclose(f);
301 if (ok == 0) {
302 return 0;
304 m->maxfreeram = m->free;
305 if (nvram_match("t_cafree", "1")) m->maxfreeram += (m->cached + m->buffers);
306 return 1;
309 #ifdef TCONFIG_IPV6
310 #define IP6ADDR_MAX_CNT 3 // wan, lan, lan-ll
311 static void print_ipv6_addrs(void)
313 char buf[INET6_ADDRSTRLEN];
314 int found;
315 char *addrtype;
316 struct ifaddrs *ifap, *ifa;
317 struct sockaddr_in6 *s6;
319 if (!ipv6_enabled() || (getifaddrs(&ifap) != 0))
320 return;
322 found = 0;
323 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
324 if ((ifa->ifa_addr == NULL) || (ifa->ifa_addr->sa_family != AF_INET6))
325 continue;
327 s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
329 if (strncmp(ifa->ifa_name, nvram_safe_get("lan_ifname"), IFNAMSIZ) == 0) {
330 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
331 addrtype = "lan_ll";
332 else
333 addrtype = "lan";
335 else if (strncmp(ifa->ifa_name, get_wan6face(), IFNAMSIZ) == 0) {
336 if (!IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
337 addrtype = "wan";
338 else
339 continue;
341 else
342 continue;
344 if (inet_ntop(ifa->ifa_addr->sa_family, &(s6->sin6_addr), buf, sizeof(buf)) != NULL) {
345 web_printf("\tip6_%s: '%s',\n",
346 addrtype, buf);
347 if (++found >= IP6ADDR_MAX_CNT)
348 break;
351 freeifaddrs(ifap);
355 void asp_calc6rdlocalprefix(int argc, char **argv)
357 struct in6_addr prefix_addr, local_prefix_addr;
358 int prefix_len = 0, relay_prefix_len = 0, local_prefix_len = 0;
359 struct in_addr wanip_addr;
360 char local_prefix[INET6_ADDRSTRLEN];
361 char s[128];
363 if (argc != 3) return;
365 inet_pton(AF_INET6, argv[0], &prefix_addr);
366 prefix_len = atoi(argv[1]);
367 relay_prefix_len = atoi(argv[2]);
368 inet_pton(AF_INET, get_wanip(), &wanip_addr);
370 if (calc_6rd_local_prefix(&prefix_addr, prefix_len, relay_prefix_len,
371 &wanip_addr, &local_prefix_addr, &local_prefix_len) &&
372 inet_ntop(AF_INET6, &local_prefix_addr, local_prefix, sizeof(local_prefix)) != NULL) {
373 sprintf(s, "\nlocal_prefix = '%s/%d';\n", local_prefix, local_prefix_len);
374 web_puts(s);
377 #endif
379 int get_flashsize()
382 # cat /proc/mtd
383 dev: size erasesize name
384 mtd0: 00020000 00010000 "pmon"
385 mtd1: 007d0000 00010000 "linux"
387 FILE *f;
388 char s[512];
389 unsigned int size;
390 char partname[16];
391 int found = 0;
393 if ((f = fopen("/proc/mtd", "r")) != NULL) {
394 while (fgets(s, sizeof(s), f)) {
395 if (sscanf(s, "%*s %X %*s %16s", &size, partname) != 2) continue;
396 if (strcmp(partname, "\"linux\"") == 0) {
397 found = 1;
398 break;
401 fclose(f);
403 if (found) {
404 if ((size > 0x2000000) && (size < 0x4000000)) return 64;
405 else if ((size > 0x1000000) && (size < 0x2000000)) return 32;
406 else if ((size > 0x800000) && (size < 0x1000000)) return 16;
407 else if ((size > 0x400000) && (size < 0x800000)) return 8;
408 else if ((size > 0x200000) && (size < 0x400000)) return 4;
409 else if ((size > 0x100000) && (size < 0x200000)) return 2;
410 else return 1;
412 else {
413 return 0;
417 void asp_etherstates(int argc, char **argv)
419 FILE *f;
420 char s[32], *a, b[16];
421 unsigned n;
423 if (nvram_match("lan_state", "1")) {
425 web_puts("\netherstates = {");
427 system("/usr/sbin/ethstate");
428 n = 0;
429 if ((f = fopen("/tmp/ethernet.state", "r")) != NULL) {
430 while (fgets(s, sizeof(s), f)) {
431 if (sscanf(s, "Port 0: %s", b) == 1) a="port0";
432 else if (sscanf(s, "Port 1: %s", b) == 1) a="port1";
433 else if (sscanf(s, "Port 2: %s", b) == 1) a="port2";
434 else if (sscanf(s, "Port 3: %s", b) == 1) a="port3";
435 else if (sscanf(s, "Port 4: %s", b) == 1) a="port4";
436 else continue;
438 web_printf("%s\t%s: '%s'", n ? ",\n" : "", a, b);
439 n++;
441 fclose(f);
443 web_puts("\n};\n");
444 } else {
445 web_puts("\netherstates = {\tport0: 'disabled'\n};\n");
449 void asp_anonupdate(int argc, char **argv)
451 FILE *f;
452 char s[32], *a, b[16];
453 unsigned n;
455 if ( nvram_match("tomatoanon_answer", "1") && nvram_match("tomatoanon_enable", "1") && nvram_match("tomatoanon_notify", "1") ) {
457 web_puts("\nanonupdate = {");
459 n = 0;
460 if ((f = fopen("/tmp/anon.version", "r")) != NULL) {
461 while (fgets(s, sizeof(s), f)) {
462 if (sscanf(s, "have_update=%s", b) == 1) a="update";
463 else continue;
465 web_printf("%s\t%s: '%s'", n ? ",\n" : "", a, b);
466 n++;
468 fclose(f);
470 web_puts("\n};\n");
471 } else {
472 web_puts("\nanonupdate = {\tupdate: 'no'\n};\n");
476 void asp_sysinfo(int argc, char **argv)
478 struct sysinfo si;
479 char s[64];
480 meminfo_t mem;
482 char system_type[64];
483 char cpu_model[64];
484 char bogomips[8];
485 char cpuclk[8];
487 get_cpuinfo(system_type, cpu_model, bogomips, cpuclk);
489 web_puts("\nsysinfo = {\n");
491 #ifdef TCONFIG_IPV6
492 print_ipv6_addrs();
493 #endif
494 sysinfo(&si);
495 get_memory(&mem);
496 web_printf(
497 "\tuptime: %ld,\n"
498 "\tuptime_s: '%s',\n"
499 "\tloads: [%ld, %ld, %ld],\n"
500 "\ttotalram: %ld,\n"
501 "\tfreeram: %ld,\n"
502 "\tshareram: %ld,\n"
503 "\tbufferram: %ld,\n"
504 "\tcached: %ld,\n"
505 "\ttotalswap: %ld,\n"
506 "\tfreeswap: %ld,\n"
507 "\ttotalfreeram: %ld,\n"
508 "\tprocs: %d,\n"
509 "\tflashsize: %d,\n"
510 "\tsystemtype: '%s',\n"
511 "\tcpumodel: '%s',\n"
512 "\tbogomips: '%s',\n"
513 "\tcpuclk: '%s'",
514 si.uptime,
515 reltime(s, si.uptime),
516 si.loads[0], si.loads[1], si.loads[2],
517 mem.total, mem.free,
518 mem.shared, mem.buffers, mem.cached,
519 mem.swaptotal, mem.swapfree,
520 mem.maxfreeram,
521 si.procs,
522 get_flashsize(),
523 system_type,
524 cpu_model,
525 bogomips,
526 cpuclk);
528 web_puts("};\n");
531 void asp_activeroutes(int argc, char **argv)
533 FILE *f;
534 char s[512];
535 char dev[17];
536 unsigned long dest;
537 unsigned long gateway;
538 unsigned long flags;
539 unsigned long mask;
540 unsigned metric;
541 struct in_addr ia;
542 char s_dest[16];
543 char s_gateway[16];
544 char s_mask[16];
545 int n;
547 web_puts("\nactiveroutes = [");
548 n = 0;
549 if ((f = fopen("/proc/net/route", "r")) != NULL) {
550 while (fgets(s, sizeof(s), f)) {
551 if (sscanf(s, "%16s%lx%lx%lx%*s%*s%u%lx", dev, &dest, &gateway, &flags, &metric, &mask) != 6) continue;
552 if ((flags & RTF_UP) == 0) continue;
553 if (dest != 0) {
554 ia.s_addr = dest;
555 strcpy(s_dest, inet_ntoa(ia));
557 else {
558 strcpy(s_dest, "default");
560 if (gateway != 0) {
561 ia.s_addr = gateway;
562 strcpy(s_gateway, inet_ntoa(ia));
564 else {
565 strcpy(s_gateway, "*");
567 ia.s_addr = mask;
568 strcpy(s_mask, inet_ntoa(ia));
569 web_printf("%s['%s','%s','%s','%s',%u]", n ? "," : "", dev, s_dest, s_gateway, s_mask, metric);
570 ++n;
572 fclose(f);
575 #ifdef TCONFIG_IPV6
576 int pxlen;
577 char addr6x[80];
578 struct sockaddr_in6 snaddr6;
579 char addr6[40], nhop6[40];
581 if ((ipv6_enabled()) &&
582 (f = fopen("/proc/net/ipv6_route", "r")) != NULL) {
583 while (fgets(s, sizeof(s), f)) {
584 if (sscanf(s, "%32s%x%*s%*s%32s%x%*s%*s%lx%s\n",
585 addr6x+14, &pxlen, addr6x+40+7, &metric, &flags, dev) != 6) continue;
587 if ((flags & RTF_UP) == 0) continue;
589 int i = 0;
590 char *p = addr6x+14;
591 do {
592 if (!*p) {
593 if (i == 40) { // nul terminator for 1st address?
594 addr6x[39] = 0; // Fixup... need 0 instead of ':'.
595 ++p; // Skip and continue.
596 continue;
598 goto OUT;
600 addr6x[i++] = *p++;
601 if (!((i+1) % 5)) {
602 addr6x[i++] = ':';
604 } while (i < 40+28+7);
606 inet_pton(AF_INET6, addr6x, (struct sockaddr *) &snaddr6.sin6_addr);
607 if (IN6_IS_ADDR_UNSPECIFIED(&snaddr6.sin6_addr))
608 strcpy(addr6, "default");
609 else
610 inet_ntop(AF_INET6, &snaddr6.sin6_addr, addr6, sizeof(addr6));
612 inet_pton(AF_INET6, addr6x + 40, (struct sockaddr *) &snaddr6.sin6_addr);
613 if (IN6_IS_ADDR_UNSPECIFIED(&snaddr6.sin6_addr))
614 strcpy(nhop6, "*");
615 else
616 inet_ntop(AF_INET6, &snaddr6.sin6_addr, nhop6, sizeof(nhop6));
618 web_printf("%s['%s','%s','%s','%d',%u]", n ? "," : "", dev, addr6, nhop6, pxlen, metric);
619 ++n;
621 OUT:
622 fclose(f);
624 #endif
626 web_puts("];\n");
629 void asp_cgi_get(int argc, char **argv)
631 const char *v;
632 int i;
634 for (i = 0; i < argc; ++i) {
635 v = webcgi_get(argv[i]);
636 if (v) web_puts(v);
640 void asp_time(int argc, char **argv)
642 time_t t;
643 char s[64];
645 t = time(NULL);
646 if (t < Y2K) {
647 web_puts("Not Available");
649 else {
650 strftime(s, sizeof(s), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
651 web_puts(s);
655 #ifdef TCONFIG_SDHC
656 void asp_mmcid(int argc, char **argv) {
657 FILE *f;
658 char s[32], *a, b[16];
659 unsigned n, size;
661 web_puts("\nmmcid = {");
662 n = 0;
663 if ((f = fopen("/proc/mmc/status", "r")) != NULL) {
664 while (fgets(s, sizeof(s), f)) {
665 size=1;
666 if (sscanf(s, "Card Type : %16s", b) == 1) a="type";
667 else if (sscanf(s, "Spec Version : %16s", b) == 1) a="spec";
668 else if (sscanf(s, "Num. of Blocks : %d", &size) == 1) { a="size"; snprintf(b,sizeof(b),"%lld",((unsigned long long)size)*512); }
669 else if (sscanf(s, "Voltage Range : %16s", b) == 1) a="volt";
670 else if (sscanf(s, "Manufacture ID : %16s", b) == 1) a="manuf";
671 else if (sscanf(s, "Application ID : %16s", b) == 1) a="appl";
672 else if (sscanf(s, "Product Name : %16s", b) == 1) a="prod";
673 else if (sscanf(s, "Revision : %16s", b) == 1) a="rev";
674 else if (sscanf(s, "Serial Number : %16s", b) == 1) a="serial";
675 else if (sscanf(s, "Manu. Date : %8c", b) == 1) { a="date"; b[9]=0; }
676 else continue;
677 web_printf(size==1 ? "%s\t%s: '%s'" : "%s\t%s: %s", n ? ",\n" : "", a, b);
678 n++;
680 fclose(f);
682 web_puts("\n};\n");
684 #endif
686 void asp_wanup(int argc, char **argv)
688 web_puts(check_wanup() ? "1" : "0");
691 void asp_wanstatus(int argc, char **argv)
693 const char *p;
695 if ((using_dhcpc()) && (f_exists("/var/lib/misc/dhcpc.renewing"))) {
696 p = "Renewing...";
698 else if (check_wanup()) {
699 p = "Connected";
701 else if (f_exists("/var/lib/misc/wan.connecting")) {
702 p = "Connecting...";
704 else {
705 p = "Disconnected";
707 web_puts(p);
710 void asp_link_uptime(int argc, char **argv)
712 struct sysinfo si;
713 char buf[64];
714 long uptime;
716 buf[0] = '-';
717 buf[1] = 0;
718 if (check_wanup()) {
719 sysinfo(&si);
720 if (f_read("/var/lib/misc/wantime", &uptime, sizeof(uptime)) == sizeof(uptime)) {
721 reltime(buf, si.uptime - uptime);
724 web_puts(buf);
727 void asp_rrule(int argc, char **argv)
729 char s[32];
730 int i;
732 i = nvram_get_int("rruleN");
733 sprintf(s, "rrule%d", i);
734 web_puts("\nrrule = '");
735 web_putj(nvram_safe_get(s));
736 web_printf("';\nrruleN = %d;\n", i);
739 void asp_compmac(int argc, char **argv)
741 char mac[32];
742 char ifname[32];
744 if (get_client_info(mac, ifname)) {
745 web_puts(mac);
749 void asp_ident(int argc, char **argv)
751 web_puth(nvram_safe_get("router_name"));
754 void asp_statfs(int argc, char **argv)
756 struct statfs sf;
757 int mnt;
759 if (argc != 2) return;
761 // used for /cifs/, /jffs/... if it returns squashfs type, assume it's not mounted
762 if ((statfs(argv[0], &sf) != 0) || (sf.f_type == 0x73717368)) {
763 mnt = 0;
764 memset(&sf, 0, sizeof(sf));
765 #ifdef TCONFIG_JFFS2
766 // for jffs, try to get total size from mtd partition
767 if (strncmp(argv[1], "jffs", 4) == 0) {
768 int part;
770 if (mtd_getinfo(argv[1], &part, (int *)&sf.f_blocks)) {
771 sf.f_bsize = 1;
774 #endif
776 else {
777 mnt = 1;
780 web_printf(
781 "\n%s = {\n"
782 "\tmnt: %d,\n"
783 "\tsize: %llu,\n"
784 "\tfree: %llu\n"
785 "};\n",
786 argv[1], mnt,
787 ((uint64_t)sf.f_bsize * sf.f_blocks),
788 ((uint64_t)sf.f_bsize * sf.f_bfree));
791 void asp_notice(int argc, char **argv)
793 char s[256];
794 char buf[2048];
796 if (argc != 1) return;
797 snprintf(s, sizeof(s), "/var/notice/%s", argv[0]);
798 if (f_read_string(s, buf, sizeof(buf)) <= 0) return;
799 web_putj(buf);
802 void wo_wakeup(char *url)
804 char *mac;
805 char *p;
806 char *end;
808 if ((mac = webcgi_get("mac")) != NULL) {
809 end = mac + strlen(mac);
810 while (mac < end) {
811 while ((*mac == ' ') || (*mac == '\t') || (*mac == '\r') || (*mac == '\n')) ++mac;
812 if (*mac == 0) break;
814 p = mac;
815 while ((*p != 0) && (*p != ' ') && (*p != '\r') && (*p != '\n')) ++p;
816 *p = 0;
818 eval("ether-wake", "-b", "-i", nvram_safe_get("lan_ifname"), mac);
819 if (strcmp(nvram_safe_get("lan1_ifname"), "") != 0)
820 eval("ether-wake", "-b", "-i", nvram_safe_get("lan1_ifname"), mac);
821 if (strcmp(nvram_safe_get("lan2_ifname"), "") != 0)
822 eval("ether-wake", "-b", "-i", nvram_safe_get("lan2_ifname"), mac);
823 if (strcmp(nvram_safe_get("lan3_ifname"), "") != 0)
824 eval("ether-wake", "-b", "-i", nvram_safe_get("lan3_ifname"), mac);
825 mac = p + 1;
828 common_redirect();
831 void asp_dns(int argc, char **argv)
833 char s[128];
834 int i;
835 const dns_list_t *dns;
837 dns = get_dns(); // static buffer
838 strcpy(s, "\ndns = [");
839 for (i = 0 ; i < dns->count; ++i) {
840 sprintf(s + strlen(s), "%s'%s:%u'", i ? "," : "", inet_ntoa(dns->dns[i].addr), dns->dns[i].port);
842 strcat(s, "];\n");
843 web_puts(s);
846 int resolve_addr(const char *ip, char *host)
848 struct addrinfo hints;
849 struct addrinfo *res;
850 int ret;
852 memset(&hints, 0, sizeof(hints));
853 hints.ai_family = AF_UNSPEC;
854 hints.ai_socktype = SOCK_STREAM;
856 ret = getaddrinfo(ip, NULL, &hints, &res);
857 if (ret == 0) {
858 ret = getnameinfo(res->ai_addr, res->ai_addrlen, host, NI_MAXHOST, NULL, 0, 0);
859 freeaddrinfo(res);
861 return ret;
864 void wo_resolve(char *url)
866 char *p;
867 char *ip;
868 char host[NI_MAXHOST];
869 char comma;
870 char *js;
872 comma = ' ';
873 web_puts("\nresolve_data = [\n");
874 if ((p = webcgi_get("ip")) != NULL) {
875 while ((ip = strsep(&p, ",")) != NULL) {
876 if (resolve_addr(ip, host) != 0) continue;
877 js = js_string(host);
878 web_printf("%c['%s','%s']", comma, ip, js);
879 free(js);
880 comma = ',';
883 web_puts("];\n");