2021年3月3日 星期三

【Linux】取得所有網卡裝置名稱範例 in C

在ubuntu上,用C取得所有網卡裝置名稱範例程式,試了這個範例,在某段會卡住,基本上網卡名稱是拿的到的,目前夠用,就先留下來,以後需要再拿來改。

#include <net/if.h>

#include <sys/ioctl.h>

 

#define MAXINTERFACES 16

 

int main (argc, argv)

   register int argc;

   register char *argv[];

{

   register int fd, intrface, retn = 0;

   struct ifreq buf[MAXINTERFACES];

   struct arpreq arp;

   struct ifconf ifc;

   if ((fd = socket (AF_INET, SOCK_DGRAM, 0)) >= 0) {

       ifc.ifc_len = sizeof buf;

       ifc.ifc_buf = (caddr_t) buf;

       if (!ioctl (fd, SIOCGIFCONF, (char *) &ifc))

       {

           //獲取接口信息

           intrface = ifc.ifc_len / sizeof (struct ifreq);

           printf("interface num is intrface=%d\n\n\n",intrface);

           //根據接口信息循環獲取設備IP和MAC地址

           while (intrface-- > 0) {

               //獲取設備名稱

               printf ("net device %s\n", buf[intrface].ifr_name);

 

               //判斷網卡類型

               if (!(ioctl (fd, SIOCGIFFLAGS, (char *) &buf[intrface]))) {

                   if (buf[intrface].ifr_flags & IFF_PROMISC) {

                       puts ("the interface is PROMISC");

                       retn++;

                   }

               }

               else {

                   char str[256];

                   sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);

                   perror (str);

               }

               //判斷網卡狀態

               if (buf[intrface].ifr_flags & IFF_UP) {

                   puts("the interface status is UP");

               }

               else {

                   puts("the interface status is DOWN");

               }

               //獲取當前網卡的IP地址

               if (!(ioctl (fd, SIOCGIFADDR, (char *) &buf[intrface]))) {

                   puts("IP address is:");

                   puts((char *)inet_ntoa(((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr));

                   puts("");

                   //puts (buf[intrface].ifr_addr.sa_data);

               }

               else {

                   char str[256];

                   sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);

                   perror (str);

               }

               /* this section can't get Hardware Address,I don't know whether the reason is module driver*/

               #ifdef SOLARIS

               //獲取MAC地址

               arp.arp_pa.sa_family = AF_INET;

               arp.arp_ha.sa_family = AF_INET;

               ((struct sockaddr_in*)&arp.arp_pa)->sin_addr.s_addr=((struct sockaddr_in*)(&buf[intrface].ifr_addr))->sin_addr.s_addr;

               if (!(ioctl (fd, SIOCGARP, (char *) &arp))) {

                   puts ("HW address is:");

                   //以十六進制顯示MAC地址

                   printf("%02x:%02x:%02x:%02x:%02x:%02x\n",

                       (unsigned char)arp.arp_ha.sa_data[0],

                       (unsigned char)arp.arp_ha.sa_data[1],

                       (unsigned char)arp.arp_ha.sa_data[2],

                       (unsigned char)arp.arp_ha.sa_data[3],

                       (unsigned char)arp.arp_ha.sa_data[4],

                       (unsigned char)arp.arp_ha.sa_data[5]);

                   puts("");

                   puts("");

               }

               #else

               #if 0

               /*Get HW ADDRESS of the net card */

               if (!(ioctl (fd, SIOCGENADDR, (char *) &buf[intrface]))) {

                   puts ("HW address is:");

                   printf("%02x:%02x:%02x:%02x:%02x:%02x\n",

                       (unsigned char)buf[intrface].ifr_enaddr[0],

                       (unsigned char)buf[intrface].ifr_enaddr[1],

                       (unsigned char)buf[intrface].ifr_enaddr[2],

                       (unsigned char)buf[intrface].ifr_enaddr[3],

                       (unsigned char)buf[intrface].ifr_enaddr[4],

                       (unsigned char)buf[intrface].ifr_enaddr[5]);

                   puts("");

                   puts("");

               }

               #endif

               if (!(ioctl (fd, SIOCGIFHWADDR, (char *) &buf[intrface]))) {

                   puts ("HW address is:");

                   printf("%02x:%02x:%02x:%02x:%02x:%02x\n",

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[0],

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[1],

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[2],

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[3],

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[4],

                       (unsigned char)buf[intrface].ifr_hwaddr.sa_data[5]);

                   puts("");

                   puts("");

               }

               #endif

               else {

                   char str[256];

                   sprintf (str, "cpm: ioctl device %s", buf[intrface].ifr_name);

                   perror (str);

               }

           } //while

       } else

           perror ("cpm: ioctl");

   } else

       perror ("cpm: socket");

   close (fd);

   return retn;

}


關於地址轉換函數,包含inet_addr(), inet_aton()和inet_ntoa()三個函數用於二進制地址格式與點分十進制之間的相互轉換,但是僅僅適用於IPv4,兩個新函數inet_ntop( )和inet_pton()具有相似的功能,並且同時支持IPv4和IPv6。

inet_addr(), inet_aton()和inet_ntoa()函數

inet_addr()函數
功能:inet_addr()函數用於將點分十進制IP地址轉換成網絡字節序IP地址;
原型:in_addr_t inet_addr(const char *cp);
返回值:如果正確執行將返回一個無符號長整數型數。如果傳入的字符串不是一個合法的IP地址,將返回INADDR_NONE;
頭文件:arpa/inet.h (Linux)

inet_aton()函數
功能:inet_aton()函數用於將點分十進制IP地址轉換成網絡字節序IP地址;
原型:int inet_aton(const char *string, struct in_addr *addr);
返回值:如果這個函數成功,函數的返回值非零,如果輸入地址不正確則會返回零;
頭文件:sys/socket.h (Linux)

inet_ntoa()函數
功能inet_ntoa()函數用於網絡字節序IP轉化點分十進制IP;
原型:char *inet_ntoa (struct in_addr);
返回值:若無錯誤發生,inet_ntoa()返回一個字符指針。否則的話,返回NULL。其中的數據應在下一個WINDOWS套接口調用前複製出來;
頭文件:arpa/inet.h (Linux)

inet_ntop()和inet_pton()函數

inet_ntop()函數
功能:inet_ntop()函數用於將網絡字節序的二進制地址轉換成文本字符串;
原型:const char *inet_pton(int domain, const void *restrict addr, char *restrict str, socklen_t size);
返回值:若成功,返回地址字符串指針;若出錯,返回NULL;
頭文件:arpa/inet.h (Linux)

inet_pton()函數
功能:inet_pton()函數用於將文本字符串格式轉換成網絡字節序二進制地址;
原型:int inet_pton(int domain, const char *restrict str, void *restrict addr);
返回值:若成功,返回1;若格式無效,返回0;若出錯,返回-1;
頭文件:arpa/inet.h (Linux)

REF

沒有留言:

張貼留言