1/* 2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <string.h> 25#include <stdio.h> 26#include <sys/errno.h> 27#include <sys/signal.h> 28#include <sys/types.h> 29#include <sys/socket.h> 30#include <sys/stat.h> 31#include <sys/un.h> 32#include <unistd.h> 33#include <sys/param.h> 34#include <sys/fcntl.h> 35#include <CoreFoundation/CoreFoundation.h> 36#include <CoreFoundation/CFUserNotification.h> 37#include <SystemConfiguration/SystemConfiguration.h> 38#include <SystemConfiguration/SCPrivate.h> // for SCLog() 39#include <SystemConfiguration/SCPreferencesPathKey.h> 40#include <IOKit/pwr_mgt/IOPMLib.h> 41#include <IOKit/IOMessage.h> 42#include <mach/mach_time.h> 43#include <mach/task_special_ports.h> 44#include <mach/mach.h> 45#include <mach/message.h> 46#include <mach/boolean.h> 47#include <mach/mach_error.h> 48#include <mach/mach_time.h> 49#include <notify.h> 50#include <sys/sysctl.h> 51#include <ifaddrs.h> 52#include <SystemConfiguration/SCNetworkSignature.h> 53 54#include "scnc_mach_server.h" 55#include "scnc_main.h" 56#include "ppp_msg.h" 57#include "ppp_privmsg.h" 58#include "scnc_client.h" 59#include "ipsec_manager.h" 60#include "ppp_manager.h" 61#include "ppp_option.h" 62#include "ppp_socket_server.h" 63#include "scnc_utils.h" 64#include "if_ppplink.h" 65#include "PPPControllerPriv.h" 66#include "pppd.h" 67 68/* ----------------------------------------------------------------------------- 69 Declarations 70 ----------------------------------------------------------------------------- */ 71 72int racoon_send_cmd_start_dpd(int fd, u_int32_t address) ; 73 74 75static void 76startProbe (struct service *serv) 77{ 78 if (serv->type == TYPE_IPSEC) { 79 racoon_send_cmd_start_dpd(serv->u.ipsec.controlfd, 80 serv->u.ipsec.peer_address.sin_addr.s_addr); 81 serv->u.ipsec.awaiting_peer_resp = 1; 82 } 83} 84 85static const char * 86getPortMappingType (struct service *serv) 87{ 88 if (serv) { 89 switch (serv->type) { 90 case TYPE_IPSEC: return (const char *)"IPSec"; 91 } 92 } 93 94 return (const char *)"INVALID"; 95} 96 97static int 98isServiceConnected (struct service *serv) 99{ 100 switch (serv->type) { 101 case TYPE_IPSEC: return (serv->u.ipsec.phase != IPSEC_IDLE); 102 } 103 return 0; 104} 105 106static const char * 107getInterfaceName (struct service *serv) 108{ 109 if (serv) { 110 switch (serv->type) { 111 case TYPE_IPSEC: return (const char*)serv->u.ipsec.lower_interface; 112 } 113 } 114 return (const char *)"NULL"; 115} 116 117static u_int32_t 118getInterfaceNameSize (struct service *serv) 119{ 120 if (serv) { 121 switch (serv->type) { 122 case TYPE_IPSEC: return sizeof(serv->u.ipsec.lower_interface); 123 } 124 } 125 return 4; // "NULL" 126} 127 128static uint32_t 129getInterfaceIndex (struct service *serv) 130{ 131 const char *str = getInterfaceName(serv); 132 133 if (str) 134 return if_nametoindex(str); 135 return 0; 136} 137 138static void 139clearOnePortMapping (mdns_nat_mapping_t *mapping) 140{ 141 if (mapping) { 142 // what about mapping->mDNSRef_fd? 143 if (mapping->mDNSRef != NULL) { 144 DNSServiceRefDeallocate(mapping->mDNSRef); 145 } 146 bzero(mapping, sizeof(*mapping)); 147 } 148} 149 150static int 151ignorePortMappingUpdate (DNSServiceRef sdRef, 152 struct service *serv, 153 char *sd_name, 154 char *if_name, 155 uint32_t if_name_siz, 156 uint32_t interfaceIndex, 157 uint32_t publicAddress, 158 DNSServiceProtocol protocol, 159 uint16_t privatePort, 160 uint16_t publicPort) 161{ 162 int i = 0, vpn = 0, found = 0; 163 struct ifaddrs *ifap = NULL; 164 u_int8_t interfaceName[sizeof(serv->u.ipsec.lower_interface)]; 165 166 /* check if address still exist */ 167 if (getifaddrs(&ifap) == 0) { 168 struct ifaddrs *ifa; 169 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 170 if (ifa->ifa_name 171 && ifa->ifa_addr 172 && (!strncmp(ifa->ifa_name, "utun", 4) || !strncmp(ifa->ifa_name, "ppp", 3)) 173 && ifa->ifa_addr->sa_family == AF_INET 174 && (ALIGNED_CAST(struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == htonl(publicAddress)) { 175 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping update for %s ignored: related to VPN interface. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 176 sd_name, 177 ifa->ifa_name, 178 publicAddress, 179 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 180 privatePort, 181 publicPort); 182 vpn = 1; 183 } 184 if (ifa->ifa_name 185 && ifa->ifa_addr 186 && !strncmp(ifa->ifa_name, if_name, if_name_siz) 187 && ifa->ifa_addr->sa_family == AF_INET 188 && (ALIGNED_CAST(struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == serv->u.ipsec.our_address.sin_addr.s_addr) { 189 found = 1; 190 } 191 } 192 freeifaddrs(ifap); 193 } else { 194 SCLog(TRUE, LOG_ERR, CFSTR("%s port-mapping update for %s ignored: failed to get interface list."), 195 sd_name, 196 if_name); 197 return 1; 198 } 199 200 if (vpn) { 201 return 1; 202 } 203 204 if_indextoname(interfaceIndex, (char *)interfaceName); 205 if (!strncmp((const char *)interfaceName, (const char *)if_name, if_name_siz)) { 206 if (strstr(if_name, "ppp") || strstr(if_name, "utun")) { 207 // change on PPP interface... we don't care 208 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping update for %s ignored: underlying interface is PPP/VPN. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 209 sd_name, 210 if_name, 211 publicAddress, 212 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 213 privatePort, 214 publicPort); 215 return 1; 216 } else { 217 /* check if address still exist */ 218 if (found) { 219 return 0; 220 } else { 221 if (!publicAddress || (!publicPort && privatePort)) { 222 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping update for %s ignored: underlying interface down. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 223 sd_name, 224 if_name, 225 publicAddress, 226 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 227 privatePort, 228 publicPort); 229 for (i = 0; i < serv->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 230 if (serv->nat_mapping[i].mDNSRef_tmp == sdRef) { 231 serv->nat_mapping[i].up = 0; 232 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s flagged down because of no connectivity."), sd_name, if_name); 233 } 234 } 235 return 1; 236 } 237 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping update for %s ignored: underlying interface's address changed. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 238 sd_name, 239 if_name, 240 publicAddress, 241 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 242 privatePort, 243 publicPort); 244 return 1; 245 } 246 } 247 } else if (publicAddress && !publicPort && !privatePort && !protocol) { 248 // an update on the NAT's public IP 249 return 0; 250 } else { 251 // public interface disappeared? 252 if (!publicAddress && !publicPort && !privatePort && !protocol) { 253 return 0; 254 } 255 /* check if address still exist */ 256 if (serv->type == TYPE_IPSEC && serv->u.ipsec.our_address.sin_addr.s_addr == htonl(publicAddress) && found) { 257 return 0; 258 } 259 // change due to another interface, ignore for now 260 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping update for %s ignored: not for interface %s. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 261 sd_name, 262 interfaceName, 263 if_name, 264 publicAddress, 265 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 266 privatePort, 267 publicPort); 268 return 1; 269 } 270} 271 272#define FAR_FUTURE (60.0 * 60.0 * 24.0 * 365.0 * 1000.0) 273#define PUBLIC_NAT_PORT_MAPPING_TIMEOUT 20 274 275static void 276stop_public_nat_port_mapping_timer (struct service *serv) 277{ 278 if (serv->type == TYPE_IPSEC) { 279 if (serv->u.ipsec.port_mapping_timerref) { 280 CFRunLoopRemoveTimer(serv->u.ipsec.port_mapping_timerrun, serv->u.ipsec.port_mapping_timerref, kCFRunLoopCommonModes); 281 my_CFRelease(&serv->u.ipsec.port_mapping_timerref); 282 } 283 } 284} 285 286static void 287public_port_mapping_timeout (CFRunLoopTimerRef timer, void *info) 288{ 289 struct service *serv = info; 290 291 if (serv->type == TYPE_IPSEC) { 292 SCLog(TRUE, LOG_ERR, CFSTR("NAT's public interface down for more than %d secs... starting faster probe."), 293 PUBLIC_NAT_PORT_MAPPING_TIMEOUT); 294 startProbe(serv); 295 } 296} 297 298static void 299start_public_nat_port_mapping_timer (struct service *serv) 300{ 301 CFRunLoopTimerContext context = { 0, serv, NULL, NULL, NULL }; 302 303 if (serv->type == TYPE_IPSEC) { 304 if (serv->u.ipsec.interface_timerref || serv->u.ipsec.port_mapping_timerref) { 305 return; 306 } 307 308 SCLog(TRUE, LOG_INFO, CFSTR("starting wait-port-mapping timer for IPSec: %d secs"), PUBLIC_NAT_PORT_MAPPING_TIMEOUT); 309 serv->u.ipsec.port_mapping_timerref = CFRunLoopTimerCreate(NULL, CFAbsoluteTimeGetCurrent() + PUBLIC_NAT_PORT_MAPPING_TIMEOUT, FAR_FUTURE, 0, 0, public_port_mapping_timeout, &context); 310 if (!serv->u.ipsec.port_mapping_timerref) { 311 SCLog(TRUE, LOG_ERR, CFSTR("IPSec Controller: public interface down, cannot create RunLoop timer... starting faster probe.")); 312 startProbe(serv); 313 return; 314 } 315 CFRunLoopAddTimer(serv->u.ipsec.port_mapping_timerrun, serv->u.ipsec.port_mapping_timerref, kCFRunLoopCommonModes); 316 } 317} 318 319static void clearPortMapping (struct service *serv); 320 321static void 322setPortMappingCallback (DNSServiceRef sdRef, 323 DNSServiceFlags flags, 324 uint32_t interfaceIndex, 325 DNSServiceErrorType errorCode, 326 uint32_t nPublicAddress, /* four byte IPv4 address in network byte order */ 327 DNSServiceProtocol protocol, 328 uint16_t nPrivatePort, 329 uint16_t nPublicPort, /* may be different than the requested port */ 330 uint32_t ttl, /* may be different than the requested ttl */ 331 void *context) 332{ 333 uint32_t publicAddress = ntohl(nPublicAddress); 334 uint16_t privatePort = ntohs(nPrivatePort); 335 uint16_t publicPort = ntohs(nPublicPort); 336 int i; 337 struct service *serv = (__typeof__(serv))context; 338 const char *sd_name = getPortMappingType(serv); 339 int is_connected = isServiceConnected(serv); 340 const char *if_name = getInterfaceName(serv); 341 u_int32_t if_name_siz = getInterfaceNameSize(serv); 342 343 if (serv->u.ipsec.modecfg_defaultroute) { 344 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping update for %s ignored: VPN is the Primary interface. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d"), 345 sd_name, 346 if_name, 347 publicAddress, 348 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 349 privatePort, 350 publicPort); 351 clearPortMapping(serv); 352 return; 353 } 354 355 if (errorCode != kDNSServiceErr_NoError && errorCode != kDNSServiceErr_DoubleNAT) { 356 SCLog(TRUE, LOG_ERR, CFSTR("%s failed to set port-mapping for %s, errorCode: %d."), sd_name, if_name, errorCode); 357 if (errorCode == kDNSServiceErr_NATPortMappingUnsupported || errorCode == kDNSServiceErr_NATPortMappingDisabled) { 358 for (i = 0; i < serv->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 359 if (serv->nat_mapping[i].mDNSRef_tmp == sdRef) { 360 SCLog(TRUE, LOG_ERR, CFSTR("%s port-mapping for %s became invalid. is Connected: %d, Protocol: %s, Private Port: %d, Previous publicAddress: (%x), Previous publicPort: (%d)."), 361 sd_name, 362 if_name, 363 is_connected, 364 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 365 privatePort, 366 serv->nat_mapping[i].reflexive.addr, 367 serv->nat_mapping[i].reflexive.port); 368 if (serv->nat_mapping[i].up && is_connected) { 369 SCLog(TRUE, LOG_NOTICE, CFSTR("%s public port-mapping for %s changed... starting faster probe."), sd_name, if_name); 370 startProbe(serv); 371 } else { 372 clearPortMapping(serv); 373 } 374 return; 375 } 376 } 377 } else if (errorCode == kDNSServiceErr_ServiceNotRunning) { 378 clearPortMapping(serv); 379 } 380 return; 381 } 382 383 if (ignorePortMappingUpdate(sdRef, serv, (char *)sd_name, (char *)if_name, if_name_siz, interfaceIndex, publicAddress, protocol, privatePort, publicPort)) { 384 return; 385 } 386 387 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s, Protocol: %s, Private Port: %d, Public Address: %x, Public Port: %d, TTL: %d%s."), 388 sd_name, 389 if_name, 390 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 391 privatePort, 392 publicAddress, 393 publicPort, 394 ttl, 395 (errorCode == kDNSServiceErr_DoubleNAT)? " (Double NAT)" : "."); 396 397 // generate a disconnect if we were already connected and we just detected a change in publicAddress or publicPort 398 for (i = 0; i < serv->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 399 if (serv->nat_mapping[i].mDNSRef_tmp == sdRef) { 400 if (serv->nat_mapping[i].up && !publicAddress && !publicPort) { 401 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping for %s indicates public interface down. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 402 sd_name, 403 if_name, 404 publicAddress, 405 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 406 privatePort, 407 publicPort); 408 start_public_nat_port_mapping_timer(serv); 409 return; 410 } else if (serv->nat_mapping[i].up) { 411 stop_public_nat_port_mapping_timer(serv); 412 } 413 414 if (serv->type == TYPE_IPSEC && serv->u.ipsec.our_address.sin_addr.s_addr == htonl(publicAddress) && 415 privatePort == publicPort) { 416 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping update for %s indicates no NAT. Public Address: %x, Protocol: %s, Private Port: %d, Public Port: %d."), 417 sd_name, 418 if_name, 419 publicAddress, 420 (protocol == 0)? "None":((protocol == kDNSServiceProtocol_UDP)? "UDP":"TCP"), 421 privatePort, 422 publicPort); 423 } 424 425 if (serv->nat_mapping[i].interfaceIndex == interfaceIndex && 426 serv->nat_mapping[i].protocol == protocol && 427 serv->nat_mapping[i].privatePort == privatePort) { 428 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s consistent. is Connected: %d, interface: %d, protocol: %d, privatePort: %d."), 429 sd_name, if_name, is_connected, interfaceIndex, protocol, privatePort); 430 } else { 431 // inconsistency (mostly because of mdns api only works for the primary interface): TODO revise 432 if (serv->nat_mapping[i].interfaceIndex != interfaceIndex) { 433 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s inconsistent. is Connected: %d, Previous interface: %d, Current interface %d."), 434 sd_name, if_name, is_connected, serv->nat_mapping[i].interfaceIndex, interfaceIndex); 435 serv->nat_mapping[i].interfaceIndex = interfaceIndex; 436 } 437 if (serv->nat_mapping[i].protocol != protocol) { 438 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s inconsistent. is Connected: %d, Previous protocol: %x, Current protocol %x."), 439 sd_name, if_name, is_connected, serv->nat_mapping[i].protocol, protocol); 440 serv->nat_mapping[i].protocol = protocol; 441 } else if (serv->nat_mapping[i].privatePort != privatePort) { 442 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s inconsistent. is Connected: %d, Previous privatePort: %d, Current privatePort %d."), 443 sd_name, if_name, serv->nat_mapping[i].privatePort, privatePort); 444 serv->nat_mapping[i].privatePort = privatePort; 445 } 446 } 447 // is mapping up? 448 if (!serv->nat_mapping[i].up) { 449 if (serv->nat_mapping[i].reflexive.addr != publicAddress) { 450 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s initialized. is Connected: %d, Previous publicAddress: (%x), Current publicAddress %x."), 451 sd_name, if_name, is_connected, serv->nat_mapping[i].reflexive.addr, publicAddress); 452 serv->nat_mapping[i].reflexive.addr = publicAddress; 453 } 454 if (serv->nat_mapping[i].reflexive.port != publicPort) { 455 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s initialized. is Connected: %d, Previous publicPort: (%d), Current publicPort %d."), 456 sd_name, if_name, is_connected, serv->nat_mapping[i].reflexive.port, publicPort); 457 serv->nat_mapping[i].reflexive.port = publicPort; 458 } 459 if (serv->nat_mapping[i].reflexive.addr && 460 ((!privatePort && !serv->nat_mapping[i].reflexive.port) || (serv->nat_mapping[i].reflexive.port))) { 461 // flag up mapping 462 serv->nat_mapping[i].up = 1; 463 SCLog(TRUE, LOG_INFO, CFSTR("%s port-mapping for %s fully initialized. Flagging up."), sd_name, if_name); 464 } 465 return; 466 } 467 468 if (serv->nat_mapping[i].reflexive.addr != publicAddress) { 469 SCLog(TRUE, LOG_ERR, CFSTR("%s port-mapping for %s changed. is Connected: %d, Previous publicAddress: (%x), Current publicAddress %x."), 470 sd_name, if_name, is_connected, serv->nat_mapping[i].reflexive.addr, publicAddress); 471 if (is_connected) { 472 if (!privatePort || publicAddress) { 473 SCLog(TRUE, LOG_ERR, CFSTR("NAT's public address down or changed... starting faster probe.")); 474 startProbe(serv); 475 return; 476 } 477 // let function that handles (KEV_INET_NEW_ADDR || KEV_INET_CHANGED_ADDR || KEV_INET_ADDR_DELETED) deal with the connection 478 return; 479 } 480 serv->nat_mapping[i].reflexive.addr = publicAddress; 481 return; 482 } 483 if (serv->nat_mapping[i].reflexive.port != publicPort) { 484 SCLog(TRUE, LOG_ERR, CFSTR("%s port-mapping for %s changed. is Connected: %d, Previous publicPort: (%d), Current publicPort %d."), 485 sd_name, if_name, is_connected, serv->nat_mapping[i].reflexive.port, publicPort); 486 if (is_connected) { 487 if (!privatePort || publicPort) { 488 SCLog(TRUE, LOG_ERR, CFSTR("NAT's public port down or changed... starting faster probe.")); 489 startProbe(serv); 490 return; 491 } 492 // let function that handles (KEV_INET_NEW_ADDR || KEV_INET_CHANGED_ADDR || KEV_INET_ADDR_DELETED) deal with the connection 493 return; 494 } 495 serv->nat_mapping[i].reflexive.port = publicPort; 496 return; 497 } 498 if (errorCode == kDNSServiceErr_DoubleNAT) { 499 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping for %s hasn't changed, however there's a Double NAT. is Connected: %d."), 500 sd_name, if_name, is_connected); 501 } 502 return; 503 } 504 } 505 return; 506} 507 508static void 509clearPortMapping (struct service *serv) 510{ 511 int i; 512 const char *sd_name = getPortMappingType(serv); 513 const char *if_name = getInterfaceName(serv); 514 515 stop_public_nat_port_mapping_timer(serv); 516 517 if (!serv->nat_mapping_cnt) 518 return; 519 520 SCLog(TRUE, LOG_INFO, CFSTR("%s clearing port-mapping for %s."), sd_name, if_name); 521 522 for (i = 0; i < serv->nat_mapping_cnt && i < MDNS_NAT_MAPPING_MAX; i++) { 523 clearOnePortMapping(&serv->nat_mapping[i]); 524 } 525 serv->nat_mapping_cnt = 0; 526} 527 528static int 529setPortMapping (struct service *serv, 530 mdns_nat_mapping_t *mapping, 531 uint32_t interfaceIndex, 532 DNSServiceProtocol protocol, 533 uint16_t privatePort, 534 int probeOnly) 535{ 536 DNSServiceErrorType err = kDNSServiceErr_NoError; 537 uint16_t publicPort; 538 uint32_t ttl; 539 const char *sd_name = getPortMappingType(serv); 540 const char *if_name = getInterfaceName(serv); 541 542 if (mapping == NULL) { 543 SCLog(TRUE, LOG_ERR, CFSTR("%s invalid mapping pointer for %s."), sd_name, if_name); 544 return -1; 545 } 546 547 if (!probeOnly) { 548 publicPort = 0; 549 ttl = 2 * 3600; // 2 hours 550 } else { 551 publicPort = 0; 552 ttl = 0; 553 protocol = 0; 554 privatePort = 0; 555 interfaceIndex = 0; 556 } 557 558 if (mapping->mDNSRef == NULL) { 559 err = DNSServiceCreateConnection(&mapping->mDNSRef); 560 if (err != kDNSServiceErr_NoError || mapping->mDNSRef == NULL) { 561 SCLog(TRUE, LOG_ERR, CFSTR("%s Error calling DNSServiceCreateConnection for %s, error: %d."), sd_name, if_name, err); 562 clearOnePortMapping(mapping); 563 return -1; 564 } 565 err = DNSServiceSetDispatchQueue(mapping->mDNSRef, dispatch_get_current_queue()); 566 if (err != kDNSServiceErr_NoError) { 567 SCLog(TRUE, LOG_ERR, CFSTR("%s Error calling DNSServiceSetDispatchQueue for %s, error: %d."), sd_name, if_name, err); 568 clearOnePortMapping(mapping); 569 return -1; 570 } 571 if (!serv->u.ipsec.port_mapping_timerrun) { 572 serv->u.ipsec.port_mapping_timerrun = (__typeof__(serv->u.ipsec.port_mapping_timerrun))my_CFRetain(CFRunLoopGetCurrent()); 573 } 574 } 575 mapping->mDNSRef_tmp = mapping->mDNSRef; 576 err = DNSServiceNATPortMappingCreate(&mapping->mDNSRef_tmp, kDNSServiceFlagsShareConnection, interfaceIndex, protocol, htons(privatePort), publicPort, ttl, setPortMappingCallback, serv); 577 if (err != kDNSServiceErr_NoError) { 578 SCLog(TRUE, LOG_ERR, CFSTR("%s Error calling DNSServiceNATPortMappingCreate for %s, error: %d."), sd_name, if_name, err); 579 clearOnePortMapping(mapping); 580 return -1; 581 } 582 mapping->interfaceIndex = interfaceIndex; 583 mapping->protocol = protocol; 584 mapping->privatePort = privatePort; 585 bzero(&mapping->reflexive, sizeof(mapping->reflexive)); 586 587 SCLog(TRUE, LOG_INFO, CFSTR("%s set port-mapping for %s, interface: %d, protocol: %d, privatePort: %d."), sd_name, if_name, interfaceIndex, protocol, privatePort); 588 return 0; 589} 590 591static void 592ipsecSetPortMapping (struct service *serv) 593{ 594 const char *if_name = getInterfaceName(serv); 595 u_int32_t interfaceIndex = getInterfaceIndex(serv); 596 597 // exit early if interface is PPP/VPN 598 if (strstr(if_name, "ppp") || strstr(if_name, "utun")) { 599 return; 600 } 601 602 if (setPortMapping(serv, &serv->nat_mapping[0], interfaceIndex, 0, 0, 1) == 0) { 603 serv->nat_mapping_cnt++; 604 } 605#if 0 // <rdar://problem/8001582> 606 if (setPortMapping(serv, &serv->nat_mapping[1], interfaceIndex, kDNSServiceProtocol_UDP, (u_int16_t)500, 0) == 0) { 607 serv->nat_mapping_cnt++; 608 } 609 if (setPortMapping(serv, &serv->nat_mapping[2], interfaceIndex, kDNSServiceProtocol_UDP, (u_int16_t)4500, 0) == 0) { 610 serv->nat_mapping_cnt++; 611 } 612#endif 613} 614 615void 616nat_port_mapping_set (struct service *serv) 617{ 618 if (!serv) 619 return; 620 621 if (serv->u.ipsec.modecfg_defaultroute) { 622 const char *sd_name = getPortMappingType(serv); 623 const char *if_name = getInterfaceName(serv); 624 625 SCLog(TRUE, LOG_NOTICE, CFSTR("%s port-mapping API for %s ignored: VPN is the primary interface."), 626 sd_name, 627 if_name); 628 return; 629 } 630 631 if (serv->nat_mapping_cnt) { 632 clearPortMapping(serv); 633 } 634 635 switch (serv->type) { 636 case TYPE_PPP: break; 637 case TYPE_IPSEC: ipsecSetPortMapping(serv); break; 638 } 639} 640 641void 642nat_port_mapping_clear (struct service *serv) 643{ 644 if (!serv) 645 return; 646 647 clearPortMapping(serv); 648} 649