QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1310|回复: 14

libpcap数据截包的一个疑问??

[复制链接]
发表于 2004-10-4 01:26:08 | 显示全部楼层 |阅读模式
最近使用libpcap编写截包程序.
我把截取到的数据包打印出来地址和端口(只截取UDP和TCP. ARP的数据包).

1.如果我选择设备eth0截包. 能截取到UDP和TCP数据包. 可是截取的数据包显示出来之后发现. 地址都是很奇怪的. 比如出现'0.0.0.0:17 ==> 162.154.2.1:32565'这样的东西. 可是我的机子应该没发送这种数据包
2.如果我选择设备ppp0截包. 那么截取不到数据包(只是UDP,TCP,ARP). 因为以太网之中的帧类型不会出现 0x0806(ARP)和0x0800(IP)这样的数据包. 出现的帧类型都是 0x8864,0x26之类的数据包. 所以截取不到UDP & TCP的数据

我很疑惑这个问题. 不知道大家有相关编程经验的人有没有一些解释. 谢谢~~~~~

ps:我现在使用的系统是FC1. 带的libpcap是 0.6.2.太老了.我想换了.怎么换?有直接使用的rpm吗? 当然有SRC的更好
 楼主| 发表于 2004-10-4 22:30:35 | 显示全部楼层
没人回答吗?
自己顶一下吧
回复

使用道具 举报

发表于 2004-10-4 22:41:02 | 显示全部楼层
有的问题是tcp的,以前看过,快忘光了。

服务程序监听端口,例如监听23端口,每进行一次连接服务程序都会从系统获得一个空的端口号来建立连接,然后继续监听23,所以就会有162.154.2.1:32565这样的东西,至于0.0.0.0好像是个固定的功能地址。

即使你的系统没有进行有用的通信,如果链接在一个活跃的网里,你的系统也是需要不断的处理各种来自网络的诸如查询,广播之类的包。你拿一个类似于sniffer的工具就会看到你的系统一直就不闲着。

总之,我是忘的差不多了,还需要别人继续指点或者找本tcp/ip的文档来看。
回复

使用道具 举报

发表于 2004-10-4 22:41:32 | 显示全部楼层

Re: libpcap数据截包的一个疑问??

[quote:8baec7d171="daixi"]最近使用libpcap编写截包程序.
我把截取到的数据包打印出来地址和端口(只截取UDP和TCP. ARP的数据包).

1.如果我选择设备eth0截包. 能截取到UDP和TCP数据包. 可是截取的数据包显示出来之后发现. 地址都是很奇怪的. 比如出现'0.0.0.0:17 ==> 162.154.2.1:32565'这样的东西. 可是我的机子应该没发送这种数据包[/quote]你的地址提取有没问题?
2.如果我选择设备ppp0截包. 那么截取不到数据包(只是UDP,TCP,ARP). 因为以太网之中的帧类型不会出现 0x0806(ARP)和0x0800(IP)这样的数据包. 出现的帧类型都是 0x8864,0x26之类的数据包. 所以截取不到UDP & TCP的数据
为何没有ARP和IP包?

最好把能运行的、能揭示你的问题的、最简化的源代码贴出来。代码才能说明一切   
回复

使用道具 举报

 楼主| 发表于 2004-10-4 22:59:42 | 显示全部楼层
#include <stdio.h>
#include <stdlib.h>
#include <net/ethernet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <pcap.h>

#define MY_ETH_LEN 14
#define MY_DEBUG

void proc_ip_tcp(struct iphdr *pip, const unsigned char *packet, unsigned int plen) {
}

void proc_ip_udp(struct iphdr *pip, const unsigned char *packet, unsigned int plen) {
        struct udphdr *pudp = NULL;
        char *pdata = NULL;
        int data_len = 0;
        struct in_addr ins;
        char *sa;
        struct in_addr ind;
        char *da;
       
        pudp = (struct udphdr *)(packet + MY_ETH_LEN + pip->ihl);
        pdata = (char *)(packet + MY_ETH_LEN + pip->ihl + pudp->len);
        data_len = plen - MY_ETH_LEN - pip->ihl - pudp->len;
       
        ins.s_addr = pip->saddr;
        sa = (char *)inet_ntoa(ins);
        ind.s_addr = pip->daddr;
        da = (char *)inet_ntoa(ind);
        printf("IP - UDP:\n");
        printf("ttl=%u\n", pip->ttl);
        printf("%s:%u ==> %s:%u\n", sa, pudp->source, da, pudp->dest);
        printf("======> Length: %u\n", plen);
}

void proc_ip(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        struct iphdr *pip = (struct iphdr *)(packet + MY_ETH_LEN);
       
        switch(pip->protocol) {
                case IPPROTO_TCP:
                        proc_ip_tcp(pip, packet, pkthdr->caplen);
                        break;
                case IPPROTO_UDP:
                        proc_ip_udp(pip, packet, pkthdr->caplen);
                        break;
                default:
                        break;
        }
}

void proc_arp(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        printf("===> ARP\n");
}

void proc_rarp(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        printf("===> RARP\n");
}

void my_callback(unsigned char *unless, const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        struct ether_header *peth = (struct ether_header *)packet;
        u_int16_t eth_type = ntohs(peth->ether_type);
       
        #ifdef MY_DEBUG
        printf("Capture one packet! Eth_Type: 0x%x\n", eth_type);
        #endif
       
        switch(eth_type) {
                case ETHERTYPE_IP:
                        proc_ip(pkthdr, packet);
                        break;
                case ETHERTYPE_ARP:
                        proc_arp(pkthdr, packet);
                        break;
                case ETHERTYPE_REVARP:
                        proc_rarp(pkthdr, packet);
                        break;
                default:
                        break;
        }
        return;
}

void proc_cap(char *device, char *filter) {
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *descr;
       
        descr = pcap_open_live(device, BUFSIZ, 0, -1, errbuf);
        if(descr == NULL) {
                printf("Cannot open device live!\n");
                return;
        }
       
        pcap_loop(descr, 100, my_callback, NULL);
}

void show_help() {
        printf("Usage: capdump -d device_name -f filter_string\n");
        printf("    -d assign a device name(needed)\n");
        printf("    -f assign a filter string(optional)\n");
}

void my_main(int argc, char *argv[]) {
        int c = 0;
        char *device = NULL;
        char *filter = NULL;
        int h = 0;
       
        while((c = getopt(argc, argv, "d:f:h")) != -1) {
                switch(c) {
                        case 'd':
                                device = optarg;
                                break;
                        case 'f':
                                filter = optarg;
                                break;
                        case 'h':
                                show_help();
                                h = 1;
                                break;
                        default:
                                break;
                }
        }
        #ifdef MY_DEBUG
        printf("Device: %s, Filter: %s\n", device, filter);
        #endif
       
        if(h == 1) return;
       
        if(device==NULL) {
                printf("Cannot get device!\n");
                return;
        }
       
        proc_cap(device, filter);
}

int main(int argc, char *argv[]) {
        my_main(argc, argv);
        return 0;
}

上面是代码
很简单.
在函数 proc_ip_udp 之中输出的结果就是我贴子描述的了
真是奇怪了.
回复

使用道具 举报

发表于 2004-10-4 23:09:57 | 显示全部楼层
我记得Ethereal是用的libpcap,装套看看,与你的有什么不同。

http://www.ethereal.com/
回复

使用道具 举报

 楼主| 发表于 2004-10-4 23:14:08 | 显示全部楼层
我的实在是简单
纯粹是为了学习使用
还有一个就是方便随时可以看到自己机子TCP和UDP数据包的走向
其他的没什么.
回复

使用道具 举报

发表于 2004-10-5 11:16:32 | 显示全部楼层
在端口前加个ntohs函数转换一下。
你有ppp0端口?ppp协议不能用以太网的方法解析。
回复

使用道具 举报

 楼主| 发表于 2004-10-5 17:41:21 | 显示全部楼层
O.K.

我看看先
弄不明白了,再来问了.
回复

使用道具 举报

发表于 2004-10-5 20:21:36 | 显示全部楼层
我改过的[quote:7dd034c398="daixi"][code:1]#include <stdio.h>
#include <stdlib.h>
#include <net/ethernet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <pcap.h>

#define MY_ETH_LEN 14
#define MY_DEBUG

void proc_ip_tcp(struct iphdr *pip, const unsigned char *packet, unsigned int plen) {
}

void proc_ip_udp(struct iphdr *pip, const unsigned char *packet, unsigned int plen) {
        struct udphdr *pudp = NULL;
        char *pdata = NULL;
        int data_len = 0;
        struct in_addr ins;
        char *sa;
        struct in_addr ind;
        char *da;
        //下面改
        pudp = (struct udphdr *)(packet + sizeof(struct   ether_header)+sizeof(struct iphdr));
        pdata = (char *)(pudp + pudp->len);
         //改完
        data_len = plen - MY_ETH_LEN - pip->ihl - pudp->len;

       
        ins.s_addr = pip->saddr;
        sa = (char *)inet_ntoa(ins);
        ind.s_addr = pip->daddr;
        da = (char *)inet_ntoa(ind);
        printf("IP - UDP:\n");
        printf("ttl=%u\n", pip->ttl);
         //改
        printf("%s:%u ==> %s:%u\n", sa, ntohs(pudp->source), da, ntohs(pudp->dest));
          //改完
        printf("======> Length: %u\n", plen);
}

void proc_ip(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        struct iphdr *pip = (struct iphdr *)(packet + MY_ETH_LEN);
       
        switch(pip->protocol) {
                case IPPROTO_TCP:
                        proc_ip_tcp(pip, packet, pkthdr->caplen);
                        break;
                case IPPROTO_UDP:
                        proc_ip_udp(pip, packet, pkthdr->caplen);
                        break;
                default:
                        break;
        }
}

void proc_arp(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        printf("===> ARP\n");
}

void proc_rarp(const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        printf("===> RARP\n");
}

void my_callback(unsigned char *unless, const struct pcap_pkthdr *pkthdr, const unsigned char *packet) {
        struct ether_header *peth = (struct ether_header *)packet;
        u_int16_t eth_type = ntohs(peth->ether_type);
       
        #ifdef MY_DEBUG
        printf("Capture one packet! Eth_Type: 0x%x\n", eth_type);
        #endif
       
        switch(eth_type) {
                case ETHERTYPE_IP:
                        proc_ip(pkthdr, packet);
                        break;
                case ETHERTYPE_ARP:
                        proc_arp(pkthdr, packet);
                        break;
                case ETHERTYPE_REVARP:
                        proc_rarp(pkthdr, packet);
                        break;
                default:
                        break;
        }
        return;
}

void proc_cap(char *device, char *filter) {
        char errbuf[PCAP_ERRBUF_SIZE];
        pcap_t *descr;
       
        descr = pcap_open_live(device, BUFSIZ, 0, -1, errbuf);
        if(descr == NULL) {
                printf("Cannot open device live!\n");
                return;
        }
       
        pcap_loop(descr, 100, my_callback, NULL);
}

void show_help() {
        printf("Usage: capdump -d device_name -f filter_string\n");
        printf("    -d assign a device name(needed)\n");
        printf("    -f assign a filter string(optional)\n");
}

void my_main(int argc, char *argv[]) {
        int c = 0;
        char *device = NULL;
        char *filter = NULL;
        int h = 0;
       
        while((c = getopt(argc, argv, "d:f:h")) != -1) {
                switch(c) {
                        case 'd':
                                device = optarg;
                                break;
                        case 'f':
                                filter = optarg;
                                break;
                        case 'h':
                                show_help();
                                h = 1;
                                break;
                        default:
                                break;
                }
        }
        #ifdef MY_DEBUG
        printf("Device: %s, Filter: %s\n", device, filter);
        #endif
       
        if(h == 1) return;
       
        if(device==NULL) {
                printf("Cannot get device!\n");
                return;
        }
       
        proc_cap(device, filter);
}

int main(int argc, char *argv[]) {
        my_main(argc, argv);
        return 0;
}


[/code:1][/quote]
回复

使用道具 举报

 楼主| 发表于 2004-10-5 21:03:13 | 显示全部楼层
//下面改
   pudp = (struct udphdr *)(packet + sizeof(struct   ether_header)+sizeof(struct iphdr));
   pdata = (char *)(pudp + pudp->len);
         //改完

老大
这一段好像有问题. IP头有可选部分的
这样计算可能不太准确
回复

使用道具 举报

 楼主| 发表于 2004-10-6 13:25:24 | 显示全部楼层
又没有人看到我的问题了吗?
嘿嘿
我自己顶一下
回复

使用道具 举报

发表于 2004-10-6 13:41:06 | 显示全部楼层
楼上的对
回复

使用道具 举报

 楼主| 发表于 2004-10-7 21:48:18 | 显示全部楼层
我使用 ethereal 截包测试了一下
如果在 eth0 截包的话. 在以太网头和IP头之间加了一个pppoe头
字节数不定,看具体的帧类型了
而且以太网头的帧类型就是 0x8864或者是 0x8863
呵呵

如果跳过这几个字节
我的程序应该能正确显示出来了
至于其他的一些帧类型 0x26等等之类的
只能等以后多找到一些资料才能知道是干什么的了

斑竹说的对,确实不能按照平常的方法去解析数据包
一定要按照pppoe协议去解析数据包的
回复

使用道具 举报

 楼主| 发表于 2004-10-7 21:53:42 | 显示全部楼层
补充一下
刚才在网上找到了华为公司的一个关于pppoe协议的一个word文档
呵呵
可以参考一下了
地址是:
http://www.net130.com/tutorial/other/PPPOE%20xy.doc

另外RFC文档也是很好的资料了
http://www.faqs.org/rfcs/rfc2516.html

需要的兄弟可以看看
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-7 10:53 , Processed in 0.052350 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表