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

📄 547.htm

📁 unix高级编程原吗
💻 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="548.htm">下一篇</a>]
<hr><p align="left"><small>发信人: guru (好读书,不求甚解), 信区: UNP <br>

标  题: Packet Capture With libpcap and other (2) <br>

发信站: UNIX编程 (2001年08月04日11:16:00 星期六), 站内信件 <br>

  <br>

Capturing Our First Packet <br>

  <br>

-------------------------------------------------------------------------------- <br>

(P.S. Hey peeps, sorry this was such a long time coming... graduating and gettin <br>

g a job is a major pain in the ass... as things settle down I will certainly hav <br>

e more time to work on this :-) :-) :-) ) <br>

Well now we sort of know the nature of packet capture, we have identified that w <br>

e do in fact have an interface to pull things from, how about we go ahead and gr <br>

ab a packet! <br>

"Just give me the damn example and let me hack...", you cry <br>

Very well..... Here you go.. download from here.. testpcap1.c or just cut and pa <br>

ste below. <br>

  <br>

/*************************************************** <br>

* file:     testpcap1.c <br>

* Date:     Thu Mar 08 17:14:36 MST 2001 <br>

* Author:   Martin Casado <br>

* Location: LAX Airport (hehe) <br>

* <br>

* <br>

* Simple single packet capture program <br>

*****************************************************/ <br>

#include <stdio.h> <br>

#include <stdlib.h> <br>

#include <pcap.h> /* if this gives you an error try pcap/pcap.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> /* includes net/ethernet.h */ <br>

  <br>

int main(int argc, char **argv) <br>

{ <br>

    int i; <br>

    char *dev; <br>

    char errbuf[PCAP_ERRBUF_SIZE]; <br>

    pcap_t* descr; <br>

    const u_char *packet; <br>

    struct pcap_pkthdr hdr;     /* pcap.h */ <br>

    struct ether_header *eptr;  /* net/ethernet.h */ <br>

  <br>

    u_char *ptr; /* printing out hardware header info */ <br>



  <br>

    /* grab a device to peak into... */ <br>

    dev = pcap_lookupdev(errbuf); <br>

  <br>

    if(dev == NULL) <br>

    { <br>

        printf("%s\n",errbuf); <br>

        exit(1); <br>

    } <br>

  <br>

    printf("DEV: %s\n",dev); <br>

  <br>

    /* open the device for sniffing. <br>

  <br>

       pcap_t *pcap_open_live(char *device,int snaplen, int prmisc,int to_ms, <br>

       char *ebuf) <br>

  <br>

       snaplen - maximum size of packets to capture in bytes <br>

       promisc - set card in promiscuous mode? <br>

       to_ms   - time to wait for packets in miliseconds before read <br>

       times out <br>

       errbuf  - if something happens, place error string here <br>



  <br>

       Note if you change "prmisc" param to anything other than zero, you will <br>

       get all packets your device sees, whether they are intendeed for you or <br>

       not!! Be sure you know the rules of the network you are running on <br>

       before you set your card in promiscuous mode!!     */ <br>

  <br>

    descr = pcap_open_live(dev,BUFSIZ,0,-1,errbuf); <br>

  <br>

    if(descr == NULL) <br>

    { <br>

        printf("pcap_open_live(): %s\n",errbuf); <br>

        exit(1); <br>

    } <br>

  <br>

  <br>

    /* <br>

       grab a packet from descr (yay!) <br>

       u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h) <br>

       so just pass in the descriptor we got from <br>

       our call to pcap_open_live and an allocated <br>

       struct pcap_pkthdr                                 */ <br>

  <br>

  <br>

    packet = pcap_next(descr,&hdr); <br>

  <br>

    if(packet == NULL) <br>

    {/* dinna work *sob* */ <br>

        printf("Didn't grab packet\n"); <br>

        exit(1); <br>

    } <br>

  <br>

    /*  struct pcap_pkthdr { <br>

        struct timeval ts;   time stamp <br>

        bpf_u_int32 caplen;  length of portion present <br>

        bpf_u_int32;         lebgth this packet (off wire) <br>

        } <br>

     */ <br>

  <br>

    printf("Grabbed packet of length %d\n",hdr.len); <br>

    printf("Recieved at ..... %s\n",ctime((const time_t*)&hdr.ts.tv_sec)); <br>

    printf("Ethernet address length is %d\n",ETHER_HDR_LEN); <br>

  <br>

    /* lets start with the ether header... */ <br>

    eptr = (struct ether_header *) packet; <br>

  <br>

  <br>

    /* Do a couple of checks to see what packet type we have..*/ <br>

    if (ntohs (eptr->ether_type) == ETHERTYPE_IP) <br>

    { <br>

        printf("Ethernet type hex:%x dec:%d is an IP packet\n", <br>

                ntohs(eptr->ether_type), <br>

                ntohs(eptr->ether_type)); <br>

    }else  if (ntohs (eptr->ether_type) == ETHERTYPE_ARP) <br>

    { <br>

        printf("Ethernet type hex:%x dec:%d is an ARP packet\n", <br>

                ntohs(eptr->ether_type), <br>

                ntohs(eptr->ether_type)); <br>

    }else { <br>

        printf("Ethernet type %x not IP", ntohs(eptr->ether_type)); <br>

        exit(1); <br>

    } <br>

  <br>

    /* THANK YOU RICHARD STEVENS!!! RIP*/ <br>

    ptr = eptr->ether_dhost; <br>

    i = ETHER_ADDR_LEN; <br>

    printf(" Destination Address:  "); <br>

    do{ <br>

        printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++); <br>



    }while(--i>0); <br>

    printf("\n"); <br>

  <br>

    ptr = eptr->ether_shost; <br>

    i = ETHER_ADDR_LEN; <br>

    printf(" Source Address:  "); <br>

    do{ <br>

        printf("%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++); <br>

    }while(--i>0); <br>

    printf("\n"); <br>

  <br>

    return 0; <br>

} <br>

  <br>

Well, that wasn't too bad was it?! Lets give her a test run .. <br>

  <br>

[root@pepe libpcap]# ./a.out <br>

DEV: eth0 <br>

Grabbed packet of length 76 <br>

Recieved at time..... Mon Mar 12 22:23:29 2001 <br>

  <br>

Ethernet address length is 14 <br>



Ethernet type hex:800 dec:2048 is an IP packet <br>

 Destination Address:   0:20:78:d1:e8:1 <br>

 Source Address:   0:a0:cc:56:c2:91 <br>

[root@pepe libpcap]# <br>

  <br>

After typing a.out I jumped into another terminal and tried to ping www.google.c <br>

om. The output captured the ICMP packet used to ping www.google.com. If you don' <br>

t know exactly what goes on under the covers of a network you may be curios how <br>

the computer <br>

obtained the destination ethernet address. Aha! You don't actually think that th <br>

e destination address of the ethernet packet is the same as the machine at www.g <br>

oogle.com do you!? <br>

"..uhhh of course not",you stammer <br>

The destination address is most likely your gateway... aka the computer that tie <br>

s your network to the internet. The packet must first find its way to your gatew <br>

ay which will then forward it to a router or make its own routing decisions as t <br>

o where the <br>

packet should go next. Lets do a quick sanity check to see if we in fact are sen <br>

ding to the router.... ho hum!! You can use the route command to get your gatewa <br>

ys IP. <br>

[root@pepe libpcap]# /sbin/route <br>

Kernel IP routing table <br>



Destination     Gateway         Genmask         Flags Metric Ref    Use Iface <br>

192.168.1.0     *               255.255.255.0   U     0      0        0 eth0 <br>

127.0.0.0       *               255.0.0.0       U     0      0        0 lo <br>

default         192.168.1.1     0.0.0.0         UG    0      0        0 eth0 <br>

  <br>

and then use the arpcommand to get the cached ethernet address... <br>

[root@pepe libpcap]# /sbin/arp <br>

Address   HWtype HWaddress     Flags Mask    Iface <br>

192.168.1.1             ether   00:20:78:D1:E8:01   C                     eth0 <br>

  <br>

If your gateway is not in your arp cache, try and telnet to it, and then retry t <br>

he arp command. Hey, by the way, this could certainly be the long, painful, bloo <br>

dy, ignorant way of getting the gateway hardware address but I couldn't think of <br>

 another <br>

way... <br>

  <br>

Notice that my gateway's address matches the destination address of the packet t <br>

hat I captured. All packets leaving my machine that are not sent to a machine on <br>

 my network must go through the gateway. Alas!!!! We have still not answered the <br>

  <br>

question... "how did my computer know the gateway hardware address"? Let me then <br>

 digress for a moment. My computer knows the IP address of the gateway and is ce <br>



rtainly savy enough to send outbound packets to it. As you can see from the hand <br>

y-dandy arp <br>

command there is an internal table (the arp cache) which maps IP addresses to ha <br>

rdware addresses. "AAAUUGHH!!! BUT HOW DID IT CONSTUCT THE ARP CACHE!!!!", you s <br>

cream! <br>

  <br>

Hardware addresses on ethernet are obtained using the Address Resolution Protoco <br>

l or ARP. ARP is is described in RFC826 which can be found... Here! Pretty much <br>

what happenes is when you send a packet, the kernel first checks the arp cache t <br>

o see if <br>

you already have the hardware address for the higher level destination address. <br>

If not, the kernel sends an arp request which is of type... ETHERTYPE_ARP which <br>

is defined in net/ethernet.h as follows. <br>

  <br>

#define ETHERTYPE_ARP  0x0806  /* Address resolution */ <br>

  <br>

On recieveing the arp packet, the machine with the high level address (in my cas <br>

e the gateway) will reply with an arp reply, basically saying.. I DO! send it he <br>

re! Shall we test it out?! (to bad... I'm gonna do it anyways :-P) <br>

[root@pepe libpcap]# /sbin/arp -n    # look at arp cache <br>

Address   HWtype HWaddress     Flags Mask    Iface <br>

192.168.1.1             ether   00:20:78:D1:E8:01   C                     eth0 <br>



  <br>

[root@pepe libpcap]# /sbin/arp -n -d 192.168.1.1  #delete gateqay entrance <br>

[root@pepe libpcap]# /sbin/arp -n   #make sure gateway hardware addy is empty <br>

  <br>

Address   HWtype HWaddress     Flags Mask    Iface <br>

192.168.1.1                     (incomplete)                              eth0 <br>

[root@pepe libpcap]# ./a.out <br>

DEV: eth0 <br>

Grabbed packet of length 42 <br>

Recieved at time..... Tue Mar 13 00:36:49 2001 <br>

  <br>

Ethernet address length is 14 <br>

Ethernet type hex:806 dec:2054 is an ARP packet <br>

 Destination Address:   ff:ff:ff:ff:ff:ff <br>

 Source Address:   0:a0:cc:56:c2:91 <br>

[root@pepe libpcap]#echo YAY <br>

  <br>

So as you can see, once the hardware address was removed the the cache, my compu <br>

ter needed to send an arp request to broadcast (i.e. ff:ff:ff:ff:ff:ff) looking <br>

for the owner of the higher level address, in this case IP 192.168.1.1. What do <br>

you think <br>

would happen if you cleared your arp cache and modified testpcap1.c to capture 2 <br>



 packets?! Hey I know why don't you try it :-P~~~~ <br>

  <br>

Lets now disect the packet by checking out <net/ethernet.h> right now we are not <br>

 concerned with the network or transport protocol, we just want to peer into the <br>

 ethernet headers.... Lets say that we are runnig at 10Mb/s... <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>

So it looks like the first ETH_ALEN bytes are the destination ethernet address ( <br>

look at linux/if_ether.h for the definition of ETH_ALEN :-) of the packet (presu <br>

medly your machine). The next ETH_ALEN bytes are the source. Finally, the last w <br>

ord is the <br>

packet type. Here are the protocol ID's on my machine from net/ethernet.h <br>

  <br>

/* Ethernet protocol ID's */ <br>

#define ETHERTYPE_PUP  0x0200      /* Xerox PUP */ <br>



#define ETHERTYPE_IP  0x0800  /* IP */ <br>

#define ETHERTYPE_ARP  0x0806  /* Address resolution */ <br>

#define ETHERTYPE_REVARP 0x8035  /* Reverse ARP */ <br>

  <br>

For the purpose of this tutorial I will be focusing on IP and perhaps a little b <br>

it on ARP... the truth is I have no idea what the hell Xerox PUP is. <br>

  <br>

Ack! Allright so where are we now? We know the most basic of methods for grabbin <br>

g a packet. We covered how hardware addresses are resolved and what a basic ethe <br>

rnet packet looks like. Still we are using a sad, sad 1% of the functionality of <br>

 libpcap, <br>

and we haven't even begun to peer into the packets themselves (other than the ha <br>

rdware headers) so much to do and so little time :-) As you can probably tell by <br>

 now, it would be near impossible to do any real protocol analysis with a progra <br>

m that <br>

simply captures one packet at a time. What we really want to do is write a simpl <br>

e packet capturing engine that will nab as many packets as possible while filter <br>

ing out those we dont want. In the next section we will construct a simple packe <br>

t capturing <br>

engine which will aid us in packet dissection (eww, that kinda sounds gross) lat <br>

er on. <br>

  <br>



  <br>

-------------------------------------------------------------------------------- <br>

  <br>

[prev] [socket home ] [next] <br>

-- <br>

telnet apue.dhs.org 2323 or http://apue.dhs.org <br>

APUE:UNIX环境编程 <br>

UNP:UNIX网络编程 <br>

UKP:UNIX内核编程 <br>

BIBLE:高手传经 <br>

FTPDOC:资源共享 <br>

※ 来源:·UNIX编程 www.tiaozhan.com/unixbbs/·[FROM: 202.114.36.176] <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="537.htm">上一层</a>][<a href="548.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -