1 /* Tests for RAW sockets (LWIP) - by D.C. van Moolenbroek */ 2 /* This test needs to be run as root: creating raw sockets is root-only. */ 3 #include <stdlib.h> 4 #include <string.h> 5 #include <stddef.h> 6 #include <sys/mman.h> 7 #include <sys/param.h> 8 #include <sys/socket.h> 9 #include <net/route.h> 10 #include <netinet/in.h> 11 #include <netinet/ip.h> 12 #include <netinet/udp.h> 13 #include <netinet/icmp6.h> 14 #include <netinet/in_pcb.h> 15 #include <netinet6/in6_pcb.h> 16 #include <arpa/inet.h> 17 #include <machine/vmparam.h> 18 #include <unistd.h> 19 #include <fcntl.h> 20 #include <assert.h> 21 22 #include "common.h" 23 #include "socklib.h" 24 25 #define ITERATIONS 2 26 27 #define TEST_PROTO 253 /* from RFC 3692 */ 28 #define TEST_ICMPV6_TYPE_A 200 /* from RFC 4443 */ 29 #define TEST_ICMPV6_TYPE_B 201 /* from RFC 4443 */ 30 31 static const enum state raw_states[] = { 32 S_NEW, S_N_SHUT_R, S_N_SHUT_W, S_N_SHUT_RW, 33 S_BOUND, S_CONNECTED, S_SHUT_R, S_SHUT_W, 34 S_SHUT_RW, 35 }; 36 37 static const int raw_results[][__arraycount(raw_states)] = { 38 [C_ACCEPT] = { 39 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, 40 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, 41 -EOPNOTSUPP, 42 }, 43 [C_BIND] = { 44 0, 0, 0, 0, 45 0, -EINVAL, -EINVAL, -EINVAL, 46 -EINVAL, 47 }, 48 [C_CONNECT] = { 49 0, 0, 0, 0, 50 0, 0, 0, 0, 51 0, 52 }, 53 [C_GETPEERNAME] = { 54 -ENOTCONN, -ENOTCONN, -ENOTCONN, -ENOTCONN, 55 -ENOTCONN, 0, 0, 0, 56 0, 57 }, 58 [C_GETSOCKNAME] = { 59 0, 0, 0, 0, 60 0, 0, 0, 0, 61 0, 62 }, 63 [C_GETSOCKOPT_ERR] = { 64 0, 0, 0, 0, 65 0, 0, 0, 0, 66 0, 67 }, 68 [C_GETSOCKOPT_KA] = { 69 0, 0, 0, 0, 70 0, 0, 0, 0, 71 0, 72 }, 73 [C_GETSOCKOPT_RB] = { 74 0, 0, 0, 0, 75 0, 0, 0, 0, 76 0, 77 }, 78 [C_IOCTL_NREAD] = { 79 0, 0, 0, 0, 80 0, 0, 0, 0, 81 0, 82 }, 83 [C_LISTEN] = { 84 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, 85 -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, -EOPNOTSUPP, 86 -EOPNOTSUPP, 87 }, 88 [C_RECV] = { 89 -EAGAIN, 0, -EAGAIN, 0, 90 -EAGAIN, -EAGAIN, 0, -EAGAIN, 91 0, 92 }, 93 [C_RECVFROM] = { 94 -EAGAIN, 0, -EAGAIN, 0, 95 -EAGAIN, -EAGAIN, 0, -EAGAIN, 96 0, 97 }, 98 [C_SEND] = { 99 -EDESTADDRREQ, -EDESTADDRREQ, -EPIPE, -EPIPE, 100 -EDESTADDRREQ, 1, 1, -EPIPE, 101 -EPIPE, 102 }, 103 [C_SENDTO] = { 104 1, 1, -EPIPE, -EPIPE, 105 1, 1, 1, -EPIPE, 106 -EPIPE, 107 }, 108 [C_SELECT_R] = { 109 0, 1, 0, 1, 110 0, 0, 1, 0, 111 1, 112 }, 113 [C_SELECT_W] = { 114 1, 1, 1, 1, 115 1, 1, 1, 1, 116 1, 117 }, 118 [C_SELECT_X] = { 119 0, 0, 0, 0, 120 0, 0, 0, 0, 121 0, 122 }, 123 [C_SETSOCKOPT_BC] = { 124 0, 0, 0, 0, 125 0, 0, 0, 0, 126 0, 127 }, 128 [C_SETSOCKOPT_KA] = { 129 0, 0, 0, 0, 130 0, 0, 0, 0, 131 0, 132 }, 133 [C_SETSOCKOPT_L] = { 134 0, 0, 0, 0, 135 0, 0, 0, 0, 136 0, 137 }, 138 [C_SETSOCKOPT_RA] = { 139 0, 0, 0, 0, 140 0, 0, 0, 0, 141 0, 142 }, 143 [C_SHUTDOWN_R] = { 144 0, 0, 0, 0, 145 0, 0, 0, 0, 146 0, 147 }, 148 [C_SHUTDOWN_RW] = { 149 0, 0, 0, 0, 150 0, 0, 0, 0, 151 0, 152 }, 153 [C_SHUTDOWN_W] = { 154 0, 0, 0, 0, 155 0, 0, 0, 0, 156 0, 157 }, 158 }; 159 160 /* 161 * Set up a RAW socket file descriptor in the requested state and pass it to 162 * socklib_sweep_call() along with local and remote addresses and their length. 163 */ 164 static int 165 raw_sweep(int domain, int type, int protocol, enum state state, 166 enum call call) 167 { 168 struct sockaddr_in sinA, sinB; 169 struct sockaddr_in6 sin6A, sin6B; 170 struct sockaddr *addrA, *addrB; 171 socklen_t addr_len; 172 int r, fd, fd2; 173 174 if (domain == AF_INET) { 175 memset(&sinA, 0, sizeof(sinA)); 176 sinA.sin_family = domain; 177 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 178 179 memcpy(&sinB, &sinA, sizeof(sinB)); 180 181 addrA = (struct sockaddr *)&sinA; 182 addrB = (struct sockaddr *)&sinB; 183 addr_len = sizeof(sinA); 184 } else { 185 assert(domain == AF_INET6); 186 187 memset(&sin6A, 0, sizeof(sin6A)); 188 sin6A.sin6_family = domain; 189 memcpy(&sin6A.sin6_addr, &in6addr_loopback, 190 sizeof(sin6A.sin6_addr)); 191 192 memcpy(&sin6B, &sin6A, sizeof(sin6B)); 193 194 addrA = (struct sockaddr *)&sin6A; 195 addrB = (struct sockaddr *)&sin6B; 196 addr_len = sizeof(sin6A); 197 } 198 199 /* Create a bound remote socket. */ 200 if ((fd2 = socket(domain, type | SOCK_NONBLOCK, protocol)) < 0) e(0); 201 202 if (bind(fd2, addrB, addr_len) != 0) e(0); 203 204 switch (state) { 205 case S_NEW: 206 case S_N_SHUT_R: 207 case S_N_SHUT_W: 208 case S_N_SHUT_RW: 209 if ((fd = socket(domain, type | SOCK_NONBLOCK, 210 protocol)) < 0) e(0); 211 212 switch (state) { 213 case S_N_SHUT_R: if (shutdown(fd, SHUT_RD)) e(0); break; 214 case S_N_SHUT_W: if (shutdown(fd, SHUT_WR)) e(0); break; 215 case S_N_SHUT_RW: if (shutdown(fd, SHUT_RDWR)) e(0); break; 216 default: break; 217 } 218 219 break; 220 221 case S_BOUND: 222 case S_CONNECTED: 223 case S_SHUT_R: 224 case S_SHUT_W: 225 case S_SHUT_RW: 226 if ((fd = socket(domain, type | SOCK_NONBLOCK, 227 protocol)) < 0) e(0); 228 229 if (bind(fd, addrA, addr_len) != 0) e(0); 230 231 if (state == S_BOUND) 232 break; 233 234 if (connect(fd, addrB, addr_len) != 0) e(0); 235 236 switch (state) { 237 case S_SHUT_R: if (shutdown(fd, SHUT_RD)) e(0); break; 238 case S_SHUT_W: if (shutdown(fd, SHUT_WR)) e(0); break; 239 case S_SHUT_RW: if (shutdown(fd, SHUT_RDWR)) e(0); break; 240 default: break; 241 } 242 243 break; 244 245 default: 246 fd = -1; 247 e(0); 248 } 249 250 r = socklib_sweep_call(call, fd, addrA, addrB, addr_len); 251 252 if (close(fd) != 0) e(0); 253 if (fd2 != -1 && close(fd2) != 0) e(0); 254 255 return r; 256 } 257 258 /* 259 * Sweep test for socket calls versus socket states of RAW sockets. 260 */ 261 static void 262 test92a(void) 263 { 264 265 subtest = 1; 266 267 socklib_sweep(AF_INET, SOCK_RAW, TEST_PROTO, raw_states, 268 __arraycount(raw_states), (const int *)raw_results, raw_sweep); 269 270 socklib_sweep(AF_INET6, SOCK_RAW, TEST_PROTO, raw_states, 271 __arraycount(raw_states), (const int *)raw_results, raw_sweep); 272 } 273 274 /* 275 * Basic I/O test for raw sockets. 276 */ 277 static void 278 test92b(void) 279 { 280 struct sockaddr_in sinA, sinB, sinC; 281 struct sockaddr_in6 sin6A, sin6B, sin6C; 282 socklen_t len; 283 unsigned int i; 284 uint8_t buf[256], packet[5]; 285 int fd, fd2; 286 287 subtest = 2; 288 289 /* First test IPv4. */ 290 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 291 292 memset(&sinA, 0, sizeof(sinA)); 293 sinA.sin_family = AF_INET; 294 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 295 296 for (i = 0; i < __arraycount(packet); i++) 297 packet[i] = (uint8_t)(-i); 298 299 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA, 300 sizeof(sinA)) != sizeof(packet)) e(0); 301 302 memset(buf, 0, sizeof(buf)); 303 len = sizeof(sinB); 304 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sinB, 305 &len) != sizeof(struct ip) + sizeof(packet)) e(0); 306 307 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0); 308 309 if (len != sizeof(sinB)) e(0); 310 if (sinB.sin_len != sizeof(sinB)) e(0); 311 if (sinB.sin_family != AF_INET) e(0); 312 if (sinB.sin_port != htons(0)) e(0); 313 if (sinB.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) e(0); 314 315 /* 316 * Test two additional things: 317 * 318 * 1) a non-zero port number is ignored when sending; 319 * 2) multiple raw sockets may receive the same packet. 320 */ 321 sinA.sin_port = htons(22); 322 323 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 324 325 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sinA, 326 sizeof(sinA)) != sizeof(packet)) e(0); 327 328 memset(buf, 0, sizeof(buf)); 329 len = sizeof(sinC); 330 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sinC, 331 &len) != sizeof(struct ip) + sizeof(packet)) e(0); 332 333 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0); 334 335 if (len != sizeof(sinC)) e(0); 336 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0); 337 338 memset(buf, 0, sizeof(buf)); 339 len = sizeof(sinC); 340 if (recvfrom(fd2, buf, sizeof(buf), 0, (struct sockaddr *)&sinC, 341 &len) != sizeof(struct ip) + sizeof(packet)) e(0); 342 343 if (memcmp(&buf[sizeof(struct ip)], packet, sizeof(packet)) != 0) e(0); 344 345 if (len != sizeof(sinC)) e(0); 346 if (memcmp(&sinB, &sinC, sizeof(sinB)) != 0) e(0); 347 348 if (close(fd2) != 0) e(0); 349 if (close(fd) != 0) e(0); 350 351 /* Then test IPv6. */ 352 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 353 354 memset(&sin6A, 0, sizeof(sin6A)); 355 sin6A.sin6_family = AF_INET6; 356 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr)); 357 358 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A, 359 sizeof(sin6A)) != sizeof(packet)) e(0); 360 361 memset(buf, 0, sizeof(buf)); 362 len = sizeof(sin6B); 363 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6B, 364 &len) != sizeof(packet)) e(0); 365 366 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0); 367 368 if (len != sizeof(sin6B)) e(0); 369 if (sin6B.sin6_len != sizeof(sin6B)) e(0); 370 if (sin6B.sin6_family != AF_INET6) e(0); 371 if (sin6B.sin6_port != htons(0)) e(0); 372 if (memcmp(&sin6B.sin6_addr, &in6addr_loopback, 373 sizeof(sin6B.sin6_addr)) != 0) e(0); 374 375 /* As above. */ 376 sin6A.sin6_port = htons(22); 377 378 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 379 380 if (sendto(fd, packet, sizeof(packet), 0, (struct sockaddr *)&sin6A, 381 sizeof(sin6A)) != sizeof(packet)) e(0); 382 383 memset(buf, 0, sizeof(buf)); 384 len = sizeof(sin6C); 385 if (recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6C, 386 &len) != sizeof(packet)) e(0); 387 388 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0); 389 390 if (len != sizeof(sin6C)) e(0); 391 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0); 392 393 memset(buf, 0, sizeof(buf)); 394 len = sizeof(sin6C); 395 if (recvfrom(fd2, buf, sizeof(buf), 0, (struct sockaddr *)&sin6C, 396 &len) != sizeof(packet)) e(0); 397 398 if (memcmp(buf, packet, sizeof(packet)) != 0) e(0); 399 400 if (len != sizeof(sin6C)) e(0); 401 if (memcmp(&sin6B, &sin6C, sizeof(sin6B)) != 0) e(0); 402 403 if (close(fd2) != 0) e(0); 404 if (close(fd) != 0) e(0); 405 } 406 407 /* 408 * Test the IPV6_CHECKSUM socket option. 409 */ 410 static void 411 test92c(void) 412 { 413 struct sockaddr_in6 sin6; 414 struct icmp6_hdr icmp6_hdr; 415 uint8_t buf[6], buf2[6], *buf3; 416 socklen_t len; 417 unsigned int i; 418 int fd, fd2, val; 419 420 subtest = 3; 421 422 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 423 424 if (shutdown(fd, SHUT_RD) != 0) e(0); 425 426 /* For non-ICMPv6 sockets, checksumming is disabled by default. */ 427 len = sizeof(val); 428 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0); 429 if (len != sizeof(val)) e(0); 430 if (val != -1) e(0); 431 432 /* Test bad offsets. */ 433 val = -2; 434 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 435 sizeof(val)) != -1) e(0); 436 if (errno != EINVAL) e(0); 437 438 val = 1; 439 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 440 sizeof(val)) != -1) e(0); 441 if (errno != EINVAL) e(0); 442 443 /* Now test real checksum computation. */ 444 val = 0; 445 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 446 sizeof(val)) != 0) e(0); 447 448 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 449 450 if (shutdown(fd2, SHUT_WR) != 0) e(0); 451 452 memset(buf, 0, sizeof(buf)); 453 buf[2] = 0xfe; 454 buf[3] = 0x95; 455 buf[4] = 0x4d; 456 457 memset(&sin6, 0, sizeof(sin6)); 458 sin6.sin6_family = AF_INET6; 459 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr)); 460 461 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5) 462 e(0); 463 464 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0); 465 466 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0); 467 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0); 468 469 /* Turn on checksum verification on the receiving socket. */ 470 val = 0; 471 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 472 sizeof(val)) != 0) e(0); 473 474 /* 475 * The current value of the checksum field should not be incorporated 476 * in the checksum, as that would result in an invalid checksum. 477 */ 478 buf[0] = 0xab; 479 buf[1] = 0xcd; 480 481 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5) 482 e(0); 483 484 if (recv(fd2, buf2, sizeof(buf2), 0) != 5) e(0); 485 486 if (buf2[0] != 0xb3 || buf2[1] != 0x65) e(0); 487 if (memcmp(&buf2[2], &buf[2], 3) != 0) e(0); 488 489 /* 490 * Turn off checksum computation on the sending side, so that the 491 * packet ends up being dropped on the receiving side. 492 */ 493 val = -1; 494 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 495 sizeof(val)) != 0) e(0); 496 497 if (sendto(fd, buf, 5, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 5) 498 e(0); 499 500 /* Send some packets that are too small to contain the checksum. */ 501 if (sendto(fd, buf, 0, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) 502 e(0); 503 if (sendto(fd, buf, 1, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 1) 504 e(0); 505 506 /* 507 * If this recv call is "too soon" (it should not be) and the packets 508 * arrive later anyway, then we will get a failure below. 509 */ 510 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0); 511 if (errno != EWOULDBLOCK) e(0); 512 513 buf[0] = 0; 514 buf[1] = 0x67; 515 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, 516 sizeof(sin6)) != 4) e(0); 517 518 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0); 519 if (memcmp(buf, buf2, 4) != 0) e(0); 520 521 /* 522 * We repeat some of the tests with a non-zero checksum offset, just to 523 * be sure. 524 */ 525 val = 2; 526 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 527 sizeof(val)) != 0) e(0); 528 529 len = sizeof(val); 530 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0); 531 if (len != sizeof(val)) e(0); 532 if (val != 2) e(0); 533 534 buf[0] = 0x56; 535 buf[1] = 0x78; 536 537 for (i = 0; i <= 3; i++) { 538 if (sendto(fd, buf, i, 0, (struct sockaddr *)&sin6, 539 sizeof(sin6)) != -1) e(0); 540 if (errno != EINVAL) e(0); 541 } 542 543 val = 2; 544 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 545 sizeof(val)) != 0) e(0); 546 547 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, 548 sizeof(sin6)) != 4) e(0); 549 550 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0); 551 if (memcmp(buf, buf2, 2) != 0) e(0); 552 if (buf2[2] != 0xa8 || buf2[3] != 0x84) e(0); 553 554 val = -1; 555 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 556 sizeof(val)) != 0) e(0); 557 558 buf[2] = 0xa8; 559 buf[3] = 0x85; /* deliberately bad checksum */ 560 561 /* All these should be dropped on the receiver side. */ 562 for (i = 0; i <= 4; i++) { 563 if (sendto(fd, buf, i, 0, (struct sockaddr *)&sin6, 564 sizeof(sin6)) != i) e(0); 565 } 566 567 buf[3] = 0x84; /* good checksum */ 568 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4) 569 e(0); 570 571 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0); 572 if (memcmp(buf, buf2, 4) != 0) e(0); 573 574 if (recv(fd2, buf2, sizeof(buf2), MSG_DONTWAIT) != -1) e(0); 575 if (errno != EWOULDBLOCK) e(0); 576 577 val = -1; 578 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 579 sizeof(val)) != 0) e(0); 580 if (setsockopt(fd2, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 581 sizeof(val)) != 0) e(0); 582 583 buf[3] = 0x85; 584 if (sendto(fd, buf, 4, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 4) 585 e(0); 586 587 if (recv(fd2, buf2, sizeof(buf2), 0) != 4) e(0); 588 if (memcmp(buf, buf2, 4) != 0) e(0); 589 590 /* 591 * The following is a lwIP-specific test: lwIP does not support storing 592 * generated checksums beyond the first pbuf. We do not know the size 593 * of the first pbuf until we actually send a packet, so the setsockopt 594 * call will not fail, but sending the packet will. Depending on the 595 * buffer allocation strategy, the following test may or may not 596 * trigger this case; simply ensure that we do not crash the service. 597 */ 598 if ((buf3 = malloc(4096)) == NULL) e(0); 599 600 val = 4094; 601 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 602 sizeof(val)) != 0) e(0); 603 604 /* This call may or may not fail, but if it fails, it yields EINVAL. */ 605 if (sendto(fd, buf3, 4096, 0, (struct sockaddr *)&sin6, 606 sizeof(sin6)) == -1 && errno != EINVAL) e(0); 607 608 free(buf3); 609 610 if (close(fd2) != 0) e(0); 611 if (close(fd) != 0) e(0); 612 613 /* For ICMPv6 packets, checksumming is always enabled. */ 614 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 615 616 len = sizeof(val); 617 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, &len) != 0) e(0); 618 if (len != sizeof(val)) e(0); 619 if (val != 2) e(0); 620 621 val = -1; 622 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 623 sizeof(val)) != -1) e(0); 624 if (errno != EINVAL) e(0); 625 626 memset(&icmp6_hdr, 0, sizeof(icmp6_hdr)); 627 icmp6_hdr.icmp6_type = TEST_ICMPV6_TYPE_A; 628 icmp6_hdr.icmp6_code = 123; 629 icmp6_hdr.icmp6_cksum = htons(0); 630 631 len = offsetof(struct icmp6_hdr, icmp6_dataun); 632 if (sendto(fd, &icmp6_hdr, len, 0, (struct sockaddr *)&sin6, 633 sizeof(sin6)) != len) e(0); 634 635 if (recv(fd, &icmp6_hdr, sizeof(icmp6_hdr), 0) != len) e(0); 636 637 if (icmp6_hdr.icmp6_type != TEST_ICMPV6_TYPE_A) e(0); 638 if (icmp6_hdr.icmp6_code != 123) e(0); 639 if (ntohs(icmp6_hdr.icmp6_cksum) != 0x3744) e(0); 640 641 if (close(fd) != 0) e(0); 642 643 /* For IPv4 and non-RAW IPv6 sockets, the option does not work. */ 644 for (i = 0; i <= 2; i++) { 645 switch (i) { 646 case 0: fd = socket(AF_INET6, SOCK_DGRAM, 0); break; 647 case 1: fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6); break; 648 case 2: fd = socket(AF_INET, SOCK_RAW, TEST_PROTO); break; 649 } 650 if (fd < 0) e(0); 651 652 val = -1; 653 if (setsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 654 sizeof(val)) != -1) e(0); 655 if (errno != ENOPROTOOPT) e(0); 656 657 len = sizeof(val); 658 if (getsockopt(fd, IPPROTO_IPV6, IPV6_CHECKSUM, &val, 659 &len) != -1) e(0); 660 if (errno != ENOPROTOOPT) e(0); 661 662 if (close(fd) != 0) e(0); 663 } 664 } 665 666 /* 667 * Test the ICMP6_FILTER socket option. 668 */ 669 static void 670 test92d(void) 671 { 672 struct sockaddr_in6 sin6; 673 struct sockaddr_in sin; 674 struct icmp6_filter filter; 675 struct icmp6_hdr packet; 676 socklen_t len; 677 struct timeval tv; 678 unsigned int i; 679 int fd, fd2; 680 681 subtest = 4; 682 683 /* 684 * We use two different sockets to eliminate the possibility that the 685 * filter is also applied when sending packets--it should not be. 686 */ 687 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 688 689 if (shutdown(fd, SHUT_WR) != 0) e(0); 690 691 len = sizeof(filter); 692 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0) 693 e(0); 694 695 /* We do not aim to test the ICMP6_FILTER macros here. */ 696 for (i = 0; i <= UINT8_MAX; i++) 697 if (!ICMP6_FILTER_WILLPASS(i, &filter)) e(0); 698 699 if ((fd2 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 700 701 ICMP6_FILTER_SETBLOCKALL(&filter); 702 if (setsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 703 sizeof(filter)) != 0) e(0); 704 705 len = sizeof(filter); 706 if (getsockopt(fd2, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0) 707 e(0); 708 709 for (i = 0; i <= UINT8_MAX; i++) 710 if (ICMP6_FILTER_WILLPASS(i, &filter)) e(0); 711 712 ICMP6_FILTER_SETPASSALL(&filter); 713 ICMP6_FILTER_SETBLOCK(TEST_ICMPV6_TYPE_A, &filter); 714 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 715 sizeof(filter)) != 0) e(0); 716 717 memset(&sin6, 0, sizeof(sin6)); 718 sin6.sin6_family = AF_INET6; 719 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr)); 720 721 memset(&packet, 0, sizeof(packet)); 722 packet.icmp6_type = TEST_ICMPV6_TYPE_A; 723 packet.icmp6_code = 12; 724 725 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6, 726 sizeof(sin6)) != sizeof(packet)) e(0); 727 728 packet.icmp6_type = TEST_ICMPV6_TYPE_B; 729 packet.icmp6_code = 34; 730 731 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6, 732 sizeof(sin6)) != sizeof(packet)) e(0); 733 734 memset(&packet, 0, sizeof(packet)); 735 736 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0); 737 if (packet.icmp6_type != TEST_ICMPV6_TYPE_B) e(0); 738 if (packet.icmp6_code != 34) e(0); 739 740 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0); 741 if (errno != EWOULDBLOCK) e(0); 742 743 ICMP6_FILTER_SETBLOCKALL(&filter); 744 ICMP6_FILTER_SETPASS(TEST_ICMPV6_TYPE_A, &filter); 745 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 746 sizeof(filter)) != 0) e(0); 747 748 memset(&packet, 0, sizeof(packet)); 749 packet.icmp6_type = TEST_ICMPV6_TYPE_B; 750 packet.icmp6_code = 56; 751 752 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6, 753 sizeof(sin6)) != sizeof(packet)) e(0); 754 755 packet.icmp6_type = TEST_ICMPV6_TYPE_A; 756 packet.icmp6_code = 78; 757 758 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6, 759 sizeof(sin6)) != sizeof(packet)) e(0); 760 761 /* 762 * RFC 3542 states that setting a zero-length filter resets the filter. 763 * This seems like one of those things that a standardization RFC 764 * should not mandate: it is redundant at the API level (one can set a 765 * PASSALL filter, which is the required default), it relies on an edge 766 * case (setsockopt taking a zero-length argument), and as a "shortcut" 767 * it does not even cover a case that is likely to occur (no actual 768 * program would reset its filter on a regular basis). Presumably it 769 * is a way to deallocate filter memory on some platforms, but was that 770 * worth the RFC inclusion? Anyhow, we support it; NetBSD does not. 771 */ 772 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, NULL, 0) != 0) e(0); 773 774 packet.icmp6_type = TEST_ICMPV6_TYPE_B; 775 packet.icmp6_code = 90; 776 777 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin6, 778 sizeof(sin6)) != sizeof(packet)) e(0); 779 780 memset(&packet, 0, sizeof(packet)); 781 782 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0); 783 if (packet.icmp6_type != TEST_ICMPV6_TYPE_A) e(0); 784 if (packet.icmp6_code != 78) e(0); 785 786 if (recv(fd, &packet, sizeof(packet), 0) != sizeof(packet)) e(0); 787 if (packet.icmp6_type != TEST_ICMPV6_TYPE_B) e(0); 788 if (packet.icmp6_code != 90) e(0); 789 790 if (recv(fd, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0); 791 if (errno != EWOULDBLOCK) e(0); 792 793 if (recv(fd2, &packet, sizeof(packet), MSG_DONTWAIT) != -1) e(0); 794 if (errno != EWOULDBLOCK) e(0); 795 796 len = sizeof(filter); 797 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, &len) != 0) 798 e(0); 799 800 for (i = 0; i <= UINT8_MAX; i++) 801 if (!ICMP6_FILTER_WILLPASS(i, &filter)) e(0); 802 803 if (close(fd2) != 0) e(0); 804 805 /* 806 * Let's get weird and send an ICMPv6 packet from an IPv4 socket. 807 * Currently, such packets are always dropped based on the rule that 808 * IPv6 sockets with checksumming enabled drop all IPv4 packets. As it 809 * happens, that is also all that is keeping this packet from arriving. 810 */ 811 if ((fd2 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 812 813 ICMP6_FILTER_SETBLOCKALL(&filter); 814 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 815 sizeof(filter)) != 0) e(0); 816 817 memset(&sin, 0, sizeof(sin)); 818 sin.sin_family = AF_INET; 819 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 820 821 memset(&packet, 0, sizeof(packet)); 822 packet.icmp6_type = TEST_ICMPV6_TYPE_A; 823 packet.icmp6_code = 123; 824 packet.icmp6_cksum = htons(0); /* TODO: use valid checksum */ 825 826 if (sendto(fd2, &packet, sizeof(packet), 0, (struct sockaddr *)&sin, 827 sizeof(sin)) != sizeof(packet)) e(0); 828 829 /* 830 * If the packet were to arrive at all, it should arrive instantly, so 831 * this is just an excuse to use SO_RCVTIMEO. 832 */ 833 tv.tv_sec = 0; 834 tv.tv_usec = 100000; 835 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) != 0) 836 e(0); 837 838 if (recv(fd, &packet, sizeof(packet), 0) != -1) e(0); 839 if (errno != EWOULDBLOCK) e(0); 840 841 if (close(fd2) != 0) e(0); 842 843 if (close(fd) != 0) e(0); 844 845 /* Make sure ICMP6_FILTER works on IPv6-ICMPv6 sockets only. */ 846 for (i = 0; i <= 2; i++) { 847 switch (i) { 848 case 0: fd = socket(AF_INET6, SOCK_DGRAM, 0); break; 849 case 1: fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO); break; 850 case 2: fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6); break; 851 } 852 if (fd < 0) e(0); 853 854 if (setsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 855 sizeof(filter)) != -1) e(0); 856 if (errno != ENOPROTOOPT) e(0); 857 858 len = sizeof(filter); 859 if (getsockopt(fd, IPPROTO_ICMPV6, ICMP6_FILTER, &filter, 860 &len) != -1) e(0); 861 if (errno != ENOPROTOOPT) e(0); 862 863 if (close(fd) != 0) e(0); 864 } 865 } 866 867 /* 868 * Test that IPPROTO_ICMPV6 has no special value on IPv4 raw sockets. In 869 * particular, test that no checksum is generated or verified. By now we have 870 * already tested that none of the IPv6 socket options work on such sockets. 871 */ 872 static void 873 test92e(void) 874 { 875 char buf[sizeof(struct ip) + sizeof(struct icmp6_hdr)]; 876 struct sockaddr_in sin; 877 struct icmp6_hdr packet; 878 int fd; 879 880 subtest = 5; 881 882 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 883 884 memset(&packet, 0, sizeof(packet)); 885 packet.icmp6_type = TEST_ICMPV6_TYPE_A; 886 packet.icmp6_code = 123; 887 packet.icmp6_cksum = htons(0); 888 889 memset(&sin, 0, sizeof(sin)); 890 sin.sin_family = AF_INET; 891 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 892 893 if (sendto(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&sin, 894 sizeof(sin)) != sizeof(packet)) e(0); 895 896 if (recv(fd, buf, sizeof(buf), 0) != sizeof(buf)) e(0); 897 898 memcpy(&packet, &buf[sizeof(struct ip)], sizeof(packet)); 899 if (packet.icmp6_type != TEST_ICMPV6_TYPE_A) e(0); 900 if (packet.icmp6_code != 123) e(0); 901 if (packet.icmp6_cksum != htons(0)) e(0); 902 903 if (close(fd) != 0) e(0); 904 } 905 906 struct testpkt { 907 struct ip ip; 908 struct udphdr udp; 909 uint8_t data[6]; 910 } __packed; 911 912 /* 913 * Test the IP_HDRINCL socket option. 914 */ 915 static void 916 test92f(void) 917 { 918 struct sockaddr_in sin; 919 struct testpkt pkt, pkt2; 920 socklen_t len; 921 char buf[7]; 922 unsigned int i; 923 int fd, fd2, val; 924 925 subtest = 6; 926 927 /* See if we can successfully feign a UDP packet. */ 928 memset(&pkt, 0, sizeof(pkt)); 929 pkt.ip.ip_v = IPVERSION; 930 pkt.ip.ip_hl = sizeof(pkt.ip) >> 2; 931 pkt.ip.ip_tos = 123; 932 pkt.ip.ip_len = sizeof(pkt); /* swapped by OS */ 933 pkt.ip.ip_id = htons(456); 934 pkt.ip.ip_off = IP_DF; /* swapped by OS */ 935 pkt.ip.ip_ttl = 78; 936 pkt.ip.ip_p = IPPROTO_UDP; 937 pkt.ip.ip_sum = htons(0); /* filled by OS */ 938 pkt.ip.ip_src.s_addr = htonl(INADDR_LOOPBACK); 939 pkt.ip.ip_dst.s_addr = htonl(INADDR_LOOPBACK); 940 pkt.udp.uh_sport = htons(TEST_PORT_B); 941 pkt.udp.uh_dport = htons(TEST_PORT_A); 942 pkt.udp.uh_sum = htons(0); /* lazy.. */ 943 pkt.udp.uh_ulen = htons(sizeof(pkt.udp) + sizeof(pkt.data)); 944 memcpy(pkt.data, "Hello!", sizeof(pkt.data)); 945 946 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0); 947 948 if (shutdown(fd, SHUT_RD) != 0) e(0); 949 950 /* IP_HDRINCL is never enabled by default. */ 951 len = sizeof(val); 952 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0); 953 if (len != sizeof(val)) e(0); 954 if (val != 0) e(0); 955 956 val = 1; 957 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0) 958 e(0); 959 960 len = sizeof(val); 961 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0); 962 if (len != sizeof(val)) e(0); 963 if (val != 1) e(0); 964 965 if ((fd2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) e(0); 966 967 memset(&sin, 0, sizeof(sin)); 968 sin.sin_family = AF_INET; 969 sin.sin_port = htons(TEST_PORT_A); 970 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 971 972 if (bind(fd2, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0); 973 974 sin.sin_port = htons(0); 975 976 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin, 977 sizeof(sin)) != sizeof(pkt)) e(0); 978 979 if (recv(fd2, &buf, sizeof(buf), 0) != sizeof(pkt.data)) e(0); 980 if (memcmp(buf, pkt.data, sizeof(pkt.data)) != 0) e(0); 981 982 if (close(fd2) != 0) e(0); 983 if (close(fd) != 0) e(0); 984 985 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 986 987 len = sizeof(val); 988 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, &len) != 0) e(0); 989 if (len != sizeof(val)) e(0); 990 if (val != 0) e(0); 991 992 if (shutdown(fd, SHUT_RD) != 0) e(0); 993 994 /* See if we can receive a packet for our own protocol. */ 995 pkt.ip.ip_p = TEST_PROTO; 996 997 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 998 999 val = 1; 1000 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0) 1001 e(0); 1002 1003 if (sendto(fd, &pkt, sizeof(pkt), 0, (struct sockaddr *)&sin, 1004 sizeof(sin)) != sizeof(pkt)) e(0); 1005 1006 if (recv(fd2, &pkt2, sizeof(pkt2), 0) != sizeof(pkt2)) e(0); 1007 1008 if (pkt2.ip.ip_v != pkt.ip.ip_v) e(0); 1009 if (pkt2.ip.ip_hl != pkt.ip.ip_hl) e(0); 1010 if (pkt2.ip.ip_tos != pkt.ip.ip_tos) e(0); 1011 if (pkt2.ip.ip_len != pkt.ip.ip_len) e(0); 1012 if (pkt2.ip.ip_id != pkt.ip.ip_id) e(0); 1013 if (pkt2.ip.ip_off != pkt.ip.ip_off) e(0); 1014 if (pkt2.ip.ip_ttl != pkt.ip.ip_ttl) e(0); 1015 if (pkt2.ip.ip_p != pkt.ip.ip_p) e(0); 1016 if (pkt2.ip.ip_sum == htons(0)) e(0); 1017 if (pkt2.ip.ip_src.s_addr != pkt.ip.ip_src.s_addr) e(0); 1018 if (pkt2.ip.ip_dst.s_addr != pkt.ip.ip_dst.s_addr) e(0); 1019 1020 /* 1021 * Test sending packets with weird sizes to ensure that we do not crash 1022 * the service. These packets would never arrive anyway. 1023 */ 1024 if (sendto(fd, &pkt, 0, 0, (struct sockaddr *)&sin, 1025 sizeof(sin)) != -1) e(0); 1026 if (errno != EINVAL) e(0); 1027 if (sendto(fd, &pkt, sizeof(pkt.ip) - 1, 0, (struct sockaddr *)&sin, 1028 sizeof(sin)) != -1) e(0); 1029 if (errno != EINVAL) e(0); 1030 if (sendto(fd, &pkt, sizeof(pkt.ip), 0, (struct sockaddr *)&sin, 1031 sizeof(sin)) != sizeof(pkt.ip)) e(0); 1032 1033 if (recv(fd2, &pkt2, sizeof(pkt2), MSG_DONTWAIT) != -1) e(0); 1034 if (errno != EWOULDBLOCK) e(0); 1035 1036 if (close(fd2) != 0) e(0); 1037 if (close(fd) != 0) e(0); 1038 1039 /* Ensure that the socket option does not work on other types. */ 1040 for (i = 0; i <= 1; i++) { 1041 switch (i) { 1042 case 0: fd = socket(AF_INET, SOCK_DGRAM, 0); break; 1043 case 1: fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO); break; 1044 } 1045 if (fd < 0) e(0); 1046 1047 len = sizeof(val); 1048 if (getsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, 1049 &len) != -1) e(0); 1050 if (errno != ENOPROTOOPT) e(0); 1051 1052 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, 1053 sizeof(val)) != -1) e(0); 1054 if (errno != ENOPROTOOPT) e(0); 1055 1056 if (close(fd) != 0) e(0); 1057 } 1058 } 1059 1060 /* 1061 * Test the IPPROTO_RAW socket protocol. This test mostly shows that the 1062 * IPPROTO_RAW protocol is nothing special: for both IPv4 and IPv6, it sends 1063 * and receives packets with that protocol number. We already tested earlier 1064 * that IP_HDRINCL is disabled by default on IPPROTO_RAW sockets, too. 1065 */ 1066 static void 1067 test92g(void) 1068 { 1069 struct sockaddr_in sin; 1070 struct sockaddr_in6 sin6; 1071 char buf[sizeof(struct ip) + 1]; 1072 int fd; 1073 1074 subtest = 7; 1075 1076 if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) e(0); 1077 1078 memset(&sin, 0, sizeof(sin)); 1079 sin.sin_family = AF_INET; 1080 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1081 1082 if (sendto(fd, "A", 1, 0, (struct sockaddr *)&sin, 1083 sizeof(sin)) != 1) e(0); 1084 1085 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != sizeof(buf)) e(0); 1086 if (buf[sizeof(struct ip)] != 'A') e(0); 1087 1088 if (close(fd) != 0) e(0); 1089 1090 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0) e(0); 1091 1092 memset(&sin6, 0, sizeof(sin6)); 1093 sin6.sin6_family = AF_INET6; 1094 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr)); 1095 1096 if (sendto(fd, "B", 1, 0, (struct sockaddr *)&sin6, 1097 sizeof(sin6)) != 1) e(0); 1098 1099 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != 1) e(0); 1100 if (buf[0] != 'B') e(0); 1101 1102 if (close(fd) != 0) e(0); 1103 } 1104 1105 /* 1106 * Test that connected raw sockets perform correct source-based filtering. 1107 */ 1108 static void 1109 test92h(void) 1110 { 1111 struct sockaddr_in sinA, sinB; 1112 struct sockaddr_in6 sin6A, sin6B; 1113 struct sockaddr sa; 1114 socklen_t len; 1115 char buf[sizeof(struct ip) + 1]; 1116 int fd, fd2; 1117 1118 subtest = 8; 1119 1120 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1121 1122 len = sizeof(sinB); 1123 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0); 1124 if (errno != ENOTCONN) e(0); 1125 1126 memset(&sinA, 0, sizeof(sinA)); 1127 sinA.sin_family = AF_INET; 1128 sinA.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1129 1130 /* 1131 * First test that packets with the right source are accepted. 1132 * Unfortunately, source and destination are the same in this case, so 1133 * this test is far from perfect. 1134 */ 1135 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0); 1136 1137 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != 0) e(0); 1138 1139 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1140 1141 if (sendto(fd2, "A", 1, 0, (struct sockaddr *)&sinA, 1142 sizeof(sinA)) != 1) e(0); 1143 1144 buf[0] = '\0'; 1145 if (recv(fd2, buf, sizeof(buf), 0) != sizeof(struct ip) + 1) e(0); 1146 if (buf[sizeof(struct ip)] != 'A') e(0); 1147 1148 buf[0] = '\0'; 1149 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != 1150 sizeof(struct ip) + 1) e(0); 1151 if (buf[sizeof(struct ip)] != 'A') e(0); 1152 1153 memset(&sa, 0, sizeof(sa)); 1154 sa.sa_family = AF_UNSPEC; 1155 1156 sinA.sin_addr.s_addr = htonl(INADDR_NONE); 1157 1158 /* While here, test unconnecting the socket. */ 1159 if (connect(fd, &sa, sizeof(sa)) != 0) e(0); 1160 1161 if (getpeername(fd, (struct sockaddr *)&sinB, &len) != -1) e(0); 1162 if (errno != ENOTCONN) e(0); 1163 1164 /* Then test that packets with the wrong source are ignored. */ 1165 if (connect(fd, (struct sockaddr *)&sinA, sizeof(sinA)) != 0) e(0); 1166 1167 if (sendto(fd2, "B", 1, 0, (struct sockaddr *)&sinB, 1168 sizeof(sinB)) != 1) e(0); 1169 1170 buf[0] = '\0'; 1171 if (recv(fd2, buf, sizeof(buf), 0) != sizeof(struct ip) + 1) e(0); 1172 if (buf[sizeof(struct ip)] != 'B') e(0); 1173 1174 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0); 1175 if (errno != EWOULDBLOCK) e(0); 1176 1177 if (close(fd2) != 0) e(0); 1178 if (close(fd) != 0) e(0); 1179 1180 /* Repeat for IPv6, but now the other way around. */ 1181 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1182 1183 len = sizeof(sin6B); 1184 if (getpeername(fd, (struct sockaddr *)&sin6B, &len) != -1) e(0); 1185 if (errno != ENOTCONN) e(0); 1186 1187 memset(&sin6A, 0, sizeof(sin6A)); 1188 sin6A.sin6_family = AF_INET6; 1189 memcpy(&sin6A.sin6_addr, &in6addr_loopback, sizeof(sin6A.sin6_addr)); 1190 1191 memcpy(&sin6B, &sin6A, sizeof(sin6B)); 1192 if (inet_pton(AF_INET6, "::2", &sin6B.sin6_addr) != 1) e(0); 1193 1194 if (connect(fd, (struct sockaddr *)&sin6B, sizeof(sin6B)) != 0) e(0); 1195 1196 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1197 1198 if (sendto(fd2, "C", 1, 0, (struct sockaddr *)&sin6A, 1199 sizeof(sin6A)) != 1) e(0); 1200 1201 buf[0] = '\0'; 1202 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0); 1203 if (buf[0] != 'C') e(0); 1204 1205 if (recv(fd, buf, sizeof(buf), MSG_DONTWAIT) != -1) e(0); 1206 if (errno != EWOULDBLOCK) e(0); 1207 1208 if (connect(fd, &sa, sizeof(sa)) != 0) e(0); 1209 1210 if (connect(fd, (struct sockaddr *)&sin6A, sizeof(sin6A)) != 0) e(0); 1211 1212 if (sendto(fd2, "D", 1, 0, (struct sockaddr *)&sin6A, 1213 sizeof(sin6A)) != 1) e(0); 1214 1215 buf[0] = '\0'; 1216 if (recv(fd2, buf, sizeof(buf), 0) != 1) e(0); 1217 if (buf[0] != 'D') e(0); 1218 1219 buf[0] = '\0'; 1220 if (recv(fd, buf, sizeof(buf), 0) != 1) e(0); 1221 if (buf[0] != 'D') e(0); 1222 1223 if (close(fd2) != 0) e(0); 1224 if (close(fd) != 0) e(0); 1225 } 1226 1227 /* 1228 * Test sending large and small RAW packets. This test is an altered copy of 1229 * test91e, but has been changed to IPv6 to cover a greater spectrum together. 1230 */ 1231 static void 1232 test92i(void) 1233 { 1234 struct sockaddr_in6 sin6; 1235 struct msghdr msg; 1236 struct iovec iov; 1237 char *buf; 1238 unsigned int i, j; 1239 int r, fd, fd2, val; 1240 1241 subtest = 9; 1242 1243 if ((buf = malloc(65536)) == NULL) e(0); 1244 1245 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1246 1247 memset(&sin6, 0, sizeof(sin6)); 1248 sin6.sin6_family = AF_INET6; 1249 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr)); 1250 1251 if (bind(fd, (struct sockaddr *)&sin6, sizeof(sin6)) != 0) e(0); 1252 1253 val = 65536; 1254 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val)) != 0) 1255 e(0); 1256 1257 if ((fd2 = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1258 1259 /* 1260 * A maximum send buffer size of a full packet size's worth may always 1261 * be set, although this is not necessarily the actual maximum. 1262 */ 1263 val = 65535; 1264 if (setsockopt(fd2, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val)) != 0) 1265 e(0); 1266 1267 /* Find the largest possible packet size that can actually be sent. */ 1268 for (i = 0; i < val; i += sizeof(int)) { 1269 j = i ^ 0xdeadbeef; 1270 memcpy(&buf[i], &j, sizeof(j)); 1271 } 1272 1273 for (val = 65536; val > 0; val--) { 1274 if ((r = sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, 1275 sizeof(sin6))) == val) 1276 break; 1277 if (r != -1) e(0); 1278 if (errno != EMSGSIZE) e(0); 1279 } 1280 1281 if (val != 65535 - sizeof(struct ip6_hdr)) e(0); 1282 1283 memset(buf, 0, val); 1284 buf[val] = 'X'; 1285 1286 memset(&iov, 0, sizeof(iov)); 1287 iov.iov_base = buf; 1288 iov.iov_len = val + 1; 1289 memset(&msg, 0, sizeof(msg)); 1290 msg.msg_iov = &iov; 1291 msg.msg_iovlen = 1; 1292 if (recvmsg(fd, &msg, 0) != val) e(0); 1293 if (msg.msg_flags != 0) e(0); 1294 1295 for (i = 0; i < val; i += sizeof(int)) { 1296 j = i ^ 0xdeadbeef; 1297 if (memcmp(&buf[i], &j, MIN(sizeof(j), val - i))) e(0); 1298 } 1299 if (buf[val] != 'X') e(0); 1300 1301 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 1302 val) e(0); 1303 1304 /* 1305 * Make sure that there are no off-by-one errors in the receive code, 1306 * and that MSG_TRUNC is set (only) when not the whole packet was 1307 * received. 1308 */ 1309 memset(&iov, 0, sizeof(iov)); 1310 iov.iov_base = buf; 1311 iov.iov_len = val; 1312 memset(&msg, 0, sizeof(msg)); 1313 msg.msg_iov = &iov; 1314 msg.msg_iovlen = 1; 1315 if (recvmsg(fd, &msg, 0) != val) e(0); 1316 if (msg.msg_flags != 0) e(0); 1317 1318 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 1319 val) e(0); 1320 1321 buf[val - 1] = 'Y'; 1322 1323 memset(&iov, 0, sizeof(iov)); 1324 iov.iov_base = buf; 1325 iov.iov_len = val - 1; 1326 memset(&msg, 0, sizeof(msg)); 1327 msg.msg_iov = &iov; 1328 msg.msg_iovlen = 1; 1329 if (recvmsg(fd, &msg, 0) != val - 1) e(0); 1330 if (msg.msg_flags != MSG_TRUNC) e(0); 1331 1332 for (i = 0; i < val - 1; i += sizeof(int)) { 1333 j = i ^ 0xdeadbeef; 1334 if (memcmp(&buf[i], &j, MIN(sizeof(j), val - 1 - i))) e(0); 1335 } 1336 if (buf[val - 1] != 'Y') e(0); 1337 1338 if (sendto(fd2, buf, val, 0, (struct sockaddr *)&sin6, sizeof(sin6)) != 1339 val) e(0); 1340 1341 buf[0] = 'Z'; 1342 1343 memset(&iov, 0, sizeof(iov)); 1344 iov.iov_base = buf; 1345 iov.iov_len = 0; 1346 memset(&msg, 0, sizeof(msg)); 1347 msg.msg_iov = &iov; 1348 msg.msg_iovlen = 1; 1349 if (recvmsg(fd, &msg, 0) != 0) e(0); 1350 if (msg.msg_flags != MSG_TRUNC) e(0); 1351 if (buf[0] != 'Z') e(0); 1352 1353 /* Make sure that zero-sized packets can be sent and received. */ 1354 if (sendto(fd2, buf, 0, 0, (struct sockaddr *)&sin6, 1355 sizeof(sin6)) != 0) e(0); 1356 1357 /* 1358 * Note how we currently assume that packets sent over localhost will 1359 * arrive immediately, so that we can use MSG_DONTWAIT to avoid that 1360 * the test freezes. 1361 */ 1362 memset(&msg, 0, sizeof(msg)); 1363 msg.msg_iov = &iov; 1364 msg.msg_iovlen = 1; 1365 if (recvmsg(fd, &msg, MSG_DONTWAIT) != 0) e(0); 1366 if (msg.msg_flags != 0) e(0); 1367 if (buf[0] != 'Z') e(0); 1368 1369 if (recv(fd, buf, val, MSG_DONTWAIT) != -1) e(0); 1370 if (errno != EWOULDBLOCK) e(0); 1371 1372 /* 1373 * When sending lots of small packets, ensure that fewer packets arrive 1374 * than we sent. This sounds weird, but we cannot actually check the 1375 * internal TCP/IP buffer granularity and yet we want to make sure that 1376 * the receive queue is measured in terms of buffers rather than packet 1377 * sizes. In addition, we check that older packets are favored, 1378 * instead discarding new ones when the receive buffer is full. 1379 */ 1380 for (i = 0; i < 65536 / sizeof(j); i++) { 1381 j = i; 1382 if (sendto(fd2, &j, sizeof(j), 0, (struct sockaddr *)&sin6, 1383 sizeof(sin6)) != sizeof(j)) e(0); 1384 } 1385 1386 for (i = 0; i < 1025; i++) { 1387 r = recv(fd, &j, sizeof(j), MSG_DONTWAIT); 1388 if (r == -1) { 1389 if (errno != EWOULDBLOCK) e(0); 1390 break; 1391 } 1392 if (r != sizeof(j)) e(0); 1393 if (i != j) e(0); 1394 } 1395 if (i == 1025) e(0); 1396 1397 if (close(fd2) != 0) e(0); 1398 if (close(fd) != 0) e(0); 1399 1400 free(buf); 1401 } 1402 1403 /* 1404 * Test sending and receiving with bad pointers. 1405 */ 1406 static void 1407 test92j(void) 1408 { 1409 struct sockaddr_in sin; 1410 char *ptr; 1411 int i, fd; 1412 1413 subtest = 10; 1414 1415 if ((ptr = mmap(NULL, PAGE_SIZE * 2, PROT_READ | PROT_WRITE, 1416 MAP_ANON | MAP_PRIVATE, -1, 0)) == MAP_FAILED) e(0); 1417 1418 if (munmap(&ptr[PAGE_SIZE], PAGE_SIZE) != 0) e(0); 1419 1420 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1421 1422 memset(&sin, 0, sizeof(sin)); 1423 sin.sin_family = AF_INET; 1424 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1425 1426 if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)) != 0) e(0); 1427 1428 memset(ptr, 'A', PAGE_SIZE); 1429 1430 if (sendto(fd, &ptr[PAGE_SIZE / 2], PAGE_SIZE, 0, 1431 (struct sockaddr *)&sin, sizeof(sin)) != -1) e(0); 1432 if (errno != EFAULT) e(0); 1433 1434 memset(ptr, 'B', PAGE_SIZE); 1435 1436 if (sendto(fd, ptr, PAGE_SIZE - sizeof(struct ip), 0, 1437 (struct sockaddr *)&sin, sizeof(sin)) != 1438 PAGE_SIZE - sizeof(struct ip)) e(0); 1439 1440 memset(ptr, 0, PAGE_SIZE); 1441 1442 if (recvfrom(fd, &ptr[PAGE_SIZE / 2], PAGE_SIZE, 0, NULL, 0) != -1) 1443 e(0); 1444 if (errno != EFAULT) e(0); 1445 1446 if (recvfrom(fd, ptr, PAGE_SIZE * 2, 0, NULL, 0) != PAGE_SIZE) e(0); 1447 for (i = sizeof(struct ip); i < PAGE_SIZE; i++) 1448 if (ptr[i] != 'B') e(0); 1449 1450 if (close(fd) != 0) e(0); 1451 1452 if (munmap(ptr, PAGE_SIZE) != 0) e(0); 1453 } 1454 1455 /* 1456 * Test basic sysctl(2) socket enumeration support. 1457 */ 1458 static void 1459 test92k(void) 1460 { 1461 struct kinfo_pcb ki; 1462 struct sockaddr_in lsin, rsin; 1463 struct sockaddr_in6 lsin6, rsin6; 1464 int fd, fd2, val; 1465 1466 subtest = 11; 1467 1468 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1469 &ki) != 0) e(0); 1470 1471 if ((fd = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1472 1473 memset(&lsin, 0, sizeof(lsin)); 1474 lsin.sin_len = sizeof(lsin); 1475 lsin.sin_family = AF_INET; 1476 1477 memset(&rsin, 0, sizeof(rsin)); 1478 rsin.sin_len = sizeof(rsin); 1479 rsin.sin_family = AF_INET; 1480 1481 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1482 &ki) != 1) e(0); 1483 if (ki.ki_type != SOCK_RAW) e(0); 1484 if (ki.ki_tstate != 0) e(0); 1485 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0); 1486 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0); 1487 if (ki.ki_sndq != 0) e(0); 1488 if (ki.ki_rcvq != 0) e(0); 1489 1490 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1491 &ki) != 0) e(0); 1492 1493 lsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1494 1495 if (bind(fd, (struct sockaddr *)&lsin, sizeof(lsin)) != 0) e(0); 1496 1497 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1498 &ki) != 1) e(0); 1499 if (ki.ki_type != SOCK_RAW) e(0); 1500 if (ki.ki_tstate != 0) e(0); 1501 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0); 1502 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0); 1503 if (ki.ki_sndq != 0) e(0); 1504 if (ki.ki_rcvq != 0) e(0); 1505 if (ki.ki_pflags & INP_HDRINCL) e(0); 1506 1507 rsin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1508 if (connect(fd, (struct sockaddr *)&rsin, sizeof(rsin)) != 0) e(0); 1509 1510 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1511 &ki) != 1) e(0); 1512 if (ki.ki_type != SOCK_RAW) e(0); 1513 if (ki.ki_tstate != 0) e(0); 1514 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0); 1515 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0); 1516 if (ki.ki_sndq != 0) e(0); 1517 if (ki.ki_rcvq != 0) e(0); 1518 1519 if ((fd2 = socket(AF_INET, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1520 1521 if (sendto(fd2, "ABC", 3, 0, (struct sockaddr *)&lsin, 1522 sizeof(lsin)) != 3) e(0); 1523 1524 if (close(fd2) != 0) e(0); 1525 1526 val = 1; 1527 if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) != 0) 1528 e(0); 1529 1530 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1531 &ki) != 1) e(0); 1532 if (ki.ki_type != SOCK_RAW) e(0); 1533 if (ki.ki_tstate != 0) e(0); 1534 if (memcmp(&ki.ki_src, &lsin, sizeof(lsin)) != 0) e(0); 1535 if (memcmp(&ki.ki_dst, &rsin, sizeof(rsin)) != 0) e(0); 1536 if (ki.ki_sndq != 0) e(0); 1537 if (ki.ki_rcvq < 3) e(0); /* size is rounded up */ 1538 if (!(ki.ki_pflags & INP_HDRINCL)) e(0); 1539 1540 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1541 &ki) != 0) e(0); 1542 1543 if (close(fd) != 0) e(0); 1544 1545 /* Test IPv6 sockets as well. */ 1546 if ((fd = socket(AF_INET6, SOCK_RAW, TEST_PROTO)) < 0) e(0); 1547 1548 memset(&lsin6, 0, sizeof(lsin6)); 1549 lsin6.sin6_len = sizeof(lsin6); 1550 lsin6.sin6_family = AF_INET6; 1551 1552 memset(&rsin6, 0, sizeof(rsin6)); 1553 rsin6.sin6_len = sizeof(rsin6); 1554 rsin6.sin6_family = AF_INET6; 1555 1556 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1557 &ki) != 1) e(0); 1558 if (ki.ki_type != SOCK_RAW) e(0); 1559 if (ki.ki_tstate != 0) e(0); 1560 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0); 1561 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0); 1562 if (ki.ki_sndq != 0) e(0); 1563 if (ki.ki_rcvq != 0) e(0); 1564 1565 memcpy(&lsin6.sin6_addr, &in6addr_loopback, sizeof(lsin6.sin6_addr)); 1566 if (bind(fd, (struct sockaddr *)&lsin6, sizeof(lsin6)) != 0) e(0); 1567 1568 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1569 &ki) != 1) e(0); 1570 if (ki.ki_type != SOCK_RAW) e(0); 1571 if (ki.ki_tstate != 0) e(0); 1572 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0); 1573 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0); 1574 if (ki.ki_sndq != 0) e(0); 1575 if (ki.ki_rcvq != 0) e(0); 1576 if (!(ki.ki_pflags & IN6P_IPV6_V6ONLY)) e(0); 1577 1578 memcpy(&rsin6.sin6_addr, &in6addr_loopback, sizeof(rsin6.sin6_addr)); 1579 if (connect(fd, (struct sockaddr *)&rsin6, sizeof(rsin6)) != 0) 1580 e(0); 1581 1582 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1583 &ki) != 1) e(0); 1584 if (ki.ki_type != SOCK_RAW) e(0); 1585 if (ki.ki_tstate != 0) e(0); 1586 if (memcmp(&ki.ki_src, &lsin6, sizeof(lsin6)) != 0) e(0); 1587 if (memcmp(&ki.ki_dst, &rsin6, sizeof(rsin6)) != 0) e(0); 1588 if (ki.ki_sndq != 0) e(0); 1589 if (ki.ki_rcvq != 0) e(0); 1590 if (!(ki.ki_pflags & IN6P_IPV6_V6ONLY)) e(0); 1591 1592 if (socklib_find_pcb("net.inet.raw.pcblist", TEST_PROTO, 0, 0, 1593 &ki) != 0) e(0); 1594 1595 if (close(fd) != 0) e(0); 1596 1597 if (socklib_find_pcb("net.inet6.raw6.pcblist", TEST_PROTO, 0, 0, 1598 &ki) != 0) e(0); 1599 } 1600 1601 /* 1602 * Test local and remote IPv6 address handling. In particular, test scope IDs 1603 * and IPv4-mapped IPv6 addresses. 1604 */ 1605 static void 1606 test92l(void) 1607 { 1608 1609 subtest = 12; 1610 1611 socklib_test_addrs(SOCK_RAW, TEST_PROTO); 1612 } 1613 1614 /* 1615 * Test setting and retrieving basic multicast transmission options. 1616 */ 1617 static void 1618 test92m(void) 1619 { 1620 1621 subtest = 13; 1622 1623 socklib_multicast_tx_options(SOCK_RAW); 1624 } 1625 1626 /* 1627 * Test multicast support. 1628 */ 1629 static void 1630 test92n(void) 1631 { 1632 1633 subtest = 14; 1634 1635 socklib_test_multicast(SOCK_RAW, TEST_PROTO); 1636 } 1637 1638 /* 1639 * Test small and large ICMP echo ("ping") packets. This test aims to confirm 1640 * expected behavior resulting from the LWIP service's memory pool policies: 1641 * lwIP should reply to ICMP echo requests that fit in a single 512-byte buffer 1642 * (including space for ethernet headers, even on loopback interfaces), but not 1643 * to requests exceeding a single buffer. 1644 */ 1645 static void 1646 test92o(void) 1647 { 1648 struct sockaddr_in6 sin6; 1649 struct icmp6_hdr packet; 1650 char buf[512]; 1651 int fd; 1652 1653 subtest = 15; 1654 1655 /* IPv6 only for now, for simplicity reasons. */ 1656 if ((fd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) e(0); 1657 1658 memset(&sin6, 0, sizeof(sin6)); 1659 sin6.sin6_family = AF_INET6; 1660 memcpy(&sin6.sin6_addr, &in6addr_loopback, sizeof(sin6.sin6_addr)); 1661 1662 memset(&packet, 0, sizeof(packet)); 1663 packet.icmp6_type = ICMP6_ECHO_REQUEST; 1664 packet.icmp6_code = 0; 1665 packet.icmp6_id = getpid(); 1666 packet.icmp6_seq = 1; 1667 1668 memset(buf, 'A', sizeof(buf)); 1669 memcpy(buf, &packet, sizeof(packet)); 1670 1671 if (sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sin6, 1672 sizeof(sin6)) != sizeof(buf)) e(0); 1673 1674 packet.icmp6_seq = 2; 1675 1676 memset(buf, 'B', sizeof(buf)); 1677 memcpy(buf, &packet, sizeof(packet)); 1678 1679 if (sendto(fd, buf, sizeof(buf) - 100, 0, (struct sockaddr *)&sin6, 1680 sizeof(sin6)) != sizeof(buf) - 100) e(0); 1681 1682 do { 1683 memset(buf, '\0', sizeof(buf)); 1684 1685 if (recv(fd, buf, sizeof(buf), 0) <= 0) e(0); 1686 1687 memcpy(&packet, buf, sizeof(packet)); 1688 } while (packet.icmp6_type == ICMP6_ECHO_REQUEST); 1689 1690 if (packet.icmp6_type != ICMP6_ECHO_REPLY) e(0); 1691 if (packet.icmp6_code != 0) e(0); 1692 if (packet.icmp6_id != getpid()) e(0); 1693 if (packet.icmp6_seq != 2) e(0); 1694 if (buf[sizeof(buf) - 101] != 'B') e(0); 1695 1696 if (close(fd) != 0) e(0); 1697 } 1698 1699 /* 1700 * Test program for LWIP RAW sockets. 1701 */ 1702 int 1703 main(int argc, char ** argv) 1704 { 1705 int i, m; 1706 1707 start(92); 1708 1709 if (argc == 2) 1710 m = atoi(argv[1]); 1711 else 1712 m = 0xFFFF; 1713 1714 for (i = 0; i < ITERATIONS; i++) { 1715 if (m & 0x0001) test92a(); 1716 if (m & 0x0002) test92b(); 1717 if (m & 0x0004) test92c(); 1718 if (m & 0x0008) test92d(); 1719 if (m & 0x0010) test92e(); 1720 if (m & 0x0020) test92f(); 1721 if (m & 0x0040) test92g(); 1722 if (m & 0x0080) test92h(); 1723 if (m & 0x0100) test92i(); 1724 if (m & 0x0200) test92j(); 1725 if (m & 0x0400) test92k(); 1726 if (m & 0x0400) test92k(); 1727 if (m & 0x0800) test92l(); 1728 if (m & 0x1000) test92m(); 1729 if (m & 0x2000) test92n(); 1730 if (m & 0x4000) test92o(); 1731 } 1732 1733 quit(); 1734 /* NOTREACHED */ 1735 } 1736