summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-04-14 05:27:19 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2018-04-15 15:45:13 +0200
commit0b12a85f27e9a41f8fd10536ebd23768f0d97519 (patch)
treebb981631edcee904820cc64c3b4e584799176f62
parentb11f5f47bd663361f2a5d82a073fbf7d7178e37b (diff)
send: account for route-based MTU
It might be that a particular route has a different MTU than the interface, via `ip route add ... dev wg0 mtu 1281`, for example. In this case, it's important that we don't accidently pad beyond the end of the MTU. We accomplish that in this patch by carrying forward the MTU from the dst if it exists. We also add a unit test for this issue. Reported-by: Roman Mamedov <rm.wg@romanrm.net> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--src/device.c5
-rw-r--r--src/queueing.h1
-rw-r--r--src/send.c7
-rwxr-xr-xsrc/tests/netns.sh13
-rw-r--r--src/tests/qemu/kernel.config3
5 files changed, 26 insertions, 3 deletions
diff --git a/src/device.c b/src/device.c
index 1614d61..d64653d 100644
--- a/src/device.c
+++ b/src/device.c
@@ -120,6 +120,7 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
struct sk_buff *next;
struct sk_buff_head packets;
sa_family_t family;
+ u32 mtu;
int ret;
if (unlikely(skb_examine_untrusted_ip_hdr(skb) != skb->protocol)) {
@@ -142,6 +143,8 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
goto err_peer;
}
+ mtu = dst_mtu(skb_dst(skb));
+
__skb_queue_head_init(&packets);
if (!skb_is_gso(skb))
skb->next = NULL;
@@ -168,6 +171,8 @@ static netdev_tx_t xmit(struct sk_buff *skb, struct net_device *dev)
*/
skb_dst_drop(skb);
+ PACKET_CB(skb)->mtu = mtu;
+
__skb_queue_tail(&packets, skb);
} while ((skb = next) != NULL);
diff --git a/src/queueing.h b/src/queueing.h
index d5948f3..c507536 100644
--- a/src/queueing.h
+++ b/src/queueing.h
@@ -46,6 +46,7 @@ struct packet_cb {
u64 nonce;
struct noise_keypair *keypair;
atomic_t state;
+ u32 mtu;
u8 ds;
};
#define PACKET_PEER(skb) (((struct packet_cb *)skb->cb)->keypair->entry.peer)
diff --git a/src/send.c b/src/send.c
index dddcc0b..9c9f694 100644
--- a/src/send.c
+++ b/src/send.c
@@ -116,11 +116,11 @@ static inline unsigned int skb_padding(struct sk_buff *skb)
* isn't strictly neccessary, but it's better to be cautious here, especially
* if that code ever changes.
*/
- unsigned int last_unit = skb->len % skb->dev->mtu;
+ unsigned int last_unit = skb->len % PACKET_CB(skb)->mtu;
unsigned int padded_size = (last_unit + MESSAGE_PADDING_MULTIPLE - 1) & ~(MESSAGE_PADDING_MULTIPLE - 1);
- if (padded_size > skb->dev->mtu)
- padded_size = skb->dev->mtu;
+ if (padded_size > PACKET_CB(skb)->mtu)
+ padded_size = PACKET_CB(skb)->mtu;
return padded_size - last_unit;
}
@@ -178,6 +178,7 @@ void packet_send_keepalive(struct wireguard_peer *peer)
return;
skb_reserve(skb, DATA_PACKET_HEAD_ROOM);
skb->dev = peer->device->dev;
+ PACKET_CB(skb)->mtu = skb->dev->mtu;
skb_queue_tail(&peer->staged_packet_queue, skb);
net_dbg_ratelimited("%s: Sending keepalive packet to peer %llu (%pISpfsc)\n", peer->device->dev->name, peer->internal_id, &peer->endpoint.addr);
}
diff --git a/src/tests/netns.sh b/src/tests/netns.sh
index 57d0b28..d1950a0 100755
--- a/src/tests/netns.sh
+++ b/src/tests/netns.sh
@@ -169,6 +169,19 @@ ip1 link set wg0 mtu $big_mtu
ip2 link set wg0 mtu $big_mtu
tests
+# Test that route MTUs work with the padding
+ip1 link set wg0 mtu 1300
+ip2 link set wg0 mtu 1300
+n1 wg set wg0 peer "$pub2" endpoint 127.0.0.1:2
+n2 wg set wg0 peer "$pub1" endpoint 127.0.0.1:1
+n0 iptables -A INPUT -m length --length 1360 -j DROP
+n1 ip route add 192.168.241.2/32 dev wg0 mtu 1299
+n2 ip route add 192.168.241.1/32 dev wg0 mtu 1299
+n2 ping -c 1 -W 1 -s 1269 192.168.241.1
+n2 ip route delete 192.168.241.1/32 dev wg0 mtu 1299
+n1 ip route delete 192.168.241.2/32 dev wg0 mtu 1299
+n0 iptables -F INPUT
+
ip1 link set wg0 mtu $orig_mtu
ip2 link set wg0 mtu $orig_mtu
diff --git a/src/tests/qemu/kernel.config b/src/tests/qemu/kernel.config
index 1f16016..6c3adc0 100644
--- a/src/tests/qemu/kernel.config
+++ b/src/tests/qemu/kernel.config
@@ -11,13 +11,16 @@ CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_IPV6=y
CONFIG_NETFILTER=y
+CONFIG_NETFILTER_ADVANCED=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_NAT=y
CONFIG_NETFILTER_XTABLES=y
CONFIG_NETFILTER_XT_NAT=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
CONFIG_NF_CONNTRACK_IPV4=y
CONFIG_NF_NAT_IPV4=y
CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_NAT=y
CONFIG_TTY=y
CONFIG_BINFMT_ELF=y