summaryrefslogtreecommitdiff
path: root/pr/src/io/prmapopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'pr/src/io/prmapopt.c')
-rw-r--r--pr/src/io/prmapopt.c82
1 files changed, 80 insertions, 2 deletions
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)