]> Zhao Yanbai Git Server - minix.git/commitdiff
Socket options SO_RCVBUF, SO_SNDBUF, and TCP_NODELAY.
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 17 Feb 2006 13:45:41 +0000 (13:45 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 17 Feb 2006 13:45:41 +0000 (13:45 +0000)
lib/ip/getsockopt.c
lib/ip/setsockopt.c

index 9994f56d114bb1d6eadf937a9b7ecd79dfa4210c..537e0c945136b0b366b5d50594b4988720676e0a 100644 (file)
@@ -5,21 +5,27 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <netinet/tcp.h>
 
 #include <net/gen/in.h>
 #include <net/gen/tcp.h>
 #include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
 
 #define DEBUG 0
 
 static int _tcp_getsockopt(int socket, int level, int option_name,
        void *_RESTRICT option_value, socklen_t *_RESTRICT option_len);
+static int _udp_getsockopt(int socket, int level, int option_name,
+       void *_RESTRICT option_value, socklen_t *_RESTRICT option_len);
 
 int getsockopt(int socket, int level, int option_name,
         void *_RESTRICT option_value, socklen_t *_RESTRICT option_len)
 {
        int r;
        nwio_tcpopt_t tcpopt;
+       nwio_udpopt_t udpopt;
 
        r= ioctl(socket, NWIOGTCPOPT, &tcpopt);
        if (r != -1 || errno != ENOTTY)
@@ -33,10 +39,22 @@ int getsockopt(int socket, int level, int option_name,
                        option_value, option_len);
        }
 
+       r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+       if (r != -1 || errno != ENOTTY)
+       {
+               if (r == -1)
+               {
+                       /* Bad file descriptor */
+                       return -1;
+               }
+               return _udp_getsockopt(socket, level, option_name,
+                       option_value, option_len);
+       }
+
 #if DEBUG
        fprintf(stderr, "getsockopt: not implemented for fd %d\n", socket);
 #endif
-       errno= ENOSYS;
+       errno= ENOTSOCK;
        return -1;
 }
 
@@ -55,12 +73,57 @@ static int _tcp_getsockopt(int socket, int level, int option_name,
                *option_len= sizeof(i);
                return 0;
        }
+       if (level == SOL_SOCKET && option_name == SO_RCVBUF)
+       {
+               i= 32*1024;     /* Receive buffer in the current
+                                * implementation
+                                */
+               if (*option_len < sizeof(i))
+                       memcpy(option_value, &i, *option_len);
+               else
+                       memcpy(option_value, &i, sizeof(i));
+               *option_len= sizeof(i);
+               return 0;
+       }
+       if (level == SOL_SOCKET && option_name == SO_SNDBUF)
+       {
+               i= 32*1024;     /* Send buffer in the current implementation */
+               if (*option_len < sizeof(i))
+                       memcpy(option_value, &i, *option_len);
+               else
+                       memcpy(option_value, &i, sizeof(i));
+               *option_len= sizeof(i);
+               return 0;
+       }
+       if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
+       {
+               i= 0;   /* nodelay is always off */
+               if (*option_len < sizeof(i))
+                       memcpy(option_value, &i, *option_len);
+               else
+                       memcpy(option_value, &i, sizeof(i));
+               *option_len= sizeof(i);
+               return 0;
+       }
 #if DEBUG
        fprintf(stderr, "_tcp_getsocketopt: level %d, name %d\n",
                level, option_name);
 #endif
 
-       errno= ENOSYS;
+       errno= ENOPROTOOPT;
        return -1;
 }
 
+static int _udp_getsockopt(int socket, int level, int option_name,
+       void *_RESTRICT option_value, socklen_t *_RESTRICT option_len)
+{
+       int i;
+
+#if DEBUG
+       fprintf(stderr, "_udp_getsocketopt: level %d, name %d\n",
+               level, option_name);
+#endif
+
+       errno= ENOSYS;
+       return -1;
+}
index 905ea9b94953a7c9378f8a182458f30bacf9772c..e6ef3631d15d3231d04fd1145c14826b9d002052 100644 (file)
@@ -4,21 +4,28 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <netinet/tcp.h>
 
 #include <net/gen/in.h>
 #include <net/gen/tcp.h>
 #include <net/gen/tcp_io.h>
+#include <net/gen/udp.h>
+#include <net/gen/udp_io.h>
 
 #define DEBUG 0
 
 static int _tcp_setsockopt(int socket, int level, int option_name,
        const void *option_value, socklen_t option_len);
 
+static int _udp_setsockopt(int socket, int level, int option_name,
+       const void *option_value, socklen_t option_len);
+
 int setsockopt(int socket, int level, int option_name,
         const void *option_value, socklen_t option_len)
 {
        int r;
        nwio_tcpopt_t tcpopt;
+       nwio_udpopt_t udpopt;
 
        r= ioctl(socket, NWIOGTCPOPT, &tcpopt);
        if (r != -1 || errno != ENOTTY)
@@ -32,10 +39,22 @@ int setsockopt(int socket, int level, int option_name,
                        option_value, option_len);
        }
 
+       r= ioctl(socket, NWIOGUDPOPT, &udpopt);
+       if (r != -1 || errno != ENOTTY)
+       {
+               if (r == -1)
+               {
+                       /* Bad file descriptor */
+                       return -1;
+               }
+               return _udp_setsockopt(socket, level, option_name,
+                       option_value, option_len);
+       }
+
 #if DEBUG
        fprintf(stderr, "setsockopt: not implemented for fd %d\n", socket);
 #endif
-       errno= ENOSYS;
+       errno= ENOTSOCK;
        return -1;
 }
 
@@ -62,6 +81,64 @@ static int _tcp_setsockopt(int socket, int level, int option_name,
                }
                return 0;
        }
+       if (level == SOL_SOCKET && option_name == SO_RCVBUF)
+       {
+               if (option_len != sizeof(i))
+               {
+                       errno= EINVAL;
+                       return -1;
+               }
+               i= *(int *)option_value;
+               if (i > 32*1024)
+               {
+                       /* The receive buffer is limited to 32K at the moment.
+                        */
+                       errno= ENOSYS;
+                       return -1;
+               }
+               /* There is no way to reduce the receive buffer, do we have to
+                * let this call fail for smaller buffers?
+                */
+               return 0;
+       }
+       if (level == SOL_SOCKET && option_name == SO_SNDBUF)
+       {
+               if (option_len != sizeof(i))
+               {
+                       errno= EINVAL;
+                       return -1;
+               }
+               i= *(int *)option_value;
+               if (i > 32*1024)
+               {
+                       /* The send buffer is limited to 32K at the moment.
+                        */
+                       errno= ENOSYS;
+                       return -1;
+               }
+               /* There is no way to reduce the send buffer, do we have to
+                * let this call fail for smaller buffers?
+                */
+               return 0;
+       }
+       if (level == IPPROTO_TCP && option_name == TCP_NODELAY)
+       {
+               if (option_len != sizeof(i))
+               {
+                       errno= EINVAL;
+                       return -1;
+               }
+               i= *(int *)option_value;
+               if (i)
+               {
+                       /* At the moment there is no way to turn on 
+                        * nodelay.
+                        */
+                       errno= ENOSYS;
+                       return -1;
+               }
+               return 0;
+       }
 #if DEBUG
        fprintf(stderr, "_tcp_setsocketopt: level %d, name %d\n",
                level, option_name);
@@ -71,3 +148,17 @@ static int _tcp_setsockopt(int socket, int level, int option_name,
        return -1;
 }
 
+static int _udp_setsockopt(int socket, int level, int option_name,
+       const void *option_value, socklen_t option_len)
+{
+       int i;
+
+#if DEBUG
+       fprintf(stderr, "_udp_setsocketopt: level %d, name %d\n",
+               level, option_name);
+#endif
+
+       errno= ENOSYS;
+       return -1;
+}
+