欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-03 23:21:35
...

    最近项目中需要获取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