Merge Tomato 1.25
[tomato.git] / release / src / router / httpd / misc.c
blob9cfc36cc184389011dfbe681dca547a99328a1d7
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 #include <wlioctl.h>
27 #include <wlutils.h>
29 // to javascript-safe string
30 char *js_string(const char *s)
32 unsigned char c;
33 char *buffer;
34 char *b;
36 if ((buffer = malloc((strlen(s) * 4) + 1)) != NULL) {
37 b = buffer;
38 while ((c = *s++) != 0) {
39 if ((c == '"') || (c == '\'') || (c == '\\') || (!isprint(c))) {
40 b += sprintf(b, "\\x%02x", c);
42 else {
43 *b++ = c;
46 *b = 0;
48 return buffer;
51 // to html-safe string
52 char *html_string(const char *s)
54 unsigned char c;
55 char *buffer;
56 char *b;
58 if ((buffer = malloc((strlen(s) * 6) + 1)) != NULL) {
59 b = buffer;
60 while ((c = *s++) != 0) {
61 if ((c == '&') || (c == '<') || (c == '>') || (c == '"') || (c == '\'') || (!isprint(c))) {
62 b += sprintf(b, "&#%d;", c);
64 else {
65 *b++ = c;
68 *b = 0;
70 return buffer;
73 // removes \r
74 char *unix_string(const char *s)
76 char *buffer;
77 char *b;
78 char c;
80 if ((buffer = malloc(strlen(s) + 1)) != NULL) {
81 b = buffer;
82 while ((c = *s++) != 0)
83 if (c != '\r') *b++ = c;
84 *b = 0;
86 return buffer;
89 // # days, ##:##:##
90 char *reltime(char *buf, time_t t)
92 int days;
93 int m;
95 if (t < 0) t = 0;
96 days = t / 86400;
97 m = t / 60;
98 sprintf(buf, "%d day%s, %02d:%02d:%02d", days, ((days==1) ? "" : "s"), ((m / 60) % 24), (m % 60), (int)(t % 60));
99 return buf;
102 int get_client_info(char *mac, char *ifname)
104 FILE *f;
105 char s[256];
106 char ips[16];
109 # cat /proc/net/arp
110 IP address HW type Flags HW address Mask Device
111 192.168.0.1 0x1 0x2 00:01:02:03:04:05 * vlan1
112 192.168.1.5 0x1 0x2 00:05:06:07:08:09 * br0
115 if ((f = fopen("/proc/net/arp", "r")) != NULL) {
116 while (fgets(s, sizeof(s), f)) {
117 if (sscanf(s, "%15s %*s %*s %17s %*s %16s", ips, mac, ifname) == 3) {
118 if (inet_addr(ips) == clientsai.sin_addr.s_addr) {
119 fclose(f);
120 return 1;
124 fclose(f);
126 return 0;
133 // <% lanip(mode); %>
134 // <mode>
135 // 1 return first 3 octets (192.168.1)
136 // 2 return last octet (1)
137 // else return full (192.168.1.1)
139 void asp_lanip(int argc, char **argv)
141 char *nv, *p;
142 char s[64];
143 char mode;
145 mode = argc ? *argv[0] : 0;
147 if ((nv = nvram_get("lan_ipaddr")) != NULL) {
148 strcpy(s, nv);
149 if ((p = strrchr(s, '.')) != NULL) {
150 *p = 0;
151 web_puts((mode == '1') ? s : (mode == '2') ? (p + 1) : nv);
156 void asp_lipp(int argc, char **argv)
158 char *one = "1";
159 asp_lanip(1, &one);
162 // <% psup(process); %>
163 // returns 1 if process is running
165 void asp_psup(int argc, char **argv)
167 if (argc == 1) web_printf("%d", pidof(argv[0]) > 0);
170 void wo_vpn_status(char *url)
172 #ifdef TCONFIG_OPENVPN
173 char buf[256];
174 char *type;
175 char *str;
176 int num;
177 FILE *fp;
179 type = 0;
180 if ( str = webcgi_get("server") )
181 type = "server";
182 else if ( str = webcgi_get("client") )
183 type = "client";
185 num = str? atoi(str): 0;
186 if ( type && num > 0 )
188 // Trigger OpenVPN to update the status file
189 snprintf(&buf[0], sizeof(buf), "vpn%s%d", type, num);
190 killall(&buf[0], SIGUSR2);
192 // Give it a chance to update the file
193 sleep(1);
195 // Read the status file and repeat it verbatim to the caller
196 snprintf(&buf[0], sizeof(buf), "/etc/openvpn/%s%d/status", type, num);
197 fp = fopen(&buf[0], "r");
198 if( fp != NULL )
200 while (fgets(&buf[0], sizeof(buf), fp) != NULL)
201 web_puts(&buf[0]);
202 fclose(fp);
205 #endif
209 # cat /proc/meminfo
210 total: used: free: shared: buffers: cached:
211 Mem: 14872576 12877824 1994752 0 1236992 4837376
212 Swap: 0 0 0
213 MemTotal: 14524 kB
214 MemFree: 1948 kB
215 MemShared: 0 kB
216 Buffers: 1208 kB
217 Cached: 4724 kB
218 SwapCached: 0 kB
219 Active: 4364 kB
220 Inactive: 2952 kB
221 HighTotal: 0 kB
222 HighFree: 0 kB
223 LowTotal: 14524 kB
224 LowFree: 1948 kB
225 SwapTotal: 0 kB
226 SwapFree: 0 kB
230 typedef struct {
231 unsigned long total;
232 unsigned long free;
233 unsigned long shared;
234 unsigned long buffers;
235 unsigned long cached;
236 unsigned long swaptotal;
237 unsigned long swapfree;
238 unsigned long maxfreeram;
239 } meminfo_t;
241 static int get_memory(meminfo_t *m)
243 FILE *f;
244 char s[128];
245 int ok = 0;
247 if ((f = fopen("/proc/meminfo", "r")) != NULL) {
248 while (fgets(s, sizeof(s), f)) {
249 if (strncmp(s, "Mem:", 4) == 0) {
250 if (sscanf(s + 6, "%ld %*d %ld %ld %ld %ld", &m->total, &m->free, &m->shared, &m->buffers, &m->cached) == 5)
251 ++ok;
253 else if (strncmp(s, "SwapTotal:", 10) == 0) {
254 m->swaptotal = strtoul(s + 12, NULL, 10) * 1024;
255 ++ok;
257 else if (strncmp(s, "SwapFree:", 9) == 0) {
258 m->swapfree = strtoul(s + 11, NULL, 10) * 1024;
259 ++ok;
260 break;
263 fclose(f);
265 if (ok != 3) {
266 memset(m, 0, sizeof(*m));
267 return 0;
269 m->maxfreeram = m->free;
270 if (nvram_match("t_cafree", "1")) m->maxfreeram += m->cached;
271 return 1;
274 void asp_sysinfo(int argc, char **argv)
276 struct sysinfo si;
277 char s[64];
278 meminfo_t mem;
280 web_puts("\nsysinfo = {\n");
281 sysinfo(&si);
282 get_memory(&mem);
283 web_printf(
284 "\tuptime: %ld,\n"
285 "\tuptime_s: '%s',\n"
286 "\tloads: [%ld, %ld, %ld],\n"
287 "\ttotalram: %ld,\n"
288 "\tfreeram: %ld,\n"
289 "\tshareram: %ld,\n"
290 "\tbufferram: %ld,\n"
291 "\tcached: %ld,\n"
292 "\ttotalswap: %ld,\n"
293 "\tfreeswap: %ld,\n"
294 "\ttotalfreeram: %ld,\n"
295 "\tprocs: %d\n",
296 si.uptime,
297 reltime(s, si.uptime),
298 si.loads[0], si.loads[1], si.loads[2],
299 mem.total, mem.free,
300 mem.shared, mem.buffers, mem.cached,
301 mem.swaptotal, mem.swapfree,
302 mem.maxfreeram,
303 si.procs);
304 web_puts("};\n");
307 void asp_activeroutes(int argc, char **argv)
309 FILE *f;
310 char s[512];
311 char dev[17];
312 unsigned long dest;
313 unsigned long gateway;
314 unsigned long flags;
315 unsigned long mask;
316 unsigned metric;
317 struct in_addr ia;
318 char s_dest[16];
319 char s_gateway[16];
320 char s_mask[16];
321 int n;
323 web_puts("\nactiveroutes = [");
324 n = 0;
325 if ((f = fopen("/proc/net/route", "r")) != NULL) {
326 while (fgets(s, sizeof(s), f)) {
327 if (sscanf(s, "%16s%lx%lx%lx%*s%*s%u%lx", dev, &dest, &gateway, &flags, &metric, &mask) != 6) continue;
328 if ((flags & RTF_UP) == 0) continue;
329 if (dest != 0) {
330 ia.s_addr = dest;
331 strcpy(s_dest, inet_ntoa(ia));
333 else {
334 strcpy(s_dest, "default");
336 if (gateway != 0) {
337 ia.s_addr = gateway;
338 strcpy(s_gateway, inet_ntoa(ia));
340 else {
341 strcpy(s_gateway, "*");
343 ia.s_addr = mask;
344 strcpy(s_mask, inet_ntoa(ia));
345 web_printf("%s['%s','%s','%s','%s',%u]", n ? "," : "", dev, s_dest, s_gateway, s_mask, metric);
346 ++n;
348 fclose(f);
350 web_puts("];\n");
353 void asp_cgi_get(int argc, char **argv)
355 const char *v;
356 int i;
358 for (i = 0; i < argc; ++i) {
359 v = webcgi_get(argv[i]);
360 if (v) web_puts(v);
364 void asp_time(int argc, char **argv)
366 time_t t;
367 char s[64];
369 t = time(NULL);
370 if (t < Y2K) {
371 web_puts("Not Available");
373 else {
374 strftime(s, sizeof(s), "%a, %d %b %Y %H:%M:%S %z", localtime(&t));
375 web_puts(s);
379 void asp_wanup(int argc, char **argv)
381 web_puts(check_wanup() ? "1" : "0");
384 void asp_wanstatus(int argc, char **argv)
386 const char *p;
388 if ((using_dhcpc()) && (f_exists("/var/lib/misc/dhcpc.renewing"))) {
389 p = "Renewing...";
391 else if (check_wanup()) {
392 p = "Connected";
394 else if (f_exists("/var/lib/misc/wan.connecting")) {
395 p = "Connecting...";
397 else {
398 p = "Disconnected";
400 web_puts(p);
403 void asp_link_uptime(int argc, char **argv)
405 struct sysinfo si;
406 char buf[64];
407 long uptime;
409 buf[0] = '-';
410 buf[1] = 0;
411 if (check_wanup()) {
412 sysinfo(&si);
413 if (f_read("/var/lib/misc/wantime", &uptime, sizeof(uptime)) == sizeof(uptime)) {
414 reltime(buf, si.uptime - uptime);
417 web_puts(buf);
420 void asp_bandwidth(int argc, char **argv)
422 char *name;
423 int sig;
425 if ((nvram_match("rstats_enable", "1")) && (argc == 1)) {
426 if (strcmp(argv[0], "speed") == 0) {
427 sig = SIGUSR1;
428 name = "/var/spool/rstats-speed.js";
430 else {
431 sig = SIGUSR2;
432 name = "/var/spool/rstats-history.js";
434 unlink(name);
435 killall("rstats", sig);
436 f_wait_exists(name, 5);
437 do_file(name);
438 unlink(name);
442 void asp_rrule(int argc, char **argv)
444 char s[32];
445 int i;
447 i = nvram_get_int("rruleN");
448 sprintf(s, "rrule%d", i);
449 web_puts("\nrrule = '");
450 web_putj(nvram_safe_get(s));
451 web_printf("';\nrruleN = %d;\n", i);
454 void asp_compmac(int argc, char **argv)
456 char mac[32];
457 char ifname[32];
459 if (get_client_info(mac, ifname)) {
460 web_puts(mac);
464 void asp_ident(int argc, char **argv)
466 web_puth(nvram_safe_get("router_name"));
469 void asp_statfs(int argc, char **argv)
471 struct statfs sf;
473 if (argc != 2) return;
475 // used for /cifs/, /jffs/... if it returns squashfs type, assume it's not mounted
476 if ((statfs(argv[0], &sf) != 0) || (sf.f_type == 0x73717368))
477 memset(&sf, 0, sizeof(sf));
479 web_printf(
480 "\n%s = {\n"
481 "\tsize: %llu,\n"
482 "\tfree: %llu\n"
483 "};\n",
484 argv[1],
485 ((uint64_t)sf.f_bsize * sf.f_blocks),
486 ((uint64_t)sf.f_bsize * sf.f_bfree));
489 void asp_notice(int argc, char **argv)
491 char s[256];
492 char buf[2048];
494 if (argc != 1) return;
495 snprintf(s, sizeof(s), "/var/notice/%s", argv[0]);
496 if (f_read_string(s, buf, sizeof(buf)) <= 0) return;
497 web_putj(buf);
500 void wo_wakeup(char *url)
502 char *mac;
503 char *p;
504 char *end;
506 if ((mac = webcgi_get("mac")) != NULL) {
507 end = mac + strlen(mac);
508 while (mac < end) {
509 while ((*mac == ' ') || (*mac == '\t') || (*mac == '\r') || (*mac == '\n')) ++mac;
510 if (*mac == 0) break;
512 p = mac;
513 while ((*p != 0) && (*p != ' ') && (*p != '\r') && (*p != '\n')) ++p;
514 *p = 0;
516 eval("ether-wake", "-i", nvram_safe_get("lan_ifname"), mac);
517 mac = p + 1;
520 common_redirect();
523 void asp_dns(int argc, char **argv)
525 char s[128];
526 int i;
527 const dns_list_t *dns;
529 dns = get_dns(); // static buffer
530 strcpy(s, "\ndns = [");
531 for (i = 0 ; i < dns->count; ++i) {
532 sprintf(s + strlen(s), "%s'%s'", i ? "," : "", inet_ntoa(dns->dns[i]));
534 strcat(s, "];\n");
535 web_puts(s);
538 void wo_resolve(char *url)
540 char *p;
541 char *ip;
542 struct hostent *he;
543 struct in_addr ia;
544 char comma;
545 char *js;
547 comma = ' ';
548 web_puts("\nresolve_data = [\n");
549 if ((p = webcgi_get("ip")) != NULL) {
550 while ((ip = strsep(&p, ",")) != NULL) {
551 ia.s_addr = inet_addr(ip);
552 he = gethostbyaddr(&ia, sizeof(ia), AF_INET);
553 js = js_string(he ? he->h_name : "");
554 web_printf("%c['%s','%s']", comma, inet_ntoa(ia), js);
555 free(js);
556 comma = ',';
559 web_puts("];\n");