Author : Thamer Al-Harbash
Page : << Previous 4 Next >>
Depending on what you want to send, you initially open a
socket and give it its type.
sockd = socket(AF_INET,SOCK_RAW,<protocol>);
You can choose from any protocol including IPPROTO_RAW.
The protocol number goes into the IP header verbatim.
IPPROTO_RAW places 0 in the IP header.
Most systems have a socket option IP_HDRINCL which allows
you to include your own IP header along with the rest of
the packet. If your system doesn't have this option, you
may or may not be able to include your own IP header. If
it is available, you should use it as such:
char on = 1;
setsockopt(sockd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
Of course, if you don't want to include an IP header, you
can always specify a protocol in the creation of the
socket and slip your transport level header under it.
You then build the packet and use a normal sendto().
2.2.2) How do I build a TCP/IP packet?
Examples can be found at http://www.whitefang.com/rin/
which attempt to illustrate the details involved. They
also illustrate some of the bugs mentioned below.
Briefly, you need to actually write the packet out in
memory and hand it over to the socket where it will
hopefully fire it away and await more packets.
2.2.3) How can I listen for packets with a raw socket?
Traditionally the BSD socket API did not allow you to
listen to just any incoming packet via a raw socket.
Although Linux (2.0.30 was the last version I had a look
at), did allow this, it has to do with their own
implementation of the TCP/IP stack. Correct BSD semantics
allow you to get some packets which match a certain
category (see below).
There's a logical reason behind this; for example TCP
packets are always handled by the kernel. If the port is
open, send a SYN-ACK and establish the connection, or
send back a RST. On the other hand, some types of ICMP (I
compiled a small list below), the kernel can't handle.
Like an ICMP echo reply, is passed to a matching raw
socket, since it was meant for a user program to receive
it.
The solution is to firewall that particular port if it
was a UDP or TCP packet, and sniff it with a packet
capturing API (a list is mentioned above). This prevents
the TCP/IP stack from handling the packet, thus it will
be ignored and you can handle it yourself without
intervention.
If you don't firewall it, and reply yourself you'll wind
up having additional responses from your operating
system!
Here's a concise explanation of the semantics of a raw
BSD socket, taken from a Usenet post by W. Richard
Stevens
From <rstevens@kohala.com> (Sun Jul 6 12:07:07 1997) :
"The semantics of BSD raw sockets are:
- TCP and UDP: no one other than the kernel gets these.
- ICMP: a copy of each ICMP gets passed to each matching raw
socket, except for a few that the kernel generates the reply
for: ICMP echo request, timestamp request, and mask request.
- IGMP: all of these get passed to all matching raw sockets.
- all other protocols that the kernel doesn't deal with (OSPF,
etc.): these all get passed to all matching raw sockets."
After looking at the icmp_input() routine from the
4.4BSD's TCP/IP stack, it seems the following ICMP types
will be passed to matching raw sockets:
Echo Reply: (0)
Router Advertisement (9)
Time Stamp Reply (13)
Mask Reply (18)
2.3) What bugs should I look out for when using a raw socket?
Page : << Previous 4 Next >>