diff options
author | Dragana Damjanovic <dd.mozilla@gmail.com> | 2021-06-09 16:21:38 +0000 |
---|---|---|
committer | Dragana Damjanovic <dd.mozilla@gmail.com> | 2021-06-09 16:21:38 +0000 |
commit | 1d4e53982bd859a32df415f4994cfb162bd730d7 (patch) | |
tree | 25be47b311ecf7831454debc8bf8757f5451584b | |
parent | 7d8d4535c0b843e647586df079a757894a048238 (diff) | |
download | nspr-hg-1d4e53982bd859a32df415f4994cfb162bd730d7.tar.gz |
Bug 1713681 - Add set/getsockopt for the don't-fragment option. r=kaie,bwc,valentin
Differential Revision: https://phabricator.services.mozilla.com/D116658
-rw-r--r-- | pr/include/prio.h | 2 | ||||
-rw-r--r-- | pr/src/io/prmapopt.c | 82 | ||||
-rw-r--r-- | pr/src/pthreads/ptio.c | 47 | ||||
-rw-r--r-- | pr/tests/sockopt.c | 5 |
4 files changed, 134 insertions, 2 deletions
diff --git a/pr/include/prio.h b/pr/include/prio.h index d5cff257..8b331a32 100644 --- a/pr/include/prio.h +++ b/pr/include/prio.h @@ -205,6 +205,7 @@ typedef enum PRSockOption PR_SockOpt_Broadcast, /* enable broadcast */ PR_SockOpt_Reuseport, /* allow local address & port reuse on * platforms that support it */ + PR_SockOpt_DontFrag, /* Do not fragment flag */ PR_SockOpt_Last } PRSockOption; @@ -230,6 +231,7 @@ typedef struct PRSocketOptionData PRBool reuse_addr; /* Allow local address reuse */ PRBool reuse_port; /* Allow local address & port reuse on * platforms that support it */ + PRBool dont_fragment; /* Do not fragment flag */ PRBool keep_alive; /* Keep connections alive */ PRBool mcast_loopback; /* IP multicast loopback */ PRBool no_delay; /* Don't delay send to coalesce packets */ diff --git a/pr/src/io/prmapopt.c b/pr/src/io/prmapopt.c index b6653e4b..375a73d2 100644 --- a/pr/src/io/prmapopt.c +++ b/pr/src/io/prmapopt.c @@ -33,6 +33,15 @@ #include "primpl.h" +#if defined(LINUX) || defined(ANDROID) +#include <netinet/in.h> +#endif + +#ifdef DARWIN +#include <netinet/in.h> +#include <netinet/ip.h> +#endif + #ifdef HAVE_NETINET_TCP_H #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */ #endif @@ -174,6 +183,28 @@ PRStatus PR_CALLBACK _PR_SocketGetSocketOption(PRFileDesc *fd, PRSocketOptionDat (char*)&data->value.mcast_if.inet.ip, &length); break; } + case PR_SockOpt_DontFrag: + { +#if !defined(WIN32) && !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID) + PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); + rv = PR_FAILURE; +#else +#ifdef WIN32 /* Winsock */ + DWORD value; +#else + PRIntn value; +#endif + length = sizeof(value); + rv = _PR_MD_GETSOCKOPT( + fd, level, name, (char*)&value, &length); +#if defined(WIN32) || defined(DARWIN) + data->value.dont_fragment = value; +#else + data->value.dont_fragment = (value == IP_PMTUDISC_DO) ? 1 : 0; +#endif +#endif /* !(!defined(WIN32) && !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID)) */ + break; + } default: PR_NOT_REACHED("Unknown socket option"); break; @@ -306,6 +337,27 @@ PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOpt sizeof(data->value.mcast_if.inet.ip)); break; } + case PR_SockOpt_DontFrag: + { +#if !defined(WIN32) && !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID) + PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); + rv = PR_FAILURE; +#else +#if defined(WIN32) /* Winsock */ + DWORD value; + value = (data->value.dont_fragment) ? 1 : 0; +#elif defined(LINUX) || defined(ANDROID) + PRIntn value; + value = (data->value.dont_fragment) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; +#elif defined(DARWIN) + PRIntn value; + value = data->value.dont_fragment; +#endif + rv = _PR_MD_SETSOCKOPT( + fd, level, name, (char*)&value, sizeof(value)); +#endif /* !(!defined(WIN32) && !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID)) */ + break; + } default: PR_NOT_REACHED("Unknown socket option"); break; @@ -400,6 +452,23 @@ PRStatus PR_CALLBACK _PR_SocketSetSocketOption(PRFileDesc *fd, const PRSocketOpt #define IP_TOS _PR_NO_SUCH_SOCKOPT #endif +/* set/get IP do not fragment */ +#if defined(WIN32) +#ifndef IP_DONTFRAGMENT +#define IP_DONTFRAGMENT _PR_NO_SUCH_SOCKOPT +#endif + +#elif defined(LINUX) || defined(ANDROID) +#ifndef IP_MTU_DISCOVER +#define IP_MTU_DISCOVER _PR_NO_SUCH_SOCKOPT +#endif + +#elif defined(DARWIN) +#ifndef IP_DONTFRAG +#define IP_DONTFRAG _PR_NO_SUCH_SOCKOPT +#endif +#endif + #ifndef TCP_NODELAY /* don't delay to coalesce data */ #define TCP_NODELAY _PR_NO_SUCH_SOCKOPT #endif @@ -424,14 +493,23 @@ PRStatus _PR_MapOptionName( 0, SO_LINGER, SO_REUSEADDR, SO_KEEPALIVE, SO_RCVBUF, SO_SNDBUF, IP_TTL, IP_TOS, IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP, IP_MULTICAST_IF, IP_MULTICAST_TTL, IP_MULTICAST_LOOP, - TCP_NODELAY, TCP_MAXSEG, SO_BROADCAST, SO_REUSEPORT + TCP_NODELAY, TCP_MAXSEG, SO_BROADCAST, SO_REUSEPORT, +#if defined(WIN32) + IP_DONTFRAGMENT, +#elif defined(LINUX) || defined(ANDROID) + IP_MTU_DISCOVER, +#elif defined(DARWIN) + IP_DONTFRAG, +#else + _PR_NO_SUCH_SOCKOPT, +#endif }; static PRInt32 socketLevels[PR_SockOpt_Last] = { 0, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, SOL_SOCKET, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, IPPROTO_IP, - IPPROTO_TCP, IPPROTO_TCP, SOL_SOCKET, SOL_SOCKET + IPPROTO_TCP, IPPROTO_TCP, SOL_SOCKET, SOL_SOCKET, IPPROTO_IP }; if ((optname < PR_SockOpt_Linger) diff --git a/pr/src/pthreads/ptio.c b/pr/src/pthreads/ptio.c index 3ad2d80a..a2bc3e71 100644 --- a/pr/src/pthreads/ptio.c +++ b/pr/src/pthreads/ptio.c @@ -155,6 +155,15 @@ static ssize_t (*pt_aix_sendfile_fptr)() = NULL; #include "primpl.h" +#if defined(LINUX) || defined(ANDROID) +#include <netinet/in.h> +#endif + +#ifdef DARWIN +#include <netinet/in.h> +#include <netinet/ip.h> +#endif + #ifdef HAVE_NETINET_TCP_H #include <netinet/tcp.h> /* TCP_NODELAY, TCP_MAXSEG */ #endif @@ -3146,6 +3155,25 @@ static PRStatus pt_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) || (sizeof(data->value.mcast_if.inet.ip) == length)); break; } + case PR_SockOpt_DontFrag: + { +#if !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID) + PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); + rv = PR_FAILURE; +#else + PRIntn value; + length = sizeof(value); + rv = getsockopt( + fd->secret->md.osfd, level, name, (char*)&value, + &length); +#if defined(DARWIN) + data->value.dont_fragment = value; +#else + data->value.dont_fragment = (value == IP_PMTUDISC_DO) ? 1 : 0; +#endif +#endif /* !(!defined(DARWIN) && !defined(LINUX) && !defined(ANDROID)) */ + break; + } default: PR_NOT_REACHED("Unknown socket option"); break; @@ -3259,6 +3287,25 @@ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *dat sizeof(data->value.mcast_if.inet.ip)); break; } + case PR_SockOpt_DontFrag: + { +#if !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID) + PR_SetError(PR_OPERATION_NOT_SUPPORTED_ERROR, 0); + rv = PR_FAILURE; +#else + PRIntn value; +#if defined(LINUX) || defined(ANDROID) + value = (data->value.dont_fragment) ? IP_PMTUDISC_DO + : IP_PMTUDISC_DONT; +#elif defined(DARWIN) + value = data->value.dont_fragment; +#endif + rv = setsockopt( + fd->secret->md.osfd, level, name, (char*)&value, + sizeof(value)); +#endif /* !defined(DARWIN) && !defined(LINUX) && !defined(ANDROID)) */ + break; + } default: PR_NOT_REACHED("Unknown socket option"); break; diff --git a/pr/tests/sockopt.c b/pr/tests/sockopt.c index 540a19b9..d1a04451 100644 --- a/pr/tests/sockopt.c +++ b/pr/tests/sockopt.c @@ -61,6 +61,7 @@ int main(int argc, char **argv) "PR_SockOpt_MaxSegment", /* maximum segment size */ "PR_SockOpt_Broadcast", /* Enable broadcast */ "PR_SockOpt_Reuseport", /* allow local address & port reuse */ + "PR_SockOpt_DontFrag", /* do not fragment */ "PR_SockOpt_Last" }; @@ -144,6 +145,10 @@ int main(int argc, char **argv) data.value.reuse_port = PR_TRUE; break; #endif + case PR_SockOpt_DontFrag: + data.value.dont_fragment = PR_TRUE; + break; + default: continue; } |