计网_C语言编程获取本机的mac地址以及mac下pcap编程报错Undefined symbols for architecture x86_64-"_pcap_*****"...的解决办法

来源:互联网 发布:易语言手机轰炸机源码 编辑:程序博客网 时间:2024/05/16 12:38

本文包含以下两部分:

  • ## C语言编程获取本机的mac地址
  • ## mac下pcap编程报错Undefined symbols for architecture x86_64:”__pcap_*****”, referenced from: _main in…的解决方法

关键词:计算机网络; pcap; libpcap; mac; mac地址;

本学期计网lab老师要求我实现用C语言获取本机的mac地址。但像我这么懒的人眼珠一转就想直接调shell,但问过了老师,直接调shell的命令不行,也就意味着system(“ipconfig”)这样的代码不允许出现。不让用就算了吧,那就自己搞。当然,老师明确说了不会就问度娘,那我就问问。。。

上网查了一下,网上相关的实现有很多,比如有调用API的、通过访问网卡获取的,等等。但我这么懒,肯定不想访问网卡什么的(其实也挺容易的),那么应该怎么办呢?

受到ping命令的启发,我的想法是通过一次网络连接请求,获取本机mac地址。在构思结束后我上网查相关资料,才发现我的想法对应的是一个叫ARP协议的东西。好高兴自己居然独立想出来了一个高级的东西~(并不,只是你的思路别人已经造好了轮子而已。。)

ARP的C语言实现网络上有:传送门,但这个太长,我感觉很多功能并不需要。

我利用ARP协议获取本机的mac地址的思路是:模拟接收到一个数据包,并且发送数据包回应(此部分类似ping命令),然后捕获我们回应的数据包进行解析,得到本机的mac地址并不是完全基于ARP,更正为抓取ping命令发送的ICMP包

既然是捕获数据包,那就要用到我们”大名鼎鼎“的数据包捕获函数库PCAP了。

要使用PCAP可能你需要在自己的电脑上安装libpcap这个函数库(是叫函数库嘛?问号脸。。。。)

mac我并没有安装libpcap,好像是自带pcap库了?(便利性赞一个)。其他系统要安装可以百度一下。

好了废话不多说,直接上代码:

/**************************myMacAddress.c*************************************  * Copyright (C) 2017 by guoayng (Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)*  * 实现了C语言获取本机的mac地址 * 备注: * 网上相关的实现有很多,比如有调用API的、通过访问网卡获取的,等等。并且问过了老师,直接调shell的命令不行,也就意味着system(“ipconfig”)这样的代码不允许出现 * 但我不想访问网卡什么的,那么应该怎么办呢? * 受到ping命令的启发,我的想法是通过一次网络连接请求,获取本机mac地址 * 在构思结束后我上网查相关资料,才发现我的想法对应的是一个叫ARP协议的东西 * ARP的C语言实现网络上有:http://blog.csdn.net/wangpengqi/article/details/46240505,但这个太长,我感觉很多功能并不需要 * 我利用ARP协议获取本机的mac地址的思路是:模拟接收到一个数据包,并且发送数据包回应(此部分类似ping命令),然后截取我们回应的数据包进行解析,得到本机的mac地址 * 参考了http://blog.csdn.net/wypblog/article/details/7456829 的资料后,我写出了以下代码。 ****************************************************************************/  #include <stdio.h>#include <pcap/pcap.h>#include <netinet/if_ether.h>int main(){    pcap_t *sniffer_des;    char errbuf[PCAP_ERRBUF_SIZE];// PCAP_ERRBUF_SIZE is in {/usr/include/pcap/pcap.h}                                  // the Defination is {#define PCAP_ERRBUF_SIZE 256}    char *net_dev;    bpf_u_int32 net, mask;    struct bpf_program fp;          // 可理解为结构体实例化(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)    const u_char *packet;    struct pcap_pkthdr hdr;         // 可理解为结构体实例化    struct ether_header *eth_header;// 可理解为结构体实例化    u_char *ptr;    net_dev = "en7";//此处为我的网卡编号,一般的机子此处应为eth0    if(pcap_lookupnet(net_dev, &net, &mask, errbuf) == -1){        printf("get net error:%s\n", errbuf);        return 1;    }    sniffer_des = pcap_open_live(net_dev, 1024, 1, 5000, errbuf);// 调用PCAP_API中的pcap_open_live    // sniffer_des = pcap_open_live(net_dev, 65535, 1, 5000, errbuf);// 调用PCAP_API中的pcap_open_live    // 参考http://blog.csdn.net/cheng_fangang/article/details/8608126 :发现在pcap_t* handle = pcap_open_live(sDevice, 65535, 1, 0, errbuf);这个函数时有问题了,当设置到1024的时候一点都不丢包,但是65535的时候就丢包了,(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)    // 看了pcap的pcap_open_live函数也没有看明白什么原因,我怀疑时内部处理分配内存的时候,每一个包分配65535大小肯定比分配处理1024包大小的内存耗时,所以导致丢包。    // 请各位用pcap的时候牢记这个东东吧,我可吃过苦了。。。。    if(sniffer_des == NULL){        printf("pcap_open_live%s\n", errbuf);        return 1;    }    if(pcap_setfilter(sniffer_des, &fp) == -1){        printf("pcap_setfilter() error\n");        return 1;    }    packet = pcap_next(sniffer_des, &hdr);    if(packet == NULL){        printf("pacap_next() failed\n");        return 1;    }    eth_header = (struct ether_header*)packet;    if(ntohs(eth_header->ether_type) != ETHERTYPE_IP){// ETHERTYPE_IP is in {/usr/include/net/ethernet.h},                                                       // the Defination is {#define ETHERTYPE_IP 0x0800}==>IP数据报的以太网帧类型也是0x0800(IPv4: 0x0800)        printf("not ethernet packet\n");              // 若ether_type(类型)不是ip数据报,则报错(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)        return 1;    }    ptr = eth_header->ether_shost;    int i = 0;    printf("\nMy Physical Adress(MAC):");    while(i < ETHER_ADDR_LEN){                          // The number of bytes in an ethernet (MAC) address.                                                        // #define  ETHER_ADDR_LEN      6        printf(" %x:", *ptr++);        i++;    }    printf("\n");    return 0;}

好了进入下一部分,gcc编译时报错如下信息:(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

Undefined symbols for architecture x86_64:  "_pcap_lookupnet", referenced from:      _main in xxxx.o

以上错误是由于没有告诉gcc要链接造成的。是的,不要以为include了pcap.h就够了,在编译的时候还需要:(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

~$ gcc myMacAddress.c -l pcap -o sgyMac

看到-l pcap了吗,这是告诉gcc还要动态链接pcap库

然后,成功编译。(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)

调用

调用很简单,另一个终端ping本机地址如192.168.1.10,然后新开一个终端,输入:
note:有时候会由于权限不够,需要sudo

~$ sudo ./sgyMac

回车,等待一会儿,得到完美输出:

~$ sudo ./sgyMacPassword:My Physical Adress(MAC): xx: xx: xx: xx: xx: xx://我的mac地址不在这里贴出来了

与终端命令ifconfig的结果对比后,完全正确。

文中所用C代码运行时并没有返回mac地址,而是报“not ethernet packet”

因为代码基于抓包,所以我自己在测试的时候也发生过这种情况,没有返回MAC地址。经过测试我发现,在有线连接和手机热点下的无线连接,程序都可以正常运行,但大局域网(比如商场的公共Wi-Fi)下很小几率会报这个错,我猜测是丢包?不是很清楚为什么。我可以确定的是只要是固定连接(网线那种或者开手机热点只给自己用那种),程序都可以获得MAC地址,但其他情况下就很迷。这个如果各位有想法可以在评论里与我交流。

至此本文结束!

References

[1] https://ubuntuforums.org/showthread.php?t=125444
[2] https://stackoverflow.com/questions/25583379/libpcap-not-linking-netbeans
[3] http://blog.csdn.net/wypblog/article/details/7456829
[4] http://blog.csdn.net/cheng_fangang/article/details/8608126

(Copyright © http://blog.csdn.net/s_gy_zetrov. All Rights Reserved)


visitor tracker
访客追踪插件


阅读全文
0 0