Hi Oliver, On Sun, Mar 17, 2024 at 06:52:54AM -0400, Oliver Crumrine wrote: > On Sun, Mar 17, 2024 at 02:55:08PM +0100, Alejandro Colomar wrote: > > On Sun, Mar 17, 2024 at 05:02:39AM -0400, Oliver Crumrine wrote: > > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); > > > > Why use IPPROTO_UDP? ip(7)'s SYNOPSIS uses 0. Are there any other > Both are fine, but I can change the code to zero. > > protocols available with (AF_INET, SOCK_DGRAM)? > According to the ip(7) man page, only IPPROTO_UDPLITE, which functions > basically the same as udp, going as far as to use the same protocol > handler. I believe it's just a difference in the way checksums are > handled between UDP and UDPLITE. Ahh, ok, then IPPROTO_UDP is fine. > > > > Now about the patch, it seems to miss IP_RETOPTS, which is also handled > > in ip_cmsg_recv_offset()? Or am I missing something? > > > According to the ip(7) man page, IP_RETOPTS functions the same as > IP_RECVOPTS, which already properly states it is not supported on > SOCK_STREAM sockets. I still prefer if we state it's not supported. One could think that this one might be a version supported by SOCK_STREAM. > > Please resend the programs when you send v2 of the patch, not send the > > client programs, and show a diff of both programs. > I don't think this warrants a v2 -- I haven't changed the patch at all, > but I'll resend the programs, and heres a diff of the dgram server > program, the only one I changed: Actually, the diff I was interested in is the diff between the dgram and the stream servers. Have a lovely day! Alex > > --- a/testDgramSocketServer.c 2024-03-17 06:47:47.440033068 -0400 > +++ b/testDgramSocketServer.c 2024-03-17 06:48:15.800033455 -0400 > @@ -22,7 +22,7 @@ > struct sockaddr_in local_addr; > int s; > > - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); > + s = socket(AF_INET, SOCK_DGRAM, 0); > if (s == -1){ > err(1, "error creating socket"); > } > > > > Have a lovely day! > > Alex > > > > > if(s == -1){ > > > err(1, "error creating socket"); > > > } > > > > > > memset(&server_addr, 0, sizeof(server_addr)); > > > > > > server_addr.sin_family = AF_INET; > > > server_addr.sin_port = htons(PORT); > > > if(inet_pton(AF_INET, ADDR, &server_addr.sin_addr) != 1){ //I realize I'm checking the return value differently here. If you read the man page for inet_pton, it'll make sense. > > > err(1, "error converting network address"); > > > } > > > > > > if(sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){ > > > err(1, "error sending data"); > > > } > > > > > > close(s); > > > } > > > > > #include<stdio.h> > > > #include<err.h> > > > #include<string.h> > > > #include<stdlib.h> > > > #include<arpa/inet.h> > > > #include<sys/socket.h> > > > #include<unistd.h> > > > > > > #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. > > > #define SOCKOPT IP_RECVORIGDSTADDR > > > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO > > > #define RECIVEOPTION IP_ORIGDSTADDR > > > > > > int main(void){ > > > struct sockaddr_in local_addr; > > > int s; > > > > > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); > > > 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"); > > > } > > > > > > while(1){ > > > 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(s, &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(s); > > > return 0; > > > } > > > > > #include <stdio.h> > > > #include <err.h> > > > #include <string.h> > > > #include <stdlib.h> > > > #include <arpa/inet.h> > > > #include <sys/socket.h> > > > #include <unistd.h> > > > > > > #define PORT 8888 //The port on which to send data > > > #define ADDR "127.0.0.1" //The internet address to send packets to > > > > > > int main(void){ > > > int s; > > > struct sockaddr_in server_addr; > > > > > > char buf[] = "testing 1 2 3\n"; > > > > > > s = socket(AF_INET, SOCK_STREAM, 0); > > > if(s == -1){ > > > err(1, "error creating socket"); > > > } > > > > > > memset(&server_addr, 0, sizeof(server_addr)); > > > > > > server_addr.sin_family = AF_INET; > > > server_addr.sin_port = htons(PORT); > > > if(inet_pton(AF_INET, ADDR, &server_addr.sin_addr) != 1){ // I realize I'm checking the return value differently here. If you read the man page for inet_pton, it'll make sense. > > > err(1, "error converting network address"); > > > } > > > > > > if(connect(s, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){ > > > err(1, "error connecting"); > > > } > > > if(send(s, buf, strlen(buf), 0) == -1){ > > > err(1, "error sending data"); > > > } > > > > > > close(s); > > > } > > > > > #include<stdio.h> > > > #include<err.h> > > > #include<string.h> > > > #include<stdlib.h> > > > #include<arpa/inet.h> > > > #include<sys/socket.h> > > > #include<unistd.h> > > > > > > #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. > > > #define SOCKOPT IP_RECVORIGDSTADDR > > > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO > > > #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\n"); > > > } > > > 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; > > > } > > > > > > -- > > <https://www.alejandro-colomar.es/> > > > #include<stdio.h> > #include<err.h> > #include<string.h> > #include<stdlib.h> > #include<arpa/inet.h> > #include<sys/socket.h> > #include<unistd.h> > > #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. > #define SOCKOPT IP_RECVORIGDSTADDR > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO > #define RECIVEOPTION IP_ORIGDSTADDR > > int main(void){ > struct sockaddr_in local_addr; > int s; > > s = socket(AF_INET, SOCK_DGRAM, 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"); > } > > while(1){ > 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(s, &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(s); > return 0; > } > #include<stdio.h> > #include<err.h> > #include<string.h> > #include<stdlib.h> > #include<arpa/inet.h> > #include<sys/socket.h> > #include<unistd.h> > > #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. > #define SOCKOPT IP_RECVORIGDSTADDR > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO > #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\n"); > } > 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; > } -- <https://www.alejandro-colomar.es/>
Attachment:
signature.asc
Description: PGP signature