⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 549.htm

📁 unix高级编程原吗
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<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 + -