在Linux上嗅探以太网接口
Sniffing an ethernet interface on linux
我正在尝试从特定接口中捕获数据包,而是从所有接口中获取数据包。我在做什么错?
bool Snooper::raw_init (const char *device)
{
uid_t privid = geteuid();
int retval;
bool retVal = false;
do {
if ((retval = setuid(0)) != 0) {
perror("seteuid error");
break;
}
cap_t caps = cap_get_proc();
cap_value_t cap_list[2];
cap_list[0] = CAP_NET_RAW;
cap_list[1] = CAP_SETUID;
if ((retval = cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_list, CAP_SET)) == -1) {
perror("cap_set_flag error");
break;
}
if ((retval = cap_set_proc(caps)) == -1) {
perror("cap_set_proc error");
break;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof (struct ifreq));
/* Open A Raw Socket */
if ((m_sockfd = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL))) < 1) {
perror("Snooper::raw_init:socket Error");
break;
}
/* Set the device to use */
strncpy(ifr.ifr_name, device, strlen(device) + 1);
/* Get the current flags that the device might have */
if (ioctl(m_sockfd, SIOCGIFFLAGS, &ifr) == -1) {
perror("Error: Could not retrieve the flags from the device.n");
break;
}
printf("The interface is ::: %sn", device);
perror("Retrieved flags from interface successfully");
/* Set the old flags plus the IFF_PROMISC flag */
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(m_sockfd, SIOCSIFFLAGS, &ifr) == -1) {
perror("Error: Could not set flag IFF_PROMISC");
break;
}
printf("Setting interface ::: %s ::: to promiscn", device);
/* Configure the device */
if (ioctl(m_sockfd, SIOCGIFINDEX, &ifr) < 0) {
perror("Error: Error getting the device index.n");
break;
}
retVal = true;
} while(false);
if ((retval = seteuid(privid)) != 0) {
perror("seteuid error");
}
return retVal;
}
我首先验证我可以提起扎根,因为IFF_Promisc需要它。然后为UDP流量创建套接字,为设备预成立IOCTL,最后为Promisc。
。现在我有一个插座,我在RECV上循环,但是我也从其他接口中获取数据包。
要从特定接口捕获数据包,必须使用bind
函数将套接字绑定到该接口。您可以查看此答案以示例。
一个可能能够帮助您的小型pcap
程序
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<pcap/pcap.h>
#include<netinet/if_ether.h>
#include<netinet/ip.h>
#include<netinet/tcp.h>
void process_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *buffer)
{
// printf("In Process_Packetn");
struct ethhdr *eth = (struct ethhdr *)(buffer);
printf("%.2x: %.2x: %.2x: %.2x: %.2x: %.2x: %.2x:n ", eth->h_dest[0], eth->h_dest[1], eth->h_dest[2], eth->h_dest[3], eth->h_dest[4], eth->h_dest[5], eth->h_dest[6]);
printf("%x n", htons(eth->h_proto));
if(htons(eth->h_proto)== ETHERTYPE_ARP)
{
printf("ARP PACKETn");
}
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
int ipheader = iph-> ihl *4;
printf("Source IP Address :%sn ", inet_ntoa(iph->saddr));
printf("Destination IP Address :%sn ", inet_ntoa(iph->daddr));
}
int main()
{
pcap_if_t *alldevspec,*devices;
pcap_addr_t *a;
pcap_t *handle;
const char filter_exp[]="IP";
bpf_u_int32 netp;
char errbuf[PCAP_ERRBUF_SIZE];
struct bpf_program fp;
int ret=0, count =1, n=0;
char devs[100][100],*devicename;
ret = pcap_findalldevs(&alldevspec,errbuf);
if(ret < 0)
{
printf("Error in finding the devicesn");
return -1;
}
for(devices = alldevspec; devices!= NULL; devices = devices->next)
{
printf("%d %s-%s n",count, devices->name,devices->description);
for(a=devices->addresses;a;a=a->next)
{
printf("family %d n", (a->addr)->sa_family);
if(devices->name != NULL)
{
strcpy(devs[count], devices->name);
}
switch((a->addr)->sa_family)
{
case AF_INET:
printf("%s n",inet_ntoa(((struct sockaddr_in*)a->addr)->sin_addr.s_addr));
break;
case AF_INET6:
break;
}
}
++count;
}
printf("Enter the device u want to selectn");
scanf("%d",&n);
devicename = devs[n];
handle = pcap_open_live(devicename,65536,1,-1,errbuf);
if(handle == NULL)
{
printf("Error in opening the devicen");
return -1;
}
pcap_compile(handle,&fp, filter_exp,-1,netp);
pcap_setfilter(handle, &fp);
pcap_loop(handle,-1,process_packet,NULL);
return 0;
}
相关文章:
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- Windows.h与GLFW.h的接口
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 为重写std::exception的库生成swig接口时出错
- 内联如何影响模块接口中的成员函数
- COM 接口 c# 封送数组数组
- 如何在 SCIP C++ 接口中获取 MILP 约束矩阵中的系数值
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如何绑定 C++ gRPC 客户端的网络接口
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 如何从实现接口的模板化类实例访问结构
- 带有进度表的 curl 多接口程序
- 动态获取 esp32 的 mac 地址并在以太网库中使用它.
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 我可以在具有一个标头和一个接口的 cpp 文件中有多个嵌入吗?
- 如何使用Qt在Windows上检查网络接口类型是以太网或无线
- 在Linux上嗅探以太网接口
- 是否可以以编程方式检测 Windows XP 上特定以太网接口上的 IP 地址更改?