#include #include #include #include #include #include #include #define PORT 8888 //The port on which to listen for incoming data //Hi Alex, //These are the two lines that allow you to switch between the three socket options outlined in my patch //The socket options tell the kernel to add a control message (cmsg), allowing the program //to recieve the data it is requesting. The three options are: IP_RECVTOS for the type of service byte, //IP_RECVORIGDSTADDR for the orignial dst address, and IP_PKTINFO for some random packet info, and IP_RETOPTS //for some random ip packet options #define SOCKOPT IP_RECVORIGDSTADDR //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, IP_PKTINFO, and IP_OPTIONS #define RECIVEOPTION IP_ORIGDSTADDR int main(void){ struct sockaddr_in local_addr; int s; s = socket(AF_INET, SOCK_STREAM, 0); if (s == -1){ err(1, "error creating socket"); } memset(&local_addr, 0, sizeof(local_addr)); local_addr.sin_family = AF_INET; local_addr.sin_port = htons(PORT); local_addr.sin_addr.s_addr = htonl(INADDR_ANY); int yes = 1; if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){ err(1, "error setting socket option"); } if(bind(s, (struct sockaddr*)&local_addr, sizeof(local_addr) ) == -1){ err(1, "error binding to port. try changing it or running as root"); } if(listen(s, 10) == -1){ //10 is the backlog of un-accepted connections. its just an arbitrary number err(1, "error listening on port"); } while(1){ int connfd = accept(s, (struct sockaddr*)NULL, NULL); if(connfd == -1){ err(1, "error accepting connection"); } if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){ //stream sockets should have this set on the connected socket as well. I left it above for uniformity between the two programs. err(1, "error setting socket option"); } struct msghdr mhdr; struct iovec iov[1]; struct cmsghdr *cmhdr; char control[1000]; char databuf[BUFSIZ]; unsigned char tos = 0; mhdr.msg_name = &local_addr; mhdr.msg_namelen = sizeof(local_addr); mhdr.msg_iov = iov; mhdr.msg_iovlen = 1; mhdr.msg_control = &control; mhdr.msg_controllen = sizeof(control); iov[0].iov_base = databuf; iov[0].iov_len = sizeof(databuf); memset(databuf, 0, sizeof(databuf)); //this is blocking int msglen = recvmsg(connfd, &mhdr, 0); if (msglen == -1){ err(1, "recvmsg"); } cmhdr = CMSG_FIRSTHDR(&mhdr); while (cmhdr) { printf("cmsg recieved\n"); if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) { //read the byte recieved tos = ((unsigned char *)CMSG_DATA(cmhdr))[0]; } cmhdr = CMSG_NXTHDR(&mhdr, cmhdr); } //print out the first byte of data recieved in hex. You can verify this in wireshark if you like. printf("data read: %sbyte = %02X\n", databuf, tos); close(connfd); } close(s); return 0; }