From: Alejandro Colomar <alx@kernel.org>
To: Oliver Crumrine <ozlinuxc@gmail.com>
Cc: linux-man@vger.kernel.org
Subject: Re: [PATCH] ip.7: Add not supported by SOCK_STREAM to socket options
Date: Sun, 17 Mar 2024 16:17:36 +0100 [thread overview]
Message-ID: <ZfcJkAGXJw6Dr9Ez@debian> (raw)
In-Reply-To: <hxkixsi6uymkjmt4ughda2xmh6guzcaccrjbvsuasndyuvq5rz@36oqfaepfiql>
[-- Attachment #1: Type: text/plain, Size: 16698 bytes --]
Hi Oliver,
On Sun, Mar 17, 2024 at 06:52:54AM -0400, Oliver Crumrine wrote:
> On Sun, Mar 17, 2024 at 02:55:08PM +0100, Alejandro Colomar wrote:
> > On Sun, Mar 17, 2024 at 05:02:39AM -0400, Oliver Crumrine wrote:
> > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> >
> > Why use IPPROTO_UDP? ip(7)'s SYNOPSIS uses 0. Are there any other
> Both are fine, but I can change the code to zero.
> > protocols available with (AF_INET, SOCK_DGRAM)?
> According to the ip(7) man page, only IPPROTO_UDPLITE, which functions
> basically the same as udp, going as far as to use the same protocol
> handler. I believe it's just a difference in the way checksums are
> handled between UDP and UDPLITE.
Ahh, ok, then IPPROTO_UDP is fine.
> >
> > Now about the patch, it seems to miss IP_RETOPTS, which is also handled
> > in ip_cmsg_recv_offset()? Or am I missing something?
> >
> According to the ip(7) man page, IP_RETOPTS functions the same as
> IP_RECVOPTS, which already properly states it is not supported on
> SOCK_STREAM sockets.
I still prefer if we state it's not supported. One could think that
this one might be a version supported by SOCK_STREAM.
> > Please resend the programs when you send v2 of the patch, not send the
> > client programs, and show a diff of both programs.
> I don't think this warrants a v2 -- I haven't changed the patch at all,
> but I'll resend the programs, and heres a diff of the dgram server
> program, the only one I changed:
Actually, the diff I was interested in is the diff between the dgram
and the stream servers.
Have a lovely day!
Alex
>
> --- a/testDgramSocketServer.c 2024-03-17 06:47:47.440033068 -0400
> +++ b/testDgramSocketServer.c 2024-03-17 06:48:15.800033455 -0400
> @@ -22,7 +22,7 @@
> struct sockaddr_in local_addr;
> int s;
>
> - s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> + s = socket(AF_INET, SOCK_DGRAM, 0);
> if (s == -1){
> err(1, "error creating socket");
> }
>
>
> > Have a lovely day!
> > Alex
> >
> > > if(s == -1){
> > > err(1, "error creating socket");
> > > }
> > >
> > > memset(&server_addr, 0, sizeof(server_addr));
> > >
> > > server_addr.sin_family = AF_INET;
> > > server_addr.sin_port = htons(PORT);
> > > if(inet_pton(AF_INET, ADDR, &server_addr.sin_addr) != 1){ //I realize I'm checking the return value differently here. If you read the man page for inet_pton, it'll make sense.
> > > err(1, "error converting network address");
> > > }
> > >
> > > if(sendto(s, buf, strlen(buf), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
> > > err(1, "error sending data");
> > > }
> > >
> > > close(s);
> > > }
> >
> > > #include<stdio.h>
> > > #include<err.h>
> > > #include<string.h>
> > > #include<stdlib.h>
> > > #include<arpa/inet.h>
> > > #include<sys/socket.h>
> > > #include<unistd.h>
> > >
> > > #define PORT 8888 //The port on which to listen for incoming data
> > >
> > >
> > > //Hi Alex,
> > > //These are the two lines that allow you to switch between the three socket options outlined in my patch
> > > //The socket options tell the kernel to add a control message (cmsg), allowing the program
> > > //to recieve the data it is requesting. The three options are: IP_RECVTOS for the type of service byte,
> > > //IP_RECVORIGDSTADDR for the orignial dst address, and IP_PKTINFO for some random packet info.
> > > #define SOCKOPT IP_RECVORIGDSTADDR
> > > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO
> > > #define RECIVEOPTION IP_ORIGDSTADDR
> > >
> > > int main(void){
> > > struct sockaddr_in local_addr;
> > > int s;
> > >
> > > s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
> > > if (s == -1){
> > > err(1, "error creating socket");
> > > }
> > >
> > > memset(&local_addr, 0, sizeof(local_addr));
> > >
> > > local_addr.sin_family = AF_INET;
> > > local_addr.sin_port = htons(PORT);
> > > local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
> > >
> > > int yes = 1;
> > > if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){
> > > err(1, "error setting socket option");
> > > }
> > >
> > >
> > > if(bind(s, (struct sockaddr*)&local_addr, sizeof(local_addr) ) == -1){
> > > err(1, "error binding to port. try changing it or running as root");
> > > }
> > >
> > > while(1){
> > > struct msghdr mhdr;
> > > struct iovec iov[1];
> > > struct cmsghdr *cmhdr;
> > > char control[1000];
> > > char databuf[BUFSIZ];
> > > unsigned char tos = 0;
> > >
> > > mhdr.msg_name = &local_addr;
> > > mhdr.msg_namelen = sizeof(local_addr);
> > > mhdr.msg_iov = iov;
> > > mhdr.msg_iovlen = 1;
> > > mhdr.msg_control = &control;
> > > mhdr.msg_controllen = sizeof(control);
> > > iov[0].iov_base = databuf;
> > > iov[0].iov_len = sizeof(databuf);
> > > memset(databuf, 0, sizeof(databuf));
> > >
> > > //this is blocking
> > > int msglen = recvmsg(s, &mhdr, 0);
> > > if (msglen == -1){
> > > err(1, "recvmsg");
> > > }
> > > cmhdr = CMSG_FIRSTHDR(&mhdr);
> > > while (cmhdr) {
> > > printf("cmsg recieved\n");
> > > if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) {
> > > //read the byte recieved
> > > tos = ((unsigned char *)CMSG_DATA(cmhdr))[0];
> > > }
> > > cmhdr = CMSG_NXTHDR(&mhdr, cmhdr);
> > > }
> > > //print out the first byte of data recieved in hex. You can verify this in wireshark if you like.
> > > printf("data read: %sbyte = %02X\n", databuf, tos);
> > >
> > > }
> > >
> > > close(s);
> > > return 0;
> > > }
> >
> > > #include <stdio.h>
> > > #include <err.h>
> > > #include <string.h>
> > > #include <stdlib.h>
> > > #include <arpa/inet.h>
> > > #include <sys/socket.h>
> > > #include <unistd.h>
> > >
> > > #define PORT 8888 //The port on which to send data
> > > #define ADDR "127.0.0.1" //The internet address to send packets to
> > >
> > > int main(void){
> > > int s;
> > > struct sockaddr_in server_addr;
> > >
> > > char buf[] = "testing 1 2 3\n";
> > >
> > > s = socket(AF_INET, SOCK_STREAM, 0);
> > > if(s == -1){
> > > err(1, "error creating socket");
> > > }
> > >
> > > memset(&server_addr, 0, sizeof(server_addr));
> > >
> > > server_addr.sin_family = AF_INET;
> > > server_addr.sin_port = htons(PORT);
> > > if(inet_pton(AF_INET, ADDR, &server_addr.sin_addr) != 1){ // I realize I'm checking the return value differently here. If you read the man page for inet_pton, it'll make sense.
> > > err(1, "error converting network address");
> > > }
> > >
> > > if(connect(s, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1){
> > > err(1, "error connecting");
> > > }
> > > if(send(s, buf, strlen(buf), 0) == -1){
> > > err(1, "error sending data");
> > > }
> > >
> > > close(s);
> > > }
> >
> > > #include<stdio.h>
> > > #include<err.h>
> > > #include<string.h>
> > > #include<stdlib.h>
> > > #include<arpa/inet.h>
> > > #include<sys/socket.h>
> > > #include<unistd.h>
> > >
> > > #define PORT 8888 //The port on which to listen for incoming data
> > >
> > >
> > > //Hi Alex,
> > > //These are the two lines that allow you to switch between the three socket options outlined in my patch
> > > //The socket options tell the kernel to add a control message (cmsg), allowing the program
> > > //to recieve the data it is requesting. The three options are: IP_RECVTOS for the type of service byte,
> > > //IP_RECVORIGDSTADDR for the orignial dst address, and IP_PKTINFO for some random packet info.
> > > #define SOCKOPT IP_RECVORIGDSTADDR
> > > //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO
> > > #define RECIVEOPTION IP_ORIGDSTADDR
> > >
> > > int main(void){
> > > struct sockaddr_in local_addr;
> > > int s;
> > >
> > > s = socket(AF_INET, SOCK_STREAM, 0);
> > > if (s == -1){
> > > err(1, "error creating socket");
> > > }
> > >
> > > memset(&local_addr, 0, sizeof(local_addr));
> > >
> > > local_addr.sin_family = AF_INET;
> > > local_addr.sin_port = htons(PORT);
> > > local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
> > >
> > > int yes = 1;
> > > if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){
> > > err(1, "error setting socket option");
> > > }
> > >
> > >
> > > if(bind(s, (struct sockaddr*)&local_addr, sizeof(local_addr) ) == -1){
> > > err(1, "error binding to port. try changing it or running as root");
> > > }
> > >
> > > if(listen(s, 10) == -1){ //10 is the backlog of un-accepted connections. its just an arbitrary number
> > > err(1, "error listening on port");
> > > }
> > >
> > > while(1){
> > > int connfd = accept(s, (struct sockaddr*)NULL, NULL);
> > > if(connfd == -1){
> > > err(1, "error accepting connection");
> > > }
> > > if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){ //stream sockets should have this set on the connected socket as well. I left it above for uniformity between the two programs.
> > > err(1, "error setting socket option");
> > > }
> > >
> > > struct msghdr mhdr;
> > > struct iovec iov[1];
> > > struct cmsghdr *cmhdr;
> > > char control[1000];
> > > char databuf[BUFSIZ];
> > > unsigned char tos = 0;
> > >
> > > mhdr.msg_name = &local_addr;
> > > mhdr.msg_namelen = sizeof(local_addr);
> > > mhdr.msg_iov = iov;
> > > mhdr.msg_iovlen = 1;
> > > mhdr.msg_control = &control;
> > > mhdr.msg_controllen = sizeof(control);
> > > iov[0].iov_base = databuf;
> > > iov[0].iov_len = sizeof(databuf);
> > > memset(databuf, 0, sizeof(databuf));
> > >
> > > //this is blocking
> > > int msglen = recvmsg(connfd, &mhdr, 0);
> > > if (msglen == -1){
> > > err(1, "recvmsg\n");
> > > }
> > > cmhdr = CMSG_FIRSTHDR(&mhdr);
> > > while (cmhdr) {
> > > printf("cmsg recieved\n");
> > > if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) {
> > > //read the byte recieved
> > > tos = ((unsigned char *)CMSG_DATA(cmhdr))[0];
> > > }
> > > cmhdr = CMSG_NXTHDR(&mhdr, cmhdr);
> > > }
> > > //print out the first byte of data recieved in hex. You can verify this in wireshark if you like.
> > > printf("data read: %sbyte = %02X\n", databuf, tos);
> > > close(connfd);
> > > }
> > >
> > > close(s);
> > > return 0;
> > > }
> >
> >
> > --
> > <https://www.alejandro-colomar.es/>
>
>
> #include<stdio.h>
> #include<err.h>
> #include<string.h>
> #include<stdlib.h>
> #include<arpa/inet.h>
> #include<sys/socket.h>
> #include<unistd.h>
>
> #define PORT 8888 //The port on which to listen for incoming data
>
>
> //Hi Alex,
> //These are the two lines that allow you to switch between the three socket options outlined in my patch
> //The socket options tell the kernel to add a control message (cmsg), allowing the program
> //to recieve the data it is requesting. The three options are: IP_RECVTOS for the type of service byte,
> //IP_RECVORIGDSTADDR for the orignial dst address, and IP_PKTINFO for some random packet info.
> #define SOCKOPT IP_RECVORIGDSTADDR
> //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO
> #define RECIVEOPTION IP_ORIGDSTADDR
>
> int main(void){
> struct sockaddr_in local_addr;
> int s;
>
> s = socket(AF_INET, SOCK_DGRAM, 0);
> if (s == -1){
> err(1, "error creating socket");
> }
>
> memset(&local_addr, 0, sizeof(local_addr));
>
> local_addr.sin_family = AF_INET;
> local_addr.sin_port = htons(PORT);
> local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
>
> int yes = 1;
> if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){
> err(1, "error setting socket option");
> }
>
>
> if(bind(s, (struct sockaddr*)&local_addr, sizeof(local_addr) ) == -1){
> err(1, "error binding to port. try changing it or running as root");
> }
>
> while(1){
> struct msghdr mhdr;
> struct iovec iov[1];
> struct cmsghdr *cmhdr;
> char control[1000];
> char databuf[BUFSIZ];
> unsigned char tos = 0;
>
> mhdr.msg_name = &local_addr;
> mhdr.msg_namelen = sizeof(local_addr);
> mhdr.msg_iov = iov;
> mhdr.msg_iovlen = 1;
> mhdr.msg_control = &control;
> mhdr.msg_controllen = sizeof(control);
> iov[0].iov_base = databuf;
> iov[0].iov_len = sizeof(databuf);
> memset(databuf, 0, sizeof(databuf));
>
> //this is blocking
> int msglen = recvmsg(s, &mhdr, 0);
> if (msglen == -1){
> err(1, "recvmsg");
> }
> cmhdr = CMSG_FIRSTHDR(&mhdr);
> while (cmhdr) {
> printf("cmsg recieved\n");
> if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) {
> //read the byte recieved
> tos = ((unsigned char *)CMSG_DATA(cmhdr))[0];
> }
> cmhdr = CMSG_NXTHDR(&mhdr, cmhdr);
> }
> //print out the first byte of data recieved in hex. You can verify this in wireshark if you like.
> printf("data read: %sbyte = %02X\n", databuf, tos);
>
> }
>
> close(s);
> return 0;
> }
> #include<stdio.h>
> #include<err.h>
> #include<string.h>
> #include<stdlib.h>
> #include<arpa/inet.h>
> #include<sys/socket.h>
> #include<unistd.h>
>
> #define PORT 8888 //The port on which to listen for incoming data
>
>
> //Hi Alex,
> //These are the two lines that allow you to switch between the three socket options outlined in my patch
> //The socket options tell the kernel to add a control message (cmsg), allowing the program
> //to recieve the data it is requesting. The three options are: IP_RECVTOS for the type of service byte,
> //IP_RECVORIGDSTADDR for the orignial dst address, and IP_PKTINFO for some random packet info.
> #define SOCKOPT IP_RECVORIGDSTADDR
> //This field is synonymous with the above one. Valid options are: IP_TOS, IP_ORIGDSTADDR, and IP_PKTINFO
> #define RECIVEOPTION IP_ORIGDSTADDR
>
> int main(void){
> struct sockaddr_in local_addr;
> int s;
>
> s = socket(AF_INET, SOCK_STREAM, 0);
> if (s == -1){
> err(1, "error creating socket");
> }
>
> memset(&local_addr, 0, sizeof(local_addr));
>
> local_addr.sin_family = AF_INET;
> local_addr.sin_port = htons(PORT);
> local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
>
> int yes = 1;
> if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){
> err(1, "error setting socket option");
> }
>
>
> if(bind(s, (struct sockaddr*)&local_addr, sizeof(local_addr) ) == -1){
> err(1, "error binding to port. try changing it or running as root");
> }
>
> if(listen(s, 10) == -1){ //10 is the backlog of un-accepted connections. its just an arbitrary number
> err(1, "error listening on port");
> }
>
> while(1){
> int connfd = accept(s, (struct sockaddr*)NULL, NULL);
> if(connfd == -1){
> err(1, "error accepting connection");
> }
> if(setsockopt(s, IPPROTO_IP, SOCKOPT, &yes, sizeof(yes)) == -1){ //stream sockets should have this set on the connected socket as well. I left it above for uniformity between the two programs.
> err(1, "error setting socket option");
> }
>
> struct msghdr mhdr;
> struct iovec iov[1];
> struct cmsghdr *cmhdr;
> char control[1000];
> char databuf[BUFSIZ];
> unsigned char tos = 0;
>
> mhdr.msg_name = &local_addr;
> mhdr.msg_namelen = sizeof(local_addr);
> mhdr.msg_iov = iov;
> mhdr.msg_iovlen = 1;
> mhdr.msg_control = &control;
> mhdr.msg_controllen = sizeof(control);
> iov[0].iov_base = databuf;
> iov[0].iov_len = sizeof(databuf);
> memset(databuf, 0, sizeof(databuf));
>
> //this is blocking
> int msglen = recvmsg(connfd, &mhdr, 0);
> if (msglen == -1){
> err(1, "recvmsg\n");
> }
> cmhdr = CMSG_FIRSTHDR(&mhdr);
> while (cmhdr) {
> printf("cmsg recieved\n");
> if (cmhdr->cmsg_level == IPPROTO_IP && cmhdr->cmsg_type == RECIVEOPTION) {
> //read the byte recieved
> tos = ((unsigned char *)CMSG_DATA(cmhdr))[0];
> }
> cmhdr = CMSG_NXTHDR(&mhdr, cmhdr);
> }
> //print out the first byte of data recieved in hex. You can verify this in wireshark if you like.
> printf("data read: %sbyte = %02X\n", databuf, tos);
> close(connfd);
> }
>
> close(s);
> return 0;
> }
--
<https://www.alejandro-colomar.es/>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2024-03-17 15:17 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
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
[not found] ` <hxkixsi6uymkjmt4ughda2xmh6guzcaccrjbvsuasndyuvq5rz@36oqfaepfiql>
2024-03-17 15:17 ` Alejandro Colomar [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZfcJkAGXJw6Dr9Ez@debian \
--to=alx@kernel.org \
--cc=linux-man@vger.kernel.org \
--cc=ozlinuxc@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox