summaryrefslogtreecommitdiffstatshomepage
path: root/src/receive.c
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2016-08-29 20:49:30 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2016-08-29 22:37:44 +0200
commit007d4e7f64dc4ee4bce01023143df3487119c47a (patch)
tree3a7938ead9cd85d270c50acab4fd316c2f9df6c9 /src/receive.c
parentnetns: remove dangling $@ (diff)
downloadwireguard-monolithic-historical-007d4e7f64dc4ee4bce01023143df3487119c47a.tar.xz
wireguard-monolithic-historical-007d4e7f64dc4ee4bce01023143df3487119c47a.zip
send: properly encapsulate ECN
We're not leaking the DSCP, but we do deal with ECN.
Diffstat (limited to 'src/receive.c')
-rw-r--r--src/receive.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/receive.c b/src/receive.c
index 5dc9c5b..fee2f21 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -6,6 +6,7 @@
#include "timers.h"
#include "messages.h"
#include "cookie.h"
+#include <net/ip_tunnels.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/udp.h>
@@ -175,6 +176,11 @@ void packet_process_queued_handshake_packets(struct work_struct *work)
}
}
+struct packet_cb {
+ u8 ds;
+};
+#define PACKET_CB(skb) ((struct packet_cb *)skb->cb)
+
static void receive_data_packet(struct sk_buff *skb, struct wireguard_peer *peer, struct sockaddr_storage *addr, bool used_new_key, int err)
{
struct net_device *dev;
@@ -214,9 +220,11 @@ static void receive_data_packet(struct sk_buff *skb, struct wireguard_peer *peer
skb->dev = dev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
- if (ip_hdr(skb)->version == 4)
+ if (ip_hdr(skb)->version == 4) {
skb->protocol = htons(ETH_P_IP);
- else if (ip_hdr(skb)->version == 6) {
+ if (INET_ECN_is_ce(PACKET_CB(skb)->ds))
+ IP_ECN_set_ce(ip_hdr(skb));
+ } else if (ip_hdr(skb)->version == 6) {
if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
++dev->stats.rx_errors;
++dev->stats.rx_length_errors;
@@ -224,6 +232,8 @@ static void receive_data_packet(struct sk_buff *skb, struct wireguard_peer *peer
goto packet_processed;
}
skb->protocol = htons(ETH_P_IPV6);
+ if (INET_ECN_is_ce(PACKET_CB(skb)->ds))
+ IP6_ECN_set_ce(skb, ipv6_hdr(skb));
} else {
++dev->stats.rx_errors;
++dev->stats.rx_length_errors;
@@ -294,6 +304,7 @@ void packet_receive(struct wireguard_device *wg, struct sk_buff *skb)
queue_work(wg->workqueue, &wg->incoming_handshakes_work);
break;
case MESSAGE_DATA:
+ PACKET_CB(skb)->ds = ip_tunnel_get_dsfield(ip_hdr(skb), skb);
packet_consume_data(skb, offset, wg, receive_data_packet);
break;
default: