Linux系统编程获取IP,子网掩码,网关等

时间:2019-02-20
本文章向大家介绍Linux系统编程获取IP,子网掩码,网关等,主要包括Linux系统编程获取IP,子网掩码,网关等使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

    最近项目中需要获取linux系统的所有网口信息并设置默认网口,通过查询资料发现通过linux提供的ioctl()函数可以获取相关信息。下面首先介绍几个需要使用到的结构体,然后提供一个实例。

     1. 结构体ifconf和ifreq

//ifconf通常是用来保存所有接口信息的
struct ifconf 
{
    int    ifc_len;            /* size of buffer    */
    union 
    {
        char *ifcu_buf;                        /* input from user->kernel*/
        struct ifreq *ifcu_req;        /* return from kernel->user*/
    } ifc_ifcu;
};
 
//ifreq用来保存某个接口的信息
struct ifreq {
    char ifr_name[IFNAMSIZ];
    union {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        short ifru_flags;
        int ifru_metric;
        caddr_t ifru_data;
    } ifr_ifru;
};

    2. 结构体sockaddr和sockaddr_in

struct sockaddr {
    unsigned short    sa_family;    // 2 bytes address family, AF_xxx
    char              sa_data[14];     // 14 bytes of protocol address
};
 
struct sockaddr_in {
    short            sin_family;       // 2 bytes e.g. AF_INET, AF_INET6
    unsigned short   sin_port;    // 2 bytes e.g. htons(3490)
    struct in_addr   sin_addr;     // 4 bytes see struct in_addr, below
    char             sin_zero[8];     // 8 bytes zero this if you want to
}; 
struct in_addr {
    unsigned long s_addr;          // 4 bytes load with inet_pton()
};

    二者长度一样,都是16个字节,即占用的内存大小是一致的,因此可以互相转化。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。

    3. 实例

  #include <stdio.h>
  #include <string.h>
  #include <net/if.h>
  #include <sys/ioctl.h>
  #include <arpa/inet.h>
  #include <errno.h>
   
  int getInterfaceInfo(void)
  {
      int fd;
      int interfaceNum = 0;
      struct ifreq buf[16];
      struct ifconf ifc;
      struct ifreq ifrcopy;
      char mac[16] = {0};
      char ip[32] = {0};
      char broadAddr[32] = {0};
      char subnetMask[32] = {0};
  
      if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
      {
          perror("socket");
  
          close(fd);
          return -1;
      }
  
      ifc.ifc_len = sizeof(buf);
      ifc.ifc_buf = (caddr_t)buf;
      if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc))//获取所有网口信息
      {
          interfaceNum = ifc.ifc_len / sizeof(struct ifreq);
          printf("interface num = %dn", interfaceNum);
          while (interfaceNum-- > 0) //逐个提取
          {
              printf("ndevice name: %sn", buf[interfaceNum].ifr_name);
  
              //ignore the interface that not up or not runing  
              ifrcopy = buf[interfaceNum];
              if (ioctl(fd, SIOCGIFFLAGS, &ifrcopy))//设置网口标记
              {
                  printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);  
                  close(fd);
                  return -1;
              }
  
              //get the mac of this interface  
              if (!ioctl(fd, SIOCGIFHWADDR, (char *)(&buf[interfaceNum])))
              {
                  memset(mac, 0, sizeof(mac));
                  snprintf(mac, sizeof(mac), "%02x%02x%02x%02x%02x%02x",
                      (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[0],
                      (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[1],
                      (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[2],
                      (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[3],
                      (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[4],
                     (unsigned char)buf[interfaceNum].ifr_hwaddr.sa_data[5]);
                  printf("device mac: %sn", mac);
              }
              else
              {
                  printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                  close(fd);
                  return -1;
              }
  
              //get the IP of this interface    
              if (!ioctl(fd, SIOCGIFADDR, (char *)&buf[interfaceNum]))
              {
                  snprintf(ip, sizeof(ip), "%s",
                      (char *)inet_ntoa(((struct sockaddr_in * &
                    (buf[interfaceNum].ifr_addr))->sin_addr));
                  printf("device ip: %sn", ip);
              }
              else
              {
                  printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                  close(fd);
                  return -1;
              }
  
              //get the broad address of this interface    
              if (!ioctl(fd, SIOCGIFBRDADDR, &buf[interfaceNum]))
              {
                  snprintf(broadAddr, sizeof(broadAddr), "%s",
                      (char *)inet_ntoa(((struct sockaddr_in *)&
                        (buf[interfaceNum].ifr_broadaddr))->sin_addr));
                  printf("device broadAddr: %sn", broadAddr);
              }
              else
              {
                  printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                  close(fd);
                  return -1;
              }
   
             //get the subnet mask of this interface  
             if (!ioctl(fd, SIOCGIFNETMASK, &buf[interfaceNum]))
             {
                 snprintf(subnetMask, sizeof(subnetMask), "%s",
                     (char *)inet_ntoa(((struct sockaddr_in *)&
                        (buf[interfaceNum].ifr_netmask))->sin_addr));
                 printf("device subnetMask: %sn", subnetMask);
             }
             else
             {
                 printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
                 close(fd);
                 return -1; 
             }
         }
     }
     else
     {
         printf("ioctl: %s [%s:%d]n", strerror(errno), __FILE__, __LINE__);
         close(fd);
         return -1;
     }
   
     close(fd);
     return 0;
}

int main(void)
{
     getInterfaceInfo();
     return 0;
}

 

 

 

 

 

参考:

https://blog.csdn.net/CYKsky/article/details/77986645

https://www.cnblogs.com/fnlingnzb-learner/p/6427388.html