关于 ethernet/IP header host/addr 使用 libpcap 的问题?
Problems about ethernet/IP header host/addr using libpcap?
我正在使用 libpcap 解码一些 ip 数据包。
但是我发现我解码的以太网ether_shost/ether_dhost和ipsaddr/daddr是一样的
我哪里搞砸了?
提前致谢。
这里是回调函数的一部分:
void
got_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet)
{
...
eth_h = (struct ether_header *) packet;
struct ether_addr shost, dhost;
memcpy(&shost, eth_h->ether_shost, sizeof(shost));
memcpy(&dhost, eth_h->ether_dhost, sizeof(dhost));
printf("L2 DLT_EN10MB: %s -> %s\n", ether_ntoa(&shost), ether_ntoa(&dhost)); // shost == dhost?
if (ntohs(eth_h->ether_type) != ETHERTYPE_IP) {
return;
}
// only work for L2 DLT_EN10MB
ip_h = (struct iphdr *) (packet + sizeof(struct ether_header));
if (ip_h->version != 4) {
return;
}
struct in_addr saddr, daddr;
saddr.s_addr = ip_h->saddr;
daddr.s_addr = ip_h->daddr;
printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr)); // saddr == daddr?
printf("%" PRIu32 " -> %" PRIu32 "\n", ntohl(ip_h->saddr), ntohl(ip_h->daddr)); // actually not the same
...
}
inet_ntoa
执行以下操作:
- 将地址的字符串形式放入缓冲区
- Returns缓冲区的地址
关键是每次调用它时它都使用相同的缓冲区!
所以当这条线运行时:
printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr));
首先它将一个地址放入缓冲区,然后将另一个地址放入缓冲区,然后将缓冲区的内容打印两次。
您可以通过将字符串存储在您自己的单独缓冲区中来解决此问题:
char saddr_str[INET_ADDRSTRLEN];
char daddr_str[INET_ADDRSTRLEN];
strcpy(saddr_str, inet_ntoa(saddr));
strcpy(daddr_str, inet_ntoa(daddr));
printf("%s -> %s\n", saddr_str, daddr_str);
或调用 printf
两次:
printf("%s -> ", inet_ntoa(saddr));
printf("%s\n", inet_ntoa(daddr));
ether_ntoa
有同样的问题
我正在使用 libpcap 解码一些 ip 数据包。
但是我发现我解码的以太网ether_shost/ether_dhost和ipsaddr/daddr是一样的
我哪里搞砸了?
提前致谢。
这里是回调函数的一部分:
void
got_packet(u_char *args, const struct pcap_pkthdr *header,
const u_char *packet)
{
...
eth_h = (struct ether_header *) packet;
struct ether_addr shost, dhost;
memcpy(&shost, eth_h->ether_shost, sizeof(shost));
memcpy(&dhost, eth_h->ether_dhost, sizeof(dhost));
printf("L2 DLT_EN10MB: %s -> %s\n", ether_ntoa(&shost), ether_ntoa(&dhost)); // shost == dhost?
if (ntohs(eth_h->ether_type) != ETHERTYPE_IP) {
return;
}
// only work for L2 DLT_EN10MB
ip_h = (struct iphdr *) (packet + sizeof(struct ether_header));
if (ip_h->version != 4) {
return;
}
struct in_addr saddr, daddr;
saddr.s_addr = ip_h->saddr;
daddr.s_addr = ip_h->daddr;
printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr)); // saddr == daddr?
printf("%" PRIu32 " -> %" PRIu32 "\n", ntohl(ip_h->saddr), ntohl(ip_h->daddr)); // actually not the same
...
}
inet_ntoa
执行以下操作:
- 将地址的字符串形式放入缓冲区
- Returns缓冲区的地址
关键是每次调用它时它都使用相同的缓冲区!
所以当这条线运行时:
printf("%s -> %s\n", inet_ntoa(saddr), inet_ntoa(daddr));
首先它将一个地址放入缓冲区,然后将另一个地址放入缓冲区,然后将缓冲区的内容打印两次。
您可以通过将字符串存储在您自己的单独缓冲区中来解决此问题:
char saddr_str[INET_ADDRSTRLEN];
char daddr_str[INET_ADDRSTRLEN];
strcpy(saddr_str, inet_ntoa(saddr));
strcpy(daddr_str, inet_ntoa(daddr));
printf("%s -> %s\n", saddr_str, daddr_str);
或调用 printf
两次:
printf("%s -> ", inet_ntoa(saddr));
printf("%s\n", inet_ntoa(daddr));
ether_ntoa
有同样的问题