1/* $Id: sockmisc.c,v 1.17.4.4 2005/10/04 09:54:27 manubsd Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include "config.h" 33 34#include <sys/types.h> 35#include <sys/param.h> 36#include <sys/socket.h> 37#include <sys/uio.h> 38 39#include <netinet/in.h> 40#ifndef HAVE_NETINET6_IPSEC 41#include <netinet/ipsec.h> 42#else 43#include <netinet6/ipsec.h> 44#endif 45 46#if defined(INET6) && !defined(INET6_ADVAPI) && \ 47 defined(IP_RECVDSTADDR) && !defined(IPV6_RECVDSTADDR) 48#define IPV6_RECVDSTADDR IP_RECVDSTADDR 49#endif 50 51#include <stdlib.h> 52#include <stdio.h> 53#include <string.h> 54#include <errno.h> 55#ifdef HAVE_UNISTD_H 56#include <unistd.h> 57#endif 58#include <fcntl.h> 59 60#include "var.h" 61#include "misc.h" 62#include "plog.h" 63#include "sockmisc.h" 64#include "debug.h" 65#include "gcmalloc.h" 66#include "libpfkey.h" 67 68#ifndef IP_IPSEC_POLICY 69#define IP_IPSEC_POLICY 16 /* XXX: from linux/in.h */ 70#endif 71 72#ifndef IPV6_IPSEC_POLICY 73#define IPV6_IPSEC_POLICY 34 /* XXX: from linux/???.h per 74 "Tom Lendacky" <toml@us.ibm.com> */ 75#endif 76 77const int niflags = 0; 78 79/* 80 * compare two sockaddr without port number. 81 * OUT: 0: equal. 82 * 1: not equal. 83 */ 84int 85cmpsaddrwop(addr1, addr2) 86 const struct sockaddr_storage *addr1; 87 const struct sockaddr_storage *addr2; 88{ 89 caddr_t sa1, sa2; 90 91 if (addr1 == 0 && addr2 == 0) 92 return 0; 93 if (addr1 == 0 || addr2 == 0) 94 return 1; 95 96 if (addr1->ss_len != addr2->ss_len 97 || addr1->ss_family != addr2->ss_family) 98 return 1; 99 switch (addr1->ss_family) { 100 case AF_INET: 101 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 102 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 103 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 104 return 1; 105 break; 106#ifdef INET6 107 case AF_INET6: 108 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 109 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 110 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 111 return 1; 112 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 113 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 114 return 1; 115 break; 116#endif 117 default: 118 return 1; 119 } 120 121 return 0; 122} 123 124/* 125 * compare two sockaddr without port number using prefix. 126 * OUT: 0: equal. 127 * 1: not equal. 128 */ 129int 130cmpsaddrwop_withprefix(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2, int prefix) 131{ 132 u_int32_t mask; 133 int i; 134 135 if (addr1 == 0 && addr2 == 0) 136 return 0; 137 if (addr1 == 0 || addr2 == 0) 138 return 1; 139 140 if (addr1->ss_len != addr2->ss_len 141 || addr1->ss_family != addr2->ss_family) 142 return 1; 143 switch (addr1->ss_family) { 144 case AF_INET: 145 mask = ~0; 146 mask <<= 32-prefix; 147 if ((((struct sockaddr_in *)addr1)->sin_addr.s_addr & htonl(mask)) != 148 (((struct sockaddr_in *)addr2)->sin_addr.s_addr & htonl(mask))) 149 return 1; 150 break; 151#ifdef INET6 152 case AF_INET6: 153 for (i = 0; i < 4; i++) { 154 if (prefix >= 32) { 155 mask = ~0; 156 prefix -= 32; 157 } else if (prefix == 0) 158 mask = 0; 159 else { 160 mask = ~0; 161 mask <<= 32-prefix; 162 prefix = 0; 163 } 164 if ((((struct sockaddr_in6 *)addr1)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)) != 165 (((struct sockaddr_in6 *)addr2)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask))) 166 return 1; 167 } 168 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 169 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 170 return 1; 171 break; 172#endif 173 default: 174 return 1; 175 } 176 177 return 0; 178} 179 180 181/* 182 * compare two sockaddr with port, taking care wildcard. 183 * addr1 is a subject address, addr2 is in a database entry. 184 * OUT: 0: equal. 185 * 1: not equal. 186 */ 187int 188cmpsaddrwild(addr1, addr2) 189 const struct sockaddr_storage *addr1; 190 const struct sockaddr_storage *addr2; 191{ 192 caddr_t sa1, sa2; 193 u_short port1, port2; 194 195 if (addr1 == 0 && addr2 == 0) 196 return 0; 197 if (addr1 == 0 || addr2 == 0) 198 return 1; 199 200 if (addr1->ss_len != addr2->ss_len 201 || addr1->ss_family != addr2->ss_family) 202 return 1; 203 204 switch (addr1->ss_family) { 205 case AF_INET: 206 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 207 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 208 port1 = ((struct sockaddr_in *)addr1)->sin_port; 209 port2 = ((struct sockaddr_in *)addr2)->sin_port; 210 if (!(port1 == IPSEC_PORT_ANY || 211 port2 == IPSEC_PORT_ANY || 212 port1 == port2)) 213 return 1; 214 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 215 return 1; 216 break; 217#ifdef INET6 218 case AF_INET6: 219 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 220 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 221 port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 222 port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 223 if (!(port1 == IPSEC_PORT_ANY || 224 port2 == IPSEC_PORT_ANY || 225 port1 == port2)) 226 return 1; 227 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 228 return 1; 229 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 230 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 231 return 1; 232 break; 233#endif 234 default: 235 return 1; 236 } 237 238 return 0; 239} 240 241/* 242 * compare two sockaddr with strict match on port. 243 * OUT: 0: equal. 244 * 1: not equal. 245 */ 246int 247cmpsaddrstrict(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2) 248{ 249 caddr_t sa1, sa2; 250 u_short port1, port2; 251 252 if (addr1 == 0 && addr2 == 0) 253 return 0; 254 if (addr1 == 0 || addr2 == 0) 255 return 1; 256 257 if (addr1->ss_len != addr2->ss_len 258 || addr1->ss_family != addr2->ss_family) 259 return 1; 260 261 switch (addr1->ss_family) { 262 case AF_INET: 263 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 264 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 265 port1 = ((struct sockaddr_in *)addr1)->sin_port; 266 port2 = ((struct sockaddr_in *)addr2)->sin_port; 267 if (port1 != port2) 268 return 1; 269 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 270 return 1; 271 break; 272#ifdef INET6 273 case AF_INET6: 274 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 275 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 276 port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 277 port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 278 if (port1 != port2) 279 return 1; 280 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 281 return 1; 282 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 283 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 284 return 1; 285 break; 286#endif 287 default: 288 return 1; 289 } 290 291 return 0; 292} 293 294/* 295 * compare two sockaddr with strict match on port using prefix. 296 * OUT: 0: equal. 297 * 1: not equal. 298 */ 299int 300cmpsaddrstrict_withprefix(const struct sockaddr_storage *addr1, const struct sockaddr_storage *addr2, int prefix) 301{ 302 u_short port1, port2; 303 u_int32_t mask; 304 int i; 305 306 if (addr1 == 0 && addr2 == 0) 307 return 0; 308 if (addr1 == 0 || addr2 == 0) 309 return 1; 310 311 if (addr1->ss_len != addr2->ss_len 312 || addr1->ss_family != addr2->ss_family) 313 return 1; 314 315 switch (addr1->ss_family) { 316 case AF_INET: 317 port1 = ((struct sockaddr_in *)addr1)->sin_port; 318 port2 = ((struct sockaddr_in *)addr2)->sin_port; 319 if (port1 != port2) 320 return 1; 321 mask = ~0; 322 mask <<= 32-prefix; 323 if ((((struct sockaddr_in *)addr1)->sin_addr.s_addr & htonl(mask)) != 324 (((struct sockaddr_in *)addr2)->sin_addr.s_addr & htonl(mask))) 325 return 1; 326 break; 327#ifdef INET6 328 case AF_INET6: 329 port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 330 port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 331 if (port1 != port2) 332 return 1; 333 for (i = 0; i < 4; i++) { 334 if (prefix >= 32) { 335 mask = ~0; 336 prefix -= 32; 337 } else if (prefix == 0) 338 mask = 0; 339 else { 340 mask = ~0; 341 mask <<= 32-prefix; 342 prefix = 0; 343 } 344 if ((((struct sockaddr_in6 *)addr1)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask)) != 345 (((struct sockaddr_in6 *)addr2)->sin6_addr.__u6_addr.__u6_addr32[i] & htonl(mask))) 346 return 1; 347 } 348 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 349 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 350 return 1; 351 break; 352#endif 353 default: 354 return 1; 355 } 356 357 return 0; 358} 359 360 361/* get local address against the destination. */ 362struct sockaddr_storage * 363getlocaladdr(struct sockaddr *remote) 364{ 365 struct sockaddr_storage *local; 366 u_int local_len = sizeof(struct sockaddr); 367 int s; /* for dummy connection */ 368 369 /* allocate buffer */ 370 if ((local = racoon_calloc(1, local_len)) == NULL) { 371 plog(ASL_LEVEL_ERR, 372 "failed to get address buffer.\n"); 373 goto err; 374 } 375 376 /* get real interface received packet */ 377 if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) { 378 plog(ASL_LEVEL_ERR, 379 "socket (%s)\n", strerror(errno)); 380 goto err; 381 } 382 383 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { 384 plog(ASL_LEVEL_ERR, "failed to put localaddr socket in non-blocking mode\n"); 385 } 386 387 setsockopt_bypass(s, remote->sa_family); 388 389 if (connect(s, remote, sysdep_sa_len(remote)) < 0) { 390 plog(ASL_LEVEL_ERR, 391 "connect (%s)\n", strerror(errno)); 392 close(s); 393 goto err; 394 } 395 396 if (getsockname(s, (struct sockaddr *)local, &local_len) < 0) { 397 plog(ASL_LEVEL_ERR, 398 "getsockname (%s)\n", strerror(errno)); 399 close(s); 400 return NULL; 401 } 402 403 close(s); 404 return local; 405 406 err: 407 if (local != NULL) 408 racoon_free(local); 409 return NULL; 410} 411 412/* 413 * Receive packet, with src/dst information. It is assumed that necessary 414 * setsockopt() have already performed on socket. 415 */ 416int 417recvfromto(int s, 418 void *buf, 419 size_t buflen, 420 int flags, 421 struct sockaddr_storage *from, 422 socklen_t *fromlen, 423 struct sockaddr_storage *to, 424 u_int *tolen) 425{ 426 int otolen; 427 ssize_t len; 428 struct sockaddr_storage ss; 429 struct msghdr m; 430 struct cmsghdr *cm, *cm_prev; 431 struct iovec iov[2]; 432 u_int32_t cmsgbuf[256/sizeof(u_int32_t)]; // Wcast-align fix - force 32 bit alignment 433#if defined(INET6) && defined(INET6_ADVAPI) 434 struct in6_pktinfo *pi; 435#endif /*INET6_ADVAPI*/ 436 struct sockaddr_in *sin; 437#ifdef INET6 438 struct sockaddr_in6 *sin6; 439#endif 440 441 len = sizeof(ss); 442 if (getsockname(s, (struct sockaddr *)&ss, (socklen_t*)&len) < 0) { 443 plog(ASL_LEVEL_ERR, 444 "getsockname (%s)\n", strerror(errno)); 445 return -1; 446 } 447 448 m.msg_name = (caddr_t)from; 449 m.msg_namelen = *fromlen; 450 iov[0].iov_base = (caddr_t)buf; 451 iov[0].iov_len = buflen; 452 m.msg_iov = iov; 453 m.msg_iovlen = 1; 454 memset(cmsgbuf, 0, sizeof(cmsgbuf)); 455 cm = (struct cmsghdr *)cmsgbuf; 456 m.msg_control = (caddr_t)cm; 457 m.msg_controllen = sizeof(cmsgbuf); 458 while ((len = recvmsg(s, &m, flags)) < 0) { 459 if (errno == EINTR) 460 continue; 461 plog(ASL_LEVEL_ERR, "recvmsg (%s)\n", strerror(errno)); 462 return -1; 463 } 464 if (len == 0) { 465 return 0; 466 } 467 *fromlen = m.msg_namelen; 468 469 otolen = *tolen; 470 *tolen = 0; 471 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m), cm_prev = NULL; 472 m.msg_controllen != 0 && cm && cm != cm_prev; 473 cm_prev = cm, cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) { 474#if 0 475 plog(ASL_LEVEL_ERR, 476 "cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type);) 477#endif 478#if defined(INET6) && defined(INET6_ADVAPI) 479 if (ss.ss_family == AF_INET6 480 && cm->cmsg_level == IPPROTO_IPV6 481 && cm->cmsg_type == IPV6_PKTINFO 482 && otolen >= sizeof(*sin6)) { 483 pi = ALIGNED_CAST(struct in6_pktinfo *)(CMSG_DATA(cm)); 484 *tolen = sizeof(*sin6); 485 sin6 = (struct sockaddr_in6 *)to; 486 memset(sin6, 0, sizeof(*sin6)); 487 sin6->sin6_family = AF_INET6; 488 sin6->sin6_len = sizeof(*sin6); 489 memcpy(&sin6->sin6_addr, &pi->ipi6_addr, 490 sizeof(sin6->sin6_addr)); 491 /* XXX other cases, such as site-local? */ 492 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 493 sin6->sin6_scope_id = pi->ipi6_ifindex; 494 else 495 sin6->sin6_scope_id = 0; 496 sin6->sin6_port = 497 ((struct sockaddr_in6 *)&ss)->sin6_port; 498 otolen = -1; /* "to" already set */ 499 continue; 500 } 501#endif 502#if defined(INET6) && defined(IPV6_RECVDSTADDR) 503 if (ss.ss_family == AF_INET6 504 && cm->cmsg_level == IPPROTO_IPV6 505 && cm->cmsg_type == IPV6_RECVDSTADDR 506 && otolen >= sizeof(*sin6)) { 507 *tolen = sizeof(*sin6); 508 sin6 = (struct sockaddr_in6 *)to; 509 memset(sin6, 0, sizeof(*sin6)); 510 sin6->sin6_family = AF_INET6; 511 sin6->sin6_len = sizeof(*sin6); 512 memcpy(&sin6->sin6_addr, CMSG_DATA(cm), 513 sizeof(sin6->sin6_addr)); 514 sin6->sin6_port = 515 ((struct sockaddr_in6 *)&ss)->sin6_port; 516 otolen = -1; /* "to" already set */ 517 continue; 518 } 519#endif 520 if (ss.ss_family == AF_INET 521 && cm->cmsg_level == IPPROTO_IP 522 && cm->cmsg_type == IP_RECVDSTADDR 523 && otolen >= sizeof(*sin)) { 524 *tolen = sizeof(*sin); 525 sin = (struct sockaddr_in *)to; 526 memset(sin, 0, sizeof(*sin)); 527 sin->sin_family = AF_INET; 528 sin->sin_len = sizeof(*sin); 529 memcpy(&sin->sin_addr, CMSG_DATA(cm), 530 sizeof(sin->sin_addr)); 531 sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port; 532 otolen = -1; /* "to" already set */ 533 continue; 534 } 535 } 536 plogdump(ASL_LEVEL_DEBUG, buf, buflen, "@@@@@@ data from readmsg:\n"); 537 return len; 538} 539 540/* send packet, with fixing src/dst address pair. */ 541int 542sendfromto(s, buf, buflen, src, dst, cnt) 543 int s, cnt; 544 const void *buf; 545 size_t buflen; 546 struct sockaddr_storage *src; 547 struct sockaddr_storage *dst; 548{ 549 struct sockaddr_storage ss; 550 int len; 551 int i; 552 553 if (src->ss_family != dst->ss_family) { 554 plog(ASL_LEVEL_ERR, 555 "address family mismatch\n"); 556 return -1; 557 } 558 559 len = sizeof(ss); 560 if (getsockname(s, (struct sockaddr *)&ss, (socklen_t*)&len) < 0) { 561 plog(ASL_LEVEL_ERR, 562 "getsockname (%s)\n", strerror(errno)); 563 return -1; 564 } 565 566 plog(ASL_LEVEL_DEBUG, 567 "sockname %s\n", saddr2str((struct sockaddr *)&ss)); 568 plog(ASL_LEVEL_DEBUG, 569 "send packet from %s\n", saddr2str((struct sockaddr *)src)); 570 plog(ASL_LEVEL_DEBUG, 571 "send packet to %s\n", saddr2str((struct sockaddr *)dst)); 572 573 if (src->ss_family != ss.ss_family) { 574 plog(ASL_LEVEL_ERR, 575 "address family mismatch\n"); 576 return -1; 577 } 578 579 switch (src->ss_family) { 580#if defined(INET6) && defined(INET6_ADVAPI) 581 case AF_INET6: 582 { 583 struct msghdr m; 584 struct cmsghdr *cm; 585 struct iovec iov[2]; 586 u_int32_t cmsgbuf[256/sizeof(u_int32_t)]; // Wcast-align fix - force 32 bit alignment 587 struct in6_pktinfo *pi; 588 int ifindex; 589 struct sockaddr_in6 src6, dst6; 590 591 memcpy(&src6, src, sizeof(src6)); 592 memcpy(&dst6, dst, sizeof(dst6)); 593 594 /* XXX take care of other cases, such as site-local */ 595 ifindex = 0; 596 if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr) 597 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) { 598 ifindex = src6.sin6_scope_id; /*???*/ 599 } 600 601 /* XXX some sanity check on dst6.sin6_scope_id */ 602 603 /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */ 604 src6.sin6_flowinfo = dst6.sin6_flowinfo = 0; 605 606 memset(&m, 0, sizeof(m)); 607 m.msg_name = (caddr_t)&dst6; 608 m.msg_namelen = sizeof(dst6); 609 iov[0].iov_base = (char *)buf; 610 iov[0].iov_len = buflen; 611 m.msg_iov = iov; 612 m.msg_iovlen = 1; 613 614 memset(cmsgbuf, 0, sizeof(cmsgbuf)); 615 cm = (struct cmsghdr *)cmsgbuf; 616 m.msg_control = (caddr_t)cm; 617 m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 618 619 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 620 cm->cmsg_level = IPPROTO_IPV6; 621 cm->cmsg_type = IPV6_PKTINFO; 622 pi = ALIGNED_CAST(struct in6_pktinfo *)CMSG_DATA(cm); 623 memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr)); 624 pi->ipi6_ifindex = ifindex; 625 626 plog(ASL_LEVEL_DEBUG, 627 "src6 %s %d\n", 628 saddr2str((struct sockaddr *)&src6), 629 src6.sin6_scope_id); 630 plog(ASL_LEVEL_DEBUG, 631 "dst6 %s %d\n", 632 saddr2str((struct sockaddr *)&dst6), 633 dst6.sin6_scope_id); 634 635 for (i = 0; i < cnt; i++) { 636 len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/); 637 if (len < 0) { 638 plog(ASL_LEVEL_ERR, 639 "sendmsg (%s)\n", strerror(errno)); 640 if (errno != EHOSTUNREACH && errno != ENETDOWN && errno != ENETUNREACH) { 641 return -1; 642 } 643 // <rdar://problem/6609744> treat these failures like 644 // packet loss, in case the network interface is flaky 645 len = 0; 646 } 647 plog(ASL_LEVEL_DEBUG, 648 "%d times of %d bytes message will be sent " 649 "to %s\n", 650 i + 1, len, saddr2str((struct sockaddr *)dst)); 651 } 652 653 return len; 654 } 655#endif 656 default: 657 { 658 int needclose = 0; 659 int sendsock; 660 661 if (ss.ss_family == src->ss_family && memcmp(&ss, src, sysdep_sa_len((struct sockaddr *)src)) == 0) { 662 sendsock = s; 663 needclose = 0; 664 } else { 665 int yes = 1; 666 /* 667 * Use newly opened socket for sending packets. 668 * NOTE: this is unsafe, because if the peer is quick enough 669 * the packet from the peer may be queued into sendsock. 670 * Better approach is to prepare bind'ed udp sockets for 671 * each of the interface addresses. 672 */ 673 sendsock = socket(src->ss_family, SOCK_DGRAM, 0); 674 if (sendsock < 0) { 675 plog(ASL_LEVEL_ERR, 676 "socket (%s)\n", strerror(errno)); 677 return -1; 678 } 679 if (fcntl(sendsock, F_SETFL, O_NONBLOCK) == -1) { 680 plog(ASL_LEVEL_ERR, "failed to put sendsock socket in non-blocking mode\n"); 681 } 682 if (setsockopt(sendsock, SOL_SOCKET, 683 SO_REUSEPORT, 684 (void *)&yes, sizeof(yes)) < 0) { 685 plog(ASL_LEVEL_ERR, 686 "setsockopt SO_REUSEPORT (%s)\n", 687 strerror(errno)); 688 close(sendsock); 689 return -1; 690 } 691#ifdef IPV6_USE_MIN_MTU 692 if (src->ss_family == AF_INET6 && 693 setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 694 (void *)&yes, sizeof(yes)) < 0) { 695 plog(ASL_LEVEL_ERR, 696 "setsockopt IPV6_USE_MIN_MTU (%s)\n", 697 strerror(errno)); 698 close(sendsock); 699 return -1; 700 } 701#endif 702 if (setsockopt_bypass(sendsock, src->ss_family) < 0) { 703 close(sendsock); 704 return -1; 705 } 706 707 if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len((struct sockaddr *)src)) < 0) { 708 plog(ASL_LEVEL_ERR, 709 "bind 1 (%s)\n", strerror(errno)); 710 close(sendsock); 711 return -1; 712 } 713 needclose = 1; 714 } 715 716 plogdump(ASL_LEVEL_DEBUG, (void*)buf, buflen, "@@@@@@ data being sent:\n"); 717 718 for (i = 0; i < cnt; i++) { 719 len = sendto(sendsock, buf, buflen, 0, (struct sockaddr *)dst, sysdep_sa_len((struct sockaddr *)dst)); 720 if (len < 0) { 721 plog(ASL_LEVEL_ERR, 722 "sendto (%s)\n", strerror(errno)); 723 if (errno != EHOSTUNREACH && errno != ENETDOWN && errno != ENETUNREACH) { 724 if (needclose) 725 close(sendsock); 726 return -1; 727 } 728 plog(ASL_LEVEL_ERR, 729 "treating socket error (%s) like packet loss\n", strerror(errno)); 730 // else treat these failures like a packet loss 731 len = 0; 732 } 733 plog(ASL_LEVEL_DEBUG, 734 "%d times of %d bytes message will be sent " 735 "to %s\n", 736 i + 1, len, saddr2str((struct sockaddr *)dst)); 737 } 738 //plog(ASL_LEVEL_DEBUG, "sent %d bytes", buflen); 739 740 if (needclose) 741 close(sendsock); 742 743 return len; 744 } 745 } 746} 747 748int 749setsockopt_bypass(int so, int family) 750{ 751 int level; 752 char *buf; 753 char *policy; 754 755 switch (family) { 756 case AF_INET: 757 level = IPPROTO_IP; 758 break; 759#ifdef INET6 760 case AF_INET6: 761 level = IPPROTO_IPV6; 762 break; 763#endif 764 default: 765 plog(ASL_LEVEL_ERR, 766 "unsupported address family %d\n", family); 767 return -1; 768 } 769 770 policy = "in bypass"; 771 buf = ipsec_set_policy(policy, strlen(policy)); 772 if (buf == NULL) { 773 plog(ASL_LEVEL_ERR, 774 "ipsec_set_policy (%s)\n", 775 ipsec_strerror()); 776 return -1; 777 } 778 if (setsockopt(so, level, 779 (level == IPPROTO_IP ? 780 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 781 buf, ipsec_get_policylen(buf)) < 0) { 782 plog(ASL_LEVEL_ERR, 783 "setsockopt IP_IPSEC_POLICY (%s)\n", 784 strerror(errno)); 785 return -1; 786 } 787 racoon_free(buf); 788 789 policy = "out bypass"; 790 buf = ipsec_set_policy(policy, strlen(policy)); 791 if (buf == NULL) { 792 plog(ASL_LEVEL_ERR, 793 "ipsec_set_policy (%s)\n", 794 ipsec_strerror()); 795 return -1; 796 } 797 if (setsockopt(so, level, 798 (level == IPPROTO_IP ? 799 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 800 buf, ipsec_get_policylen(buf)) < 0) { 801 plog(ASL_LEVEL_ERR, 802 "setsockopt IP_IPSEC_POLICY (%s)\n", 803 strerror(errno)); 804 return -1; 805 } 806 racoon_free(buf); 807 808 return 0; 809} 810 811struct sockaddr_storage * 812newsaddr(int len) 813{ 814 struct sockaddr_storage *new; 815 816 if ((new = racoon_calloc(1, sizeof(*new))) == NULL) { 817 plog(ASL_LEVEL_ERR, 818 "%s\n", strerror(errno)); 819 goto out; 820 } 821 /* initial */ 822 new->ss_len = len; 823out: 824 return new; 825} 826 827struct sockaddr_storage * 828dupsaddr(struct sockaddr_storage *addr) 829{ 830 struct sockaddr_storage *new; 831 832 new = racoon_calloc(1, sizeof(*new)); 833 if (new == NULL) { 834 plog(ASL_LEVEL_ERR, "%s\n", strerror(errno)); 835 return NULL; 836 } 837 838 memcpy(new, addr, addr->ss_len); 839 840 return new; 841} 842 843char * 844saddr2str(const struct sockaddr *saddr) 845{ 846 static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 847 char addr[NI_MAXHOST], port[NI_MAXSERV]; 848 849 if (saddr == NULL) { 850 buf[0] = '\0'; 851 return buf; 852 } 853 854 if (saddr->sa_family == AF_UNSPEC) 855 snprintf (buf, sizeof(buf), "%s", "anonymous"); 856 else { 857 GETNAMEINFO(saddr, addr, port); 858 snprintf(buf, sizeof(buf), "%s[%s]", addr, port); 859 } 860 861 return buf; 862} 863 864char * 865saddr2str_with_prefix(const struct sockaddr *saddr, int prefix) 866{ 867 static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 868 char addr[NI_MAXHOST], port[NI_MAXSERV]; 869 870 if (saddr == NULL) { 871 buf[0] = '\0'; 872 return buf; 873 } 874 875 if (saddr->sa_family == AF_UNSPEC) 876 snprintf (buf, sizeof(buf), "%s", "anonymous"); 877 else { 878 GETNAMEINFO(saddr, addr, port); 879 snprintf(buf, sizeof(buf), "%s/%d[%s]", addr, prefix, port); 880 } 881 882 return buf; 883} 884 885 886char * 887saddrwop2str(const struct sockaddr *saddr) 888{ 889 static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 890 char addr[NI_MAXHOST]; 891 892 if (saddr == NULL) { 893 buf[0] = '\0'; 894 return buf; 895 } 896 897 GETNAMEINFO_NULL(saddr, addr); 898 snprintf(buf, sizeof(buf), "%s", addr); 899 900 return buf; 901} 902 903char * 904naddrwop2str(const struct netaddr *naddr) 905{ 906 static char buf[NI_MAXHOST + 10]; 907 static const struct sockaddr sa_any; /* this is initialized to all zeros */ 908 909 if (naddr == NULL) { 910 buf[0] = '\0'; 911 return buf; 912 } 913 914 if (memcmp(&naddr->sa, &sa_any, sizeof(sa_any)) == 0) 915 snprintf(buf, sizeof(buf), "%s", "any"); 916 else { 917 snprintf(buf, sizeof(buf), "%s", saddrwop2str((struct sockaddr *)&naddr->sa.sa)); 918 snprintf(&buf[strlen(buf)], sizeof(buf) - strlen(buf), "/%ld", naddr->prefix); 919 } 920 return buf; 921} 922 923char * 924naddrwop2str_fromto(const char *format, const struct netaddr *saddr, 925 const struct netaddr *daddr) 926{ 927 static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100]; 928 char *src, *dst; 929 930 src = racoon_strdup(naddrwop2str(saddr)); 931 dst = racoon_strdup(naddrwop2str(daddr)); 932 STRDUP_FATAL(src); 933 STRDUP_FATAL(dst); 934 /* WARNING: Be careful about the format string! Don't 935 ever pass in something that a user can modify!!! */ 936 snprintf (buf, sizeof(buf), format, src, dst); 937 racoon_free (src); 938 racoon_free (dst); 939 940 return buf; 941} 942 943char * 944saddr2str_fromto(format, saddr, daddr) 945 const char *format; 946 const struct sockaddr *saddr; 947 const struct sockaddr *daddr; 948{ 949 static char buf[2*(NI_MAXHOST + NI_MAXSERV + 10) + 100]; 950 char *src, *dst; 951 952 if (saddr) { 953 src = racoon_strdup(saddr2str(saddr)); 954 STRDUP_FATAL(src); 955 } else { 956 src = NULL; 957 } 958 if (daddr) { 959 dst = racoon_strdup(saddr2str(daddr)); 960 STRDUP_FATAL(dst); 961 } else { 962 dst = NULL; 963 } 964 /* WARNING: Be careful about the format string! Don't 965 ever pass in something that a user can modify!!! */ 966 snprintf (buf, sizeof(buf), format, src? src:"[null]", dst? dst:"[null]"); 967 if (src) { 968 racoon_free (src); 969 } 970 if (dst) { 971 racoon_free (dst); 972 } 973 974 return buf; 975} 976 977struct sockaddr_storage * 978str2saddr(char *host, char *port) 979{ 980 struct addrinfo hints, *res; 981 struct sockaddr_storage *saddr; 982 int error; 983 984 memset(&hints, 0, sizeof(hints)); 985 hints.ai_family = PF_UNSPEC; 986 hints.ai_socktype = SOCK_DGRAM; 987 hints.ai_flags = AI_NUMERICHOST; 988 error = getaddrinfo(host, port, &hints, &res); 989 if (error != 0) { 990 plog(ASL_LEVEL_ERR, 991 "getaddrinfo(%s%s%s): %s\n", 992 host, port ? "," : "", port ? port : "", 993 gai_strerror(error)); 994 return NULL; 995 } 996 if (res->ai_next != NULL) { 997 plog(ASL_LEVEL_WARNING, 998 "getaddrinfo(%s%s%s): " 999 "resolved to multiple address, " 1000 "taking the first one\n", 1001 host, port ? "," : "", port ? port : ""); 1002 } 1003 saddr = newsaddr(sizeof(*saddr)); 1004 if (saddr == NULL) { 1005 plog(ASL_LEVEL_ERR, 1006 "failed to allocate buffer.\n"); 1007 freeaddrinfo(res); 1008 return NULL; 1009 } 1010 memcpy(saddr, res->ai_addr, res->ai_addrlen); 1011 freeaddrinfo(res); 1012 1013 return saddr; 1014} 1015 1016void 1017mask_sockaddr(a, b, l) 1018 struct sockaddr_storage *a; 1019 const struct sockaddr_storage *b; 1020 size_t l; 1021{ 1022 size_t i; 1023 u_int8_t *p, alen; 1024 1025 switch (b->ss_family) { 1026 case AF_INET: 1027 alen = sizeof(struct in_addr); 1028 p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr; 1029 break; 1030#ifdef INET6 1031 case AF_INET6: 1032 alen = sizeof(struct in6_addr); 1033 p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr; 1034 break; 1035#endif 1036 default: 1037 plog(ASL_LEVEL_ERR, 1038 "invalid address family: %d\n", b->ss_family); 1039 exit(1); 1040 } 1041 1042 if ((alen << 3) < l) { 1043 plog(ASL_LEVEL_ERR, 1044 "unexpected inconsistency: %d %zu\n", b->ss_family, l); 1045 exit(1); 1046 } 1047 1048 memcpy(a, b, sysdep_sa_len((struct sockaddr *)b)); 1049 p[l / 8] &= (0xff00 >> (l % 8)) & 0xff; 1050 for (i = l / 8 + 1; i < alen; i++) 1051 p[i] = 0x00; 1052} 1053 1054/* Compute a score describing how "accurate" a netaddr is for a given sockaddr. 1055 * Examples: 1056 * Return values for address 10.20.30.40 [port 500] and given netaddresses... 1057 * 10.10.0.0/16 => -1 ... doesn't match 1058 * 0.0.0.0/0 => 0 ... matches, but only 0 bits. 1059 * 10.20.0.0/16 => 16 ... 16 bits match 1060 * 10.20.30.0/24 => 24 ... guess what ;-) 1061 * 10.20.30.40/32 => 32 ... whole address match 1062 * 10.20.30.40:500 => 33 ... both address and port match 1063 * 10.20.30.40:501 => -1 ... port doesn't match and isn't 0 (=any) 1064 */ 1065int 1066naddr_score(const struct netaddr *naddr, const struct sockaddr_storage *saddr) 1067{ 1068 static const struct netaddr naddr_any; /* initialized to all-zeros */ 1069 struct sockaddr_storage sa; 1070 u_int16_t naddr_port, saddr_port; 1071 int port_score; 1072 1073 if (!naddr || !saddr) { 1074 plog(ASL_LEVEL_ERR, 1075 "Call with null args: naddr=%p, saddr=%p\n", 1076 naddr, saddr); 1077 return -1; 1078 } 1079 1080 /* Wildcard address matches, but only 0 bits. */ 1081 if (memcmp(naddr, &naddr_any, sizeof(naddr_any)) == 0) 1082 return 0; 1083 1084 /* If families don't match we really can't do much... */ 1085 if (naddr->sa.sa.ss_family != saddr->ss_family) 1086 return -1; 1087 1088 /* If port check fail don't bother to check addresses. */ 1089 naddr_port = extract_port(&naddr->sa.sa); 1090 saddr_port = extract_port(saddr); 1091 if (naddr_port == 0 || saddr_port == 0) /* wildcard match */ 1092 port_score = 0; 1093 else if (naddr_port == saddr_port) /* exact match */ 1094 port_score = 1; 1095 else /* mismatch :-) */ 1096 return -1; 1097 1098 /* Here it comes - compare network addresses. */ 1099 mask_sockaddr(&sa, saddr, naddr->prefix); 1100 if (loglevel >= ASL_LEVEL_DEBUG) { /* debug only */ 1101 char *a1, *a2, *a3; 1102 a1 = racoon_strdup(naddrwop2str(naddr)); 1103 a2 = racoon_strdup(saddrwop2str((struct sockaddr *)saddr)); 1104 a3 = racoon_strdup(saddrwop2str((struct sockaddr *)&sa)); 1105 STRDUP_FATAL(a1); 1106 STRDUP_FATAL(a2); 1107 STRDUP_FATAL(a3); 1108 plog(ASL_LEVEL_DEBUG, 1109 "naddr=%s, saddr=%s (masked=%s)\n", 1110 a1, a2, a3); 1111 free(a1); 1112 free(a2); 1113 free(a3); 1114 } 1115 if (cmpsaddrwop(&sa, &naddr->sa.sa) == 0) 1116 return naddr->prefix + port_score; 1117 1118 return -1; 1119} 1120 1121/* Some useful functions for sockaddr_storage port manipulations. */ 1122u_int16_t 1123extract_port (const struct sockaddr_storage *addr) 1124{ 1125 u_int16_t port = -1; 1126 1127 if (!addr) 1128 return port; 1129 1130 switch (addr->ss_family) { 1131 case AF_INET: 1132 port = ((struct sockaddr_in *)addr)->sin_port; 1133 break; 1134 case AF_INET6: 1135 port = ((struct sockaddr_in6 *)addr)->sin6_port; 1136 break; 1137 default: 1138 plog(ASL_LEVEL_ERR, "unknown AF: %u\n", addr->ss_family); 1139 break; 1140 } 1141 1142 return ntohs(port); 1143} 1144 1145u_int16_t * 1146get_port_ptr (struct sockaddr_storage *addr) 1147{ 1148 u_int16_t *port_ptr; 1149 1150 if (!addr) 1151 return NULL; 1152 1153 switch (addr->ss_family) { 1154 case AF_INET: 1155 port_ptr = &(((struct sockaddr_in *)addr)->sin_port); 1156 break; 1157 case AF_INET6: 1158 port_ptr = &(((struct sockaddr_in6 *)addr)->sin6_port); 1159 break; 1160 default: 1161 plog(ASL_LEVEL_ERR, "unknown AF: %u\n", addr->ss_family); 1162 return NULL; 1163 break; 1164 } 1165 1166 return port_ptr; 1167} 1168 1169u_int16_t * 1170set_port (struct sockaddr_storage *addr, u_int16_t new_port) 1171{ 1172 u_int16_t *port_ptr; 1173 1174 port_ptr = get_port_ptr (addr); 1175 1176 if (port_ptr) 1177 *port_ptr = htons(new_port); 1178 1179 return port_ptr; 1180} 1181