pcap(Packet capture library)的简单应用
来源:互联网 发布:previous java 编辑:程序博客网 时间:2024/05/20 18:02
pcap目前是一个应用广泛的针对网络接口数据包抓取的共享库。
该系统对数据抓取提供一个高层的接口,获得指定网络的全部
数据包,包括那些目的地址不是本机的数据包。
下面的程序是一个简单的实验用例。它只是使用了pcap的一小
部分主要功能,实现对默认网络接口数据包的抓取,并实现了
简陋的不完全的分析。它可以被视为一个残疾版或毛坯版的
tcpdump。
由于我认识上的不足和我在编程时图省事,所以不可避免的出
现一些错误和不适当的地方。
程序在Fedora 11上测试过。
编译:
g++ -g -W -Wall -Wextra -o mytest -lpcap main.cpp
执行举例(必须使用root账户):
./mytest
./mytest "tcp and dst port 80"
./mytest ""
./mytest "tcp or udp"
我在程序中只对选项做了简单处理。所以引号是必须的,
否则shell会将引号中的选项展开。
参考:
pcap(3), www.tcpdump.org上的文档
main.cpp:
============================================================================
// 2011年 03月 14日 星期一 14:24:24 CST
// author: 李小丹(Li Shao Dan) 字 殊恒(shuheng)
// K.I.S.S
// S.P.O.T
/*
*
* Copyright © 2011 李小丹(Li Shao Dan)
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. 李小丹(Li Shao Dan) makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*/
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <net/ethernet.h>
#include <netinet/if_ether.h>
#include <netinet/ether.h>
#include <pcap.h>
#define BUFSIZE 4096
#define PACKET_NUMBER 333
#define FILTER_EXP "ip"
static void filter_packet(unsigned char *,
const struct pcap_pkthdr *, const unsigned char *);
static void take_ether(const unsigned char *);
static void take_ip(const unsigned char *);
static void take_tcp(const unsigned char *, size_t);
static void take_udp(const unsigned char *);
static void take_icmp(const unsigned char *);
static void print_payload(const unsigned char *, size_t);
int main(int argc, char *argv[])
{
char *dev, errbuf[PCAP_ERRBUF_SIZE];
dev = pcap_lookupdev(errbuf);
if(!dev) {
fprintf(stderr, "Can't find default device: %s/n", errbuf);
exit(1);
}
printf("Device %s/n", dev);
bpf_u_int32 mask;
bpf_u_int32 net;
if(pcap_lookupnet(dev, &net, &mask, errbuf) < 0) {
fprintf(stderr, "Can't get netmask for device %s/n", dev);
mask = 0;
net = 0;
}
pcap_t *handle;
if(!(handle = pcap_open_live(dev, BUFSIZE, 1, 1000, errbuf))) {
fprintf(stderr, "Can't find device(%s):: %s/n", dev, errbuf);
exit(2);
}
const char *filter_exp = argc == 2 ? argv[1] : FILTER_EXP;
struct bpf_program fp;
if(pcap_compile(handle, &fp, filter_exp, 0, net) < 0) {
fprintf(stderr, "Couldn't parse filter %s: %s/n",
filter_exp, pcap_geterr(handle));
exit(3);
}
if(pcap_setfilter(handle, &fp) < 0) {
fprintf(stderr, "Couldn't install filter %s: %s/n",
filter_exp, pcap_geterr(handle));
exit(4);
}
pcap_loop(handle, PACKET_NUMBER, filter_packet, 0);
pcap_freecode(&fp);
pcap_close(handle);
return 0;
}
static void filter_packet(unsigned char *args __attribute__ ((unused)),
const struct pcap_pkthdr *header __attribute__ ((unused)),
const unsigned char *packet)
{
static int packet_count = 1;
printf("Number %d packet/n", packet_count++);
take_ether(packet);
take_ip(packet);
printf("=================================================================/n");
fflush(stdout);
}
static void take_ether(const unsigned char *packet)
{
struct ether_header *ehdr = (struct ether_header *)packet;
char mac_saddr[32];
ether_ntoa_r((struct ether_addr *)ehdr->ether_shost, mac_saddr);
char mac_daddr[32];
ether_ntoa_r((struct ether_addr *)ehdr->ether_dhost, mac_daddr);
printf("Frome MAC addr %s to MAC addr %s/n",
mac_saddr, mac_daddr);
}
static void take_ip(const unsigned char *packet)
{
struct iphdr *ip = (struct iphdr *)(packet + sizeof(struct ether_header));
char ip_saddr[32];
inet_ntop(AF_INET, &ip->saddr, ip_saddr, sizeof(ip_saddr));
char ip_daddr[32];
inet_ntop(AF_INET, &ip->daddr, ip_daddr, sizeof(ip_daddr));
printf("Frome ip addr %s to ip addr %s; ttl = %d/n",
ip_saddr, ip_daddr, ip->ttl);
const unsigned char *p = (unsigned char *)ip + sizeof(struct iphdr);
switch(ip->protocol) {
case IPPROTO_TCP:
printf("Protocol is TCP/n");
take_tcp(p, ntohs(ip->tot_len) - 20);
break;
case IPPROTO_UDP:
printf("Protocol is UDP/n");
take_udp(p);
break;
case IPPROTO_ICMP:
printf("Protocol is ICMP/n");
take_icmp(p);
break;
case IPPROTO_IP:
printf("Protocol is IP/n");
break;
case IPPROTO_IGMP:
printf("Protocol is IGMP/n");
break;
case IPPROTO_SCTP:
printf("Protocol is SCTP/n");
break;
default:
printf("Unkown Protocol is %d/n", ip->protocol);
break;
}
}
static void take_tcp(const unsigned char *packet, size_t s)
{
struct tcphdr *tcp = (struct tcphdr *)packet;
printf("src port is %d, dst port is %d;/n",
ntohs(tcp->source), ntohs(tcp->dest));
size_t tcpl = tcp->doff << 2;
if((s -= tcpl) > 0) {
printf("Recv Tcp packet len is %u", s);
print_payload((packet + tcpl), s);
}
}
static void take_icmp(const unsigned char *p)
{
struct icmphdr *icmp = (struct icmphdr *)p;
switch(icmp->type) {
case ICMP_ECHOREPLY:
printf("ICMP Type is /'echo reply/'./n");
break;
case ICMP_DEST_UNREACH:
printf("ICMP Type is /'Destination Unreachable/'./n");
break;
case ICMP_SOURCE_QUENCH:
printf("ICMP Type is /'Source Quench/'./n");
break;
case ICMP_REDIRECT:
printf("ICMP Type is /'Redirect (change route)/'./n");
break;
case ICMP_ECHO:
printf("ICMP Type is /'Echo Request/'./n");
break;
case ICMP_TIME_EXCEEDED:
printf("ICMP Type is /'Time Exceeded/'./n");
break;
case ICMP_PARAMETERPROB:
printf("ICMP Type is /'Parameter Problem/'./n");
break;
case ICMP_TIMESTAMP:
printf("ICMP Type is /'Timestamp Request/'./n");
break;
case ICMP_TIMESTAMPREPLY:
printf("ICMP Type is /'Timestamp Reply/'./n");
break;
case ICMP_INFO_REQUEST:
printf("ICMP Type is /'Information Request/'./n");
break;
case ICMP_INFO_REPLY:
printf("ICMP Type is /'Information Reply/'./n");
break;
case ICMP_ADDRESS:
printf("ICMP Type is /'Address Mask Request/'./n");
break;
case ICMP_ADDRESSREPLY:
printf("ICMP Type is /'Address Mask Reply/'./n");
break;
default:
printf("Unknown type is %d!/n", icmp->type);
break;
}
printf("ICMP Code is /'%d/'/n", icmp->code);
}
static void take_udp(const unsigned char *p)
{
struct udphdr *udp = (struct udphdr *)p;
printf("Source port is %d, dest port is %d/n", ntohs(udp->source), ntohs(udp->dest));
size_t udpl = ntohs(udp->len);
size_t s = udpl - sizeof(struct udphdr);
if(s > 0) {
printf("Recv udp packet len is %u", s);
print_payload(p + sizeof(struct udphdr), s);
}
}
static void print_payload(const unsigned char *packet, size_t s)
{
for(size_t i = 0; i < s; i += 10) {
if(!(i % 10))
printf("/n%07d ", i);
for(size_t j = i; j < i + 10; ++j) {
if(j < s)
printf("%02x ", packet[j]);
else
printf(" ");
}
printf(" ");
for(size_t j = i; j < s && j < i + 10; ++j) {
if(isprint(packet[j]))
printf("%c", packet[j]);
else
printf(".");
}
}
printf("/n");
}
- pcap(Packet capture library)的简单应用
- Package Capture Library(pcap), libpcap&tcpdump
- packet capture tool: tshark
- 关于“Packet size limited during capture”的解释
- 简单的get http packet
- error: pcap library not found!
- Cisco IOS路由器的嵌入式抓包工具(Embedded Packet Capture)
- capture 中总线(BUS)的应用
- Change Data Capture 的简单测试。
- Capture network packet and send rst packet to cut connection
- Packet capture on Firewalls (ASA/PIX/FWSM)
- Packet size limited during capture: RADIUS truncated
- Remote Packet Capture for iOS Devices
- USB Packet capture for Windows Tour
- pcap-简单数据格式解析(初级)
- Remote Packet Capture Protocol//远程包捕获协议
- 借助Packet Capture实现无Root抓请求
- [Protocol Analysis]Wireshark capture packet tcp udp checksum error
- PhoneApp
- VS打开项目,无法识别工具版本4.0
- Ubuntu root用户自动登录系统
- android学习笔记3
- vim diff tips
- pcap(Packet capture library)的简单应用
- 求素数
- 求素数
- Nasdaq又出来搅局——纽约证交所和德意志交易所合并续
- 嵌入式Linux USB WIFI驱动的移植
- 把2N个球放到M个盒子里(N>=M)使得各盒中的球数为偶数
- DEMO_DYNPRO_SUBSCREENS
- javascript求日期差
- 关于Java继承的一些复习