1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 #ifndef TUN_VNET_H 3 #define TUN_VNET_H 4 5 /* High bits in flags field are unused. */ 6 #define TUN_VNET_LE 0x80000000 7 #define TUN_VNET_BE 0x40000000 8 9 #define TUN_VNET_TNL_SIZE sizeof(struct virtio_net_hdr_v1_hash_tunnel) 10 11 static inline bool tun_vnet_legacy_is_little_endian(unsigned int flags) 12 { 13 bool be = IS_ENABLED(CONFIG_TUN_VNET_CROSS_LE) && 14 (flags & TUN_VNET_BE); 15 16 return !be && virtio_legacy_is_little_endian(); 17 } 18 19 static inline long tun_get_vnet_be(unsigned int flags, int __user *argp) 20 { 21 int be = !!(flags & TUN_VNET_BE); 22 23 if (!IS_ENABLED(CONFIG_TUN_VNET_CROSS_LE)) 24 return -EINVAL; 25 26 if (put_user(be, argp)) 27 return -EFAULT; 28 29 return 0; 30 } 31 32 static inline long tun_set_vnet_be(unsigned int *flags, int __user *argp) 33 { 34 int be; 35 36 if (!IS_ENABLED(CONFIG_TUN_VNET_CROSS_LE)) 37 return -EINVAL; 38 39 if (get_user(be, argp)) 40 return -EFAULT; 41 42 if (be) 43 *flags |= TUN_VNET_BE; 44 else 45 *flags &= ~TUN_VNET_BE; 46 47 return 0; 48 } 49 50 static inline bool tun_vnet_is_little_endian(unsigned int flags) 51 { 52 return flags & TUN_VNET_LE || tun_vnet_legacy_is_little_endian(flags); 53 } 54 55 static inline u16 tun_vnet16_to_cpu(unsigned int flags, __virtio16 val) 56 { 57 return __virtio16_to_cpu(tun_vnet_is_little_endian(flags), val); 58 } 59 60 static inline __virtio16 cpu_to_tun_vnet16(unsigned int flags, u16 val) 61 { 62 return __cpu_to_virtio16(tun_vnet_is_little_endian(flags), val); 63 } 64 65 static inline long tun_vnet_ioctl(int *vnet_hdr_sz, unsigned int *flags, 66 unsigned int cmd, int __user *sp) 67 { 68 int s; 69 70 switch (cmd) { 71 case TUNGETVNETHDRSZ: 72 s = *vnet_hdr_sz; 73 if (put_user(s, sp)) 74 return -EFAULT; 75 return 0; 76 77 case TUNSETVNETHDRSZ: 78 if (get_user(s, sp)) 79 return -EFAULT; 80 if (s < (int)sizeof(struct virtio_net_hdr)) 81 return -EINVAL; 82 83 *vnet_hdr_sz = s; 84 return 0; 85 86 case TUNGETVNETLE: 87 s = !!(*flags & TUN_VNET_LE); 88 if (put_user(s, sp)) 89 return -EFAULT; 90 return 0; 91 92 case TUNSETVNETLE: 93 if (get_user(s, sp)) 94 return -EFAULT; 95 if (s) 96 *flags |= TUN_VNET_LE; 97 else 98 *flags &= ~TUN_VNET_LE; 99 return 0; 100 101 case TUNGETVNETBE: 102 return tun_get_vnet_be(*flags, sp); 103 104 case TUNSETVNETBE: 105 return tun_set_vnet_be(flags, sp); 106 107 default: 108 return -EINVAL; 109 } 110 } 111 112 static inline unsigned int tun_vnet_parse_size(netdev_features_t features) 113 { 114 if (!(features & NETIF_F_GSO_UDP_TUNNEL)) 115 return sizeof(struct virtio_net_hdr); 116 117 return TUN_VNET_TNL_SIZE; 118 } 119 120 static inline int __tun_vnet_hdr_get(int sz, unsigned int flags, 121 netdev_features_t features, 122 struct iov_iter *from, 123 struct virtio_net_hdr *hdr) 124 { 125 unsigned int parsed_size = tun_vnet_parse_size(features); 126 u16 hdr_len; 127 128 if (iov_iter_count(from) < sz) 129 return -EINVAL; 130 131 if (!copy_from_iter_full(hdr, parsed_size, from)) 132 return -EFAULT; 133 134 hdr_len = tun_vnet16_to_cpu(flags, hdr->hdr_len); 135 136 if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { 137 hdr_len = max(tun_vnet16_to_cpu(flags, hdr->csum_start) + tun_vnet16_to_cpu(flags, hdr->csum_offset) + 2, hdr_len); 138 hdr->hdr_len = cpu_to_tun_vnet16(flags, hdr_len); 139 } 140 141 if (hdr_len > iov_iter_count(from)) 142 return -EINVAL; 143 144 iov_iter_advance(from, sz - parsed_size); 145 146 return hdr_len; 147 } 148 149 static inline int tun_vnet_hdr_get(int sz, unsigned int flags, 150 struct iov_iter *from, 151 struct virtio_net_hdr *hdr) 152 { 153 return __tun_vnet_hdr_get(sz, flags, 0, from, hdr); 154 } 155 156 static inline int __tun_vnet_hdr_put(int sz, netdev_features_t features, 157 struct iov_iter *iter, 158 const struct virtio_net_hdr *hdr) 159 { 160 unsigned int parsed_size = tun_vnet_parse_size(features); 161 162 if (unlikely(iov_iter_count(iter) < sz)) 163 return -EINVAL; 164 165 if (unlikely(copy_to_iter(hdr, parsed_size, iter) != parsed_size)) 166 return -EFAULT; 167 168 if (iov_iter_zero(sz - parsed_size, iter) != sz - parsed_size) 169 return -EFAULT; 170 171 return 0; 172 } 173 174 static inline int tun_vnet_hdr_put(int sz, struct iov_iter *iter, 175 const struct virtio_net_hdr *hdr) 176 { 177 return __tun_vnet_hdr_put(sz, 0, iter, hdr); 178 } 179 180 static inline int tun_vnet_hdr_to_skb(unsigned int flags, struct sk_buff *skb, 181 const struct virtio_net_hdr *hdr) 182 { 183 return virtio_net_hdr_to_skb(skb, hdr, tun_vnet_is_little_endian(flags)); 184 } 185 186 /* 187 * Tun is not aware of the negotiated guest features, guess them from the 188 * virtio net hdr size 189 */ 190 static inline netdev_features_t tun_vnet_hdr_guest_features(int vnet_hdr_sz) 191 { 192 if (vnet_hdr_sz >= TUN_VNET_TNL_SIZE) 193 return NETIF_F_GSO_UDP_TUNNEL | NETIF_F_GSO_UDP_TUNNEL_CSUM; 194 return 0; 195 } 196 197 static inline int 198 tun_vnet_hdr_tnl_to_skb(unsigned int flags, netdev_features_t features, 199 struct sk_buff *skb, 200 const struct virtio_net_hdr_v1_hash_tunnel *hdr) 201 { 202 return virtio_net_hdr_tnl_to_skb(skb, hdr, 203 features & NETIF_F_GSO_UDP_TUNNEL, 204 features & NETIF_F_GSO_UDP_TUNNEL_CSUM, 205 tun_vnet_is_little_endian(flags)); 206 } 207 208 static inline int tun_vnet_hdr_from_skb(unsigned int flags, 209 const struct net_device *dev, 210 const struct sk_buff *skb, 211 struct virtio_net_hdr *hdr) 212 { 213 int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0; 214 215 if (virtio_net_hdr_from_skb(skb, hdr, 216 tun_vnet_is_little_endian(flags), true, 217 vlan_hlen)) { 218 struct skb_shared_info *sinfo = skb_shinfo(skb); 219 220 if (net_ratelimit()) { 221 netdev_err(dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n", 222 sinfo->gso_type, tun_vnet16_to_cpu(flags, hdr->gso_size), 223 tun_vnet16_to_cpu(flags, hdr->hdr_len)); 224 print_hex_dump(KERN_ERR, "tun: ", 225 DUMP_PREFIX_NONE, 226 16, 1, skb->head, 227 min(tun_vnet16_to_cpu(flags, hdr->hdr_len), 64), true); 228 } 229 WARN_ON_ONCE(1); 230 return -EINVAL; 231 } 232 233 return 0; 234 } 235 236 static inline int 237 tun_vnet_hdr_tnl_from_skb(unsigned int flags, 238 const struct net_device *dev, 239 const struct sk_buff *skb, 240 struct virtio_net_hdr_v1_hash_tunnel *tnl_hdr) 241 { 242 bool has_tnl_offload = !!(dev->features & NETIF_F_GSO_UDP_TUNNEL); 243 int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0; 244 245 if (virtio_net_hdr_tnl_from_skb(skb, tnl_hdr, has_tnl_offload, 246 tun_vnet_is_little_endian(flags), 247 vlan_hlen)) { 248 struct virtio_net_hdr_v1 *hdr = &tnl_hdr->hash_hdr.hdr; 249 struct skb_shared_info *sinfo = skb_shinfo(skb); 250 251 if (net_ratelimit()) { 252 int hdr_len = tun_vnet16_to_cpu(flags, hdr->hdr_len); 253 254 netdev_err(dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n", 255 sinfo->gso_type, 256 tun_vnet16_to_cpu(flags, hdr->gso_size), 257 tun_vnet16_to_cpu(flags, hdr->hdr_len)); 258 print_hex_dump(KERN_ERR, "tun: ", DUMP_PREFIX_NONE, 259 16, 1, skb->head, min(hdr_len, 64), 260 true); 261 } 262 WARN_ON_ONCE(1); 263 return -EINVAL; 264 } 265 266 return 0; 267 } 268 269 #endif /* TUN_VNET_H */ 270