Set DSCP values when sending IP packets in socket-default
This commit is contained in:
@@ -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 */
|
||||
@@ -112,6 +115,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
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user