• linux获取Mac地址


    1.基础用法,获取eth0的mac地址

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include // struct ifreq
    7. int get_mac(unsigned char binMAC[6])
    8. {
    9. int sock;
    10. struct ifreq ifr;
    11. unsigned char *puc;
    12. memset(binMAC, 0, 6);
    13. sock = socket(AF_INET, SOCK_DGRAM, 0);
    14. if (sock == -1)
    15. {
    16. perror("socket");
    17. return -1;
    18. }
    19. strcpy(ifr.ifr_name, "eth0"); // 虚拟机中是ens33
    20. if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0)
    21. {
    22. close(sock);
    23. perror("ioctl");
    24. return -1;
    25. }
    26. puc = ifr.ifr_hwaddr.sa_data;
    27. close(sock);
    28. memcpy(binMAC, puc, 6);
    29. return 0;
    30. }
    31. int main(){
    32. unsigned char mac[6];
    33. get_mac(mac);
    34. printf("get_mac: %02x-%02X-%02X-%02X-%02X-%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    35. }

    此处是通过设置ifr_name,然后通过ioctl获取mac地址,ifr_name一般是eth0或者ens33。无论是否联网都可以获取到,但是当程序运行在其他客户端,不可能要求用户那里的网卡名称也是eth0,所以此方法仅能用作本地测试,或者用命令行方式传入网卡名称,然后获取指定网卡名称的mac地址。可是ifconfig命令不是更好用更方便吗?

    2.遍历活动网卡

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include // struct ifreq
    8. int print_macs()
    9. {
    10. int sock;
    11. int i = 0, ifCount = 0;
    12. int code = 0;
    13. struct ifreq ifr;
    14. struct ifreq* it = NULL;
    15. struct ifconf ifc;
    16. unsigned char* pBuffer = NULL;
    17. unsigned char *puc = NULL;
    18. sock = socket(AF_INET, SOCK_DGRAM, 0);
    19. if (sock == -1)
    20. {
    21. perror("socket");
    22. return -1;
    23. }
    24. pBuffer = (unsigned char*)malloc(3000);
    25. ifc.ifc_len = 3000;
    26. ifc.ifc_buf = pBuffer;
    27. code = ioctl(sock, SIOCGIFCONF, &ifc);
    28. printf("ioctl return %d, ifc_len:3000->%d, ifr size:%d\n", code, ifc.ifc_len, sizeof(struct ifreq));
    29. if (code < 0)
    30. {
    31. free(pBuffer);
    32. close(sock);
    33. perror("ioctl");
    34. return -1;
    35. }
    36. it = ifc.ifc_req;
    37. ifCount = ifc.ifc_len/sizeof(struct ifreq);
    38. for(i = 0; i < ifCount; ++i){
    39. strcpy(ifr.ifr_name, it[i].ifr_name);
    40. code = ioctl(sock, SIOCGIFFLAGS, &ifr);
    41. printf("\n%d:%s:\n", i, ifr.ifr_name);
    42. if(0 == code){
    43. printf("flags:%x\n", ifr.ifr_flags);
    44. }else{
    45. printf("flagserror\n");
    46. }
    47. code = ioctl(sock, SIOCGIFHWADDR, &ifr);
    48. if(0 == code){
    49. puc = ifr.ifr_hwaddr.sa_data;
    50. printf("mac:%02x-%02x-%02x-%02x-%02x-%02x\n", \
    51. puc[0], puc[1], puc[2], puc[3], puc[4], puc[5]);
    52. }else{
    53. printf("mac:errrrrrrrr\n");
    54. }
    55. }
    56. close(sock);
    57. free(pBuffer);
    58. return 0;
    59. }
    60. int main(){
    61. print_macs();
    62. }

    ioctl调用SIOCGIFCONF只能获取到活动网卡,如果把ens33或者eth0的网络连接断开,就获取不到了。

    3.参考ifconfig

    经过方式1和2,只要能获取到网卡的名称就能获取到mac地址了,但是方式2获取不到无连接的网卡,方式1能获取mac地址却不能提前知道网卡名称。只能想着用其他方式获取网卡名称了。

    查看了ifconfig的部分源码发现:

    interface name是从/proc/net/dev中读取的。如虚拟机从该文件中读到了ens33,

    address是从/sys/class/net/ens33/address中读取的,ens33是interface name,address是ens33的其中一个属性,ens33目录下还有多个其他文件。通过文件属性查看是一个symbol link,指向一个device。

    小贴士:

    ioctl参数:

    man ioctl_list

    man的输出窗口中输入/sock可以搜索到关键词sock,下面就是sock相关的ioctl的command

    sock的ioctl参数主要是ifreq和ifconf

    man netdevice可以看到两个结构体的定义

  • 相关阅读:
    《C和指针》笔记35:结构体
    复盘一个诡异的Bug
    Redis可视化工具-Another Redis Desktop Manager 安装
    C与C++的区别
    Java--Spring之IoC控制反转;基于注解的DI
    linux下使用Docker Compose部署Spug实现公网远程访问
    liunx各大发行版(centos,rocky,ubuntu,国产麒麟kylinos)网卡配置和包管理方面的区别
    Windows安装部署启动Celery,python
    Go语言连不上 Mysql
    应用回归分析:泊松回归
  • 原文地址:https://blog.csdn.net/youyudexiaowangzi/article/details/126037809