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

Oliver Crumrine posted 1 patch 1 year, 11 months ago
There is a newer version of this series
man7/ip.7 | 9 +++++++++
1 file changed, 9 insertions(+)
[PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Oliver Crumrine 1 year, 11 months ago
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
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Alejandro Colomar 1 year, 11 months ago
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.
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Oliver Crumrine 1 year, 11 months ago
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.


#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;
}
#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;
}
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Alejandro Colomar 1 year, 11 months ago
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.
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Oliver Crumrine 1 year, 11 months ago
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
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Alejandro Colomar 1 year, 11 months ago
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.
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Peter Seiderer 1 year, 11 months ago
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
>
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Alejandro Colomar 1 year, 11 months ago
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.
Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Posted by Alejandro Colomar 1 year, 11 months ago
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.