1/* $KAME: sockmisc.c,v 1.36 2002/04/15 06:20:08 sakane 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 <sys/types.h> 33#include <sys/param.h> 34#include <sys/socket.h> 35#include <sys/uio.h> 36 37#include <netinet/in.h> 38#ifdef IPV6_INRIA_VERSION 39#include <netinet/ipsec.h> 40#else 41#include <netinet6/ipsec.h> 42#endif 43 44#include <stdlib.h> 45#include <stdio.h> 46#include <string.h> 47#include <errno.h> 48#ifdef HAVE_UNISTD_H 49#include <unistd.h> 50#endif 51 52#include "var.h" 53#include "misc.h" 54#include "plog.h" 55#include "sockmisc.h" 56#include "debug.h" 57#include "gcmalloc.h" 58#include "libipsec.h" 59 60const int niflags = 0; 61 62/* 63 * compare two sockaddr without port number. 64 * OUT: 0: equal. 65 * 1: not equal. 66 */ 67int 68cmpsaddrwop(addr1, addr2) 69 struct sockaddr *addr1; 70 struct sockaddr *addr2; 71{ 72 caddr_t sa1, sa2; 73 74 if (addr1 == 0 && addr2 == 0) 75 return 0; 76 if (addr1 == 0 || addr2 == 0) 77 return 1; 78 79#ifdef __linux__ 80 if (addr1->sa_family != addr2->sa_family) 81 return 1; 82#else 83 if (addr1->sa_len != addr2->sa_len 84 || addr1->sa_family != addr2->sa_family) 85 return 1; 86 87#endif /* __linux__ */ 88 89 switch (addr1->sa_family) { 90 case AF_INET: 91 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 92 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 93 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 94 return 1; 95 break; 96#ifdef INET6 97 case AF_INET6: 98 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 99 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 100 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 101 return 1; 102 if (((struct sockaddr_in6 *)addr1)->sin6_scope_id != 103 ((struct sockaddr_in6 *)addr2)->sin6_scope_id) 104 return 1; 105 break; 106#endif 107 default: 108 return 1; 109 } 110 111 return 0; 112} 113 114/* 115 * compare two sockaddr with port, taking care wildcard. 116 * addr1 is a subject address, addr2 is in a database entry. 117 * OUT: 0: equal. 118 * 1: not equal. 119 */ 120int 121cmpsaddrwild(addr1, addr2) 122 struct sockaddr *addr1; 123 struct sockaddr *addr2; 124{ 125 caddr_t sa1, sa2; 126 u_short port1, port2; 127 128 if (addr1 == 0 && addr2 == 0) 129 return 0; 130 if (addr1 == 0 || addr2 == 0) 131 return 1; 132 133#ifdef __linux__ 134 if (addr1->sa_family != addr2->sa_family) 135 return 1; 136#else 137 if (addr1->sa_len != addr2->sa_len 138 || addr1->sa_family != addr2->sa_family) 139 return 1; 140 141#endif /* __linux__ */ 142 143 switch (addr1->sa_family) { 144 case AF_INET: 145 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 146 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 147 port1 = ((struct sockaddr_in *)addr1)->sin_port; 148 port2 = ((struct sockaddr_in *)addr2)->sin_port; 149 if (!(port1 == IPSEC_PORT_ANY || 150 port2 == IPSEC_PORT_ANY || 151 port1 == port2)) 152 return 1; 153 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 154 return 1; 155 break; 156#ifdef INET6 157 case AF_INET6: 158 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 159 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 160 port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 161 port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 162 if (!(port1 == IPSEC_PORT_ANY || 163 port2 == IPSEC_PORT_ANY || 164 port1 == port2)) 165 return 1; 166 if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0) 167 return 1; 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 * compare two sockaddr with strict match on port. 182 * OUT: 0: equal. 183 * 1: not equal. 184 */ 185int 186cmpsaddrstrict(addr1, addr2) 187 struct sockaddr *addr1; 188 struct sockaddr *addr2; 189{ 190 caddr_t sa1, sa2; 191 u_short port1, port2; 192 193 if (addr1 == 0 && addr2 == 0) 194 return 0; 195 if (addr1 == 0 || addr2 == 0) 196 return 1; 197 198#ifdef __linux__ 199 if (addr1->sa_family != addr2->sa_family) 200 return 1; 201#else 202 if (addr1->sa_len != addr2->sa_len 203 || addr1->sa_family != addr2->sa_family) 204 return 1; 205 206#endif /* __linux__ */ 207 208 switch (addr1->sa_family) { 209 case AF_INET: 210 sa1 = (caddr_t)&((struct sockaddr_in *)addr1)->sin_addr; 211 sa2 = (caddr_t)&((struct sockaddr_in *)addr2)->sin_addr; 212 port1 = ((struct sockaddr_in *)addr1)->sin_port; 213 port2 = ((struct sockaddr_in *)addr2)->sin_port; 214 if (port1 != port2) 215 return 1; 216 if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0) 217 return 1; 218 break; 219#ifdef INET6 220 case AF_INET6: 221 sa1 = (caddr_t)&((struct sockaddr_in6 *)addr1)->sin6_addr; 222 sa2 = (caddr_t)&((struct sockaddr_in6 *)addr2)->sin6_addr; 223 port1 = ((struct sockaddr_in6 *)addr1)->sin6_port; 224 port2 = ((struct sockaddr_in6 *)addr2)->sin6_port; 225 if (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/* get local address against the destination. */ 242struct sockaddr * 243getlocaladdr(remote) 244 struct sockaddr *remote; 245{ 246 struct sockaddr *local; 247 int local_len = sizeof(struct sockaddr_storage); 248 int s; /* for dummy connection */ 249 250 /* allocate buffer */ 251 if ((local = racoon_calloc(1, local_len)) == NULL) { 252 plog(LLV_ERROR, LOCATION, NULL, 253 "failed to get address buffer.\n"); 254 goto err; 255 } 256 257 /* get real interface received packet */ 258 if ((s = socket(remote->sa_family, SOCK_DGRAM, 0)) < 0) { 259 plog(LLV_ERROR, LOCATION, NULL, 260 "socket (%s)\n", strerror(errno)); 261 goto err; 262 } 263 264 setsockopt_bypass(s, remote->sa_family); 265 266 if (connect(s, remote, sysdep_sa_len(remote)) < 0) { 267 plog(LLV_ERROR, LOCATION, NULL, 268 "connect (%s)\n", strerror(errno)); 269 close(s); 270 goto err; 271 } 272 273 if (getsockname(s, local, &local_len) < 0) { 274 plog(LLV_ERROR, LOCATION, NULL, 275 "getsockname (%s)\n", strerror(errno)); 276 close(s); 277 return NULL; 278 } 279 280 close(s); 281 return local; 282 283 err: 284 if (local != NULL) 285 racoon_free(local); 286 return NULL; 287} 288 289/* 290 * Receive packet, with src/dst information. It is assumed that necessary 291 * setsockopt() have already performed on socket. 292 */ 293int 294recvfromto(s, buf, buflen, flags, from, fromlen, to, tolen) 295 int s; 296 void *buf; 297 size_t buflen; 298 int flags; 299 struct sockaddr *from; 300 int *fromlen; 301 struct sockaddr *to; 302 int *tolen; 303{ 304 int otolen; 305 int len; 306 struct sockaddr_storage ss; 307 struct msghdr m; 308 struct cmsghdr *cm; 309 struct iovec iov[2]; 310 u_char cmsgbuf[256]; 311#if defined(INET6) && defined(ADVAPI) 312 struct in6_pktinfo *pi; 313#endif /*ADVAPI*/ 314 struct sockaddr_in *sin; 315#ifdef INET6 316 struct sockaddr_in6 *sin6; 317#endif 318 319 len = sizeof(ss); 320 if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) { 321 plog(LLV_ERROR, LOCATION, NULL, 322 "getsockname (%s)\n", strerror(errno)); 323 return -1; 324 } 325 326 m.msg_name = (caddr_t)from; 327 m.msg_namelen = *fromlen; 328 iov[0].iov_base = (caddr_t)buf; 329 iov[0].iov_len = buflen; 330 m.msg_iov = iov; 331 m.msg_iovlen = 1; 332 memset(cmsgbuf, 0, sizeof(cmsgbuf)); 333 cm = (struct cmsghdr *)cmsgbuf; 334 m.msg_control = (caddr_t)cm; 335 m.msg_controllen = sizeof(cmsgbuf); 336 if ((len = recvmsg(s, &m, flags)) < 0) { 337 plog(LLV_ERROR, LOCATION, NULL, 338 "recvmsg (%s)\n", strerror(errno)); 339 return -1; 340 } 341 *fromlen = m.msg_namelen; 342 343 otolen = *tolen; 344 *tolen = 0; 345 for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m); 346 m.msg_controllen != 0 && cm; 347 cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) { 348#if defined(INET6) && defined(ADVAPI) 349 if (ss.ss_family == AF_INET6 350 && cm->cmsg_level == IPPROTO_IPV6 351 && cm->cmsg_type == IPV6_PKTINFO 352 && otolen >= sizeof(*sin6)) { 353 pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); 354 *tolen = sizeof(*sin6); 355 sin6 = (struct sockaddr_in6 *)to; 356 memset(sin6, 0, sizeof(*sin6)); 357 sin6->sin6_family = AF_INET6; 358#ifndef __linux__ 359 sin6->sin6_len = sizeof(*sin6); 360#endif 361 memcpy(&sin6->sin6_addr, &pi->ipi6_addr, 362 sizeof(sin6->sin6_addr)); 363 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 364 sin6->sin6_scope_id = pi->ipi6_ifindex; 365 else 366 sin6->sin6_scope_id = 0; 367 sin6->sin6_port = 368 ((struct sockaddr_in6 *)&ss)->sin6_port; 369 otolen = -1; /* "to" already set */ 370 continue; 371 } 372#endif 373#ifdef __linux__ 374 if (ss.ss_family == AF_INET 375 && cm->cmsg_level == IPPROTO_IP 376 && cm->cmsg_type == IP_PKTINFO 377 && otolen >= sizeof(sin)) { 378 struct in_pktinfo *pi = (struct in_pktinfo *)(CMSG_DATA(cm)); 379 *tolen = sizeof(*sin); 380 sin = (struct sockaddr_in *)to; 381 memset(sin, 0, sizeof(*sin)); 382 sin->sin_family = AF_INET; 383 memcpy(&sin->sin_addr, &pi->ipi_addr, 384 sizeof(sin->sin_addr)); 385 sin->sin_port = 386 ((struct sockaddr_in *)&ss)->sin_port; 387 otolen = -1; /* "to" already set */ 388 continue; 389 } 390#endif 391#if defined(INET6) && defined(IPV6_RECVDSTADDR) 392 if (ss.ss_family == AF_INET6 393 && cm->cmsg_level == IPPROTO_IPV6 394 && cm->cmsg_type == IPV6_RECVDSTADDR 395 && otolen >= sizeof(*sin6)) { 396 *tolen = sizeof(*sin6); 397 sin6 = (struct sockaddr_in6 *)to; 398 memset(sin6, 0, sizeof(*sin6)); 399 sin6->sin6_family = AF_INET6; 400 sin6->sin6_len = sizeof(*sin6); 401 memcpy(&sin6->sin6_addr, CMSG_DATA(cm), 402 sizeof(sin6->sin6_addr)); 403 sin6->sin6_port = 404 ((struct sockaddr_in6 *)&ss)->sin6_port; 405 otolen = -1; /* "to" already set */ 406 continue; 407 } 408#endif 409#ifndef __linux__ 410 if (ss.ss_family == AF_INET 411 && cm->cmsg_level == IPPROTO_IP 412 && cm->cmsg_type == IP_RECVDSTADDR 413 && otolen >= sizeof(*sin)) { 414 *tolen = sizeof(*sin); 415 sin = (struct sockaddr_in *)to; 416 memset(sin, 0, sizeof(*sin)); 417 sin->sin_family = AF_INET; 418 sin->sin_len = sizeof(*sin); 419 memcpy(&sin->sin_addr, CMSG_DATA(cm), 420 sizeof(sin->sin_addr)); 421 sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port; 422 otolen = -1; /* "to" already set */ 423 continue; 424 } 425#endif 426 } 427 428 return len; 429} 430 431/* send packet, with fixing src/dst address pair. */ 432int 433sendfromto(s, buf, buflen, src, dst, cnt) 434 int s, cnt; 435 const void *buf; 436 size_t buflen; 437 struct sockaddr *src; 438 struct sockaddr *dst; 439{ 440 struct sockaddr_storage ss; 441 int len; 442 int i; 443 444 if (src->sa_family != dst->sa_family) { 445 plog(LLV_ERROR, LOCATION, NULL, 446 "address family mismatch\n"); 447 return -1; 448 } 449 450 len = sizeof(ss); 451 if (getsockname(s, (struct sockaddr *)&ss, &len) < 0) { 452 plog(LLV_ERROR, LOCATION, NULL, 453 "getsockname (%s)\n", strerror(errno)); 454 return -1; 455 } 456 457 plog(LLV_DEBUG, LOCATION, NULL, 458 "sockname %s\n", saddr2str((struct sockaddr *)&ss)); 459 plog(LLV_DEBUG, LOCATION, NULL, 460 "send packet from %s\n", saddr2str(src)); 461 plog(LLV_DEBUG, LOCATION, NULL, 462 "send packet to %s\n", saddr2str(dst)); 463 464 if (src->sa_family != ss.ss_family) { 465 plog(LLV_ERROR, LOCATION, NULL, 466 "address family mismatch\n"); 467 return -1; 468 } 469 470 switch (src->sa_family) { 471#if defined(INET6) && defined(ADVAPI) && !defined(IPV6_INRIA_VERSION) 472 case AF_INET6: 473 { 474 struct msghdr m; 475 struct cmsghdr *cm; 476 struct iovec iov[2]; 477 u_char cmsgbuf[256]; 478 struct in6_pktinfo *pi; 479 int ifindex; 480 struct sockaddr_in6 src6, dst6; 481 482 memcpy(&src6, src, sizeof(src6)); 483 memcpy(&dst6, dst, sizeof(dst6)); 484 485 ifindex = 0; 486 if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr) 487 || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) { 488 ifindex = src6.sin6_scope_id; /*???*/ 489 } 490 491 492 /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */ 493 src6.sin6_flowinfo = dst6.sin6_flowinfo = 0; 494 495 memset(&m, 0, sizeof(m)); 496 m.msg_name = (caddr_t)&dst6; 497 m.msg_namelen = sizeof(dst6); 498 iov[0].iov_base = (char *)buf; 499 iov[0].iov_len = buflen; 500 m.msg_iov = iov; 501 m.msg_iovlen = 1; 502 503 memset(cmsgbuf, 0, sizeof(cmsgbuf)); 504 cm = (struct cmsghdr *)cmsgbuf; 505 m.msg_control = (caddr_t)cm; 506 m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); 507 508 cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 509 cm->cmsg_level = IPPROTO_IPV6; 510 cm->cmsg_type = IPV6_PKTINFO; 511 pi = (struct in6_pktinfo *)CMSG_DATA(cm); 512 memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr)); 513 pi->ipi6_ifindex = ifindex; 514 515 plog(LLV_DEBUG, LOCATION, NULL, 516 "src6 %s %d\n", 517 saddr2str((struct sockaddr *)&src6), 518 src6.sin6_scope_id); 519 plog(LLV_DEBUG, LOCATION, NULL, 520 "dst6 %s %d\n", 521 saddr2str((struct sockaddr *)&dst6), 522 dst6.sin6_scope_id); 523 524 for (i = 0; i < cnt; i++) { 525 len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/); 526 if (len < 0) { 527 plog(LLV_ERROR, LOCATION, NULL, 528 "sendmsg (%s)\n", strerror(errno)); 529 return -1; 530 } 531 plog(LLV_DEBUG, LOCATION, NULL, 532 "%d times of %d bytes message will be sent " 533 "to %s\n", 534 i + 1, len, saddr2str(src)); 535 } 536 plogdump(LLV_DEBUG, (char *)buf, buflen); 537 538 return len; 539 } 540#endif 541 case AF_INET: 542 { 543 struct msghdr m; 544 struct cmsghdr *cm; 545 struct iovec iov[2]; 546 u_char cmsgbuf[256]; 547 struct in_pktinfo *pi; 548 int ifindex = 0; 549 struct sockaddr_in src6, dst6; 550 551 memcpy(&src6, src, sizeof(src6)); 552 memcpy(&dst6, dst, sizeof(dst6)); 553 554 memset(&m, 0, sizeof(m)); 555 m.msg_name = (caddr_t)&dst6; 556 m.msg_namelen = sizeof(dst6); 557 iov[0].iov_base = (char *)buf; 558 iov[0].iov_len = buflen; 559 m.msg_iov = iov; 560 m.msg_iovlen = 1; 561 562 memset(cmsgbuf, 0, sizeof(cmsgbuf)); 563 cm = (struct cmsghdr *)cmsgbuf; 564 m.msg_control = (caddr_t)cm; 565 m.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo)); 566 567 cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 568 cm->cmsg_level = IPPROTO_IP; 569 cm->cmsg_type = IP_PKTINFO; 570 pi = (struct in_pktinfo *)CMSG_DATA(cm); 571 memcpy(&pi->ipi_addr, &src6.sin_addr, sizeof(src6.sin_addr)); 572 pi->ipi_ifindex = ifindex; 573 574 plog(LLV_DEBUG, LOCATION, NULL, 575 "src4 %s\n", 576 saddr2str((struct sockaddr *)&src6)); 577 plog(LLV_DEBUG, LOCATION, NULL, 578 "dst4 %s\n", 579 saddr2str((struct sockaddr *)&dst6)); 580 581 for (i = 0; i < cnt; i++) { 582 len = sendmsg(s, &m, 0 /*MSG_DONTROUTE*/); 583 if (len < 0) { 584 plog(LLV_ERROR, LOCATION, NULL, 585 "sendmsg (%s)\n", strerror(errno)); 586 return -1; 587 } 588 plog(LLV_DEBUG, LOCATION, NULL, 589 "%d times of %d bytes message will be sent " 590 "to %s\n", 591 i + 1, len, saddr2str(src)); 592 } 593 plogdump(LLV_DEBUG, (char *)buf, buflen); 594 595 return len; 596 } 597 default: 598 { 599 int needclose = 0; 600 int sendsock; 601 602 if (ss.ss_family == src->sa_family && memcmp(&ss, src, sysdep_sa_len(src)) == 0) { 603 sendsock = s; 604 needclose = 0; 605 } else { 606 int yes = 1; 607 /* 608 * Use newly opened socket for sending packets. 609 * NOTE: this is unsafe, because if the peer is quick enough 610 * the packet from the peer may be queued into sendsock. 611 * Better approach is to prepare bind'ed udp sockets for 612 * each of the interface addresses. 613 */ 614 sendsock = socket(src->sa_family, SOCK_DGRAM, 0); 615 if (sendsock < 0) { 616 plog(LLV_ERROR, LOCATION, NULL, 617 "socket (%s)\n", strerror(errno)); 618 return -1; 619 } 620#ifndef __linux__ 621 if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEPORT, 622 (void *)&yes, sizeof(yes)) < 0) { 623 plog(LLV_ERROR, LOCATION, NULL, 624 "setsockopt (%s)\n", strerror(errno)); 625 close(sendsock); 626 return -1; 627 } 628#else 629 if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEADDR, 630 (void *)&yes, sizeof(yes)) < 0) { 631 plog(LLV_ERROR, LOCATION, NULL, 632 "setsockopt (%s)\n", strerror(errno)); 633 close(sendsock); 634 return -1; 635 } 636#endif 637#ifdef IPV6_USE_MIN_MTU 638 if (src->sa_family == AF_INET6 && 639 setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, 640 (void *)&yes, sizeof(yes)) < 0) { 641 plog(LLV_ERROR, LOCATION, NULL, 642 "setsockopt (%s)\n", strerror(errno)); 643 close(sendsock); 644 return -1; 645 } 646#endif 647 if (setsockopt_bypass(sendsock, src->sa_family) < 0) { 648 close(sendsock); 649 return -1; 650 } 651 652 if (bind(sendsock, (struct sockaddr *)src, sysdep_sa_len(src)) < 0) { 653 plog(LLV_ERROR, LOCATION, NULL, 654 "bind 1 (%s)\n", strerror(errno)); 655 close(sendsock); 656 return -1; 657 } 658 needclose = 1; 659 } 660 661 for (i = 0; i < cnt; i++) { 662 len = sendto(sendsock, buf, buflen, 0, dst, sysdep_sa_len(dst)); 663 if (len < 0) { 664 plog(LLV_ERROR, LOCATION, NULL, 665 "sendto (%s)\n", strerror(errno)); 666 if (needclose) 667 close(sendsock); 668 return len; 669 } 670 plog(LLV_DEBUG, LOCATION, NULL, 671 "%d times of %d bytes message will be sent " 672 "to %s\n", 673 i + 1, len, saddr2str(src)); 674 } 675 plogdump(LLV_DEBUG, (char *)buf, buflen); 676 677 if (needclose) 678 close(sendsock); 679 680 return len; 681 } 682 } 683} 684 685int 686setsockopt_bypass(so, family) 687 int so, family; 688{ 689 int level; 690 char *buf; 691 char *policy; 692 693 switch (family) { 694 case AF_INET: 695 level = IPPROTO_IP; 696 break; 697#ifdef INET6 698 case AF_INET6: 699 level = IPPROTO_IPV6; 700 break; 701#endif 702 default: 703 plog(LLV_ERROR, LOCATION, NULL, 704 "unsupported address family %d\n", family); 705 return -1; 706 } 707 708#ifndef IPV6_IPSEC_POLICY 709#define IPV6_IPSEC_POLICY IP_IPSEC_POLICY 710#endif 711 712 policy = "in bypass"; 713 buf = ipsec_set_policy(policy, strlen(policy)); 714 if (buf == NULL) { 715 plog(LLV_ERROR, LOCATION, NULL, 716 "ipsec_set_policy (%s)\n", 717 ipsec_strerror()); 718 return -1; 719 } 720 if (setsockopt(so, level, 721 (level == IPPROTO_IP ? 722 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 723 buf, ipsec_get_policylen(buf)) < 0) { 724 plog(LLV_ERROR, LOCATION, NULL, 725 "setsockopt (%s)\n", 726 strerror(errno)); 727 return -1; 728 } 729 racoon_free(buf); 730 731 policy = "out bypass"; 732 buf = ipsec_set_policy(policy, strlen(policy)); 733 if (buf == NULL) { 734 plog(LLV_ERROR, LOCATION, NULL, 735 "ipsec_set_policy (%s)\n", 736 ipsec_strerror()); 737 return -1; 738 } 739 if (setsockopt(so, level, 740 (level == IPPROTO_IP ? 741 IP_IPSEC_POLICY : IPV6_IPSEC_POLICY), 742 buf, ipsec_get_policylen(buf)) < 0) { 743 plog(LLV_ERROR, LOCATION, NULL, 744 "setsockopt (%s)\n", 745 strerror(errno)); 746 return -1; 747 } 748 racoon_free(buf); 749 750 return 0; 751} 752 753struct sockaddr * 754newsaddr(len) 755 int len; 756{ 757 struct sockaddr *new; 758 759 new = racoon_calloc(1, len); 760 if (new == NULL) 761 plog(LLV_ERROR, LOCATION, NULL, 762 "%s\n", strerror(errno)); 763 764#ifdef __linux__ 765 if (len == sizeof (struct sockaddr_in6)) 766 new->sa_family = AF_INET6; 767 else 768 new->sa_family = AF_INET; 769#else 770 /* initial */ 771 new->sa_len = len; 772#endif 773 774 return new; 775} 776 777struct sockaddr * 778dupsaddr(src) 779 struct sockaddr *src; 780{ 781 struct sockaddr *dst; 782 783 dst = racoon_calloc(1, sysdep_sa_len(src)); 784 if (dst == NULL) { 785 plog(LLV_ERROR, LOCATION, NULL, 786 "%s\n", strerror(errno)); 787 return NULL; 788 } 789 790 memcpy(dst, src, sysdep_sa_len(src)); 791 792 return dst; 793} 794 795char * 796saddr2str(saddr) 797 const struct sockaddr *saddr; 798{ 799 static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 800 char addr[NI_MAXHOST], port[NI_MAXSERV]; 801 802 if (saddr == NULL) 803 return NULL; 804 805 GETNAMEINFO(saddr, addr, port); 806 snprintf(buf, sizeof(buf), "%s[%s]", addr, port); 807 808 return buf; 809} 810 811char * 812saddrwop2str(saddr) 813 struct sockaddr *saddr; 814{ 815 static char buf[NI_MAXHOST + NI_MAXSERV + 10]; 816 char addr[NI_MAXHOST]; 817 818 if (saddr == NULL) 819 return NULL; 820 821 GETNAMEINFO(saddr, addr, NULL); 822 snprintf(buf, sizeof(buf), "%s", addr); 823 824 return buf; 825} 826 827struct sockaddr * 828str2saddr(host, port) 829 char *host; 830 char *port; 831{ 832 struct addrinfo hints, *res; 833 struct sockaddr *saddr; 834 int error; 835 836 memset(&hints, 0, sizeof(hints)); 837 hints.ai_family = PF_UNSPEC; 838 hints.ai_socktype = SOCK_DGRAM; 839 hints.ai_flags = AI_NUMERICHOST; 840 error = getaddrinfo(host, port, &hints, &res); 841 if (error != 0) { 842 plog(LLV_ERROR, LOCATION, NULL, 843 "getaddrinfo(%s%s%s): %s", 844 host, port ? "," : "", port ? port : "", 845 gai_strerror(error)); 846 return NULL; 847 } 848 if (res->ai_next != NULL) { 849 plog(LLV_ERROR, LOCATION, NULL, 850 "getaddrinfo(%s%s%s): " 851 "resolved to multiple address, " 852 "taking the first one", 853 host, port ? "," : "", port ? port : ""); 854 } 855 saddr = racoon_malloc(res->ai_addrlen); 856 if (saddr == NULL) { 857 plog(LLV_ERROR, LOCATION, NULL, 858 "failed to allocate buffer.\n"); 859 freeaddrinfo(res); 860 return NULL; 861 } 862 memcpy(saddr, res->ai_addr, res->ai_addrlen); 863 864 return saddr; 865} 866 867void 868mask_sockaddr(a, b, l) 869 struct sockaddr *a; 870 const struct sockaddr *b; 871 size_t l; 872{ 873 size_t i; 874 u_int8_t *p, alen; 875 876 switch (b->sa_family) { 877 case AF_INET: 878 alen = sizeof(struct in_addr); 879 p = (u_int8_t *)&((struct sockaddr_in *)a)->sin_addr; 880 break; 881#ifdef INET6 882 case AF_INET6: 883 alen = sizeof(struct in6_addr); 884 p = (u_int8_t *)&((struct sockaddr_in6 *)a)->sin6_addr; 885 break; 886#endif 887 default: 888 plog(LLV_ERROR, LOCATION, NULL, 889 "invalid family: %d\n", b->sa_family); 890 exit(1); 891 } 892 893 if ((alen << 3) < l) { 894 plog(LLV_ERROR, LOCATION, NULL, 895 "unexpected inconsistency: %d %d\n", b->sa_family, l); 896 exit(1); 897 } 898 899 memcpy(a, b, sysdep_sa_len(b)); 900 p[l / 8] &= (0xff00 >> (l % 8)) & 0xff; 901 for (i = l / 8 + 1; i < alen; i++) 902 p[i] = 0x00; 903} 904