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]

 



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


[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