For raw sockets, only root privileges can be created.
There are three main functions of raw sockets:
1. The raw socket is used to receive the ICMP,IGMP protocol package sent to the native, or to send the protocol packets.
2. Receive IP packets that are sent to the native but not capable of processing by the TCP/IP stack: Many operating systems now implement only a few commonly used protocols when implementing network parts.
such as TCP,UDP,ICMP, but like other protocols such as OSPF,GGP, the operating system is often not implemented, if
It is necessary to write the application that is located on it, it must be done with the raw socket, because the operation
The system encounters packets that it cannot handle (the upper-level protocol specified by protocol in the IP header cannot be located
The packet to the raw socket corresponding to the protocol.
3. Used to send some of their own special functions such as source address IP packet (write IP header, TCP header, etc.)
The raw socket is created in the following way:
SOCKFD = socket (pf_inet, SOCK_RAW, protocol);
The first parameter is the difference between pf_inet and af_inet: When the address family is specified, it is generally set to af_inet, that is, the IP is used, and the Protocal family is specified when you specify it.
#define AF_INET 0
#define Pf_inet Af_inet
So af_inet is exactly the same as pf_inet.
The second parameter description establishes a raw socket
The third parameter is divided into three cases:
1. The parameter protocol is used to indicate the protocol number to be received, if it is like ipproto_tcp (6)
Non-0, non-No. 255 protocols, the kernel encounters the protocol domain in the IP header and the parameters used to create the socket
Number protocol the same IP packet, it will be handed over to this rawsocket to handle. Therefore, in general,
To receive what packets, the corresponding protocol should be specified with the parameter protocol. When
When the kernel delivers packets to this raw socket, it includes the entire IP header and is already a heavy
A good set of IP packets. As follows:
---------------------------------------------------------------
|ip header|tcp Header (or x header) | Data |
---------------------------------------------------------------
The data received with Recvfrom consists of an IP header, a corresponding protocol header, and then the data (number
It can also be empty, it depends on the actual situation). But when we send IP packets, we don't have to personally
To handle the IP header, you only need to fill in the corresponding protocol header specified by the parameter protocol.
Is that, with SendTo, the buffer data we provide to it is the first word from the IP header
Section start, as below, only need to construct such a buffer.
--------------------------------------------------------------
|TCP header (or UDP header or x header) | Data |
--------------------------------------------------------------
If you want to handle the IP header yourself, you will need the IP_HDRINCL socket option as follows:
int flag = 1;
SetSockOpt (SOCKFD, Ipproto_ip, Ip_hdrincl, &flag, sizeof (int));
In this way, the buffer to be supplied at the time of delivery has the following form:
---------------------------------------------------------------
|ip header|tcp Header (or x header) | Data |
---------------------------------------------------------------
However, even in this case, when we send IP packets. It's not all the words that fill the IP header.
The IP header ID (identification) field should be set to 0, which means that the kernel
This field. At the same time, the kernel also helps you calculate the checksum of the IP header and then populates the check
Field.
2. If protocol is Ipproto_raw (255), the socket can only be used to send IP packets, not to receive any data. The data sent needs to populate the IP header itself and calculate the checksum itself.
3. If protocol is ipproto_ip (0). It is not allowed on Linux and SCO UNIX.
There are 3 ways to create sockets in the
Original socket:
1.socket (Af_inet, Sock_raw, ipproto_tcp| ipproto_udp| IPPROTO_ICMP) Send receive IP packets
2.socket (Pf_packet, Sock_raw, htons (eth_p_ip| eth_p_arp| Eth_p_all)) Send receive Ethernet data frame
3.socket (af_inet, Sock_packet, htons (eth_p_ip| eth_p_arp| Eth_p_all) is out of date, don't use AH
understand the sock_raw principle, such as the NIC received a 14+20+8+100+4 UDP Ethernet data frame.
First, the network card hard filtering the data frame (depending on the mode of the network card will have different actions,
if the Promisc promiscuous mode is set, then do not make any filtering directly to the previous input routine,
otherwise non-native Mac or broadcast Mac will be discarded directly). In the example above, if successful,
will enter the IP input routine. But before entering the IP input routine, the system checks to see if there is a pass through
socket (af_packet, Sock_raw, ...) in the system. The socket that was created. If any, and the protocol matches, the system sends a copy of the data frame to each such socket
receive buffer. Then, entering the IP input routine, the IP layer will filter the packet
. is to check or discard non-native IP or broadcast IP packets, and so on, if the successful
session will enter the UDP input routine. However, before handing over to the UDP input routine, the system checks if there is
through the socket (af_inet, Sock_raw,.). The socket that was created. If there is one and the protocol matches, the
in this case requires the IPPROTO_UDP type. The system sends a copy of the data frame to each such socket receive buffer
area. Finally, enter the UDP input routine.
1. Sockets (Af_inet, Sock_raw, IPPROTO_UDP); -Process data at the network layer
Yes: the socket can receive IP packets destined for the protocol type (TCP UDP ICMP, etc.) to this machine, as seen from the above is 20+8+100.
No: You cannot receive packets that are not destined for the local IP (IP soft filter Discards these packets that are not destined for the native IP).
No: You cannot receive packets that are sent from this computer.
If you send it, you need to organize your own TCP UDP ICMP headers. You can setsockopt to wrap your IP head
2. Socket (Pf_packet, Sock_raw, htons (x)); -process data at the data link layer
Can: Receive data frames destined for local Mac
Can: Receive a data frame sent from the local (the 3rd parameter needs to be set to Eth_p_all)
Can: Receive data frames that are not destined for the local Mac (the NIC needs to be set to Promisc promiscuous mode)
There are four types of protocol
ETH_P_IP 0x800 only receive data frames for IP types destined to native Mac
Eth_p_arp 0x806 only accepts data frames for ARP types that are destined for native Mac
Eth_p_arp 0x8035 only accepts data frames of type RARP that are destined for native Mac
The Eth_p_all 0x3 receives data frames for all types of IP arp rarp that are sent to the native Mac, receiving all types of data frames emitted from the native computer. (when promiscuous mode is turned on, it receives a data frame that is not destined for a local Mac)
3. Socket (af_inet, Sock_packet, htons (Eth_p_all)), this is generally used to grab the package program.
Summarize how to use:
1. Just want to receive IP packets destined for some kind of protocol to this machine. The first is enough.
2. For more details please use the second type. Both the Eth_p_all parameter and the promiscuous mode can make it more capable.
Two. Place the NIC in promiscuous mode
Under normal circumstances, a network interface should only respond to two data frames at the data link layer:
One is a data frame that matches your own hardware address
A broadcast data frame that is sent to all machines
If you want the NIC to receive all the data that passes through it, regardless of whether it is sent to it, you must put the NIC in promiscuous mode.
Use the Raw Socket implementation code as follows:
setsockopt (sock, Ipproto_ip, Ip_hdrincl, (char*) &flag, sizeof (flag);//Set IP header operation options
Bind (Sockraw, (psockaddr) &addrlocal, sizeof (addrlocal);//bind Sockraw to local NIC
Ioctlsocket (Sockraw, Sio_rcvall, &dwvalue); Let Sockraw accept all the data
The flag flag is used to set the IP header operation, which means to handle the IP header yourself: BOOL flag = ture;
Addrlocal for local address: sockaddr_in addrlocal;
Dwvalue for input and output parameters, 1 o'clock execution, 0 o'clock Cancel: DWORD dwvalue = 1;
The following program uses raw sockets to send TCP messages and completely manually create headers:
int sendtcp (unsigned short desport, unsigned long Desip)
{
Wsadata Wsadata;
SOCKET sock;
Sockaddr_in addr_in;
Ipheader Ipheader;
Tcpheader Tcpheader;
Psdheader Psdheader;
Char Szsendbuf[max_len] = {0};
BOOL Flag;
int rect, ntimeover;
if (WSAStartup (Makeword (2, 2), &wsadata)! = 0)
{
printf ("WSAStartup error!\n");
return false;
}
if (sock = WSASocket (Af_inet, Sock_raw, Ipproto_raw, NULL, 0,
wsa_flag_overlapped)) = = Invalid_socket)
{
printf ("Socket Setup error!\n");
return false;
}
Flag = true;
if (setsockopt (sock, Ipproto_ip, Ip_hdrincl, (char*) &flag, sizeof (flag))
==socket_error)
{
printf ("setsockopt ip_hdrincl error!\n");
return false;
}
Ntimeover = 1000;
if (setsockopt (sock, Sol_socket, So_sndtimeo, (char*) &ntimeover, sizeof
(Ntimeover)) = = Socket_error)
{
printf ("setsockopt so_sndtimeo error!\n");
return false;
}
addr_in.sin_family = af_inet;
Addr_in.sin_port = htons (Desport);
Addr_in.sin_addr. S_un. S_ADDR = inet_addr (DESIP);
Populating the IP header
Ipheader.h_verlen = (4 << 4 | sizeof (Ipheader)/sizeof (unsigned long));
ipheader.tos=0;
Ipheader.total_len = htons (sizeof (Ipheader) + sizeof (Tcpheader));
Ipheader.ident = 1;
ipheader.frag_and_flags = 0;
Ipheader.ttl = 128;
Ipheader.proto = ipproto_tcp;
ipheader.checksum = 0;
Ipheader.sourceip = inet_addr ("localhost");
Ipheader.destip = Desip;
Populating the TCP header
Tcpheader.th_dport = htons (Desport);
Tcpheader.th_sport = htons (Source_port); Source port number
Tcpheader.th_seq = htonl (0x12345678);
Tcpheader.th_ack = 0;
Tcpheader.th_lenres = (sizeof (tcpheader)/4 << 4 | 0);
Tcpheader.th_flag = 2; Flag bit detection, 2 is SYN
Tcpheader.th_win = htons (512);
tcpheader.th_urp = 0;
tcpheader.th_sum = 0;
PSDHEADER.SADDR = Ipheader.sourceip;
PSDHEADER.DADDR = Ipheader.destip;
PSDHEADER.MBZ = 0;
PSDHEADER.PTCL = ipproto_tcp;
psdheader.tcpl = htons (sizeof (Tcpheader));
Calculate the Checksum
memcpy (Szsendbuf, &psdheader, sizeof (Psdheader));
memcpy (szsendbuf + sizeof (psdheader), &tcpheader, sizeof (Tcpheader));
Tcpheader.th_sum = Checksum ((unsigned short*) szsendbuf, sizeof (psdheader) + sizeof
(Tcpheader));
memcpy (Szsendbuf, &ipheader, sizeof (Ipheader));
memcpy (szsendbuf + sizeof (ipheader), &tcpheader, sizeof (Tcpheader));
memset (szsendbuf + sizeof (ipheader) + sizeof (Tcpheader), 0, 4);
Ipheader.checksum = Checksum ((unsigned short*) szsendbuf, sizeof (ipheader) + sizeof
(Tcpheader));
memcpy (Szsendbuf, &ipheader, sizeof (Ipheader));
Rect = sendto (sock, Szsendbuf, sizeof (Ipheader) + sizeof (Tcpheader), 0,
(struct sockaddr*) &addr_in, sizeof (addr_in));
if (rect = = socket_error)
{
printf ("Send error!:%d\n", WSAGetLastError ());
return false;
}
Else
printf ("Send ok!\n");
Closesocket (sock);
WSACleanup ();
return rect;
}
2, the kernel receives the network data after the processing principle on the Rawsocket:
(1): For IP packets generated by UDP/TCP, the kernel does not pass it to any of the original sockets, but only to the corresponding UDP/TCP data processing handle (so, if you want to access TCP/UDP or other types of data through the original socket, Call the socket function to create the original socket the third parameter should be specified as Htons (ETH_P_IP), that is, by directly accessing the data link layer to achieve
(2): for IP packets, such as ICMP and EGP, which use IP packets to host data but also under the transport layer, the kernel copies a copy of the IP packets to the original socket that is passed to the protocol type, regardless of whether or not a registered handle is already in place to process the data.
(3): For packets that do not recognize the protocol type, the kernel makes the necessary checks and then checks to see if the original socket with the type match is responsible for processing the data, and if so, copies the IP packets to the matching original socket, otherwise the kernel discards the IP packet. and returns an ICMP host unreachable message to the source host.
(4): If the original socket bind to an address, the core only the destination address for the native IP address of the packets to the original socket, if a raw socket does not have a bind address, the core will send all the IP packets received to the original socket.
(5): If the original socket calls the Connect function, the core only passes the IP packet of the source address to the IP address of the connect connection to the original socket.
(6): If the original socket does not call the bind and connect functions, the core passes all IP packets matching the protocol to the original socket.
This article from "Tech record" blog, declined reprint!
Raw_socket RAW sockets