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