4 Copyright (C) 2006-2008 Jonathan Zarate
15 #include <sys/ioctl.h>
17 #include <sys/socket.h>
18 #include <arpa/inet.h>
19 #include <sys/sysinfo.h>
29 #define _dprintf cprintf
31 #define _dprintf(args...) do { } while(0)
35 int get_wan_proto(void)
37 const char *names
[] = { // order must be synced with def at shared.h
49 p
= nvram_safe_get("wan_proto");
50 for (i
= 0; names
[i
] != NULL
; ++i
) {
51 if (strcmp(p
, names
[i
]) == 0) return i
+ 1;
59 const char *proto
= nvram_safe_get("wan_proto");
60 return (strcmp(proto
, "dhcp") == 0) || (strcmp(proto
, "l2tp") == 0) || (strcmp(proto
, "heartbeat") == 0);
63 switch (get_wan_proto()) {
73 return ((nvram_match("wl_mode", "sta")) || (nvram_match("wl_mode", "wet")));
76 void notice_set(const char *path
, const char *format
, ...)
82 va_start(args
, format
);
83 vsnprintf(buf
, sizeof(buf
), format
, args
);
86 mkdir("/var/notice", 0755);
87 snprintf(p
, sizeof(p
), "/var/notice/%s", path
);
88 f_write_string(p
, buf
, 0, 0);
89 if (buf
[0]) syslog(LOG_INFO
, "notice[%s]: %s", path
, buf
);
93 // #define _x_dprintf(args...) syslog(LOG_DEBUG, args);
94 #define _x_dprintf(args...) do { } while (0);
106 proto
= get_wan_proto();
107 if (proto
== WP_DISABLED
) return 0;
109 if ((proto
== WP_PPTP
) || (proto
== WP_L2TP
) || (proto
== WP_PPPOE
)) {
110 if (f_read_string("/tmp/ppp/link", buf1
, sizeof(buf1
)) > 0) {
111 // contains the base name of a file in /var/run/ containing pid of a daemon
112 snprintf(buf2
, sizeof(buf2
), "/var/run/%s.pid", buf1
);
113 if (f_read_string(buf2
, buf1
, sizeof(buf1
)) > 0) {
114 name
= psname(atoi(buf1
), buf2
, sizeof(buf2
));
115 if (proto
== WP_PPPOE
) {
116 if (strcmp(name
, "pppoecd") == 0) up
= 1;
119 if (strcmp(name
, "pppd") == 0) up
= 1;
123 _dprintf("%s: error reading %s\n", __FUNCTION__
, buf2
);
126 unlink("/tmp/ppp/link");
127 _x_dprintf("required daemon not found, assuming link is dead\n");
131 _x_dprintf("%s: error reading %s\n", __FUNCTION__
, "/tmp/ppp/link");
134 else if (!nvram_match("wan_ipaddr", "0.0.0.0")) {
138 _x_dprintf("%s: default !up\n", __FUNCTION__
);
141 if ((up
) && ((f
= socket(AF_INET
, SOCK_DGRAM
, 0)) >= 0)) {
142 strlcpy(ifr
.ifr_name
, nvram_safe_get("wan_iface"), sizeof(ifr
.ifr_name
));
143 if (ioctl(f
, SIOCGIFFLAGS
, &ifr
) < 0) {
145 _x_dprintf("%s: SIOCGIFFLAGS\n", __FUNCTION__
);
148 if ((ifr
.ifr_flags
& IFF_UP
) == 0) {
150 _x_dprintf("%s: !IFF_UP\n", __FUNCTION__
);
158 const dns_list_t
*get_dns(void)
160 static dns_list_t dns
;
169 strlcpy(s
, nvram_safe_get("wan_dns"), sizeof(s
));
170 if ((nvram_match("dns_addget", "1")) || (s
[0] == 0)) {
172 snprintf(s
+ n
, sizeof(s
) - n
, " %s", nvram_safe_get("wan_get_dns"));
175 n
= sscanf(s
, "%15s %15s %15s %15s", d
[0], d
[1], d
[2], d
[3]);
176 for (i
= 0; i
< n
; ++i
) {
177 if (inet_pton(AF_INET
, d
[i
], &ia
) > 0) {
178 for (j
= dns
.count
- 1; j
>= 0; --j
) {
179 if (dns
.dns
[j
].s_addr
== ia
.s_addr
) break;
182 dns
.dns
[dns
.count
++].s_addr
= ia
.s_addr
;
183 if (dns
.count
== 3) break;
191 // -----------------------------------------------------------------------------
193 void set_action(int a
)
196 while (f_write("/var/lock/action", &a
, sizeof(a
), 0, 0) != sizeof(a
)) {
198 if (--r
== 0) return;
200 if (a
!= ACT_IDLE
) sleep(2);
203 int check_action(void)
208 while (f_read("/var/lock/action", &a
, sizeof(a
)) != sizeof(a
)) {
210 if (--r
== 0) return ACT_UNKNOWN
;
215 int wait_action_idle(int n
)
218 if (check_action() == ACT_IDLE
) return 1;
224 // -----------------------------------------------------------------------------
226 const char *get_wanip(void)
230 if (!check_wanup()) return "0.0.0.0";
231 switch (get_wan_proto()) {
244 return nvram_safe_get(p
);
247 long get_uptime(void)
258 return (wl_ioctl(nvram_safe_get("wl_ifname"), WLC_GET_RADIO
, &n
, sizeof(n
)) == 0) &&
259 ((n
& WL_RADIO_SW_DISABLE
) == 0);
262 void set_radio(int on
)
266 #ifndef WL_BSS_INFO_VERSION
267 #error WL_BSS_INFO_VERSION
270 #if WL_BSS_INFO_VERSION >= 108
271 n
= on
? (WL_RADIO_SW_DISABLE
<< 16) : ((WL_RADIO_SW_DISABLE
<< 16) | 1);
272 wl_ioctl(nvram_safe_get("wl_ifname"), WLC_SET_RADIO
, &n
, sizeof(n
));
278 n
= on
? 0 : WL_RADIO_SW_DISABLE
;
279 wl_ioctl(nvram_safe_get("wl_ifname"), WLC_SET_RADIO
, &n
, sizeof(n
));
286 int nvram_get_int(const char *key
)
288 return atoi(nvram_safe_get(key
));
292 long nvram_xget_long(const char *name, long min, long max, long def)
299 if ((p != NULL) && (*p != 0)) {
300 n = strtol(p, &e, 0);
301 if ((e != p) && ((*e == 0) || (*e == ' ')) && (n > min) && (n < max)) {
309 int nvram_get_file(const char *key
, const char *fname
, int max
)
315 p
= nvram_safe_get(key
);
318 n
= base64_decode(p
, b
, n
);
319 if (n
> 0) return (f_write(fname
, b
, n
, 0, 0700) == n
);
324 int nvram_set_file(const char *key
, const char *fname
, int max
)
330 if (((n
= f_read(fname
, &a
, sizeof(a
))) > 0) && (n
<= max
)) {
331 n
= base64_encode(a
, b
, n
);
339 int nvram_contains_word(const char *key
, const char *word
)
341 return (find_word(nvram_safe_get(key
), word
) != NULL
);
344 int connect_timeout(int fd
, const struct sockaddr
*addr
, socklen_t len
, int timeout
)
352 if (((flags
= fcntl(fd
, F_GETFL
, 0)) < 0) ||
353 (fcntl(fd
, F_SETFL
, flags
| O_NONBLOCK
) < 0)) {
354 _dprintf("%s: error in F_*ETFL %d\n", __FUNCTION__
, fd
);
358 if (connect(fd
, addr
, len
) < 0) {
359 // _dprintf("%s: connect %d = <0\n", __FUNCTION__, fd);
361 if (errno
!= EINPROGRESS
) {
362 _dprintf("%s: error in connect %d errno=%d\n", __FUNCTION__
, fd
, errno
);
371 r
= select(fd
+ 1, NULL
, &fds
, NULL
, &tv
);
373 _dprintf("%s: timeout in select %d\n", __FUNCTION__
, fd
);
377 if (errno
!= EINTR
) {
378 _dprintf("%s: error in select %d\n", __FUNCTION__
, fd
);
386 if ((getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, &r
, &n
) < 0) || (r
!= 0)) {
387 _dprintf("%s: error in SO_ERROR %d\n", __FUNCTION__
, fd
);
395 if (fcntl(fd
, F_SETFL
, flags
) < 0) {
396 _dprintf("%s: error in F_*ETFL %d\n", __FUNCTION__
, fd
);
400 // _dprintf("%s: OK %d\n", __FUNCTION__, fd);
407 return time(0) > Y2K;
411 // -----------------------------------------------------------------------------
414 /* stolen from the e2fsprogs/ismounted.c */
415 /* Find wherever 'file' (actually: device) is mounted.
416 * Either the exact same device-name, or another device-name.
417 * The latter is detected by comparing the rdev or dev&inode.
418 * So aliasing won't fool us---we'll still find if it's mounted.
419 * Return its mnt entry.
420 * In particular, the caller would look at the mnt->mountpoint.
421 * If "file" is an empty string, return the mntent of the first
422 * mount that is for a USB disc that is no longer accessible.
424 struct mntent
*findmntent(char *file
)
428 dev_t file_dev
=0, file_rdev
=0;
432 if ((f
= setmntent("/proc/mounts", "r")) == NULL
)
435 if (stat(file
, &st_buf
) == 0) {
436 if (S_ISBLK(st_buf
.st_mode
)) {
437 file_rdev
= st_buf
.st_rdev
;
439 file_dev
= st_buf
.st_dev
;
440 file_ino
= st_buf
.st_ino
;
443 while ((mnt
= getmntent(f
)) != NULL
) {
444 if (*file
== 0 && strncmp(mnt
->mnt_fsname
, "/dev/discs/", 11) == 0) {
445 if (stat(mnt
->mnt_fsname
, &st_buf
) != 0)
446 break; /* Device is no longer valid. */
449 if (strcmp(file
, mnt
->mnt_fsname
) == 0)
451 if (stat(mnt
->mnt_fsname
, &st_buf
) == 0) {
452 if (S_ISBLK(st_buf
.st_mode
)) {
453 if (file_rdev
&& (file_rdev
== st_buf
.st_rdev
))
456 if (file_dev
&& ((file_dev
== st_buf
.st_dev
) &&
457 (file_ino
== st_buf
.st_ino
)))
467 /* Figure out the volume label. */
468 /* If we found it, return Non-Zero and store it at the_label. */
469 #define USE_BB 0 /* Use the actual busybox .a file. */
472 char applet_name
[] = "hotplug"; /* Needed to satisfy a reference. */
473 int find_label(char *mnt_dev
, char *the_label
)
479 /* heuristic: partition name ends in a digit */
480 if ( !isdigit(mnt_dev
[strlen(mnt_dev
) - 1]))
483 cprintf("\n\nGetting volume label for '%s'\n", mnt_dev
);
485 /* it's in get_devname.c */
486 i
= get_label_uuid(mnt_dev
, &label
, &uuid
, 0);
487 cprintf("get_label_uuid= %d\n", i
);
489 cprintf(" label= %s uuid = %s\n", label
, uuid
);
490 strcpy(the_label
, label
);
496 int find_label(char *mnt_dev
, char *the_label
)
501 struct stat st_arg
, st_mou
;
504 /* heuristic: partition name ends in a digit */
505 if ( !isdigit(mnt_dev
[strlen(mnt_dev
) - 1]))
508 mfp
= popen("mount LABEL= /no-such-label", "r");
510 _dprintf("Cannot popen mount!!\n");
514 while (fgets(buf
, sizeof(buf
), mfp
)) {
515 if ((p
= strchr(buf
, '\n')))
517 if ((p
= strstr(buf
, "LABEL "))) { /* Isolate the label. */
518 if ((label
=strchr(p
+6, '\''))) {
520 if ((p
= strchr(label
, '\''))) {
522 if ((p
= strchr(p
, '/'))) { /* Isolate the device. */
523 /* See if the argument is the same as what mount gives. */
524 if (stat(mnt_dev
, &st_arg
) == 0 && stat(p
, &st_mou
) == 0) {
525 if (S_ISBLK(st_arg
.st_mode
) && S_ISBLK(st_mou
.st_mode
) &&
526 st_arg
.st_rdev
== st_mou
.st_rdev
) {
527 strcpy(the_label
, label
);