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