On Sun, Mar 17, 2024 at 03:02:53AM +0100, Alejandro Colomar wrote: > Hi Oliver, > > On Sat, Mar 16, 2024 at 02:41:13PM -0400, Oliver Crumrine wrote: > > On Sat, Mar 16, 2024 at 08:33:36PM +0100, Alejandro Colomar wrote: > > > Hi Oliver, > > > > > > On Wed, Mar 13, 2024 at 02:27:17PM -0400, Oliver Crumrine wrote: > > > > > Hi Alex, > > > > > I apologize for your repeated troubles with my test program. > > > > > I have attached a video of myself using it in the method that I > > > > > described to you. (I emailed you off-list as to avoid sending a 12 > > > > > MB video to the whole list) > > > > > > > > > > If you are using it in the same way that works for me, I don't know > > > > > what the problem is. If I could've been clearer in my instructions, let > > > > > me know for the future. > > > > > > > > > > Thanks, > > > > > Oliver > > > > > > > > Hi Alex, > > > > Were you able to make any progress whatsoever with this test program? > > > > > > I'm sorry, but I haven't been able to reproduce the behavior. The test > > > programs have several problems which I reported in previous mails. > > > Maybe there's something that makes it unstable and in your system > > > behaves differently? Please clean up those examples, and try to run > > > them in a different system, and maybe then I can reproduce it. > > > > > > Have a lovely day! > > > Alex > > > > > > > > > $ uname -a > > > Linux debian 6.8.0-rc7-alx-dirty #3 SMP PREEMPT_DYNAMIC Mon Mar 4 15:24:33 CET 2024 x86_64 GNU/Linux > > > > > > -- > > > <https://www.alejandro-colomar.es/> > > Hi Alex, > > I have cleaned up my test programs. I have also tested them on other > > systems (including on systems which I had installed the rc7 kernel > > onto). In the very slight chance that your netcat isn't working, (very > > narrow chances, but still there), I have attached client programs to go > > along with the servers. > > Thanks, > > Oliver > > I still get warnings when compiling them. There's clearly dead code in > them. > > alx@debian:~/tmp$ cc -Wall -Wextra ds.c -o ds > ds.c: In function ‘main’: > ds.c:26:14: warning: unused variable ‘buf’ [-Wunused-variable] > 26 | char buf[BUFSIZ]; > | ^~~ > alx@debian:~/tmp$ cc -Wall -Wextra dc.c -o dc > dc.c: In function ‘main’: > dc.c:16:13: warning: unused variable ‘send_len’ [-Wunused-variable] > 16 | int send_len; > | ^~~~~~~~ > > > > #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; > > > > int send_len; > > char buf[] = "testing 1 2 3\n"; > > > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); > > if(s == -1){ > > err(1, "error creating socket"); > > } > > > > memset((char*)&server_addr, 0, sizeof(server_addr)); > > You shouldn't be casting pointers that you pass to memset(3). It > accepts almost anything. That cast defeats the little type safety that > it has. > > > > > 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); > > > > > > Why two blanks here? > > > } > > > #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; > > int recv_len; > > char buf[BUFSIZ]; > > > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); > > if (s == -1){ > > err(1, "error creating socket"); > > } > > > > memset((char *) &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[1500]; > > 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 > > if ((recv_len = recvmsg(s, &mhdr, 0)) == -1){ > > err(1, "recvmsg"); > > } > > cmhdr = CMSG_FIRSTHDR(&mhdr); > > while (cmhdr) { > > printf("cmsg recieved\n"); > > if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) { > > Don't mix spaces and tabs. > > > Have a lovely night! > Alex > > > //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; > > > > int send_len; > > char buf[] = "testing 1 2 3\n"; > > > > s = socket(AF_INET, SOCK_STREAM, 0); > > if(s == -1){ > > err(1, "error creating socket"); > > } > > > > memset((char*)&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; > > int recv_len; > > char buf[BUFSIZ]; > > > > s = socket(AF_INET, SOCK_STREAM, 0); > > if (s == -1){ > > err(1, "error creating socket"); > > } > > > > memset((char *) &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[1500]; > > 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 > > if ((recv_len = recvmsg(connfd, &mhdr, 0)) == -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/> I just realized I had cc linked to a homebrew c compler on my system and that's why Wall and Wextra weren't giving me the same warnings they were giving you. Oops. Anyway, I have put cc back to gcc, and I finally see the unused variable warnings, and I cleaned them up. Peter said on the previous reply to this that netcat only worked for him when it was forced to IPv4, using the -4 option, so that may be the issue you are facing with the program.
#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_DGRAM, IPPROTO_UDP); 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; }