diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-08-29 20:49:30 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2016-08-29 22:37:44 +0200 |
commit | 007d4e7f64dc4ee4bce01023143df3487119c47a (patch) | |
tree | 3a7938ead9cd85d270c50acab4fd316c2f9df6c9 /src/receive.c | |
parent | netns: remove dangling $@ (diff) | |
download | wireguard-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.c | 15 |
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: |