linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
@ 2024-03-02 18:19 Oliver Crumrine
  2024-03-04 16:15 ` Alejandro Colomar
  0 siblings, 1 reply; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-02 18:19 UTC (permalink / raw)
  To: alx; +Cc: linux-kernel, linux-man, netdev

It was not made clear in several socket options that they were not
supported by SOCK_STREAM; this patch fixes that.

Socket options not supported by SOCK_STREAM are handled in the
ip_cmsg_recv_offset function in net/ipv4/ip_sockglue.c. The function is
called for udp sockets, and indirectly by ping and raw sockets, but not
for TCP sockets, as they don't support these options.

Signed-off-by: Oliver Crumrine <ozlinuxc@gmail.com>
---
 man7/ip.7 | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/man7/ip.7 b/man7/ip.7
index 2b4b06324..104e65feb 100644
--- a/man7/ip.7
+++ b/man7/ip.7
@@ -828,6 +828,9 @@ is not zero, the primary local address of the interface specified by the
 index overwrites
 .I ipi_spec_dst
 for the routing table lookup.
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVERR " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.15
@@ -989,6 +992,9 @@ in which the kernel returns the original destination address
 of the datagram being received.
 The ancillary message contains a
 .IR "struct sockaddr_in" .
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVTOS " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.68
@@ -998,6 +1004,9 @@ ancillary message is passed with incoming packets.
 It contains a byte which specifies the Type of Service/Precedence
 field of the packet header.
 Expects a boolean integer flag.
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVTTL " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.68
-- 
2.44.0


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-02 18:19 [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options Oliver Crumrine
@ 2024-03-04 16:15 ` Alejandro Colomar
  2024-03-05 19:31   ` Oliver Crumrine
  0 siblings, 1 reply; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-04 16:15 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man, netdev

[-- Attachment #1: Type: text/plain, Size: 2017 bytes --]

Hi Oliver,

On Sat, Mar 02, 2024 at 01:19:42PM -0500, Oliver Crumrine wrote:
> It was not made clear in several socket options that they were not
> supported by SOCK_STREAM; this patch fixes that.
> 
> Socket options not supported by SOCK_STREAM are handled in the
> ip_cmsg_recv_offset function in net/ipv4/ip_sockglue.c. The function is
> called for udp sockets, and indirectly by ping and raw sockets, but not
> for TCP sockets, as they don't support these options.
> 
> Signed-off-by: Oliver Crumrine <ozlinuxc@gmail.com>

Could you write some small example programs demonstrating that these are
not supported?  I'd like to check it with a small program, if possible.

Have a lovely say!
Alex

> ---
>  man7/ip.7 | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/man7/ip.7 b/man7/ip.7
> index 2b4b06324..104e65feb 100644
> --- a/man7/ip.7
> +++ b/man7/ip.7
> @@ -828,6 +828,9 @@ is not zero, the primary local address of the interface specified by the
>  index overwrites
>  .I ipi_spec_dst
>  for the routing table lookup.
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVERR " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.15
> @@ -989,6 +992,9 @@ in which the kernel returns the original destination address
>  of the datagram being received.
>  The ancillary message contains a
>  .IR "struct sockaddr_in" .
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVTOS " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.68
> @@ -998,6 +1004,9 @@ ancillary message is passed with incoming packets.
>  It contains a byte which specifies the Type of Service/Precedence
>  field of the packet header.
>  Expects a boolean integer flag.
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVTTL " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.68
> -- 
> 2.44.0
> 

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-04 16:15 ` Alejandro Colomar
@ 2024-03-05 19:31   ` Oliver Crumrine
  2024-03-06 10:50     ` Alejandro Colomar
  2024-03-06 10:58     ` Alejandro Colomar
  0 siblings, 2 replies; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-05 19:31 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-man, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3193 bytes --]

On Mon, Mar 04, 2024 at 05:15:52PM +0100, Alejandro Colomar wrote:
> Hi Oliver,
> 
> On Sat, Mar 02, 2024 at 01:19:42PM -0500, Oliver Crumrine wrote:
> > It was not made clear in several socket options that they were not
> > supported by SOCK_STREAM; this patch fixes that.
> > 
> > Socket options not supported by SOCK_STREAM are handled in the
> > ip_cmsg_recv_offset function in net/ipv4/ip_sockglue.c. The function is
> > called for udp sockets, and indirectly by ping and raw sockets, but not
> > for TCP sockets, as they don't support these options.
> > 
> > Signed-off-by: Oliver Crumrine <ozlinuxc@gmail.com>
> 
> Could you write some small example programs demonstrating that these are
> not supported?  I'd like to check it with a small program, if possible.
> 
> Have a lovely say!
> Alex
> 
Hi Alex,
I have attached two programs in the form of C source code below. No
special compilation options required. To change between the three
different socket options outlined in my patch, there are two options on
line 16 and 18 with a comment above them explaining how to use the
fields.

Here's how to use the programs:
0. Make sure you have netcat installed.
1. Compile the dgram one.
2. Run it.
3. Run nc localhost 8888 -u (in a seperate terminal window or tab)
4. Type whatever into netcat and press enter
5. Observe that there is a control message recieved, and there is a byte
printed, which is the first byte of the data in the control message.
6. You may repeat this for the three different socket options.
7. Repeat for the stream one, but use nc localhost 8888 (without the -u)
for #5.
8. Observe that there are no control messages recieved with the stream one,
and byte is 00, which is the initial value of the variable, before it has
a value assigned when the control messages (of which there are none) are read.

Thanks,
Oliver
> > ---
> >  man7/ip.7 | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/man7/ip.7 b/man7/ip.7
> > index 2b4b06324..104e65feb 100644
> > --- a/man7/ip.7
> > +++ b/man7/ip.7
> > @@ -828,6 +828,9 @@ is not zero, the primary local address of the interface specified by the
> >  index overwrites
> >  .I ipi_spec_dst
> >  for the routing table lookup.
> > +Not supported for
> > +.B SOCK_STREAM
> > +sockets.
> >  .TP
> >  .BR IP_RECVERR " (since Linux 2.2)"
> >  .\" Precisely: since Linux 2.1.15
> > @@ -989,6 +992,9 @@ in which the kernel returns the original destination address
> >  of the datagram being received.
> >  The ancillary message contains a
> >  .IR "struct sockaddr_in" .
> > +Not supported for
> > +.B SOCK_STREAM
> > +sockets.
> >  .TP
> >  .BR IP_RECVTOS " (since Linux 2.2)"
> >  .\" Precisely: since Linux 2.1.68
> > @@ -998,6 +1004,9 @@ ancillary message is passed with incoming packets.
> >  It contains a byte which specifies the Type of Service/Precedence
> >  field of the packet header.
> >  Expects a boolean integer flag.
> > +Not supported for
> > +.B SOCK_STREAM
> > +sockets.
> >  .TP
> >  .BR IP_RECVTTL " (since Linux 2.2)"
> >  .\" Precisely: since Linux 2.1.68
> > -- 
> > 2.44.0
> > 
> 
> -- 
> <https://www.alejandro-colomar.es/>
> Looking for a remote C programming job at the moment.



[-- Attachment #2: testDgramSocketServer.c --]
[-- Type: text/plain, Size: 2451 bytes --]

#include<stdio.h>	//printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>

#define BUFLEN 1500	//Max length of buffer
#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

void die(char *s)
{
	perror(s);
	exit(1);
}

int main(void)
{
	struct sockaddr_in si_me, si_other;
	
	int s, i, slen = sizeof(si_other) , recv_len;
	char buf[BUFLEN];
	
	if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
	{
		die("socket");
	}
	
	memset((char *) &si_me, 0, sizeof(si_me));
	
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
	{
		die("bind");
	}
	int yes = 1;
	if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) != 0){
		die("setsockopt");
	}
	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 = &si_me;
		mhdr.msg_namelen = sizeof(si_me);
		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));	
		fflush(stdout);
		
		//this is blocking
		if ((recv_len = recvmsg(s, &mhdr, 0)) == -1)
		{
			die("recvfrom()");
		}
		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 data recieved as a hex byte
    		printf("data read: %sbyte = %02X\n", databuf, tos); 	
		
	}

	close(s);
	return 0;
}

[-- Attachment #3: testStreamSocketServer.c --]
[-- Type: text/plain, Size: 2624 bytes --]

#include<stdio.h>	//printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<unistd.h>

#define BUFLEN 1500	//Max length of buffer
#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

void die(char *s)
{
	perror(s);
	exit(1);
}

int main(void)
{
	struct sockaddr_in si_me, si_other;
	
	int s, i, slen = sizeof(si_other) , recv_len;
	char buf[BUFLEN];
	
	if ((s=socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		die("socket");
	}
	
	memset((char *) &si_me, 0, sizeof(si_me));
	
	si_me.sin_family = AF_INET;
	si_me.sin_port = htons(PORT);
	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
	
	if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
	{
		die("bind");
	}
	listen(s, 10);
	while(1)
	{
		int connectedfd = accept(s, (struct sockaddr*)NULL, NULL);
		int yes = 1;                                                     	
		if(setsockopt(connectedfd, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) != 0){
			die("setsockopt");
		}

		
		
		struct msghdr mhdr;
		struct iovec iov[1];
		struct cmsghdr *cmhdr;
		char control[1000];
		char databuf[1500];
		unsigned char tos = 0;
		
		mhdr.msg_name = &si_me;
		mhdr.msg_namelen = sizeof(si_me);
		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));	
		fflush(stdout);
		
		//this is blocking
		if ((recv_len = recvmsg(connectedfd, &mhdr, 0)) == -1)
		{
			die("recvfrom()");
		}
		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 data recieved as a hex byte
    		printf("data read: %sbyte = %02X\n", databuf, tos); 	
		close(connectedfd);	
	}

	close(s);
	return 0;
}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-05 19:31   ` Oliver Crumrine
@ 2024-03-06 10:50     ` Alejandro Colomar
  2024-03-06 10:58     ` Alejandro Colomar
  1 sibling, 0 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-06 10:50 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-man, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 6383 bytes --]

Hi Oliver,

On Tue, Mar 05, 2024 at 02:31:48PM -0500, Oliver Crumrine wrote:
> #include<stdio.h>	//printf
> #include<string.h> //memset
> #include<stdlib.h> //exit(0);
> #include<arpa/inet.h>
> #include<sys/socket.h>
> #include<unistd.h>
> 
> #define BUFLEN 1500	//Max length of buffer

You could use BUFSIZ, which is in <stdio.h>.  It also removes magic
numbers like 1500 (why not 1000?).

> #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
> 
> void die(char *s)
> {
> 	perror(s);
> 	exit(1);
> }
> 
> int main(void)
> {
> 	struct sockaddr_in si_me, si_other;
> 	
> 	int s, i, slen = sizeof(si_other) , recv_len;

Unused variables 'i' and 'slen' (in both programs).

> 	char buf[BUFLEN];

Unused variable 'buf' (in both programs).

> 	
> 	if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)

This is more readable (and safer) in two lines:

	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == -1)

> 	{
> 		die("socket");

You could use
		err(1, "socket");

which is in <err.h>.

> 	}
> 	
> 	memset((char *) &si_me, 0, sizeof(si_me));
> 	
> 	si_me.sin_family = AF_INET;
> 	si_me.sin_port = htons(PORT);
> 	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
> 	
> 	if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)

The use of spaces is quite inconsistent.

> 	{
> 		die("bind");
> 	}
> 	int yes = 1;
> 	if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) != 0){

!= 0 is inconsistent with other == -1 checks.

Also placement of braces.

Have a lovely day!
Alex

> 		die("setsockopt");
> 	}
> 	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 = &si_me;
> 		mhdr.msg_namelen = sizeof(si_me);
> 		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));	
> 		fflush(stdout);
> 		
> 		//this is blocking
> 		if ((recv_len = recvmsg(s, &mhdr, 0)) == -1)
> 		{
> 			die("recvfrom()");
> 		}
> 		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 data recieved as a hex byte
>     		printf("data read: %sbyte = %02X\n", databuf, tos); 	
> 		
> 	}
> 
> 	close(s);
> 	return 0;
> }

> #include<stdio.h>	//printf
> #include<string.h> //memset
> #include<stdlib.h> //exit(0);
> #include<arpa/inet.h>
> #include<sys/socket.h>
> #include<unistd.h>
> 
> #define BUFLEN 1500	//Max length of buffer
> #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
> 
> void die(char *s)
> {
> 	perror(s);
> 	exit(1);
> }
> 
> int main(void)
> {
> 	struct sockaddr_in si_me, si_other;
> 	
> 	int s, i, slen = sizeof(si_other) , recv_len;
> 	char buf[BUFLEN];
> 	
> 	if ((s=socket(AF_INET, SOCK_STREAM, 0)) == -1)
> 	{
> 		die("socket");
> 	}
> 	
> 	memset((char *) &si_me, 0, sizeof(si_me));
> 	
> 	si_me.sin_family = AF_INET;
> 	si_me.sin_port = htons(PORT);
> 	si_me.sin_addr.s_addr = htonl(INADDR_ANY);
> 	
> 	if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
> 	{
> 		die("bind");
> 	}
> 	listen(s, 10);
> 	while(1)
> 	{
> 		int connectedfd = accept(s, (struct sockaddr*)NULL, NULL);
> 		int yes = 1;                                                     	
> 		if(setsockopt(connectedfd, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) != 0){
> 			die("setsockopt");
> 		}
> 
> 		
> 		
> 		struct msghdr mhdr;
> 		struct iovec iov[1];
> 		struct cmsghdr *cmhdr;
> 		char control[1000];
> 		char databuf[1500];
> 		unsigned char tos = 0;
> 		
> 		mhdr.msg_name = &si_me;
> 		mhdr.msg_namelen = sizeof(si_me);
> 		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));	
> 		fflush(stdout);
> 		
> 		//this is blocking
> 		if ((recv_len = recvmsg(connectedfd, &mhdr, 0)) == -1)
> 		{
> 			die("recvfrom()");
> 		}
> 		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 data recieved as a hex byte
>     		printf("data read: %sbyte = %02X\n", databuf, tos); 	
> 		close(connectedfd);	
> 	}
> 
> 	close(s);
> 	return 0;
> }


-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-05 19:31   ` Oliver Crumrine
  2024-03-06 10:50     ` Alejandro Colomar
@ 2024-03-06 10:58     ` Alejandro Colomar
  2024-03-06 13:02       ` Oliver Crumrine
  1 sibling, 1 reply; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-06 10:58 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-man, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 1576 bytes --]

Hi Oliver,

On Tue, Mar 05, 2024 at 02:31:48PM -0500, Oliver Crumrine wrote:
> Hi Alex,
> I have attached two programs in the form of C source code below. No
> special compilation options required. To change between the three
> different socket options outlined in my patch, there are two options on
> line 16 and 18 with a comment above them explaining how to use the
> fields.
> 
> Here's how to use the programs:
> 0. Make sure you have netcat installed.
> 1. Compile the dgram one.
> 2. Run it.
> 3. Run nc localhost 8888 -u (in a seperate terminal window or tab)
> 4. Type whatever into netcat and press enter
> 5. Observe that there is a control message recieved, and there is a byte
> printed, which is the first byte of the data in the control message.

Can't reproduce this.  The terminal running nc(1) isn't printing
anything.

alx@debian:~$ which nc
/usr/bin/nc
alx@debian:~$ which nc | xargs realpath
/usr/bin/nc.openbsd
alx@debian:~$ dpkg -S /bin/nc.openbsd
netcat-openbsd: /bin/nc.openbsd

> 6. You may repeat this for the three different socket options.
> 7. Repeat for the stream one, but use nc localhost 8888 (without the -u)
> for #5.
> 8. Observe that there are no control messages recieved with the stream one,
> and byte is 00, which is the initial value of the variable, before it has
> a value assigned when the control messages (of which there are none) are read.
> 
> Thanks,
> Oliver

Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-06 10:58     ` Alejandro Colomar
@ 2024-03-06 13:02       ` Oliver Crumrine
  2024-03-06 13:12         ` Alejandro Colomar
  0 siblings, 1 reply; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-06 13:02 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-kernel, linux-man

On Wed, Mar 6, 2024 at 5:58 AM Alejandro Colomar <alx@kernel.org> wrote:
>
> Hi Oliver,
>
> On Tue, Mar 05, 2024 at 02:31:48PM -0500, Oliver Crumrine wrote:
> > Hi Alex,
> > I have attached two programs in the form of C source code below. No
> > special compilation options required. To change between the three
> > different socket options outlined in my patch, there are two options on
> > line 16 and 18 with a comment above them explaining how to use the
> > fields.
> >
> > Here's how to use the programs:
> > 0. Make sure you have netcat installed.
> > 1. Compile the dgram one.
> > 2. Run it.
> > 3. Run nc localhost 8888 -u (in a seperate terminal window or tab)
> > 4. Type whatever into netcat and press enter
> > 5. Observe that there is a control message recieved, and there is a byte
> > printed, which is the first byte of the data in the control message.
>
> Can't reproduce this.  The terminal running nc(1) isn't printing
> anything.
>
> alx@debian:~$ which nc
> /usr/bin/nc
> alx@debian:~$ which nc | xargs realpath
> /usr/bin/nc.openbsd
> alx@debian:~$ dpkg -S /bin/nc.openbsd
> netcat-openbsd: /bin/nc.openbsd
>
> > 6. You may repeat this for the three different socket options.
> > 7. Repeat for the stream one, but use nc localhost 8888 (without the -u)
> > for #5.
> > 8. Observe that there are no control messages recieved with the stream one,
> > and byte is 00, which is the initial value of the variable, before it has
> > a value assigned when the control messages (of which there are none) are read.
> >
> > Thanks,
> > Oliver
>
> Have a lovely day!
> Alex
>
Hi Alex,
Type into netcat, not the program I sent.
My program is the server and prints out whatever it recieves,
along with some other stuff that lets you know which options
are supported.
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-06 13:02       ` Oliver Crumrine
@ 2024-03-06 13:12         ` Alejandro Colomar
       [not found]           ` <CAK1VsR3MsyphK+=rA7XcEigiSd6J_-QsVW+8hH1fU9xmRY3nGQ@mail.gmail.com>
  2024-03-17 11:31           ` Peter Seiderer
  0 siblings, 2 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-06 13:12 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 614 bytes --]

On Wed, Mar 06, 2024 at 08:02:10AM -0500, Oliver Crumrine wrote:
> Hi Alex,

Hi Oliver,

> Type into netcat, not the program I sent.
> My program is the server and prints out whatever it recieves,
> along with some other stuff that lets you know which options
> are supported.

Nothing either.

$ date; nc localhost 8888 -u | ts
Wed Mar  6 14:09:38 CET 2024
foo
$ echo $?
0


$ cc testDgramSocketServer.c 
$ date; ./a.out | ts
Wed Mar  6 14:09:05 CET 2024
^C
$


Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
       [not found]           ` <CAK1VsR3MsyphK+=rA7XcEigiSd6J_-QsVW+8hH1fU9xmRY3nGQ@mail.gmail.com>
@ 2024-03-13 18:27             ` Oliver Crumrine
  2024-03-13 22:35               ` Alejandro Colomar
  2024-03-16 19:33               ` Alejandro Colomar
  0 siblings, 2 replies; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-13 18:27 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-kernel, linux-man

On Wed, Mar 6, 2024 at 4:08 PM Oliver Crumrine <ozlinuxc@gmail.com> wrote:
>
> On Wed, Mar 6, 2024 at 8:12 AM Alejandro Colomar <alx@kernel.org> wrote:
> >
> > On Wed, Mar 06, 2024 at 08:02:10AM -0500, Oliver Crumrine wrote:
> > > Hi Alex,
> >
> > Hi Oliver,
> >
> > > Type into netcat, not the program I sent.
> > > My program is the server and prints out whatever it recieves,
> > > along with some other stuff that lets you know which options
> > > are supported.
> >
> > Nothing either.
> >
> > $ date; nc localhost 8888 -u | ts
> > Wed Mar  6 14:09:38 CET 2024
> > foo
> > $ echo $?
> > 0
> >
> >
> > $ cc testDgramSocketServer.c
> > $ date; ./a.out | ts
> > Wed Mar  6 14:09:05 CET 2024
> > ^C
> > $
> >
> >
> > Have a lovely day!
> > Alex
> >
> > --
> > <https://www.alejandro-colomar.es/>
> > Looking for a remote C programming job at the moment.
>
>
> 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?
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-13 18:27             ` Oliver Crumrine
@ 2024-03-13 22:35               ` Alejandro Colomar
  2024-03-16 19:33               ` Alejandro Colomar
  1 sibling, 0 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-13 22:35 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 920 bytes --]

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?

Sorry, I needed some rest this week.  I've been only attending easy
threads.  I hope I can come back to it very soon.  :-)

Have a lovely night!
Alex

> Thanks,
> Oliver
> 

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-16 19:33               ` Alejandro Colomar
@ 2024-03-16 18:41                 ` Oliver Crumrine
  2024-03-17  2:02                   ` Alejandro Colomar
  0 siblings, 1 reply; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-16 18:41 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 1603 bytes --]

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


[-- Attachment #2: testDgramSocketClient.c --]
[-- Type: text/plain, Size: 973 bytes --]

#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));
	
	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);


}

[-- Attachment #3: testDgramSocketServer.c --]
[-- Type: text/plain, Size: 2491 bytes --]

#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) {
    		        //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;
}

[-- Attachment #4: testStreamSocketClient.c --]
[-- Type: text/plain, Size: 1019 bytes --]

#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);


}

[-- Attachment #5: testStreamSocketServer.c --]
[-- Type: text/plain, Size: 3012 bytes --]

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-13 18:27             ` Oliver Crumrine
  2024-03-13 22:35               ` Alejandro Colomar
@ 2024-03-16 19:33               ` Alejandro Colomar
  2024-03-16 18:41                 ` Oliver Crumrine
  1 sibling, 1 reply; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-16 19:33 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 1172 bytes --]

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/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-16 18:41                 ` Oliver Crumrine
@ 2024-03-17  2:02                   ` Alejandro Colomar
  2024-03-17  9:02                     ` Oliver Crumrine
  0 siblings, 1 reply; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-17  2:02 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 10909 bytes --]

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/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-17  2:02                   ` Alejandro Colomar
@ 2024-03-17  9:02                     ` Oliver Crumrine
  2024-03-17 13:55                       ` Alejandro Colomar
  0 siblings, 1 reply; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-17  9:02 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: linux-man, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 11781 bytes --]

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.


[-- Attachment #2: testDgramSocketClient.c --]
[-- Type: text/plain, Size: 949 bytes --]

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

[-- Attachment #3: testDgramSocketServer.c --]
[-- Type: text/plain, Size: 2415 bytes --]

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

[-- Attachment #4: testStreamSocketClient.c --]
[-- Type: text/plain, Size: 995 bytes --]

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

[-- Attachment #5: testStreamSocketServer.c --]
[-- Type: text/plain, Size: 2934 bytes --]

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-06 13:12         ` Alejandro Colomar
       [not found]           ` <CAK1VsR3MsyphK+=rA7XcEigiSd6J_-QsVW+8hH1fU9xmRY3nGQ@mail.gmail.com>
@ 2024-03-17 11:31           ` Peter Seiderer
  2024-03-17 18:27             ` Alejandro Colomar
  1 sibling, 1 reply; 18+ messages in thread
From: Peter Seiderer @ 2024-03-17 11:31 UTC (permalink / raw)
  To: Alejandro Colomar; +Cc: Oliver Crumrine, linux-kernel, linux-man

On Wed, 6 Mar 2024 14:12:23 +0100, Alejandro Colomar <alx@kernel.org> wrote:

> On Wed, Mar 06, 2024 at 08:02:10AM -0500, Oliver Crumrine wrote:
> > Hi Alex,
>
> Hi Oliver,
>
> > Type into netcat, not the program I sent.
> > My program is the server and prints out whatever it recieves,
> > along with some other stuff that lets you know which options
> > are supported.
>
> Nothing either.
>
> $ date; nc localhost 8888 -u | ts
> Wed Mar  6 14:09:38 CET 2024
> foo
> $ echo $?
> 0

Same here, but with nc forced to IPv4

	$ nc localhost 8888  -u -4
	a

And in the other window:

	$ ./a.out
cmsg recieved
data read: a
byte = 02

Regards,
Peter

>
>
> $ cc testDgramSocketServer.c
> $ date; ./a.out | ts
> Wed Mar  6 14:09:05 CET 2024
> ^C
> $
>
>
> Have a lovely day!
> Alex
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-17  9:02                     ` Oliver Crumrine
@ 2024-03-17 13:55                       ` Alejandro Colomar
  0 siblings, 0 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-17 13:55 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-man, linux-kernel, Peter Seiderer

[-- Attachment #1: Type: text/plain, Size: 10858 bytes --]

Hi Oliver,

On Sun, Mar 17, 2024 at 05:02:39AM -0400, Oliver Crumrine wrote:
> 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. 

Okay, with the programs below, and after some whitespace fixes, I see
the following diff of the servers, which sounds reasonable:

$ diff -u d.c s.c 
--- d.c	2024-03-17 14:27:26.476377947 +0100
+++ s.c	2024-03-17 14:27:36.800391759 +0100
@@ -24,7 +24,7 @@
 	struct sockaddr_in local_addr;
 	int s;
 	
-	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+	s = socket(AF_INET, SOCK_STREAM, 0);
 	if (s == -1)
 		err(1, "error creating socket");
 	
@@ -40,8 +40,17 @@
 
 	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 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;
@@ -60,9 +69,9 @@
 		memset(databuf, 0, sizeof(databuf));	
 		
 		//this is blocking
-		int msglen = recvmsg(s, &mhdr, 0);
+		int msglen = recvmsg(connfd, &mhdr, 0);
 		if (msglen == -1)
-			err(1, "recvmsg");
+			err(1, "recvmsg\n");
 
 		cmhdr = CMSG_FIRSTHDR(&mhdr);
 		while (cmhdr) {
@@ -75,6 +84,7 @@
 		}
 		//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);

> 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.

And the programs behave as reported when adding -4.

> #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);

Why use IPPROTO_UDP?  ip(7)'s SYNOPSIS uses 0.  Are there any other
protocols available with (AF_INET, SOCK_DGRAM)?

Now about the patch, it seems to miss IP_RETOPTS, which is also handled
in ip_cmsg_recv_offset()?  Or am I missing something?

Please resend the programs when you send v2 of the patch, not send the
client programs, and show a diff of both programs.

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/>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
@ 2024-03-17 13:55 Oliver Crumrine
  2024-03-17 18:28 ` Alejandro Colomar
  0 siblings, 1 reply; 18+ messages in thread
From: Oliver Crumrine @ 2024-03-17 13:55 UTC (permalink / raw)
  To: alx; +Cc: linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 5007 bytes --]

It was not made clear in several socket options that they were not
supported by SOCK_STREAM; this patch fixes that.

Socket options not supported by SOCK_STREAM are handled in the
ip_cmsg_recv_offset function in net/ipv4/ip_sockglue.c. The function is
called for udp sockets, and indirectly by ping and raw sockets, but not
for STREAM sockets, as they don't support these options.

Signed-off-by: Oliver Crumrine <ozlinuxc@gmail.com>

v1->v2: Add IP_RETOPTS to the socket options without support on
SOCK_STREAM

Alex, I have attached the two test programs below, updated for support
with IP_RETOPTS.

I couldn't get an ip option out of netcat, so I'm attaching the client
programs, also updated with support for IP_OPTIONS, so they put an ip
option onto the packet for the server program to recieve.

Here is the diff between the two servers:
--- testDgramSocketServer.c     2024-03-17 08:32:27.623451419 -0400
+++ testStreamSocketServer.c    2024-03-17 08:21:11.860109033 -0400
@@ -23,7 +23,7 @@
        struct sockaddr_in local_addr;
        int s;

-       s = socket(AF_INET, SOCK_DGRAM, 0);
+       s = socket(AF_INET, SOCK_STREAM, 0);
        if (s == -1){
                err(1, "error creating socket");
        }
@@ -43,8 +43,20 @@
        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;
@@ -63,7 +75,7 @@
                memset(databuf, 0, sizeof(databuf));

                //this is blocking
-               int msglen = recvmsg(s, &mhdr, 0);
+               int msglen = recvmsg(connfd, &mhdr, 0);
                if (msglen == -1){
                        err(1, "recvmsg");
                }
@@ -78,6 +90,7 @@
                }
                //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);

And the clients in case you're interested:
--- testDgramSocketClient.c     2024-03-17 08:24:07.640111430 -0400
+++ testStreamSocketClient.c    2024-03-17 08:23:02.883443865 -0400
@@ -15,7 +15,7 @@

        char buf[] = "testing 1 2 3\n";

-       s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+       s = socket(AF_INET, SOCK_STREAM, 0);
        if(s == -1){
                err(1, "error creating socket");
        }
@@ -34,7 +34,10 @@
                err(1, "error converting network address");
        }

-       if(sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
+       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");
        }

---
 man7/ip.7 | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/man7/ip.7 b/man7/ip.7
index 2b4b06324..39055d3cf 100644
--- a/man7/ip.7
+++ b/man7/ip.7
@@ -828,6 +828,9 @@ is not zero, the primary local address of the interface specified by the
 index overwrites
 .I ipi_spec_dst
 for the routing table lookup.
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVERR " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.15
@@ -989,6 +992,9 @@ in which the kernel returns the original destination address
 of the datagram being received.
 The ancillary message contains a
 .IR "struct sockaddr_in" .
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVTOS " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.68
@@ -998,6 +1004,9 @@ ancillary message is passed with incoming packets.
 It contains a byte which specifies the Type of Service/Precedence
 field of the packet header.
 Expects a boolean integer flag.
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_RECVTTL " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.68
@@ -1015,6 +1024,9 @@ Identical to
 .BR IP_RECVOPTS ,
 but returns raw unprocessed options with timestamp and route record
 options not filled in for this hop.
+Not supported for
+.B SOCK_STREAM
+sockets.
 .TP
 .BR IP_ROUTER_ALERT " (since Linux 2.2)"
 .\" Precisely: since Linux 2.1.68
-- 
2.44.0


[-- Attachment #2: testDgramSocketClient.c --]
[-- Type: text/plain, Size: 1119 bytes --]

#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");
	}

	uint8_t options = 1; //noop in the language of ip options

	if(setsockopt(s, IPPROTO_IP, IP_OPTIONS, &options, 1) == -1){
		err(1, "error setting socket options");
	}

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

[-- Attachment #3: testDgramSocketServer.c --]
[-- Type: text/plain, Size: 2462 bytes --]

#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, 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_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;
}

[-- Attachment #4: testStreamSocketClient.c --]
[-- Type: text/plain, Size: 1164 bytes --]

#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");
	}

	uint8_t options = 1; //noop in the language of ip options

	if(setsockopt(s, IPPROTO_IP, IP_OPTIONS, &options, 1) == -1){
		err(1, "error setting socket options");
	}

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

[-- Attachment #5: testStreamSocketServer.c --]
[-- Type: text/plain, Size: 2994 bytes --]

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

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-17 11:31           ` Peter Seiderer
@ 2024-03-17 18:27             ` Alejandro Colomar
  0 siblings, 0 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-17 18:27 UTC (permalink / raw)
  To: Peter Seiderer; +Cc: Oliver Crumrine, linux-kernel, linux-man

[-- Attachment #1: Type: text/plain, Size: 1157 bytes --]

Hi Peter,

On Sun, Mar 17, 2024 at 12:31:35PM +0100, Peter Seiderer wrote:
> On Wed, 6 Mar 2024 14:12:23 +0100, Alejandro Colomar <alx@kernel.org> wrote:
> 
> > On Wed, Mar 06, 2024 at 08:02:10AM -0500, Oliver Crumrine wrote:
> > > Hi Alex,
> >
> > Hi Oliver,
> >
> > > Type into netcat, not the program I sent.
> > > My program is the server and prints out whatever it recieves,
> > > along with some other stuff that lets you know which options
> > > are supported.
> >
> > Nothing either.
> >
> > $ date; nc localhost 8888 -u | ts
> > Wed Mar  6 14:09:38 CET 2024
> > foo
> > $ echo $?
> > 0
> 
> Same here, but with nc forced to IPv4
> 
> 	$ nc localhost 8888  -u -4
> 	a
> 
> And in the other window:
> 
> 	$ ./a.out
> cmsg recieved
> data read: a
> byte = 02

Thanks for the help!

Have a lovely day!
Alex

> 
> Regards,
> Peter
> 
> >
> >
> > $ cc testDgramSocketServer.c
> > $ date; ./a.out | ts
> > Wed Mar  6 14:09:05 CET 2024
> > ^C
> > $
> >
> >
> > Have a lovely day!
> > Alex
> >
> 
> 

-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
  2024-03-17 13:55 Oliver Crumrine
@ 2024-03-17 18:28 ` Alejandro Colomar
  0 siblings, 0 replies; 18+ messages in thread
From: Alejandro Colomar @ 2024-03-17 18:28 UTC (permalink / raw)
  To: Oliver Crumrine; +Cc: linux-kernel, linux-man, Peter Seiderer

[-- Attachment #1: Type: text/plain, Size: 14375 bytes --]

Hi Oliver,

On Sun, Mar 17, 2024 at 09:55:50AM -0400, Oliver Crumrine wrote:
> It was not made clear in several socket options that they were not
> supported by SOCK_STREAM; this patch fixes that.
> 
> Socket options not supported by SOCK_STREAM are handled in the
> ip_cmsg_recv_offset function in net/ipv4/ip_sockglue.c. The function is
> called for udp sockets, and indirectly by ping and raw sockets, but not
> for STREAM sockets, as they don't support these options.
> 
> Signed-off-by: Oliver Crumrine <ozlinuxc@gmail.com>

Patch applied; thanks.
<https://www.alejandro-colomar.es/src/alx/linux/man-pages/man-pages.git/commit/?h=contrib&id=5675cf3b048ec65b241d51c1130b55420a5d2456>

Have a lovely day!
Alex

> 
> v1->v2: Add IP_RETOPTS to the socket options without support on
> SOCK_STREAM
> 
> Alex, I have attached the two test programs below, updated for support
> with IP_RETOPTS.
> 
> I couldn't get an ip option out of netcat, so I'm attaching the client
> programs, also updated with support for IP_OPTIONS, so they put an ip
> option onto the packet for the server program to recieve.
> 
> Here is the diff between the two servers:
> --- testDgramSocketServer.c     2024-03-17 08:32:27.623451419 -0400
> +++ testStreamSocketServer.c    2024-03-17 08:21:11.860109033 -0400
> @@ -23,7 +23,7 @@
>         struct sockaddr_in local_addr;
>         int s;
> 
> -       s = socket(AF_INET, SOCK_DGRAM, 0);
> +       s = socket(AF_INET, SOCK_STREAM, 0);
>         if (s == -1){
>                 err(1, "error creating socket");
>         }
> @@ -43,8 +43,20 @@
>         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;
> @@ -63,7 +75,7 @@
>                 memset(databuf, 0, sizeof(databuf));
> 
>                 //this is blocking
> -               int msglen = recvmsg(s, &mhdr, 0);
> +               int msglen = recvmsg(connfd, &mhdr, 0);
>                 if (msglen == -1){
>                         err(1, "recvmsg");
>                 }
> @@ -78,6 +90,7 @@
>                 }
>                 //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);
> 
> And the clients in case you're interested:
> --- testDgramSocketClient.c     2024-03-17 08:24:07.640111430 -0400
> +++ testStreamSocketClient.c    2024-03-17 08:23:02.883443865 -0400
> @@ -15,7 +15,7 @@
> 
>         char buf[] = "testing 1 2 3\n";
> 
> -       s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> +       s = socket(AF_INET, SOCK_STREAM, 0);
>         if(s == -1){
>                 err(1, "error creating socket");
>         }
> @@ -34,7 +34,10 @@
>                 err(1, "error converting network address");
>         }
> 
> -       if(sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
> +       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");
>         }
> 
> ---
>  man7/ip.7 | 12 ++++++++++++
>  1 file changed, 12 insertions(+)
> 
> diff --git a/man7/ip.7 b/man7/ip.7
> index 2b4b06324..39055d3cf 100644
> --- a/man7/ip.7
> +++ b/man7/ip.7
> @@ -828,6 +828,9 @@ is not zero, the primary local address of the interface specified by the
>  index overwrites
>  .I ipi_spec_dst
>  for the routing table lookup.
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVERR " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.15
> @@ -989,6 +992,9 @@ in which the kernel returns the original destination address
>  of the datagram being received.
>  The ancillary message contains a
>  .IR "struct sockaddr_in" .
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVTOS " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.68
> @@ -998,6 +1004,9 @@ ancillary message is passed with incoming packets.
>  It contains a byte which specifies the Type of Service/Precedence
>  field of the packet header.
>  Expects a boolean integer flag.
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_RECVTTL " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.68
> @@ -1015,6 +1024,9 @@ Identical to
>  .BR IP_RECVOPTS ,
>  but returns raw unprocessed options with timestamp and route record
>  options not filled in for this hop.
> +Not supported for
> +.B SOCK_STREAM
> +sockets.
>  .TP
>  .BR IP_ROUTER_ALERT " (since Linux 2.2)"
>  .\" Precisely: since Linux 2.1.68
> -- 
> 2.44.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_DGRAM, IPPROTO_UDP);
> 	if(s == -1){
> 		err(1, "error creating socket");
> 	}
> 
> 	uint8_t options = 1; //noop in the language of ip options
> 
> 	if(setsockopt(s, IPPROTO_IP, IP_OPTIONS, &options, 1) == -1){
> 		err(1, "error setting socket options");
> 	}
> 
> 	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, 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_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 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");
> 	}
> 
> 	uint8_t options = 1; //noop in the language of ip options
> 
> 	if(setsockopt(s, IPPROTO_IP, IP_OPTIONS, &options, 1) == -1){
> 		err(1, "error setting socket options");
> 	}
> 
> 	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, 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;
> }


-- 
<https://www.alejandro-colomar.es/>
Looking for a remote C programming job at the moment.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2024-03-17 18:28 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-02 18:19 [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options Oliver Crumrine
2024-03-04 16:15 ` Alejandro Colomar
2024-03-05 19:31   ` Oliver Crumrine
2024-03-06 10:50     ` Alejandro Colomar
2024-03-06 10:58     ` Alejandro Colomar
2024-03-06 13:02       ` Oliver Crumrine
2024-03-06 13:12         ` Alejandro Colomar
     [not found]           ` <CAK1VsR3MsyphK+=rA7XcEigiSd6J_-QsVW+8hH1fU9xmRY3nGQ@mail.gmail.com>
2024-03-13 18:27             ` Oliver Crumrine
2024-03-13 22:35               ` Alejandro Colomar
2024-03-16 19:33               ` Alejandro Colomar
2024-03-16 18:41                 ` Oliver Crumrine
2024-03-17  2:02                   ` Alejandro Colomar
2024-03-17  9:02                     ` Oliver Crumrine
2024-03-17 13:55                       ` Alejandro Colomar
2024-03-17 11:31           ` Peter Seiderer
2024-03-17 18:27             ` Alejandro Colomar
  -- strict thread matches above, loose matches on Subject: below --
2024-03-17 13:55 Oliver Crumrine
2024-03-17 18:28 ` Alejandro Colomar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).