using C code to get same info as ifconfig

前端 未结 6 768
醉话见心
醉话见心 2020-11-27 03:15

Is there a way in Linux, using C code, to get the same information that \"ifconfig eth0\" would return? I\'m interested in things like IP address, link status, and MAC addr

相关标签:
6条回答
  • 2020-11-27 03:55

    Here is how I get MAC and MTU in my code:

    void getMACAddress(std::string _iface,unsigned char MAC[6]) {
            int fd = socket(AF_INET, SOCK_DGRAM, 0);
            struct ifreq ifr;
            ifr.ifr_addr.sa_family = AF_INET;
            strncpy(ifr.ifr_name , _iface.c_str() , IFNAMSIZ-1);
            ioctl(fd, SIOCGIFHWADDR, &ifr);
            for(unsigned int i=0;i<6;i++)
                MAC[i] = ifr.ifr_hwaddr.sa_data[i];
            ioctl(fd, SIOCGIFMTU, &ifr);
            close(fd);
            printf("MTU: %d\n",ifr.ifr_mtu);
            printf("MAC:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",MAC[0],MAC[1],MAC[2],MAC[3],MAC[4],MAC[5]);
        }
    
    0 讨论(0)
  • 2020-11-27 04:02

    One simple way is to use the popen function see: http://pubs.opengroup.org/onlinepubs/009696899/functions/popen.html

    Use something like:

    FILE *fp;
    
    char returnData[64];
    
    fp = popen("/sbin/ifconfig eth0", "r");
    
    while (fgets(returnData, 64, fp) != NULL)
    {
        printf("%s", returnData);
    }
    
    pclose(fp);
    
    0 讨论(0)
  • 2020-11-27 04:03

    There is simpler approach. copied from http://man7.org/linux/man-pages/man3/getifaddrs.3.html

       #include <arpa/inet.h>
       #include <sys/socket.h>
       #include <netdb.h>
       #include <ifaddrs.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <linux/if_link.h>
    
       int main(int argc, char *argv[])
       {
           struct ifaddrs *ifaddr, *ifa;
           int family, s, n;
           char host[NI_MAXHOST];
    
           if (getifaddrs(&ifaddr) == -1) {
               perror("getifaddrs");
               exit(EXIT_FAILURE);
           }
    
           /* Walk through linked list, maintaining head pointer so we
              can free list later */
    
           for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
               if (ifa->ifa_addr == NULL)
                   continue;
    
               family = ifa->ifa_addr->sa_family;
    
               /* Display interface name and family (including symbolic
                  form of the latter for the common families) */
    
               printf("%-8s %s (%d)\n",
                      ifa->ifa_name,
                      (family == AF_PACKET) ? "AF_PACKET" :
                      (family == AF_INET) ? "AF_INET" :
                      (family == AF_INET6) ? "AF_INET6" : "???",
                      family);
    
               /* For an AF_INET* interface address, display the address */
    
               if (family == AF_INET || family == AF_INET6) {
                   s = getnameinfo(ifa->ifa_addr,
                           (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                                 sizeof(struct sockaddr_in6),
                           host, NI_MAXHOST,
                           NULL, 0, NI_NUMERICHOST);
                   if (s != 0) {
                       printf("getnameinfo() failed: %s\n", gai_strerror(s));
                       exit(EXIT_FAILURE);
                   }
    
                   printf("\t\taddress: <%s>\n", host);
    
               } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
                   struct rtnl_link_stats *stats = (struct rtnl_link_stats *)ifa->ifa_data;
    
                   printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
                          "\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",
                          stats->tx_packets, stats->rx_packets,
                          stats->tx_bytes, stats->rx_bytes);
               }
           }
    
           freeifaddrs(ifaddr);
           exit(EXIT_SUCCESS);
       }
    
    0 讨论(0)
  • 2020-11-27 04:05
    void parse_ioctl(const char *ifname)
    {
        printf("%s\n", "scarf rosari...");
        int sock;
        struct ifreq ifr;
        struct sockaddr_in *ipaddr;
        char address[INET_ADDRSTRLEN];
        size_t ifnamelen;
    
        /* copy ifname to ifr object */
        ifnamelen = strlen(ifname);
        if (ifnamelen >= sizeof(ifr.ifr_name)) {
            printf("error :%s\n", ifr.ifr_name);
            return ;
        }
        memcpy(ifr.ifr_name, ifname, ifnamelen);
        ifr.ifr_name[ifnamelen] = '\0';
    
        /* open socket */
        sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
        if (sock < 0) {
            printf("error :%s\n", "unable to open socket..");
            return;
        }
    
        /* process mac */
        if (ioctl(sock, SIOCGIFHWADDR, &ifr) != -1) {
            printf("Mac address: %02x:%02x:%02x:%02x:%02x:%02x\n",
                    (unsigned char)ifr.ifr_hwaddr.sa_data[0],
                    (unsigned char)ifr.ifr_hwaddr.sa_data[1],
                    (unsigned char)ifr.ifr_hwaddr.sa_data[2],
                    (unsigned char)ifr.ifr_hwaddr.sa_data[3],
                    (unsigned char)ifr.ifr_hwaddr.sa_data[4],
                    (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
        }
    
        /* process mtu */
        if (ioctl(sock, SIOCGIFMTU, &ifr) != -1) {
            printf("MTU: %d\n", ifr.ifr_mtu);
        }
    
        /* die if cannot get address */
        if (ioctl(sock, SIOCGIFADDR, &ifr) == -1) {
            close(sock);
            return;
        }
    
        /* process ip */
        ipaddr = (struct sockaddr_in *)&ifr.ifr_addr;
        if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
            printf("Ip address: %s\n", address);
        }
    
        /* try to get broadcast */
        if (ioctl(sock, SIOCGIFBRDADDR, &ifr) != -1) {
            ipaddr = (struct sockaddr_in *)&ifr.ifr_broadaddr;
            if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
                printf("Broadcast: %s\n", address);
            }
        }
    
        /* try to get mask */
        if (ioctl(sock, SIOCGIFNETMASK, &ifr) != -1) {
            ipaddr = (struct sockaddr_in *)&ifr.ifr_netmask;
            if (inet_ntop(AF_INET, &ipaddr->sin_addr, address, sizeof(address)) != NULL) {
                printf("Netmask: %s\n", address);
            }
        }
    
        close(sock);
    }
    

    usage :

    parse_ioctl("eth0");
    
    0 讨论(0)
  • 2020-11-27 04:07

    One way to get to the bottom of problems like this, particularly in cases when you don't have source, is strace.

    It gives you a list of all the system calls made by any program you pass it, along with their arguments and return values. If your program just dumps some info and quits rather than running for an extended time it can be pretty straightforward to just do a man on all the system calls you see that look like they might provide the info you're looking for.

    When I run

    strace ifconfig
    

    Some of the interesting calls are:

    open("/proc/net/dev", O_RDONLY)         = 6
    

    followed by a bunch of ioctls, corroborating @payne's answer:

    ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0",    ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0
    ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=84:2b:2b:b7:9e:6d}) = 0
    ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0
    ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0
    
    0 讨论(0)
  • 2020-11-27 04:09

    Yes, ifconfig itself is written in C. :) See: http://cvsweb.netbsd.org/bsdweb.cgi/src/sbin/ifconfig/ifconfig.c?rev=1.169&content-type=text/x-cvsweb-markup

    Do man netdevice to see the details (on Linux). You use the ioctl() system call.

    0 讨论(0)
提交回复
热议问题