Try to explore the network card packet capture process based on Linux C

Source: Internet
Author: User
Tags htons

In fact, it has been a long time to explore the problem of network card packet capture. I found some basic things in the last few days. I will just repeat them here.

Packet Capture first needs to know that the data transmitted through the NIC is actually through the underlying link layer (MAC). in Linux, the data traffic we obtain from the NIC is actually directly sent and received from the link layer. This article will not go into details about how to establish TCP/UDP connections (the previous section about Web server programs has been described), starting with the most critical raw socket.

Generally, the network knowledge that programmers are exposed to is limited to the following two types:

(1) stream socket (sock_stream), which is a connection-oriented socket and corresponds to TCP applications.

(2) datagram socket (sock_dgram), which is a connectionless socket and corresponds to a UDP application.

In addition to the above two basic sockets, there is also a type of original socket, which is a socket for processing the original network packets.

Streaming Sockets (sock_stream) and datagram Sockets (sock_dgram) cover TCP/IP applications at the general application level.

The method used to create the original socket is the same as that used to create a common socket, but another sock_raw option is used for the socket type. When using the socket function to create a function, specify the format type in the socket data to set the network data format that can be received from the socket.

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

FD creates the original socket for the returned socket descriptor sock_raw. The htons (eth_p_all) Here is the third parameter protocol of socket (), that is, the protocol type. Is defined in <netinet/in. h> constants are basically commonly used: eth_p_ip, eth_p_arp, eth_p_rarp or eth_p_all. Of course, there are many link layer protocols, however, we generally only care about these items, which is enough for us to use. Here is a brief introduction to the basics of sending and receiving network data. The protocol stack needs to handle two problems when organizing the data sending and receiving process: "From down", that is, the data sending task; "from down to top", that is, the data receiving task
Service. Data transmission is easier to receive, because for data receiving, the NIC Driver also needs to identify what data should be received and what should not be received.

They all have specific meanings:

Protocol

Value

Function

Eth_p_ip

Zero X 0800

Only receive data frames of the IP type that are sent to the destination MAC Machine

Eth_p_arp

Zero X 0806

Only receive ARP data frames that are sent to the destination MAC

Eth_p_rarp

Zero X 8035

Only Accept RARP data frames that are sent to the target Mac machine.

Eth_p_all

Zero X 0003

Receiving data frames sent to the destination MAC are all types of data frames (IP, ARP, RARP) on the local machine, and can also receive all data frames sent from the local machine. When the hybrid mode is enabled, the data frame sent to the destination MAC address is not a local hardware address.

Based on our own packet capture object, we can select the corresponding parameter value to obtain different data packets.

Here I chose eth_p_all to obtain all packets passing through the local machine, but one premise is that the NIC must be set to promiscuous mode ), here we must understand an important data type struct ifreq; his definition is as follows:

Struct ifreq {# define ifhwaddrlen 6 # define ifnamsiz if_namesize Union {char ifrn_name [ifnamsiz];/* interface name, e.g. "en0 ". */} ifr_ifrn; Union {struct sockaddr ifru_addr; struct sockaddr Dr; short int ifru_flags; int ifru_ivalue; int limit; struct ifmap ifru_map; char ifru_slave [ifnamsiz];/* just fits the size */Char ifru_newname [ifnamsiz]; _ caddr_t ifru_data;} ifr_ifru ;}; # define ifr_name ifr_ifrn.ifrn_name/* interface name */here is eth0 or eth1 # define ifr_hwaddr restart/* MAC address */MAC address # define ifr_addr restart/* address */source address # define ifr_dstaddr restart/* Other end of p-p lnk */destination IP address # define ifr_broadaddr ifr_ifru.ifru_broadaddr/* broadcast address */broadcast address # define ifr_netmask restart/* interface net mask */ subnet Mask # define ifr_flags blend/* flags */mode flag sets the Mixed Mode # define ifr_metric blend/* Metric */# define ifr_mtu blend/* MTU */# define ifr_map ifr_ifru.ifru_map /* device Map */# define ifr_slave failed/* slave device */# define ifr_data ifr_ifru.ifru_data/* for use by interface */# define ifr_ifindex failed/* interface Index */# define ifr_bandwidth limit /* link bandwidth */# define ifr_qlen values/* queue length */# define ifr_newname ifr_ifru.ifru_newname/* New name */# DEFINE _ iot_ifreq _ IOT (_ IOTs (char ), ifnamsiz, _ IOTs (char), 16, 0, 0) # DEFINE _ iot_ifreq_short _ IOT (_ IOTs (char), ifnamsiz, _ IOTs (short), 1, 0, 0) # DEFINE _ iot_ifreq_int _ IOT (_ IOTs (char), ifnamsiz, _ IOTs (INT), 1, 0)

There are many definitions above, but only a few are used. I have made corresponding Chinese annotations. To set the hybrid mode, set ifr_flags to iff_promisc.

After that, you need to set the socket options as follows:

Ret =int setsockopt( intsocket, int level, int option_name, const void *option_value, size_toption_len);

The first parameter socket is the socket descriptor. The second parameter level is the level of the set options. If you want to set options at the socket level, you must set the level to sol_socket. Option_name specifies the option to be set. The value of option_name depends on level.

After completing this step, you can use

{      i struct ifreq ifr;    strcpy(ifr.ifr_name, “eth0”);    ioctl(fd, SIOCGIFHWADDR, &ifr);}

Obtain the index interface of the NIC. Next we need to bind the original socket to the specified Nic.

Ret = BIND (FD, (struct sockaddr *) & sock, sizeof (sock); sock here is no longer the struct sockaddr_in during TCP connection, but struct sockaddr_ll, definition:

Struct sockaddr_ll {unsigned short sll_family;/* always af_packet */unsigned short sll_protocol;/* Physical Layer Protocol */INT sll_ifindex;/* interface number */unsigned short sll_hatype; /* Header type */unsigned char sll_pkttype;/* group type */unsigned char sll_halen;/* address length */unsigned char sll_addr [8]; /* physical layer address */};

The corresponding settings are as follows:

struct sockaddr_ll   sock;sock.sll_family = AF_PACKET;sock.sll_ifindex = stIf.ifr_ifindex;(struct   ifreq)sock.sll_protocol = htons(ETH_P_ALL);ret = bind(fd, (struct sockaddr *)&, sizeof(sock));

In this way, we can get the data on the corresponding socket through functions such as recvfrom.

Here we have obtained a packet from the NIC, but what does the packet look like? Here you must understand what is ethnet, that is, the Ethernet data frame.

The two-byte Frame Type field in the first part of an Ethernet frame specifies the specific Protocol carried by the upper layer, commonly, 0x0800 indicates IP packets, 0x0806 indicates RARP, and 0x0806 indicates the ARP protocol we will discuss. Hardware type: 1 indicates Ethernet.

When the network adapter receives a signal stream from the line, the driver of the network adapter checks the first six bytes of the data frame, that is, the MAC address of the target host, if it is the same as its NIC address, it will receive this frame. Otherwise, it is ignored directly. The data frame is then decomposed by the network driver, and the IP packet is sent to the application through the network protocol stack.

Here we can see that the Ethernet data frame header contains the MAC address and frame type, which is exactly what we need, so we need to begin to parse the Ethernet frame header, this involves another important data type, struct ether_header;

Important data information includes:

U_charether_dhost [ether_addr_len]; // dest mac address information
U_char ether_shost [ether_addr_len]; // the MAC address of the source.
U_short ether_type; // IP protocol type: IPv4 .......... And so on

Static int enumerate (const struct ether_header * pstethhead) {unsigned short usethpkttype;/* protocol type, source MAC, destination MAC */usethpkttype = ntohs (pstethhead-> ether_type ); printf ("ethtype: 0x % 04x (% s) \ n", delimiter, encrypt (plaintext); ethdump_showmac (pstethhead-> ether_shost); ethdump_showmac (pstethhead-> ether_dhost ); return 0;} ntohs (ether_type) returns a number of static void ethdump_showmac (const char achwaddr []) expressed in the host byte order {for (I = 0; I <ether_addr_len-1; I ++) {printf ("% 02x:", * (unsigned char *) & (achwaddr [I]);} printf ("% 02x] \ n", * (unsigned char *) & (achwaddr [I]);}

Next we need to parse the next section, namely, IP data packets. The corresponding data structure here is struct IP, which is somewhat complicated and I don't understand it very well, but we only need to get

U_int8_tip_p;/* Protocol */protocol type

Structin_addr ip_src, ip_dst;/* Source and DEST address */source IP address and destination IP address

Use getprotobynumber (); to return the relevant protocol information corresponding to the given Protocol number, and output the corresponding p_name.

And print the corresponding source IP and dest ip through inet_nota (ip_src. You can get the content we need now.

Static int ethdump_parseiphead (const struct IP * pstiphead) {struct protoent * pstipproto = NULL;/* protocol type, source IP address, destination IP address */pstipproto = getprotobynumber ); if (null! = Pstipproto) {printf ("IP-type: % d (% s) \ n", pstiphead-> ip_p, pstipproto-> p_name );} else {printf ("IP-type: % d (% s) \ n", pstiphead-> ip_p, "NONE ");} printf ("saddr = [% s] \ n", inet_ntoa (pstiphead-> ip_src); printf ("daddr = [% s]", inet_ntoa (pstiphead-> ip_dst )); printf ("\ n ======================================== =====\ N "); return 0 ;}

At this point, we have basically completed packet capture and analysis of the source MAC, DEST Mac, Source IP, des IP, and corresponding protocol types. Of course, further data analysis and Analysis of IP segments and protocol stacks can also be performed. The more things involved, the more complicated they will be.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.