aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tun.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/tun.c')
-rw-r--r--drivers/net/tun.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e26cbea1ce68..dd1bd7aedc3c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1183,7 +1183,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
1183 const struct iovec *iv, int len) 1183 const struct iovec *iv, int len)
1184{ 1184{
1185 struct tun_pi pi = { 0, skb->protocol }; 1185 struct tun_pi pi = { 0, skb->protocol };
1186 ssize_t total = 0; 1186 struct {
1187 __be16 h_vlan_proto;
1188 __be16 h_vlan_TCI;
1189 } veth;
1190 ssize_t total = 0, off = 0;
1187 int vlan_offset = 0; 1191 int vlan_offset = 0;
1188 1192
1189 if (!(tun->flags & TUN_NO_PI)) { 1193 if (!(tun->flags & TUN_NO_PI)) {
@@ -1248,14 +1252,11 @@ static ssize_t tun_put_user(struct tun_struct *tun,
1248 total += tun->vnet_hdr_sz; 1252 total += tun->vnet_hdr_sz;
1249 } 1253 }
1250 1254
1255 off = total;
1251 if (!vlan_tx_tag_present(skb)) { 1256 if (!vlan_tx_tag_present(skb)) {
1252 len = min_t(int, skb->len, len); 1257 len = min_t(int, skb->len, len);
1253 } else { 1258 } else {
1254 int copy, ret; 1259 int copy, ret;
1255 struct {
1256 __be16 h_vlan_proto;
1257 __be16 h_vlan_TCI;
1258 } veth;
1259 1260
1260 veth.h_vlan_proto = skb->vlan_proto; 1261 veth.h_vlan_proto = skb->vlan_proto;
1261 veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb)); 1262 veth.h_vlan_TCI = htons(vlan_tx_tag_get(skb));
@@ -1264,22 +1265,22 @@ static ssize_t tun_put_user(struct tun_struct *tun,
1264 len = min_t(int, skb->len + VLAN_HLEN, len); 1265 len = min_t(int, skb->len + VLAN_HLEN, len);
1265 1266
1266 copy = min_t(int, vlan_offset, len); 1267 copy = min_t(int, vlan_offset, len);
1267 ret = skb_copy_datagram_const_iovec(skb, 0, iv, total, copy); 1268 ret = skb_copy_datagram_const_iovec(skb, 0, iv, off, copy);
1268 len -= copy; 1269 len -= copy;
1269 total += copy; 1270 off += copy;
1270 if (ret || !len) 1271 if (ret || !len)
1271 goto done; 1272 goto done;
1272 1273
1273 copy = min_t(int, sizeof(veth), len); 1274 copy = min_t(int, sizeof(veth), len);
1274 ret = memcpy_toiovecend(iv, (void *)&veth, total, copy); 1275 ret = memcpy_toiovecend(iv, (void *)&veth, off, copy);
1275 len -= copy; 1276 len -= copy;
1276 total += copy; 1277 off += copy;
1277 if (ret || !len) 1278 if (ret || !len)
1278 goto done; 1279 goto done;
1279 } 1280 }
1280 1281
1281 skb_copy_datagram_const_iovec(skb, vlan_offset, iv, total, len); 1282 skb_copy_datagram_const_iovec(skb, vlan_offset, iv, off, len);
1282 total += len; 1283 total += skb->len + (vlan_offset ? sizeof(veth) : 0);
1283 1284
1284done: 1285done:
1285 tun->dev->stats.tx_packets++; 1286 tun->dev->stats.tx_packets++;