📄 549.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="537.htm">上一层</a>][<a href="550.htm">下一篇</a>]
<hr><p align="left"><small>发信人: guru (好读书,不求甚解), 信区: UNP <br>
标 题: Packet Capture With libpcap and other (4) <br>
发信站: UNIX编程 (2001年08月04日11:17:50 星期六), 站内信件 <br>
<br>
Packet Analysis <br>
<br>
-------------------------------------------------------------------------------- <br>
<br>
Aha, finally it is time to start using our newly obtained Jedi skills! (wheee!!) <br>
This section will focus on peaking into the packets to extract the information <br>
(which is what we wanted to begin with). First off we must arm ourselves! Go ahe <br>
ad and get <br>
all the relevent RFC's. Lets start off with RFC 791 (IP) RFC 768 (UDP) RFC 826 ( <br>
ARP) RFC 792 (ICMPv4) and of course RFC 826 (TCPv4) The truth is, once you have <br>
these files you dont really need me *sigh* but then again... why right your own <br>
code when <br>
you can just copy mine! hehe <br>
<br>
I would highly recommend you use another packet sniffer to double check your pro <br>
grams... tcpdump will do just fine, and ethereal just kicks ass, you can get eit <br>
her (and more!!) at http://www.tcpdump.org/related.html. Both of these programs <br>
are capable <br>
of analyzing all fields of a packet, plus the data. Sure we could use them inste <br>
ad of creating our own... but what fun would that be? <br>
<br>
I would prefer not to have to rewrite the main body of the program for each new <br>
example like I have done previously. Instead I am going to use the same main pro <br>
gram and only post the callback function which gets passed to the pcap_loop() or <br>
<br>
pcap_dispatch() function. Below is a copy of the main program I intend on using <br>
(nothing special), go ahead and cut and paste it or download it here. <br>
<br>
/********************************************************************** <br>
* file: pcap_main.c <br>
* date: Tue Jun 19 20:07:49 PDT 2001 <br>
* Author: Martin Casado <br>
* Last Modified:2001-Jun-23 12:55:45 PM <br>
* <br>
* Description: <br>
* main program to test different call back functions <br>
* to pcap_loop(); <br>
* <br>
* Compile with: <br>
* gcc -Wall -pedantic pcap_main.c -lpcap (-o foo_err_something) <br>
* <br>
* <br>
* Usage: <br>
* a.out (# of packets) "filter string" <br>
* <br>
**********************************************************************/ <br>
<br>
#include <pcap.h> <br>
#include <stdio.h> <br>
#include <stdlib.h> <br>
#include <errno.h> <br>
#include <sys/socket.h> <br>
#include <netinet/in.h> <br>
#include <arpa/inet.h> <br>
#include <netinet/if_ether.h> <br>
#include <net/ethernet.h> <br>
#include <netinet/ether.h> <br>
<br>
/* <br>
* workhorse function, we will be modifying this function <br>
*/ <br>
void my_callback(u_char *args,const struct pcap_pkthdr* pkthdr,c <br>
u_char* <br>
packet) <br>
{ <br>
} <br>
<br>
<br>
int main(int argc,char **argv) <br>
{ <br>
char *dev; <br>
char errbuf[PCAP_ERRBUF_SIZE]; <br>
pcap_t* de <br>
struct bpf_program fp; /* hold compiled program */ <br>
bpf_u_int32 maskp; /* subnet mask */ <br>
bpf_u_int32 netp; /* ip */ <br>
u_char* args = NULL; <br>
<br>
/* Options must be passed in as a string because I am lazy */ <br>
if(argc < 2){ <br>
fprintf(stdout,"Usage: %s numpackets \"options\"\n",argv[0]); <br>
return 0; <br>
} <br>
<br>
/* grab a device to peak into... */ <br>
dev = pcap_lookupdev(errbuf); <br>
if(dev == NULL) <br>
{ printf("%s\n",errbuf); exit(1); } <br>
<br>
/* ask pcap for the network address and mask of the device */ <br>
pcap_lookupnet(dev,&netp,&maskp,errbuf); <br>
<br>
/* open device for reading. NOTE: defaulting to <br>
* promiscuous mode*/ <br>
descr = pcap_open_live(dev,BUFSIZ,1,-1,errbuf); <br>
if(descr == NULL) <br>
{ printf("pcap_open_live(): %s\n",errbuf); exit(1); } <br>
<br>
<br>
if(argc > 2) <br>
{ <br>
/* Lets try and compile the program.. non-optimized */ <br>
if(pcap_compile(descr,&fp,argv[2],0,netp) == <br>
{ fprintf(stderr,"Error calling pcap_compile\n"); exit(1); } <br>
<br>
/* set the compiled program as the filter */ <br>
if(pcap_setfilter(descr,&fp) == -1) <br>
{ fprintf(stderr,"Error setting filter\n"); exit(1); } <br>
} <br>
<br>
/* ... and loop */ <br>
pcap_loop(descr,atoi(argv[1]),my_callback,args); <br>
<br>
fprintf(stdout,"\nfinished\n"); <br>
return 0; <br>
} <br>
<br>
<br>
I will be using the above program and merely replacing the callback function my_ <br>
callback for demo programs in this section. You may have noticed that I am passi <br>
ng in a u_char* (currently NULL) to pcap_loop(). Zhifang Wang, was kind enough t <br>
o point out <br>
that this is passed back into the callback function as the first argument. We wi <br>
ll use this later to communicate with the callback function without using yucky <br>
globals. Ok ok ok, enough startup stuff, lets go going!! I know, I know, you wan <br>
t to get <br>
right into reading the bodies of TCP packets... (don't we all?) But we'll get th <br>
ere eventually... First things first... the ethernet header. <br>
<br>
"Didn't we already do this", you ask. Sure... sort of, but we didn't spend much <br>
time on it so lets just get this out of the way. Looking at the datalink header <br>
isn't all too exciting, but it certainly is something we want to stick in our to <br>
olkit so we <br>
will gloss over the important stuff and continue on. The most important element <br>
of the ether header to us is the ether type. Remember struct ether_header from n <br>
et/ethernet.h? just so you don't have to click back, here it is again whith the <br>
definition <br>
of an ether_addr. <br>
<br>
/* This is a name for the 48 bit ethernet address available on many <br>
systems. */ <br>
struct ether_addr <br>
{ <br>
u_int8_t ether_addr_octet[ETH_ALEN]; <br>
} __attribute__ ((__packed__)); <br>
<br>
/* 10Mb/s ethernet header */ <br>
struct ether_header <br>
{ <br>
u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ <br>
u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ <br>
u_int16_t ether_type; /* packet type ID field */ <br>
} __attribute__ ((__packed__)); <br>
<br>
<br>
Fortunatly (at least in Linux) netinet/ether.h provides us with some fuzzy routi <br>
nes to convert ethernet headers to readable ascii and back.. <br>
/* Convert 48 bit Ethernet ADDRess to ASCII. */ <br>
extern char *ether_ntoa (__const struct ether_addr *__addr) __THROW; <br>
extern char *ether_ntoa_r (__const struct ether_addr *__addr, char *__buf) <br>
__THROW; <br>
<br>
/* Convert ASCII string S to 48 bit Ethernet address. */ <br>
extern struct ether_addr *ether_aton (__const char *__asc) __THROW; <br>
extern struct ether_addr *ether_aton_r (__const char *__asc, <br>
struct ether_addr *__addr) __THROW; <br>
<br>
as well as ethernet address to HOSTNAME resolution (that should ring a bell.. :- <br>
) <br>
/* Map HOSTNAME to 48 bit Ethernet address. */ <br>
extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr) <br>
__THROW; <br>
<br>
Previously I pasted some code shamelessly stolen from Steven's source code to pr <br>
int out the ethernet header, from now on we take the easy route. Here is a strai <br>
ghtforward callback function to handle ethernet headers, print out the source an <br>
d <br>
destination addresses and handle the type. <br>
<br>
u_int16_t handle_ethernet <br>
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* <br>
packet); <br>
<br>
/* looking at ethernet headers */ <br>
<br>
void my_callback(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* <br>
packet) <br>
{ <br>
u_int16_t type = handle_ethernet(args,pkthdr,packet); <br>
<br>
if(type == ETHERTYPE_IP) <br>
{/* handle IP packet */ <br>
}else if(type == ETHERTYPE_ARP) <br>
{/* handle arp packet */ <br>
} <br>
else if(type == ETHERTYPE_REVARP) <br>
{/* handle reverse arp packet */ <br>
}/* ignorw */ <br>
} <br>
<br>
u_int16_t handle_ethernet <br>
(u_char *args,const struct pcap_pkthdr* pkthdr,const u_char* <br>
packet) <br>
{ <br>
struct ether_header *eptr; /* net/ethernet.h */ <br>
<br>
/* lets start with the ether header... */ <br>
eptr = (struct ether_header *) packet; <br>
<br>
fprintf(stdout,"ethernet header source: %s" <br>
,ether_ntoa(eptr->ether_shost)); <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -