From 1991246020e790722912663a788dc8337b073b5d Mon Sep 17 00:00:00 2001 From: Philip Homburg Date: Fri, 17 Feb 2006 13:45:41 +0000 Subject: [PATCH] Socket options SO_RCVBUF, SO_SNDBUF, and TCP_NODELAY. --- lib/ip/getsockopt.c | 67 +++++++++++++++++++++++++++++++- lib/ip/setsockopt.c | 93 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 157 insertions(+), 3 deletions(-) diff --git a/lib/ip/getsockopt.c b/lib/ip/getsockopt.c index 9994f56d1..537e0c945 100644 --- a/lib/ip/getsockopt.c +++ b/lib/ip/getsockopt.c @@ -5,21 +5,27 @@ #include #include #include +#include #include #include #include +#include +#include #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; +} diff --git a/lib/ip/setsockopt.c b/lib/ip/setsockopt.c index 905ea9b94..e6ef3631d 100644 --- a/lib/ip/setsockopt.c +++ b/lib/ip/setsockopt.c @@ -4,21 +4,28 @@ #include #include #include +#include #include #include #include +#include +#include #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; +} + -- 2.44.0