diff --git a/ChangeLog b/ChangeLog
index 8e3536bd..287c0188 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,7 @@
2008-05-30
* Simplified docs for color0-9 config settings and variables.
+ * Improved $if_up for configurable behaviour.
2008-04-29
* own_window_type dock patch (thanks Morgan).
diff --git a/doc/config_settings.xml b/doc/config_settings.xml
index a5dc6ffc..c51d7e9a 100644
--- a/doc/config_settings.xml
+++ b/doc/config_settings.xml
@@ -127,6 +127,13 @@
+
+
+
+ How strict should if_up be when testing an interface for being up? The value is one of up, link or address, to check for the interface being solely up, being up and having link or being up, having link and an assigned IP address.
+
+
+
diff --git a/doc/conky.conf b/doc/conky.conf
index 1e1ec861..df96def2 100644
--- a/doc/conky.conf
+++ b/doc/conky.conf
@@ -140,6 +140,10 @@ show_graph_scale no
# Timing interval for music player thread, e.g. mpd, audacious
#music_player_interval (update_interval is default)
+# Strictness of if_up. One of: up, link or address. The later ones imply the further ones.
+# Defaults to up.
+#if_up_strictness address
+
# variable is given either in format $variable or in ${variable}. Latter
# allows characters right after the variable and must be used in network
# stuff because of an argument
diff --git a/src/conky.c b/src/conky.c
index a0c222ad..1360ebc3 100644
--- a/src/conky.c
+++ b/src/conky.c
@@ -8510,6 +8510,21 @@ static void load_config_file(const char *f)
* as per config */
}
#endif
+ CONF("if_up_strictness") {
+ if (!value) {
+ ERR("incorrect if_up_strictness value, defaulting to 'up'");
+ ifup_strictness = IFUP_UP;
+ } else if (!strcmp(value, "up")) {
+ ifup_strictness = IFUP_UP;
+ } else if (!strcmp(value, "link")) {
+ ifup_strictness = IFUP_LINK;
+ } else if (!strcmp(value, "address")) {
+ ifup_strictness = IFUP_ADDR;
+ } else {
+ ERR("incorrect if_up_strictness value, defaulting to 'up'");
+ ifup_strictness = IFUP_UP;
+ }
+ }
else {
ERR("%s: %d: no such configuration: '%s'", f, line, name);
}
diff --git a/src/conky.h b/src/conky.h
index bcbc5a67..41e66d9f 100644
--- a/src/conky.h
+++ b/src/conky.h
@@ -337,6 +337,13 @@ enum {
BATTERY_TIME
};
+/* if_up strictness selector */
+enum {
+ IFUP_UP,
+ IFUP_LINK,
+ IFUP_ADDR
+} ifup_strictness;
+
#ifdef MPD
#include "libmpdclient.h"
#endif
diff --git a/src/linux.c b/src/linux.c
index ecaac575..9baffff4 100644
--- a/src/linux.c
+++ b/src/linux.c
@@ -212,66 +212,44 @@ char *get_ioscheduler(char *disk)
int interface_up(const char *dev)
{
- int fd, dnl, ifnl, nl;
- unsigned int k;
- struct ifconf conf;
- struct sockaddr addr;
- char *ifdev;
+ int fd;
+ struct ifreq ifr;
- dnl = strlen(dev);
- if((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) {
+ if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
CRIT_ERR("could not create sockfd");
return 0;
}
-
- /* allocate memory for interface request */
- if((conf.ifc_buf = calloc(16, sizeof(struct ifreq))) == NULL) {
- CRIT_ERR("could not allocate memory for interface query");
- return 0;
- }
- conf.ifc_len = sizeof(struct ifreq) * 16;
-
- /* send a conf query ioctl to device to enumerate all interfaces */
- if(ioctl(fd, SIOCGIFCONF, &conf)) {
- /* if device does not exist, treat like not up - fail fast */
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr)) {
+ /* if device does not exist, treat like not up */
if (errno != ENODEV)
perror("SIOCGIFFLAGS");
- } else {
- /* for all enumerated interface devices ... */
- for (k = 0; k < conf.ifc_len / sizeof(struct ifreq); k++) {
- /* end of buffer - break out */
- if (!(((struct ifreq *) conf.ifc_buf) + k))
- break;
- /* get interface device name */
- ifdev = ((struct ifreq *) conf.ifc_buf)[k].ifr_ifrn.ifrn_name;
- ifnl = strlen(ifdev);
- nl = dnl > ifnl ? ifnl : dnl;
- /* if it does not match our specified device - move on */
- if (strncmp(dev, ifdev, nl) != 0) {
- continue;
- }
- /* get associated address on device */
- addr = ((struct ifreq *) conf.ifc_buf)[k].ifr_ifru.ifru_addr;
- /* if ip is 0.0.0.0 it is not up */
- if(((addr.sa_data[2] & 255) == 0 && (addr.sa_data[3] & 255) == 0 &&
- (addr.sa_data[4] & 255) == 0 && (addr.sa_data[5] & 255) == 0) ||
- /* oh yeah also include IANA link local RFC3330
- * http://www.faqs.org/rfcs/rfc3330.html
- * http://www.iana.org/assignments/ipv4-address-space Notes [6]
- * exclude 169.254.*.* how about 223.255 and 240.0??? */
- ((addr.sa_data[2] & 255) == 169 && (addr.sa_data[3] & 255) == 254)) {
- break;
- }
- /* otherwise we are good */
- free(conf.ifc_buf);
- close(fd);
- return 1;
- }
+ goto END_FALSE;
}
- /* cleanup */
+
+ if (!(ifr.ifr_flags & IFF_UP)) /* iface is not up */
+ goto END_FALSE;
+ if (ifup_strictness == IFUP_UP)
+ goto END_TRUE;
+
+ if (!(ifr.ifr_flags & IFF_RUNNING))
+ goto END_FALSE;
+ if (ifup_strictness == IFUP_LINK)
+ goto END_TRUE;
+
+ if (ioctl(fd, SIOCGIFADDR, &ifr)) {
+ perror("SIOCGIFADDR");
+ goto END_FALSE;
+ }
+ if (((struct sockaddr_in *)&(ifr.ifr_ifru.ifru_addr))->sin_addr.s_addr)
+ goto END_TRUE;
+
+END_FALSE:
close(fd);
- free(conf.ifc_buf);
return 0;
+END_TRUE:
+ close(fd);
+ return 1;
}
#define COND_FREE(x) if(x) free(x); x = 0