Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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;
}

[Index of Archives]     [Kernel Documentation]     [Netdev]     [Linux Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux