Linux Network Programming-original socket instance: Packet Analysis of MAC header, linux Network Programming
We learned through "Linux Network Programming-original socket programming" that we can get the data packets at the link layer through the original socket and recvfrom ().What we receiveWhat is the length of link layer data packets??
Link Layer Encapsulation Format
MAC header (wired LAN)
Note: CRC and PAD can be ignored in group packages.
One of the scenarios of link layer data packets:
1 unsigned char msg [1024] = {2 // -------------- group MAC---14--3 0xb8, 0x88, 0xe3, 0xe1, 0x10, 0xe6, // dst_mac: b8: 88: e3: e1: 10: e64 0xc8, 0x9c, 0xdc, 0xb7, 0x0f, 0x19, // src_mac: c8: 9c: dc: b7: 0f: 195 0x08, 0x00, // type: 0x0800 IP protocol 6 //...... ...... 7 //...... ...... 8 };
And analyze the received link layer data packets:
1 # include <stdio. h> 2 # include <string. h> 3 # include <stdlib. h> 4 # include <sys/socket. h> 5 # include <netinet/in. h> 6 # include <arpa/inet. h> 7 # include <netinet/ether. h> 8 9 int main (int argc, char * argv []) 10 {11 int I = 0; 12 unsigned char buf [1024] = ""; 13 int sock_raw_fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL); 14 while (1) 15 {16 unsigned char src_mac [18] = ""; 17 unsigned char dst_mac [18] = ""; 18 // get the data frame 19 recvfrom (sock_raw_fd, buf, sizeof (buf), 0, NULL, NULL) of the link layer ); 20 // extract the target mac and source mac21 sprintf (dst_mac, "% 02x: % 02x: % 02x: % 02x: % 02x: % 02x ", buf [0], buf [1], buf [2], buf [3], buf [4], buf [5]); 22 sprintf (src_mac, "% 02x: % 02x: % 02x: % 02x: % 02x: % 02x ", buf [6], buf [7], buf [8], buf [9], buf [10], buf [11]); 23 // determine whether an IP data packet is 24 if (buf [12] = 0x08 & buf [13] = 0x00) 25 {26 printf ("______________ IP datagram _______________ \ n"); 27 printf ("MAC: % s >>%s \ n", src_mac, dst_mac ); 28} // determine if it is an ARP packet 29 else if (buf [12] = 0x08 & buf [13] = 0x06) 30 {31 printf ("______________ ARP datagram _______________ \ n"); 32 printf ("MAC: % s >>%s \ n", src_mac, dst_mac ); 33} // determine whether the data packet is RARP 34 else if (buf [12] = 0x80 & buf [13] = 0x35) 35 {36 printf ("______________ RARP datagram _______________ \ n"); 37 printf ("MAC: % s >>%s \ n", src_mac, dst_mac ); 38} 39} 40 return 0; 41}
Note that the Administrator has the following permissions to run the program:
Each packet header has a corresponding structure. It is much easier to group or split packets through these structures.
The file describing the network protocol structure in ubuntu 12.04 is as follows:
Ethernet header (required header file: # include <net/ethernet. h> ):
In the preceding example, we use struct as the following code:
1 # include <stdio. h> 2 # include <string. h> 3 # include <stdlib. h> 4 # include <sys/socket. h> 5 # include <netinet/in. h> 6 # include <arpa/inet. h> 7 # include <netinet/ether. h> 8 # include <net/ethernet. h> // Ethernet header file 9 # include <netinet/ip. h> // ip header file 10 // # include <net/if_arp.h> // arp header file 11 12 int main (int argc, char * argv []) 13 {14 int I = 0; 15 unsigned char buf [1024] = ""; 16 int sock_raw_fd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL); 17 while (1) 18 {19 unsigned char src_mac [18] = ""; 20 unsigned char dst_mac [18] = ""; 21 // obtain the data frame 22 recvfrom (sock_raw_fd, buf, sizeof (buf), 0, NULL, NULL); 23 24 // extract mac header information (14 bytes) 25 struct ether_header * ethdr = NULL; 26 ethdr = (struct ether_header *) buf; 27 28 // extract the target mac and source mac29 sprintf (dst_mac, "% 02x: % 02x: % 02x: % 02x: % 02x: % 02x: % 02x: % 02x ", ethdr-> ether_dhost [0], ethdr-> ether_dhost [1], ethdr-> ether_dhost [2], ethdr-> ether_dhost [3], ethdr-> ether_dhost [4], ethdr-> ether_dhost [5]); 30 sprintf (src_mac, "% 02x: % 02x: % 02x: % 02x: % 02x: % 02x: % 02x ", ethdr-> ether_shost [0], ethdr-> ether_shost [1], ethdr-> ether_shost [2], ethdr-> ether_shost [3], ethdr-> ether_shost [4], ethdr-> ether_shost [5]); 31 32 // determine whether it is an IP packet 33 if (0x0800 = ntohs (ethdr-> ether_type) 34 {35 printf ("__________ IP datagram ___________ \ n "); 36 printf ("MAC: % s> % s \ n", src_mac, dst_mac); 37 38} // 0x0806 is an ARP packet, 0x8035 is RARP packet 39 else if (0x0806 = ntohs (ethdr-> ether_type) | 0x8035 = ntohs (ethdr-> ether_type )) 40 {41 printf ("______________ ARP datagram _______________ \ n"); 42 printf ("MAC: % s >>%s \ n", src_mac, dst_mac ); 43} 44 45} 46 return 0; 47}