1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 5 #include <errno.h> 6 #include <fcntl.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 #include <net/if.h> 12 #include <linux/if_tun.h> 13 #include <linux/netlink.h> 14 #include <linux/rtnetlink.h> 15 #include <sys/ioctl.h> 16 #include <sys/socket.h> 17 #include <linux/virtio_net.h> 18 #include <netinet/ip.h> 19 #include <netinet/udp.h> 20 #include "kselftest_harness.h" 21 22 static const char param_dev_tap_name[] = "xmacvtap0"; 23 static const char param_dev_dummy_name[] = "xdummy0"; 24 static unsigned char param_hwaddr_src[] = { 0x00, 0xfe, 0x98, 0x14, 0x22, 0x42 }; 25 static unsigned char param_hwaddr_dest[] = { 26 0x00, 0xfe, 0x98, 0x94, 0xd2, 0x43 27 }; 28 29 #define MAX_RTNL_PAYLOAD (2048) 30 #define PKT_DATA 0xCB 31 #define TEST_PACKET_SZ (sizeof(struct virtio_net_hdr) + ETH_HLEN + ETH_MAX_MTU) 32 33 static struct rtattr *rtattr_add(struct nlmsghdr *nh, unsigned short type, 34 unsigned short len) 35 { 36 struct rtattr *rta = 37 (struct rtattr *)((uint8_t *)nh + RTA_ALIGN(nh->nlmsg_len)); 38 rta->rta_type = type; 39 rta->rta_len = RTA_LENGTH(len); 40 nh->nlmsg_len = RTA_ALIGN(nh->nlmsg_len) + RTA_ALIGN(rta->rta_len); 41 return rta; 42 } 43 44 static struct rtattr *rtattr_begin(struct nlmsghdr *nh, unsigned short type) 45 { 46 return rtattr_add(nh, type, 0); 47 } 48 49 static void rtattr_end(struct nlmsghdr *nh, struct rtattr *attr) 50 { 51 uint8_t *end = (uint8_t *)nh + nh->nlmsg_len; 52 53 attr->rta_len = end - (uint8_t *)attr; 54 } 55 56 static struct rtattr *rtattr_add_str(struct nlmsghdr *nh, unsigned short type, 57 const char *s) 58 { 59 unsigned int strsz = strlen(s) + 1; 60 struct rtattr *rta; 61 62 rta = rtattr_add(nh, type, strsz); 63 64 memcpy(RTA_DATA(rta), s, strsz); 65 return rta; 66 } 67 68 static struct rtattr *rtattr_add_any(struct nlmsghdr *nh, unsigned short type, 69 const void *arr, size_t len) 70 { 71 struct rtattr *rta = rtattr_add(nh, type, len); 72 73 memcpy(RTA_DATA(rta), arr, len); 74 return rta; 75 } 76 77 static int dev_create(const char *dev, const char *link_type, 78 int (*fill_rtattr)(struct nlmsghdr *nh), 79 int (*fill_info_data)(struct nlmsghdr *nh)) 80 { 81 struct { 82 struct nlmsghdr nh; 83 struct ifinfomsg info; 84 unsigned char data[MAX_RTNL_PAYLOAD]; 85 } req; 86 struct rtattr *link_info, *info_data; 87 int ret, rtnl; 88 89 rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); 90 if (rtnl < 0) { 91 fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno)); 92 return 1; 93 } 94 95 memset(&req, 0, sizeof(req)); 96 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info)); 97 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE; 98 req.nh.nlmsg_type = RTM_NEWLINK; 99 100 req.info.ifi_family = AF_UNSPEC; 101 req.info.ifi_type = 1; 102 req.info.ifi_index = 0; 103 req.info.ifi_flags = IFF_BROADCAST | IFF_UP; 104 req.info.ifi_change = 0xffffffff; 105 106 rtattr_add_str(&req.nh, IFLA_IFNAME, dev); 107 108 if (fill_rtattr) { 109 ret = fill_rtattr(&req.nh); 110 if (ret) 111 return ret; 112 } 113 114 link_info = rtattr_begin(&req.nh, IFLA_LINKINFO); 115 116 rtattr_add_str(&req.nh, IFLA_INFO_KIND, link_type); 117 118 if (fill_info_data) { 119 info_data = rtattr_begin(&req.nh, IFLA_INFO_DATA); 120 ret = fill_info_data(&req.nh); 121 if (ret) 122 return ret; 123 rtattr_end(&req.nh, info_data); 124 } 125 126 rtattr_end(&req.nh, link_info); 127 128 ret = send(rtnl, &req, req.nh.nlmsg_len, 0); 129 if (ret < 0) 130 fprintf(stderr, "%s: send %s\n", __func__, strerror(errno)); 131 ret = (unsigned int)ret != req.nh.nlmsg_len; 132 133 close(rtnl); 134 return ret; 135 } 136 137 static int dev_delete(const char *dev) 138 { 139 struct { 140 struct nlmsghdr nh; 141 struct ifinfomsg info; 142 unsigned char data[MAX_RTNL_PAYLOAD]; 143 } req; 144 int ret, rtnl; 145 146 rtnl = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); 147 if (rtnl < 0) { 148 fprintf(stderr, "%s: socket %s\n", __func__, strerror(errno)); 149 return 1; 150 } 151 152 memset(&req, 0, sizeof(req)); 153 req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.info)); 154 req.nh.nlmsg_flags = NLM_F_REQUEST; 155 req.nh.nlmsg_type = RTM_DELLINK; 156 157 req.info.ifi_family = AF_UNSPEC; 158 159 rtattr_add_str(&req.nh, IFLA_IFNAME, dev); 160 161 ret = send(rtnl, &req, req.nh.nlmsg_len, 0); 162 if (ret < 0) 163 fprintf(stderr, "%s: send %s\n", __func__, strerror(errno)); 164 165 ret = (unsigned int)ret != req.nh.nlmsg_len; 166 167 close(rtnl); 168 return ret; 169 } 170 171 static int macvtap_fill_rtattr(struct nlmsghdr *nh) 172 { 173 int ifindex; 174 175 ifindex = if_nametoindex(param_dev_dummy_name); 176 if (ifindex == 0) { 177 fprintf(stderr, "%s: ifindex %s\n", __func__, strerror(errno)); 178 return -errno; 179 } 180 181 rtattr_add_any(nh, IFLA_LINK, &ifindex, sizeof(ifindex)); 182 rtattr_add_any(nh, IFLA_ADDRESS, param_hwaddr_src, ETH_ALEN); 183 184 return 0; 185 } 186 187 static int opentap(const char *devname) 188 { 189 int ifindex; 190 char buf[256]; 191 int fd; 192 struct ifreq ifr; 193 194 ifindex = if_nametoindex(devname); 195 if (ifindex == 0) { 196 fprintf(stderr, "%s: ifindex %s\n", __func__, strerror(errno)); 197 return -errno; 198 } 199 200 sprintf(buf, "/dev/tap%d", ifindex); 201 fd = open(buf, O_RDWR | O_NONBLOCK); 202 if (fd < 0) { 203 fprintf(stderr, "%s: open %s\n", __func__, strerror(errno)); 204 return -errno; 205 } 206 207 memset(&ifr, 0, sizeof(ifr)); 208 strcpy(ifr.ifr_name, devname); 209 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR | IFF_MULTI_QUEUE; 210 if (ioctl(fd, TUNSETIFF, &ifr, sizeof(ifr)) < 0) 211 return -errno; 212 return fd; 213 } 214 215 size_t build_eth(uint8_t *buf, uint16_t proto) 216 { 217 struct ethhdr *eth = (struct ethhdr *)buf; 218 219 eth->h_proto = htons(proto); 220 memcpy(eth->h_source, param_hwaddr_src, ETH_ALEN); 221 memcpy(eth->h_dest, param_hwaddr_dest, ETH_ALEN); 222 223 return ETH_HLEN; 224 } 225 226 static uint32_t add_csum(const uint8_t *buf, int len) 227 { 228 uint32_t sum = 0; 229 uint16_t *sbuf = (uint16_t *)buf; 230 231 while (len > 1) { 232 sum += *sbuf++; 233 len -= 2; 234 } 235 236 if (len) 237 sum += *(uint8_t *)sbuf; 238 239 return sum; 240 } 241 242 static uint16_t finish_ip_csum(uint32_t sum) 243 { 244 uint16_t lo = sum & 0xffff; 245 uint16_t hi = sum >> 16; 246 247 return ~(lo + hi); 248 249 } 250 251 static uint16_t build_ip_csum(const uint8_t *buf, int len, 252 uint32_t sum) 253 { 254 sum += add_csum(buf, len); 255 return finish_ip_csum(sum); 256 } 257 258 static int build_ipv4_header(uint8_t *buf, int payload_len) 259 { 260 struct iphdr *iph = (struct iphdr *)buf; 261 262 iph->ihl = 5; 263 iph->version = 4; 264 iph->ttl = 8; 265 iph->tot_len = 266 htons(sizeof(*iph) + sizeof(struct udphdr) + payload_len); 267 iph->id = htons(1337); 268 iph->protocol = IPPROTO_UDP; 269 iph->saddr = htonl((172 << 24) | (17 << 16) | 2); 270 iph->daddr = htonl((172 << 24) | (17 << 16) | 1); 271 iph->check = build_ip_csum(buf, iph->ihl << 2, 0); 272 273 return iph->ihl << 2; 274 } 275 276 static int build_udp_packet(uint8_t *buf, int payload_len, bool csum_off) 277 { 278 const int ip4alen = sizeof(uint32_t); 279 struct udphdr *udph = (struct udphdr *)buf; 280 int len = sizeof(*udph) + payload_len; 281 uint32_t sum = 0; 282 283 udph->source = htons(22); 284 udph->dest = htons(58822); 285 udph->len = htons(len); 286 287 memset(buf + sizeof(struct udphdr), PKT_DATA, payload_len); 288 289 sum = add_csum(buf - 2 * ip4alen, 2 * ip4alen); 290 sum += htons(IPPROTO_UDP) + udph->len; 291 292 if (!csum_off) 293 sum += add_csum(buf, len); 294 295 udph->check = finish_ip_csum(sum); 296 297 return sizeof(*udph) + payload_len; 298 } 299 300 size_t build_test_packet_valid_udp_gso(uint8_t *buf, size_t payload_len) 301 { 302 uint8_t *cur = buf; 303 struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf; 304 305 vh->hdr_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr); 306 vh->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; 307 vh->csum_start = ETH_HLEN + sizeof(struct iphdr); 308 vh->csum_offset = __builtin_offsetof(struct udphdr, check); 309 vh->gso_type = VIRTIO_NET_HDR_GSO_UDP; 310 vh->gso_size = ETH_DATA_LEN - sizeof(struct iphdr); 311 cur += sizeof(*vh); 312 313 cur += build_eth(cur, ETH_P_IP); 314 cur += build_ipv4_header(cur, payload_len); 315 cur += build_udp_packet(cur, payload_len, true); 316 317 return cur - buf; 318 } 319 320 size_t build_test_packet_valid_udp_csum(uint8_t *buf, size_t payload_len) 321 { 322 uint8_t *cur = buf; 323 struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf; 324 325 vh->flags = VIRTIO_NET_HDR_F_DATA_VALID; 326 vh->gso_type = VIRTIO_NET_HDR_GSO_NONE; 327 cur += sizeof(*vh); 328 329 cur += build_eth(cur, ETH_P_IP); 330 cur += build_ipv4_header(cur, payload_len); 331 cur += build_udp_packet(cur, payload_len, false); 332 333 return cur - buf; 334 } 335 336 size_t build_test_packet_crash_tap_invalid_eth_proto(uint8_t *buf, 337 size_t payload_len) 338 { 339 uint8_t *cur = buf; 340 struct virtio_net_hdr *vh = (struct virtio_net_hdr *)buf; 341 342 vh->hdr_len = ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr); 343 vh->flags = 0; 344 vh->gso_type = VIRTIO_NET_HDR_GSO_UDP; 345 vh->gso_size = ETH_DATA_LEN - sizeof(struct iphdr); 346 cur += sizeof(*vh); 347 348 cur += build_eth(cur, 0); 349 cur += sizeof(struct iphdr) + sizeof(struct udphdr); 350 cur += build_ipv4_header(cur, payload_len); 351 cur += build_udp_packet(cur, payload_len, true); 352 cur += payload_len; 353 354 return cur - buf; 355 } 356 357 FIXTURE(tap) 358 { 359 int fd; 360 }; 361 362 FIXTURE_SETUP(tap) 363 { 364 int ret; 365 366 ret = dev_create(param_dev_dummy_name, "dummy", NULL, NULL); 367 EXPECT_EQ(ret, 0); 368 369 ret = dev_create(param_dev_tap_name, "macvtap", macvtap_fill_rtattr, 370 NULL); 371 EXPECT_EQ(ret, 0); 372 373 self->fd = opentap(param_dev_tap_name); 374 ASSERT_GE(self->fd, 0); 375 } 376 377 FIXTURE_TEARDOWN(tap) 378 { 379 int ret; 380 381 if (self->fd != -1) 382 close(self->fd); 383 384 ret = dev_delete(param_dev_tap_name); 385 EXPECT_EQ(ret, 0); 386 387 ret = dev_delete(param_dev_dummy_name); 388 EXPECT_EQ(ret, 0); 389 } 390 391 TEST_F(tap, test_packet_valid_udp_gso) 392 { 393 uint8_t pkt[TEST_PACKET_SZ]; 394 size_t off; 395 int ret; 396 397 memset(pkt, 0, sizeof(pkt)); 398 off = build_test_packet_valid_udp_gso(pkt, 1021); 399 ret = write(self->fd, pkt, off); 400 ASSERT_EQ(ret, off); 401 } 402 403 TEST_F(tap, test_packet_valid_udp_csum) 404 { 405 uint8_t pkt[TEST_PACKET_SZ]; 406 size_t off; 407 int ret; 408 409 memset(pkt, 0, sizeof(pkt)); 410 off = build_test_packet_valid_udp_csum(pkt, 1024); 411 ret = write(self->fd, pkt, off); 412 ASSERT_EQ(ret, off); 413 } 414 415 TEST_F(tap, test_packet_crash_tap_invalid_eth_proto) 416 { 417 uint8_t pkt[TEST_PACKET_SZ]; 418 size_t off; 419 int ret; 420 421 memset(pkt, 0, sizeof(pkt)); 422 off = build_test_packet_crash_tap_invalid_eth_proto(pkt, 1024); 423 ret = write(self->fd, pkt, off); 424 ASSERT_EQ(ret, -1); 425 ASSERT_EQ(errno, EINVAL); 426 } 427 428 TEST_HARNESS_MAIN 429