tun.c (93cd6fa6806cb3455e8231578840afb031606352) | tun.c (cbbd26b8b1a6af9c02e2b6523e12bd50cc765059) |
---|---|
1/* 2 * TUN - Universal TUN/TAP device driver. 3 * Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. --- 1157 unchanged lines hidden (view full) --- 1166 size_t len = total_len, align = tun->align, linear; 1167 struct virtio_net_hdr gso = { 0 }; 1168 struct tun_pcpu_stats *stats; 1169 int good_linear; 1170 int copylen; 1171 bool zerocopy = false; 1172 int err; 1173 u32 rxhash; | 1/* 2 * TUN - Universal TUN/TAP device driver. 3 * Copyright (C) 1999-2002 Maxim Krasnyansky <maxk@qualcomm.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. --- 1157 unchanged lines hidden (view full) --- 1166 size_t len = total_len, align = tun->align, linear; 1167 struct virtio_net_hdr gso = { 0 }; 1168 struct tun_pcpu_stats *stats; 1169 int good_linear; 1170 int copylen; 1171 bool zerocopy = false; 1172 int err; 1173 u32 rxhash; |
1174 ssize_t n; | |
1175 1176 if (!(tun->dev->flags & IFF_UP)) 1177 return -EIO; 1178 1179 if (!(tun->flags & IFF_NO_PI)) { 1180 if (len < sizeof(pi)) 1181 return -EINVAL; 1182 len -= sizeof(pi); 1183 | 1174 1175 if (!(tun->dev->flags & IFF_UP)) 1176 return -EIO; 1177 1178 if (!(tun->flags & IFF_NO_PI)) { 1179 if (len < sizeof(pi)) 1180 return -EINVAL; 1181 len -= sizeof(pi); 1182 |
1184 n = copy_from_iter(&pi, sizeof(pi), from); 1185 if (n != sizeof(pi)) | 1183 if (!copy_from_iter_full(&pi, sizeof(pi), from)) |
1186 return -EFAULT; 1187 } 1188 1189 if (tun->flags & IFF_VNET_HDR) { 1190 if (len < tun->vnet_hdr_sz) 1191 return -EINVAL; 1192 len -= tun->vnet_hdr_sz; 1193 | 1184 return -EFAULT; 1185 } 1186 1187 if (tun->flags & IFF_VNET_HDR) { 1188 if (len < tun->vnet_hdr_sz) 1189 return -EINVAL; 1190 len -= tun->vnet_hdr_sz; 1191 |
1194 n = copy_from_iter(&gso, sizeof(gso), from); 1195 if (n != sizeof(gso)) | 1192 if (!copy_from_iter_full(&gso, sizeof(gso), from)) |
1196 return -EFAULT; 1197 1198 if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && 1199 tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2 > tun16_to_cpu(tun, gso.hdr_len)) 1200 gso.hdr_len = cpu_to_tun16(tun, tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2); 1201 1202 if (tun16_to_cpu(tun, gso.hdr_len) > len) 1203 return -EINVAL; --- 37 unchanged lines hidden (view full) --- 1241 if (IS_ERR(skb)) { 1242 if (PTR_ERR(skb) != -EAGAIN) 1243 this_cpu_inc(tun->pcpu_stats->rx_dropped); 1244 return PTR_ERR(skb); 1245 } 1246 1247 if (zerocopy) 1248 err = zerocopy_sg_from_iter(skb, from); | 1193 return -EFAULT; 1194 1195 if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && 1196 tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2 > tun16_to_cpu(tun, gso.hdr_len)) 1197 gso.hdr_len = cpu_to_tun16(tun, tun16_to_cpu(tun, gso.csum_start) + tun16_to_cpu(tun, gso.csum_offset) + 2); 1198 1199 if (tun16_to_cpu(tun, gso.hdr_len) > len) 1200 return -EINVAL; --- 37 unchanged lines hidden (view full) --- 1238 if (IS_ERR(skb)) { 1239 if (PTR_ERR(skb) != -EAGAIN) 1240 this_cpu_inc(tun->pcpu_stats->rx_dropped); 1241 return PTR_ERR(skb); 1242 } 1243 1244 if (zerocopy) 1245 err = zerocopy_sg_from_iter(skb, from); |
1249 else | 1246 else { |
1250 err = skb_copy_datagram_from_iter(skb, 0, from, len); | 1247 err = skb_copy_datagram_from_iter(skb, 0, from, len); |
1248 if (!err && msg_control) { 1249 struct ubuf_info *uarg = msg_control; 1250 uarg->callback(uarg, false); 1251 } 1252 } |
|
1251 1252 if (err) { 1253 this_cpu_inc(tun->pcpu_stats->rx_dropped); 1254 kfree_skb(skb); 1255 return -EFAULT; 1256 } 1257 1258 err = virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun)); --- 29 unchanged lines hidden (view full) --- 1288 break; 1289 } 1290 1291 /* copy skb_ubuf_info for callback when skb has no error */ 1292 if (zerocopy) { 1293 skb_shinfo(skb)->destructor_arg = msg_control; 1294 skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; 1295 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; | 1253 1254 if (err) { 1255 this_cpu_inc(tun->pcpu_stats->rx_dropped); 1256 kfree_skb(skb); 1257 return -EFAULT; 1258 } 1259 1260 err = virtio_net_hdr_to_skb(skb, &gso, tun_is_little_endian(tun)); --- 29 unchanged lines hidden (view full) --- 1290 break; 1291 } 1292 1293 /* copy skb_ubuf_info for callback when skb has no error */ 1294 if (zerocopy) { 1295 skb_shinfo(skb)->destructor_arg = msg_control; 1296 skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; 1297 skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; |
1296 } else if (msg_control) { 1297 struct ubuf_info *uarg = msg_control; 1298 uarg->callback(uarg, false); | |
1299 } 1300 1301 skb_reset_network_header(skb); 1302 skb_probe_transport_header(skb, 0); 1303 1304 rxhash = skb_get_hash(skb); 1305 netif_rx_ni(skb); 1306 --- 1263 unchanged lines hidden --- | 1298 } 1299 1300 skb_reset_network_header(skb); 1301 skb_probe_transport_header(skb, 0); 1302 1303 rxhash = skb_get_hash(skb); 1304 netif_rx_ni(skb); 1305 --- 1263 unchanged lines hidden --- |