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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.