An IP-header’s TOS field On setting and inspecting the ‘Type-of-Service’ field for outgoing or incoming datagrams Recall IP header format 32 bits IP Header version length Type of Service Identification Time-to-Live Total Length (in bytes) Fragment offset D M Protocol ID-number Header Checksum Source IP-address Destination IP-address Options Type-Of-Service 7 6 5 precedence 4 3 2 D T R 1 0 ECN This 8-bit field in the IPv4 Header has been variously defined over the years. In a modern definition it has a 6-bit field called Differentiated Services Code Point (DSCP) and a 2-bit field called Explicit Congestion Notification (ECN). Routers may use this ToS value when selecting a destination for the packet. Legend: D = requests low Delay T = requests high Throughput R = requests high Reliability Precedence Meanings for the 3-bit precedence field have been defined in Request For Comment documents (RFC791, RFC971): 111: Network Control 110: Internetwork Control 101: CRITIC/ECP 100: Flash Override 011: Flash 010: Immediate 001: Priority 000: Routine Here the middle four values pertain to national security and military communications having various levels of severity or urgency, (such as an outbreak of hostilities or a nuclear device detonation) Caveat • It should be mentioned that the ToS field’s ‘precedence’ bits are no longer used within contemporary networking systems for their originally envisioned purposes, and hence incoming IP packets which have these bits set ought to be regarded with suspicion – i.e., ask who is sending them, and why? Nevertheless… • We can employ one of the Linux ‘socket options’ to let applications manipulate the value that a socket places in the TOS field of its outgoing packets (SOL_IP, IP_TOS) • And we can employ another of the socket options to enable an application to inspect the TOS value of incoming IPv4 packets (SOL_IP, IP_RECVTOS) ‘msghdr’ and ‘cmsghdr’ • This will give us yet another example of a client-and-server application which makes use of socket options and ancillary data delivered via the ‘recvmsg()’ function ‘tweaktos.cpp’ ‘clonetos.cpp’ ‘client’ application ‘server’ application The ‘client’ sends a message having a user-specified TOS-value, and the ‘server’ echos back that message using an identical TOS-value. Our ‘private’ LAN • It’s probably a good idea, when we try out this client-and-server application, to do it on one of our ‘private’ local networks that does not ‘route’ any of our packets to any public networks (or to the Internet), so the ‘unusual’ TOS values in our ‘test-packets’ won’t arouse any unwarranted suspicions about who we are and what we’re up to! Recall ‘msghdr’ structure struct msghdr { void socklen_t struct iovec int void int int }; *msg_name; msg_namelen; *msg_iov; msg_iovlen; *msg_control; msg_controllen; flags; // optional address // size of address // scatter/gather array // no. of members // ancillary data buffer // ancillary buffer length // flags on received message struct iovec { void *iov_base; size_t iov_len; } Recall ‘cmsghdr’ structure struct cmsghdr { socklen_t int int unsigned char }; cmsg_len; cmsg_level; cmsg_type; cmsg_data[0]; // data byte count, including header // originating protocol’s ID-number // protocol-specific type ID-number // variable amount of data follows Our buffer for receiving ancillary data: ‘packages’ of ancillary data Recall the ‘CMSG’ macros int rxtos = 0; struct smsghdr for ( // to be filled in with incoming packet’s TOS *cmsg; // for use as the loop variable cmsg = CMSG_FIRSTHDR( &mymsghdr ); cmsg != NULL; cmsg = CMSG_NXTHDR( &mymsghdr, cmsg ) ) { if (( cmsg->cmsg_level == SOL_IP ) &&( cmsg->cmsg_type == IP_TOS )) memcpy( &rxtos, CMSG_DATA( cmsg ), 1 ); } Viewing memory • While learning about (or debugging) how your ancillary data arrives via ‘recvmsg()’, it may be instructive and helpful if you can get a look at memory-buffer’s contents • You can insert (temporarily) the following block of code (or some suitable variation) so you’ll see a memory ‘dump’ onscreen ‘hex’ and ‘ascii’ # shows the contents of the n-byte memory-area whose address is ‘buf’ unsigned char *cp = (unsigned char*)buf; for (int i = 0; i < n; i += 16) { printf( “\n %03X: “, i ); for (int j = 0; j < 16; j++) { if ( i+j < n ) printf( “%02X “, cp[ i+j ] ); else printf( “ “ ); } for (int j = 0; j < 16; j++) { int ch = ( i+j < n ) ? cp[ i+j ] : ‘ ‘; if (( ch < 0x20 )||( ch > 0x7E )) ch = ‘.’; printf( “%c”, ch ); } } printf( “\n\n” ); In-class exercise #1 • Modify our ‘tweaktos.cpp’ program so that it will draw a ‘dump’ of the contents of its ancillary data buffer (named ‘cbuf’) before terminating In-class exercise #2 • Modify our ‘tweaktos.cpp’ demo so that it will ALSO receive an incoming packet’s ‘Time-to-Live’ field, as well as continuing to receive its ‘Type-Of-Service’ field, and display a ‘dump’ of the ancillary data’s memory buffer to see both these items arranged as successive records in ‘cbuf’