diff --git a/package/gluon-status-page-api/src/stations.c b/package/gluon-status-page-api/src/stations.c index 132888277fe09008d2b5c318d336bafbd11ba477..24775a07f5b68c96b132f303cfdb00ce3a75e956 100644 --- a/package/gluon-status-page-api/src/stations.c +++ b/package/gluon-status-page-api/src/stations.c @@ -4,7 +4,12 @@ #include <json-c/json.h> #include <iwinfo.h> #include <net/if.h> +#include <glob.h> +#include <alloca.h> +#define NETIF_PREFIX "/sys/class/net/" +#define VIRTIF_PREFIX "/sys/devices/virtual/net/" +#define LOWERGLOB_SUFFIX "/lower_*" static struct json_object *get_stations(const struct iwinfo_ops *iw, const char *ifname) { int len; @@ -40,12 +45,68 @@ static void badrequest() { exit(1); } +// recurse down to the lowest layer-2 interface +static int interface_get_lowest(const char *ifname, char *hwifname); +static int interface_get_lowest(const char *ifname, char *hwifname) { + glob_t globbuf; + char *fnamebuf = alloca(1 + strlen(VIRTIF_PREFIX) + IF_NAMESIZE + + strlen(LOWERGLOB_SUFFIX)); + char *lowentry = NULL; + + + sprintf(fnamebuf, "%s%s%s", VIRTIF_PREFIX, ifname, LOWERGLOB_SUFFIX); + glob(fnamebuf, GLOB_NOSORT | GLOB_NOESCAPE, NULL, &globbuf); + + if (globbuf.gl_pathc == 1) { + lowentry = alloca(1 + strlen(globbuf.gl_pathv[0])); + strncpy(lowentry, globbuf.gl_pathv[0], 1 + strlen(globbuf.gl_pathv[0])); + } + + globfree(&globbuf); + + if (!lowentry) { + char *path = alloca(1 + strlen(NETIF_PREFIX) + strlen(ifname)); + sprintf(path, "%s%s", NETIF_PREFIX, ifname); + + if(access(path, F_OK) != 0) + return false; + + strncpy(hwifname, ifname, IF_NAMESIZE - 1); + return true; + } else { + char buf[PATH_MAX]; + ssize_t len; + + if ((len = readlink(lowentry, buf, sizeof(buf)-1)) != -1) + buf[len] = '\0'; + else + return false; + + if (strncmp(buf, "../", 3) == 0) { + return interface_get_lowest(strrchr(buf, '/') + 1, hwifname); + } else { + return false; + } + } +} + int main(int argc, char *argv[]) { if (argc != 2) badrequest(); const char *ifname = argv[1]; - const struct iwinfo_ops *iw = iwinfo_backend(ifname); + char hwifname[IF_NAMESIZE] = ""; + + if (strlen(ifname) >= IF_NAMESIZE) + badrequest(); + + if (strcspn(ifname, "/\\[]{}*?") != strlen(ifname)) + badrequest(); + + if (!interface_get_lowest(ifname, hwifname)) + badrequest(); + + const struct iwinfo_ops *iw = iwinfo_backend(hwifname); if (iw == NULL) badrequest(); @@ -54,7 +115,7 @@ int main(int argc, char *argv[]) { while (true) { struct json_object *obj; - obj = get_stations(iw, ifname); + obj = get_stations(iw, hwifname); printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)); fflush(stdout); json_object_put(obj);