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