"Fossies" - the Fresh Open Source Software Archive

Member "vnstat-2.9/src/ifinfo.c" (22 Aug 2021, 10704 Bytes) of package /linux/misc/vnstat-2.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ifinfo.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.7_vs_2.8.

    1 #include "common.h"
    2 #include "ibw.h"
    3 #include "ifinfo.h"
    4 
    5 int getifinfo(const char *iface)
    6 {
    7     char inface[32];
    8 
    9     ifinfo.filled = 0;
   10     ifinfo.timestamp = 0;
   11 
   12 #if defined(__linux__) && HAVE_LINUX_RTNETLINK_H
   13     if (cfg.is64bit == -2) {
   14 #if HAVE_DECL_IFLA_STATS64
   15         ifinfo.is64bit = 1;
   16 #else
   17         ifinfo.is64bit = 0;
   18 #endif
   19     } else {
   20         ifinfo.is64bit = (short)cfg.is64bit;
   21     }
   22 #else
   23     if (cfg.is64bit < 0) {
   24         ifinfo.is64bit = -1;
   25     } else {
   26         ifinfo.is64bit = (short)cfg.is64bit;
   27     }
   28 #endif
   29 
   30     if (strcmp(iface, "default") == 0) {
   31         strncpy_nt(inface, cfg.iface, 32);
   32     } else {
   33         strncpy_nt(inface, iface, 32);
   34     }
   35 
   36 #if defined(__linux__) || defined(CHECK_VNSTAT)
   37     /* try getting interface info from /proc */
   38     if (readproc(inface) == 1) {
   39         ifinfo.timestamp = time(NULL);
   40         return 1;
   41     } else {
   42         if (debug)
   43             printf("Failed to use %s as source.\n", PROCNETDEV);
   44     }
   45 
   46     /* try getting interface info from /sys */
   47     if (readsysclassnet(inface) == 1) {
   48         ifinfo.timestamp = time(NULL);
   49         return 1;
   50     }
   51 
   52 #elif defined(BSD_VNSTAT)
   53     if (readifaddrs(inface) == 1) {
   54         ifinfo.timestamp = time(NULL);
   55         return 1;
   56     }
   57 #endif
   58 
   59     snprintf(errorstring, 1024, "Unable to get interface \"%s\" statistics.", inface);
   60     printe(PT_Error);
   61     return 0;
   62 }
   63 
   64 int getifliststring(char **ifacelist, int showspeed)
   65 {
   66     char temp[64];
   67     iflist *ifl = NULL, *ifl_iterator = NULL;
   68 
   69     /* initialize list string */
   70     *ifacelist = (char *)malloc(sizeof(char));
   71     if (*ifacelist == NULL) {
   72         panicexit(__FILE__, __LINE__);
   73     }
   74     *ifacelist[0] = '\0';
   75 
   76     if (getiflist(&ifl, showspeed, 1) > 0) {
   77 
   78         ifl_iterator = ifl;
   79 
   80         while (ifl_iterator != NULL) {
   81             *ifacelist = (char *)realloc(*ifacelist, ((strlen(*ifacelist) + strlen(ifl_iterator->interface) + 2) * sizeof(char)));
   82             if (*ifacelist == NULL) {
   83                 panicexit(__FILE__, __LINE__);
   84             }
   85             strcat(*ifacelist, ifl_iterator->interface);
   86             strcat(*ifacelist, " ");
   87 
   88             if (showspeed && ifl_iterator->bandwidth > 0) {
   89                 snprintf(temp, 64, "(%u Mbit) ", ifl_iterator->bandwidth);
   90                 *ifacelist = (char *)realloc(*ifacelist, ((strlen(*ifacelist) + strlen(temp) + 1) * sizeof(char)));
   91                 if (*ifacelist == NULL) {
   92                     panicexit(__FILE__, __LINE__);
   93                 }
   94                 strcat(*ifacelist, temp);
   95             }
   96 
   97             ifl_iterator = ifl_iterator->next;
   98         }
   99 
  100         iflistfree(&ifl);
  101         return 1;
  102     }
  103 
  104     iflistfree(&ifl);
  105     return 0;
  106 }
  107 
  108 int getiflist(iflist **ifl, const int getspeed, const int validate)
  109 {
  110     int result = 0;
  111     int32_t maxbw = cfg.maxbw;
  112 
  113     /* disable MaxBandwidth during list creation to avoid having it being set as the default value when nothing is detected */
  114     cfg.maxbw = 0;
  115 #if defined(__linux__) || defined(CHECK_VNSTAT)
  116     result = getiflist_linux(ifl, getspeed, validate);
  117 #elif defined(BSD_VNSTAT)
  118     result = getiflist_bsd(ifl, getspeed, validate);
  119 #else
  120 #error vnStat only supports Linux and BSD like systems
  121 #endif
  122     cfg.maxbw = maxbw;
  123     return result;
  124 }
  125 
  126 #if defined(__linux__) || defined(CHECK_VNSTAT)
  127 int getiflist_linux(iflist **ifl, const int getspeed, const int validate)
  128 {
  129     char temp[64];
  130     char interface[32];
  131     FILE *fp;
  132     DIR *dp;
  133     struct dirent *di;
  134     char procline[512];
  135     uint32_t bwlimit = 0;
  136 
  137     if ((fp = fopen(PROCNETDEV, "r")) != NULL) {
  138 
  139         /* make list of interfaces */
  140         while (fgets(procline, 512, fp) != NULL) {
  141             sscanf(procline, "%63s", temp);
  142             if (strlen(temp) > 0 && (isdigit(temp[(strlen(temp) - 1)]) || temp[(strlen(temp) - 1)] == ':')) {
  143                 sscanf(temp, "%31[^':']s", interface);
  144                 if (validate && !isifvalid(interface)) {
  145                     continue;
  146                 }
  147                 bwlimit = 0;
  148                 if (getspeed && ibwget(interface, &bwlimit)) {
  149                     iflistadd(ifl, interface, bwlimit);
  150                 } else {
  151                     iflistadd(ifl, interface, 0);
  152                 }
  153             }
  154         }
  155 
  156         fclose(fp);
  157         return 1;
  158 
  159     } else {
  160 
  161         if ((dp = opendir(SYSCLASSNET)) != NULL) {
  162 
  163             /* make list of interfaces */
  164             while ((di = readdir(dp))) {
  165                 if (di->d_name[0] == '.' || strlen(di->d_name) > 31) {
  166                     continue;
  167                 }
  168                 if (validate && !isifvalid(di->d_name)) {
  169                     continue;
  170                 }
  171                 bwlimit = 0;
  172                 if (getspeed && ibwget(di->d_name, &bwlimit)) {
  173                     iflistadd(ifl, di->d_name, bwlimit);
  174                 } else {
  175                     iflistadd(ifl, di->d_name, 0);
  176                 }
  177             }
  178 
  179             closedir(dp);
  180             return 1;
  181         }
  182     }
  183 
  184     return 0;
  185 }
  186 #elif defined(BSD_VNSTAT)
  187 int getiflist_bsd(iflist **ifl, const int getspeed, const int validate)
  188 {
  189     struct ifaddrs *ifap, *ifa;
  190     uint32_t bwlimit = 0;
  191 
  192     if (getifaddrs(&ifap) >= 0) {
  193 
  194         /* make list of interfaces */
  195         for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  196             if (ifa->ifa_addr->sa_family != AF_LINK || strlen(ifa->ifa_name) > 31) {
  197                 continue;
  198             }
  199             if (validate && !isifvalid(ifa->ifa_name)) {
  200                 continue;
  201             }
  202             bwlimit = 0;
  203             if (getspeed && ibwget(ifa->ifa_name, &bwlimit)) {
  204                 iflistadd(ifl, ifa->ifa_name, getifspeed(ifa->ifa_name));
  205             } else {
  206                 iflistadd(ifl, ifa->ifa_name, 0);
  207             }
  208         }
  209 
  210         freeifaddrs(ifap);
  211         return 1;
  212     }
  213 
  214     return 0;
  215 }
  216 #endif
  217 
  218 int readproc(const char *iface)
  219 {
  220     FILE *fp;
  221     char temp[4][64], procline[512], *proclineptr, ifaceid[33];
  222     int check;
  223 
  224     if ((fp = fopen(PROCNETDEV, "r")) == NULL) {
  225         if (debug)
  226             printf("Error (debug): Unable to read %s: %s\n", PROCNETDEV, strerror(errno));
  227         return 0;
  228     }
  229 
  230     strncpy_nt(ifaceid, iface, 32);
  231     strcat(ifaceid, ":");
  232 
  233     check = 0;
  234     while (fgets(procline, 512, fp) != NULL) {
  235         sscanf(procline, "%63s", temp[0]);
  236         if (strncmp(ifaceid, temp[0], strlen(ifaceid)) == 0) {
  237             /* if (debug)
  238                 printf("\n%s\n", procline); */
  239             check = 1;
  240             break;
  241         }
  242     }
  243     fclose(fp);
  244 
  245     if (check == 0) {
  246         if (debug)
  247             printf("Requested interface \"%s\" not found.\n", iface);
  248         return 0;
  249     } else {
  250 
  251         strncpy_nt(ifinfo.name, iface, 32);
  252 
  253         /* get rx and tx from procline */
  254         proclineptr = strchr(procline, ':');
  255         sscanf(proclineptr + 1, "%63s %63s %*s %*s %*s %*s %*s %*s %63s %63s", temp[0], temp[1], temp[2], temp[3]);
  256 
  257         ifinfo.rx = strtoull(temp[0], (char **)NULL, 0);
  258         ifinfo.tx = strtoull(temp[2], (char **)NULL, 0);
  259 
  260         /* daemon doesn't need packet data */
  261         if (!noexit) {
  262             ifinfo.rxp = strtoull(temp[1], (char **)NULL, 0);
  263             ifinfo.txp = strtoull(temp[3], (char **)NULL, 0);
  264         }
  265 
  266         ifinfo.filled = 1;
  267     }
  268 
  269     return 1;
  270 }
  271 
  272 int readsysclassnet(const char *iface)
  273 {
  274     FILE *fp;
  275     char path[64], file[76], buffer[64];
  276 
  277     strncpy_nt(ifinfo.name, iface, 32);
  278 
  279     snprintf(path, 64, "%s/%s/statistics", SYSCLASSNET, iface);
  280 
  281     if (debug)
  282         printf("path: %s\n", path);
  283 
  284     /* rx bytes */
  285     snprintf(file, 76, "%s/rx_bytes", path);
  286     if ((fp = fopen(file, "r")) == NULL) {
  287         if (debug)
  288             printf("Unable to read: %s - %s\n", file, strerror(errno));
  289         return 0;
  290     } else {
  291         if (fgets(buffer, 64, fp) != NULL) {
  292             ifinfo.rx = strtoull(buffer, (char **)NULL, 0);
  293         } else {
  294             fclose(fp);
  295             return 0;
  296         }
  297     }
  298     fclose(fp);
  299 
  300     /* tx bytes */
  301     snprintf(file, 76, "%s/tx_bytes", path);
  302     if ((fp = fopen(file, "r")) == NULL) {
  303         if (debug)
  304             printf("Unable to read: %s - %s\n", file, strerror(errno));
  305         return 0;
  306     } else {
  307         if (fgets(buffer, 64, fp) != NULL) {
  308             ifinfo.tx = strtoull(buffer, (char **)NULL, 0);
  309         } else {
  310             fclose(fp);
  311             return 0;
  312         }
  313     }
  314     fclose(fp);
  315 
  316     /* daemon doesn't need packet data */
  317     if (!noexit) {
  318 
  319         /* rx packets */
  320         snprintf(file, 76, "%s/rx_packets", path);
  321         if ((fp = fopen(file, "r")) == NULL) {
  322             if (debug)
  323                 printf("Unable to read: %s - %s\n", file, strerror(errno));
  324             return 0;
  325         } else {
  326             if (fgets(buffer, 64, fp) != NULL) {
  327                 ifinfo.rxp = strtoull(buffer, (char **)NULL, 0);
  328             } else {
  329                 fclose(fp);
  330                 return 0;
  331             }
  332         }
  333         fclose(fp);
  334 
  335         /* tx packets */
  336         snprintf(file, 76, "%s/tx_packets", path);
  337         if ((fp = fopen(file, "r")) == NULL) {
  338             if (debug)
  339                 printf("Unable to read: %s - %s\n", file, strerror(errno));
  340             return 0;
  341         } else {
  342             if (fgets(buffer, 64, fp) != NULL) {
  343                 ifinfo.txp = strtoull(buffer, (char **)NULL, 0);
  344             } else {
  345                 fclose(fp);
  346                 return 0;
  347             }
  348         }
  349         fclose(fp);
  350     }
  351 
  352     ifinfo.filled = 1;
  353 
  354     return 1;
  355 }
  356 
  357 #if defined(BSD_VNSTAT)
  358 int getifdata(const char *iface, struct if_data *ifd)
  359 {
  360     struct ifaddrs *ifap, *ifa;
  361     int check = 0;
  362 
  363     if (getifaddrs(&ifap) < 0) {
  364         if (debug)
  365             printf("readifaddrs:getifaddrs() failed.\n");
  366         return 0;
  367     }
  368     for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
  369         if ((strcmp(ifa->ifa_name, iface) == 0) && (ifa->ifa_addr->sa_family == AF_LINK)) {
  370             if (ifa->ifa_data != NULL) {
  371                 memcpy(ifd, ifa->ifa_data, sizeof(struct if_data));
  372                 check = 1;
  373             }
  374             break;
  375         }
  376     }
  377     freeifaddrs(ifap);
  378 
  379     return check;
  380 }
  381 
  382 int readifaddrs(const char *iface)
  383 {
  384     struct if_data ifd;
  385 
  386     if (!getifdata(iface, &ifd)) {
  387         if (debug)
  388             printf("Requested interface \"%s\" not found.\n", iface);
  389         return 0;
  390     } else {
  391         strncpy_nt(ifinfo.name, iface, 32);
  392         ifinfo.rx = ifd.ifi_ibytes;
  393         ifinfo.tx = ifd.ifi_obytes;
  394         ifinfo.rxp = ifd.ifi_ipackets;
  395         ifinfo.txp = ifd.ifi_opackets;
  396         ifinfo.filled = 1;
  397 
  398         if (cfg.is64bit == -2) {
  399             if (sizeof(ifd.ifi_ibytes) == 8) {
  400                 ifinfo.is64bit = 1;
  401             } else {
  402                 ifinfo.is64bit = 0;
  403             }
  404         }
  405     }
  406 
  407     return 1;
  408 }
  409 #endif
  410 
  411 uint32_t getifspeed(const char *iface)
  412 {
  413     uint64_t speed = 0;
  414 
  415 #if defined(__linux__)
  416 
  417     FILE *fp;
  418     char file[64], buffer[64];
  419 
  420     snprintf(file, 64, "%s/%s/speed", SYSCLASSNET, iface);
  421 
  422     if ((fp = fopen(file, "r")) == NULL) {
  423         if (debug)
  424             printf("Unable to open: %s - %s\n", file, strerror(errno));
  425         return 0;
  426     } else {
  427         if (fgets(buffer, 64, fp) != NULL) {
  428             speed = strtoull(buffer, (char **)NULL, 0);
  429         } else {
  430             if (debug)
  431                 printf("Unable to read: %s - %s\n", file, strerror(errno));
  432             fclose(fp);
  433             return 0;
  434         }
  435     }
  436     fclose(fp);
  437 
  438 #elif defined(BSD_VNSTAT)
  439 
  440     struct if_data ifd;
  441 
  442     if (!getifdata(iface, &ifd)) {
  443         if (debug)
  444             printf("Requested interface \"%s\" not found.\n", iface);
  445         return 0;
  446     } else {
  447         speed = (uint64_t)ifd.ifi_baudrate;
  448     }
  449 
  450 #endif
  451 
  452     if (debug)
  453         printf("getifspeed: \"%s\": %" PRIu64 "\n", iface, speed);
  454 
  455     if (speed > 1000000) {
  456         speed = 0;
  457     }
  458     return (uint32_t)speed;
  459 }
  460 
  461 int isifavailable(const char *iface)
  462 {
  463     int ret = 0, printstatus;
  464 
  465     printstatus = disableprints;
  466     disableprints = 1;
  467     ret = getifinfo(iface);
  468     disableprints = printstatus;
  469 
  470     return ret;
  471 }
  472 
  473 int isifvalid(const char *iface)
  474 {
  475     if (strstr(iface, ":") != NULL) {
  476         return 0;
  477     } else if (strcmp(iface, "lo") == 0) {
  478         return 0;
  479     } else if (strcmp(iface, "lo0") == 0) {
  480         return 0;
  481     } else if (strcmp(iface, "sit0") == 0) {
  482         return 0;
  483     }
  484     return 1;
  485 }
  486 
  487 /* tun interfaces have speed hardcoded as 10 in the Linux kernel regardless of used interface and can't
  488 be trusted to provide correct details as a result even if the information is available:
  489 https://github.com/torvalds/linux/blob/9d31d2338950293ec19d9b095fbaa9030899dcb4/drivers/net/tun.c#L3456 */
  490 int istun(const char *iface)
  491 {
  492 #if defined(__linux__)
  493     if (strlen(iface) > 3 && strncmp(iface, "tun", 3) == 0) {
  494         if (isdigit(iface[3])) {
  495             return 1;
  496         }
  497     }
  498 #endif
  499     return 0;
  500 }