aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-02-06 13:17:55 +0100
committerMartin Willi <martin@revosec.ch>2013-02-06 15:20:32 +0100
commitea5917afd8ae8ea016309dff48f7e1761434081c (patch)
tree8e014cadd904db0c5677206ee1b6e93fdf3b2bd3
parent6e82269ee69bde777d915d75b5534958d2217a62 (diff)
downloadstrongswan-ea5917afd8ae8ea016309dff48f7e1761434081c.tar.bz2
strongswan-ea5917afd8ae8ea016309dff48f7e1761434081c.tar.xz
Set DSCP values when sending IP packets in socket-default
-rw-r--r--src/libcharon/plugins/socket_default/socket_default_socket.c66
1 files changed, 65 insertions, 1 deletions
diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c
index 942dafc2e..c0b744a68 100644
--- a/src/libcharon/plugins/socket_default/socket_default_socket.c
+++ b/src/libcharon/plugins/socket_default/socket_default_socket.c
@@ -55,6 +55,9 @@
#ifndef SOL_IPV6
#define SOL_IPV6 IPPROTO_IPV6
#endif
+#ifndef IPV6_TCLASS
+#define IPV6_TCLASS 67
+#endif
/* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that
* previously defined IPV6_PKTINFO */
@@ -113,6 +116,26 @@ struct private_socket_default_socket_t {
int ipv6_natt;
/**
+ * DSCP value set on IPv4 socket
+ */
+ u_int8_t dscp4;
+
+ /**
+ * DSCP value set on IPv4 socket for NAT-T (4500 or natt)
+ */
+ u_int8_t dscp4_natt;
+
+ /**
+ * DSCP value set on IPv6 socket (500 or port)
+ */
+ u_int8_t dscp6;
+
+ /**
+ * DSCP value set on IPv6 socket for NAT-T (4500 or natt)
+ */
+ u_int8_t dscp6_natt;
+
+ /**
* Maximum packet size to receive
*/
int max_packet;
@@ -310,6 +333,7 @@ METHOD(socket_t, sender, status_t,
struct msghdr msg;
struct cmsghdr *cmsg;
struct iovec iov;
+ u_int8_t *dscp;
src = packet->get_source(packet);
dst = packet->get_destination(packet);
@@ -326,9 +350,11 @@ METHOD(socket_t, sender, status_t,
{
case AF_INET:
skt = this->ipv4;
+ dscp = &this->dscp4;
break;
case AF_INET6:
skt = this->ipv6;
+ dscp = &this->dscp6;
break;
default:
return FAILED;
@@ -340,9 +366,11 @@ METHOD(socket_t, sender, status_t,
{
case AF_INET:
skt = this->ipv4_natt;
+ dscp = &this->dscp4_natt;
break;
case AF_INET6:
skt = this->ipv6_natt;
+ dscp = &this->dscp6_natt;
break;
default:
return FAILED;
@@ -354,6 +382,43 @@ METHOD(socket_t, sender, status_t,
return FAILED;
}
+ /* setting DSCP values per-packet in a cmsg seems not to be supported
+ * on Linux. We instead setsockopt() before sending it, this should be
+ * safe as only a single thread calls send(). */
+ if (*dscp != packet->get_dscp(packet))
+ {
+ if (family == AF_INET)
+ {
+ u_int8_t ds4;
+
+ ds4 = packet->get_dscp(packet) << 2;
+ if (setsockopt(skt, SOL_IP, IP_TOS, &ds4, sizeof(ds4)) == 0)
+ {
+ *dscp = packet->get_dscp(packet);
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to set IP_TOS on socket: %s",
+ strerror(errno));
+ }
+ }
+ else
+ {
+ u_int ds6;
+
+ ds6 = packet->get_dscp(packet) << 2;
+ if (setsockopt(skt, SOL_IPV6, IPV6_TCLASS, &ds6, sizeof(ds6)) == 0)
+ {
+ *dscp = packet->get_dscp(packet);
+ }
+ else
+ {
+ DBG1(DBG_NET, "unable to set IPV6_TCLASS on socket: %s",
+ strerror(errno));
+ }
+ }
+ }
+
memset(&msg, 0, sizeof(struct msghdr));
msg.msg_name = dst->get_sockaddr(dst);;
msg.msg_namelen = *dst->get_sockaddr_len(dst);
@@ -640,4 +705,3 @@ socket_default_socket_t *socket_default_socket_create()
return &this->public;
}
-