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

📄 439.htm

📁 unix高级编程原吗
💻 HTM
📖 第 1 页 / 共 2 页
字号:
        }; <br>

      The first element in the structure "sa_family" will be used to <br>

reference what the family <br>

   type is for the socket, in our sniffer it will be AF_INET. Next the <br>

"sa_data" element <br>

   holds the destination port and address for the socket. To make it <br>

easier to deal with the <br>

   sockaddr struct the use of the sockaddr_in structure is commonly <br>

used. Sockaddr_in <br>

   makes it easier to reference all of the elements that are contained <br>

by sockaddr. <br>

by sockaddr. <br>

   Sockaddr_in looks like: <br>

   struct sockaddr_in { <br>

             short int          sin_family;    /* Address family <br>

       */ <br>

             unsigned short int sin_port;      /* Port number <br>

       */ <br>

             struct in_addr     sin_addr;      /* Internet address <br>

       */ <br>

             unsigned char      sin_zero[8];   /* Same size as struct <br>

sockaddr */ <br>

   }; <br>

      We will use this struct and declare a variable "from" which will <br>

give us the information <br>

   on the packet that we will collect from the raw socket. For <br>

instance the var <br>

   "from.sin_addr" will give access to the packets source address (in <br>

   network byte order). The thing to mention here is that all items in <br>

the sockaddr_in <br>

   structure must be in network-byte order. When we receive the data <br>

in the sockaddr_in <br>

   struct we must then convert it back to Host-byte order. To do this we <br>

 can use some <br>

 can use some <br>

   predefined functions to convert back and forth between  host and <br>

network byteorder. <br>

   Here are the functions we will use: <br>

        ntohs       : this function converts  network byte order to host byt <br>

e <br>

order <br>

                      for a 16-bit short <br>

        ntohl       : same as above but for a 32-bit long <br>

        inet_ntoa   : this function converts a 32-bit network binary value t <br>

o <br>

a <br>

                      dotted decimal ip address <br>

        inet_aton   : converts a character string  address to the 32-bit <br>

network <br>

                      binary value <br>

        inet_addr   : takes a char string dotted decimal addr and returns a <br>

32-bit <br>

                      network binary value <br>

   To further illustrate ,say I want to know the port number that this <br>

packet originated from: <br>

        int packet_port; packet_port    =ntohs(from.sin_port); <br>

                                         ^^^^^ <br>



   If I want the source IP address of the packet we will use a special <br>

function to get it to the <br>

   123.123.123.123 format: <br>

        char *ip_addr; ip_addr  =inet_ntoa(from.sin_addr) <br>

                                 ^^^^^^^^^ <br>

line 11-12: <br>

   struct ip *ip : <br>

   struct tcp *tcp : <br>

      This is a structure that we defined in our header file "headers. <br>

h". This structure is <br>

   declared so that we can access individual fields of the ip/tcp <br>

header. The structure is like <br>

   a transparent slide with predefined fields drawn on it. When a packet <br>

 is taken off <br>

   the wire it is a stream of bits, to make sense of it the <br>

"transparency" (or cast) is laid on <br>

   top of or over the bits so the individual fields can be referenced. <br>

Line 14 : <br>

   sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); <br>

   This is the most important line in the entire program. Socket() takes <br>

 three arguments in <br>

   this form: <br>

   this form: <br>

        sockfd = socket(int family, int type, int protocol); <br>

    The first argument is the family. This could be either AF_UNIX which <br>

 is used so a process <br>

   can communicate with another process on the same host or AF_INET <br>

which is used for <br>

   internet communication between remote hosts. In this case it will be <br>

 AF_INET . Next <br>

   is the type, the type is usually between 1 of 4 choices (there are <br>

others that we will not <br>

   discuss here) the main four are : <br>

   1.   SOCK_DRAM      : used for udp datagrams <br>

   2.   SOCK_STREAM    : used for tcp packets <br>

   3.   SOCK_RAW       : used to bypass the transport layer <br>

                         and directly access the IP layer <br>

   4.   SOCK_PACKET    : this is linux specific, it is similuar to <br>

                         SOCK_RAW except it accesses the DATA LINK <br>

Layer <br>

      For our needs we will use the SOCK_RAW type. You must have root <br>

acces to open a <br>

    raw socket. The last parameter  is the protocol,the protocol value <br>

specifies what type of <br>

    traffic the socket should receive , for normal sockets this value is <br>



 usally set to "0" <br>

    because the socket can figure out if for instance the "type" of <br>

SOCK_DGRAM is <br>

    specified then the protocol should be UDP.In our case we just want <br>

to look at tcp <br>

    traffic so we will specify IPPROTO_TCP. <br>

line 15 : <br>

   while (1) <br>

  The while (1) puts the program into an infinite loop this is necessary <br>

 so that after the <br>

 first packet is processed we will loop around and grab the next. <br>

Line 18: <br>

   bytes_recieved = recvfrom(sock, buffer, sizeof buffer, 0, (struct <br>

sockaddr *)&from, &fromlen); <br>

   Now here is where we are actually reading data from the open socket <br>

"sock".The from <br>

   struct is also filled in but notice that we are casting "from" from a <br>

 "sockaddr_in" struct <br>

   to a "sockaddr" struct. We do this because the recvfrom() requires <br>

a sockaddr type but <br>

   to access the separate fields we will continue to use the sockaddr_in <br>

 structure. The <br>



   length of the "from" struct must also be present and passed by <br>

address. The recvfrom() <br>

   call will return the number of bytes on success and a -1 on error and <br>

 fill the global var <br>

   errno. <br>

   This is what we call "blocking-I/O" the recvfrom() will wait here <br>

forever until a <br>

   datagram on the open socket is ready to be processed. This is opposed <br>

 to <br>

   Non-blocking I/O which is like running a process in the background <br>

and move on to <br>

   other tasks. <br>

Line 20: <br>

   printf("Source address ::: %s\n",inet_ntoa(from.sin_addr)); <br>

   This printf uses the special function inet_ntoa() to take the value <br>

of "from.sin_addr" <br>

   which is stored in Network-byte order and outputs a value in a <br>

readable ip form such <br>

   as 192.168.1.XXX. <br>

Line 21: <br>

   ip = (struct ip *)buffer; <br>

   This is where we will overlay a predefined structure that will help <br>



us to individually <br>

   identify the fields in the packet that we pick up from the open <br>

socket. <br>

Line 22: <br>

   printf("IP header length ::: %d\n",ip->ip_length); <br>

   The thing to notice on this line is the "ip->ip_length" this will <br>

access a pointer in <br>

   memory to the ip header length the important thing to remember is <br>

that the length <br>

   will be represented in 4-byte words this will be more important later <br>

 when trying to <br>

   access items past the ip header such as the tcp header or the data <br>

portion of the packet. <br>

Line 23: <br>

   printf("Protocol ::: %d\n",ip->ip_protocol); <br>

   This gives access to the type of protocol such as 6 for tcp or 17 for <br>

 udp. <br>

Line 24: <br>

   tcp = (struct tcp *)(buffer + (4*ip->ip_length)); <br>

       Remember earlier it was mentioned that the ip header length is <br>

stored in 4 byte words, <br>

   this is where that bit of information becomes important. Here we <br>



are trying to get access <br>

   to the tcp header fields, to do this we must overlay a structure that <br>

 has the fields <br>

   predefined just as we did with ip. There is one key difference here <br>

the ip header fields <br>

   were easy to access due to the fact that the beginning of the <br>

buffer was also the beginning <br>

   of the ip header as so : <br>

        |----------------- buffer ----------------| <br>

         _________________________________________ <br>

        | ip header          |                    | <br>

        |____________________|____________________| <br>

                             ^ <br>

                             *ip <br>

                             ^ <br>

                             *buffer <br>

      So to get access to the ip header we just set a pointer casted <br>

as an ip structure to the <br>

   beginning of the buffer like "ip = (struct ip *)buffer;". To get <br>

access to the tcp header <br>

   is a little more difficult due to the fact that we must set a pointer <br>

 and cast it as a tcp <br>



   structure at the beginning of the tcp header which follows the ip <br>

header in the buffer <br>

   as so : <br>

         |----------------- buffer ---------------| <br>

          ________________________________________ <br>

         | ip header | tcp header |               | <br>

         |___________|____________|_______________| <br>

                     ^ <br>

                     *tcp <br>

This is why we use 4*ip->ip_length to find the start of the tcp header. <br>

Line 25-26: <br>

    printf("Source port ::: %d\n",ntohs(tcp->tcp_source_port); <br>

    printf("Dest port  ::: %d\n",ntohs(tcp->tcp_dest_port)); <br>

   We can now access the source and dest ports which are located in <br>

the tcp header via <br>

   the structure as defined above. <br>

     This will conclude  our  first very simple tcp sniffer. This was <br>

a very basic application <br>

   that should help define how  to access packets passing on the network <br>

 and how  to use <br>

   sockets to access the packets. Hopefully this will be the first of <br>

many papers to come, <br>



   which each proceeding paper we will add a new or more complex feature <br>

 to the sniffer. I <br>

   should also mention that there a number of great resources on the net <br>

 that should aid you <br>

   in further research in this area : <br>

        1. Beej's Guide to Network Programming <br>

             This is an awesome paper that really helps <br>

             clear up any misconceptions about network programming. <br>

                [http://www.ecst.csuchico.edu/~beej/guide/net] <br>

        2. TCP/IP Illustrated Vol 1,2,3 <br>

           W.Richard Stevens <br>

To use the above program, cut out the above code and strip off all <br>

of the line numbers. Save the edited file as sniff.c. Next cut <br>

out the header file headers.h (below) and save it to a file headers.h <br>

in the same directory. Now just compile: gcc -o sniff sniff.c <br>

You should now have the executable "sniff", to run it type <br>

#./sniff <br>

/*************************headers.h**************************/ <br>

/*structure of an ip header             */ <br>

struct ip { <br>

        unsigned int        ip_length:4;    /*little-endian*/ <br>

        unsigned int        ip_version:4; <br>



        unsigned char       ip_tos; <br>

        unsigned short      ip_total_length; <br>

        unsigned short      ip_id; <br>

        unsigned short      ip_flags; <br>

        unsigned char       ip_ttl; <br>

        unsigned char       ip_protocol; <br>

        unsigned short      ip_cksum; <br>

        unsigned int        ip_source; <br>

        unsigned int        ip_dest; <br>

}; <br>

/* Structure of a TCP header */ <br>

struct tcp { <br>

        unsigned short      tcp_source_port; <br>

        unsigned short      tcp_dest_port; <br>

        unsigned int        tcp_seqno; <br>

        unsigned int        tcp_ackno; <br>

        unsigned int        tcp_res1:4,     /*little-endian*/ <br>

        tcp_hlen:4, <br>

        tcp_fin:1, <br>

        tcp_syn:1, <br>

        tcp_rst:1, <br>

        tcp_psh:1, <br>



        tcp_ack:1, <br>

        tcp_urg:1, <br>

        tcp_res2:2; <br>

        unsigned short      tcp_winsize; <br>

        unsigned short      tcp_cksum; <br>

        unsigned short      tcp_urgent; <br>

}; <br>

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

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="317.htm">上一层</a>][<a href="440.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 + -