270 likes | 813 Views
TCP/IP Stack. 67 Bootp DHCP. 69. 25. 21. 23. 53. 161. TCP Port #. UDP Port #. IPv6 41. EGP 8. OSPF 89. 6. 17. Port address. protocol. 1. 2. IP address. frame type. MAC address. What can raw sockets do?. Bypass TCP/UDP layers Read and write ICMP and IGMP packets
E N D
TCP/IP Stack 67 Bootp DHCP 69 25 21 23 53 161 TCPPort # UDPPort # IPv641 EGP8 OSPF89 6 17 Port address protocol 1 2 IP address frametype MAC address
What can raw sockets do? • Bypass TCP/UDP layers • Read and write ICMP and IGMP packets • ping, traceroute, multicast daemon • Read and write IP datagrams with an IP protocol field not processed by the kernel • OSPF • user process versus kernel • Send and receive your own IP packets with your own IP header using the IP_HDRINCL socket option • can build and send TCP and UDP packets • testing, hacking • only superuser can create raw socket though • You need to do all protocol processing at user-level
User TCP User UDP IGMP ICMP (ping, etc) TCP TCP UDP RAW RAW port port port ICMP UDP stack TCP stack echotimestamp port 2 port 89 1 17 6 17 UDP 6 TCP 1 ICMP 2 IGMP 89 OSPF
Creating a Raw Socket int sockfd; sockfd = socket(AF_INET, SOCK_RAW, protocol); • Can we use bind() with raw sockets? • rare, no concept of port • Can we use connect() with raw sockets? • rare, only foreign ip address IPPROTO_ICMP IPPROTO_IGMP const int on = 1; setsockopt (sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on);
Raw Socket Output • Sending raw socket packets by sendto or sendmsg • If IP_HDRINCL option not set (i.e. header is not included), the starting address of the data in sendto() specifies the first byte following the IP header • If IP_HDRINCL option set, the starting address of data in sendto() specifies the first byte of the IP header. • IP Header fields modified on sending by IP_HDRINCL • IP Checksum Always filled in. • Source Address Filled in when zero. • Packet Id Filled in when zero. • Total Length Always filled in. • Example: see Steven’s code under ping/send_v4.c, ping/send_v6.c
Raw Socket Input • Received TCP/UDP packets are NEVER passed to raw sockets. If needed, link layer is the place. • Receiving raw packets by recvfrom() or recvmsg() • Most ICMP packets are passed to all matching ICMP raw sockets except a few exceptions • ICMP echo request, timestamp request • All IGMP packets are passed to all matching raw sockets • All IP datagrams with a protocol field not processed by the kernel (e.g. OSPF) are passed to all matching raw sockets • The entire datagram, including the IP header, is passed to the raw socket. Fragments are assembled first. • Example: steven’s code in ping/readloop.c and ping/proc_v4.c
Scatter read and gather writeVectored IO #include <sys/uio.h> readv(int fd, const struct iovec *iov, int iovcnt); writev(int fd, const struct iovec *iov, int iovcnt); • Send and receive from one or more buffers with a single function call struct iovec { void *iov_base; /* addr. Of buffer */ size_t iov_len; /* size of buffer */ }
sendmsg and recvmsg most general of all the IO functions recvmsg(int sock, struct msghdr *msg, int flags); sendmsg(int sock, struct msghdr *msg, int flags); MSG_PEEK MSG_WAITALL struct msghdr { void *msg_name; /* address if socket is unconnected*/ socklen_t msg_namelen; /* size of above */ struct iovec *msg_iov; int msg_iovlen; void *msg_control; /* ancillary data */ socklen_t msg_controllen; int msg_flags; /* returned status by recvmsg */ } scatter gather read/write buffer MSG_TRUNC MSG_CTRUNC. MSG_EOR (end of record) MSG_OOB
ICMP Format subtype
Create a raw socket to send/receive ICMP echo request and echo reply packets Install SIGALRM handler to process output Sending echo request packets every t second Build ICMP packets (type, code, checksum, id, seq, sending timestamp as optional data) Enter an infinite loop processing input Use recvmsg() to read from the network Parse the message and retrieve the ICMP packet Print ICMP packet information, e.g., peer IP address, round-trip time Source code: Steven’s under ping/ Ping Program
Traceroute program • Create a UDP socket and bind source port • To send probe packets with increasing TTL • For each TTL value, use timer to send a probe every three seconds, and send 3 probes in total • Create a raw socket to receive ICMP packets • If timeout, printing “ *” • If ICMP “port unreachable”, then terminate • If ICMP “TTL expired”, then printing hostname of the router and round trip time to the router • Source code: Steven’s traceroute/