1/* 2 * Copyright (c) 2000-2008, 2010-2013 Apple 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/* 25 * Modification History 26 * 27 * December 3, 2002 Dieter Siegmund <dieter@apple.com> 28 * - handle the new KEV_INET_ARPCOLLISION event 29 * - format the event into a DynamicStore key 30 * State:/Network/Interface/ifname/IPv4Collision/ip_addr/hw_addr 31 * and send a notification on the key 32 * 33 * August 8, 2002 Allan Nathanson <ajn@apple.com> 34 * - added support for KEV_INET6_xxx events 35 * 36 * January 6, 2002 Jessica Vazquez <vazquez@apple.com> 37 * - added handling for KEV_ATALK_xxx events 38 * 39 * July 2, 2001 Dieter Siegmund <dieter@apple.com> 40 * - added handling for KEV_DL_PROTO_{ATTACHED, DETACHED} 41 * - mark an interface up if the number of protocols remaining is not 0, 42 * mark an interface down if the number is zero 43 * - allocate socket on demand instead of keeping it open all the time 44 * 45 * June 23, 2001 Allan Nathanson <ajn@apple.com> 46 * - update to public SystemConfiguration.framework APIs 47 * 48 * May 17, 2001 Allan Nathanson <ajn@apple.com> 49 * - add/maintain per-interface address/netmask/destaddr information 50 * in the dynamic store. 51 * 52 * June 30, 2000 Allan Nathanson <ajn@apple.com> 53 * - initial revision 54 */ 55 56#include "eventmon.h" 57#include "cache.h" 58#include "ev_dlil.h" 59#include "ev_ipv4.h" 60#include "ev_ipv6.h" 61#include <notify.h> 62 63// from ip_fw2.c 64#define KEV_LOG_SUBCLASS 10 65 66static const char *inetEventName[] = { 67 "", 68 "INET address added", 69 "INET address changed", 70 "INET address deleted", 71 "INET destination address changed", 72 "INET broadcast address changed", 73 "INET netmask changed", 74 "INET ARP collision", 75 "INET port in use", 76}; 77 78static const char *dlEventName[] = { 79 "", 80 "KEV_DL_SIFFLAGS", 81 "KEV_DL_SIFMETRICS", 82 "KEV_DL_SIFMTU", 83 "KEV_DL_SIFPHYS", 84 "KEV_DL_SIFMEDIA", 85 "KEV_DL_SIFGENERIC", 86 "KEV_DL_ADDMULTI", 87 "KEV_DL_DELMULTI", 88 "KEV_DL_IF_ATTACHED", 89 "KEV_DL_IF_DETACHING", 90 "KEV_DL_IF_DETACHED", 91 "KEV_DL_LINK_OFF", 92 "KEV_DL_LINK_ON", 93 "KEV_DL_PROTO_ATTACHED", 94 "KEV_DL_PROTO_DETACHED", 95 "KEV_DL_LINK_ADDRESS_CHANGED", 96 "KEV_DL_WAKEFLAGS_CHANGED", 97#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT 98 "KEV_DL_IF_IDLE_ROUTE_REFCNT", 99#endif 100#ifdef KEV_DL_IFCAP_CHANGED 101 "KEV_DL_IFCAP_CHANGED", 102#endif 103#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED 104 "KEV_DL_LINK_QUALITY_METRIC_CHANGED", 105#endif 106#ifdef KEV_DL_NODE_PRESENCE 107 "KEV_DL_NODE_PRESENCE" 108#endif 109#ifdef KEV_DL_NODE_ABSENCE 110 "KEV_DL_NODE_ABSENCE" 111#endif 112#ifdef KEV_DL_MASTER_ELECTED 113 "KEV_DL_MASTER_ELECTED" 114#endif 115#ifdef KEV_DL_ISSUES 116 "KEV_DL_ISSUES", 117#endif 118}; 119 120static const char *inet6EventName[] = { 121 "", 122 "KEV_INET6_NEW_USER_ADDR", 123 "KEV_INET6_CHANGED_ADDR", 124 "KEV_INET6_ADDR_DELETED", 125 "KEV_INET6_NEW_LL_ADDR", 126 "KEV_INET6_NEW_RTADV_ADDR", 127 "KEV_INET6_DEFROUTER" 128}; 129 130#ifdef KEV_ND6_SUBCLASS 131static const char *nd6EventNameString[] = { 132 "", 133 "KEV_ND6_RA" 134}; 135#endif // KEV_ND6_SUBCLASS 136 137__private_extern__ Boolean network_changed = FALSE; 138__private_extern__ SCDynamicStoreRef store = NULL; 139__private_extern__ Boolean _verbose = FALSE; 140 141__private_extern__ 142int 143dgram_socket(int domain) 144{ 145 return (socket(domain, SOCK_DGRAM, 0)); 146} 147 148static int 149ifflags_set(int s, char * name, short flags) 150{ 151 struct ifreq ifr; 152 int ret; 153 154 bzero(&ifr, sizeof(ifr)); 155 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 156 ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr); 157 if (ret == -1) { 158 return (ret); 159 } 160 ifr.ifr_flags |= flags; 161 return (ioctl(s, SIOCSIFFLAGS, &ifr)); 162} 163 164static int 165ifflags_clear(int s, char * name, short flags) 166{ 167 struct ifreq ifr; 168 int ret; 169 170 bzero(&ifr, sizeof(ifr)); 171 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 172 ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr); 173 if (ret == -1) { 174 return (ret); 175 } 176 ifr.ifr_flags &= ~flags; 177 return (ioctl(s, SIOCSIFFLAGS, &ifr)); 178} 179 180static void 181mark_if_up(char * name) 182{ 183 int s = dgram_socket(AF_INET); 184 if (s == -1) 185 return; 186 ifflags_set(s, name, IFF_UP); 187 close(s); 188} 189 190static void 191mark_if_down(char * name) 192{ 193 int s = dgram_socket(AF_INET); 194 if (s == -1) 195 return; 196 ifflags_clear(s, name, IFF_UP); 197 close(s); 198} 199 200static void 201post_network_changed(void) 202{ 203 if (network_changed) { 204 uint32_t status; 205 206 status = notify_post(_SC_NOTIFY_NETWORK_CHANGE); 207 if (status != NOTIFY_STATUS_OK) { 208 SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: error=%ld"), status); 209 } 210 211 network_changed = FALSE; 212 } 213 214 return; 215} 216 217static void 218logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg) 219{ 220 int i; 221 int j; 222 223 if (!_verbose) { 224 return; 225 } 226 227 SCLog(TRUE, LOG_DEBUG, CFSTR("%@ event:"), evStr); 228 SCLog(TRUE, LOG_DEBUG, 229 CFSTR(" Event size=%d, id=%d, vendor=%d, class=%d, subclass=%d, code=%d"), 230 ev_msg->total_size, 231 ev_msg->id, 232 ev_msg->vendor_code, 233 ev_msg->kev_class, 234 ev_msg->kev_subclass, 235 ev_msg->event_code); 236 for (i = 0, j = KEV_MSG_HEADER_SIZE; j < ev_msg->total_size; i++, j+=4) { 237 SCLog(TRUE, LOG_DEBUG, CFSTR(" Event data[%2d] = %08lx"), i, ev_msg->event_data[i]); 238 } 239} 240 241static const char * 242inetEventNameString(uint32_t event_code) 243{ 244 if (event_code < sizeof(inetEventName) / sizeof(inetEventName[0])) { 245 return (inetEventName[event_code]); 246 } 247 return ("New Apple network INET subcode"); 248} 249 250static const char * 251inet6EventNameString(uint32_t event_code) 252{ 253 if (event_code < sizeof(inet6EventName) / sizeof(inet6EventName[0])) { 254 return (inet6EventName[event_code]); 255 } 256 return ("New Apple network INET6 subcode"); 257} 258 259static const char * 260dlEventNameString(uint32_t event_code) 261{ 262 if (event_code < sizeof(dlEventName) / sizeof(dlEventName[0])) { 263 return (dlEventName[event_code]); 264 } 265 return ("New Apple network DL subcode"); 266} 267 268static void 269copy_if_name(struct net_event_data * ev, char * ifr_name, int ifr_len) 270{ 271 snprintf(ifr_name, ifr_len, "%s%d", ev->if_name, ev->if_unit); 272 return; 273} 274 275static uint8_t info_zero[DLIL_MODARGLEN]; 276 277static void 278processEvent_Apple_Network(struct kern_event_msg *ev_msg) 279{ 280 const char * eventName = NULL; 281 int dataLen = (ev_msg->total_size - KEV_MSG_HEADER_SIZE); 282 void * event_data = &ev_msg->event_data[0]; 283 Boolean handled = TRUE; 284 char ifr_name[IFNAMSIZ]; 285 286 switch (ev_msg->kev_subclass) { 287 case KEV_INET_SUBCLASS : { 288 eventName = inetEventNameString(ev_msg->event_code); 289 switch (ev_msg->event_code) { 290 case KEV_INET_NEW_ADDR : 291 case KEV_INET_CHANGED_ADDR : 292 case KEV_INET_ADDR_DELETED : 293 case KEV_INET_SIFDSTADDR : 294 case KEV_INET_SIFBRDADDR : 295 case KEV_INET_SIFNETMASK : { 296 struct kev_in_data * ev; 297 298 ev = (struct kev_in_data *)event_data; 299 if (dataLen < sizeof(*ev)) { 300 handled = FALSE; 301 break; 302 } 303 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name)); 304 interface_update_ipv4(NULL, ifr_name); 305 break; 306 } 307 case KEV_INET_ARPCOLLISION : { 308 struct kev_in_collision * ev; 309 310 ev = (struct kev_in_collision *)event_data; 311 if ((dataLen < sizeof(*ev)) 312 || (dataLen < (sizeof(*ev) + ev->hw_len))) { 313 handled = FALSE; 314 break; 315 } 316 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name)); 317 interface_collision_ipv4(ifr_name, 318 ev->ia_ipaddr, 319 ev->hw_len, 320 ev->hw_addr); 321 break; 322 } 323#if !TARGET_OS_IPHONE 324 case KEV_INET_PORTINUSE : { 325 struct kev_in_portinuse * ev; 326 ev = (struct kev_in_portinuse *)event_data; 327 if (dataLen < sizeof(*ev)) { 328 handled = FALSE; 329 break; 330 } 331 port_in_use_ipv4(ev->port, ev->req_pid); 332 break; 333 } 334#endif /* !TARGET_OS_IPHONE */ 335 default : 336 handled = FALSE; 337 break; 338 } 339 break; 340 } 341 case KEV_INET6_SUBCLASS : { 342 struct kev_in6_data * ev; 343 344 eventName = inet6EventNameString(ev_msg->event_code); 345 ev = (struct kev_in6_data *)event_data; 346 switch (ev_msg->event_code) { 347 case KEV_INET6_NEW_USER_ADDR : 348 case KEV_INET6_CHANGED_ADDR : 349 case KEV_INET6_ADDR_DELETED : 350 case KEV_INET6_NEW_LL_ADDR : 351 case KEV_INET6_NEW_RTADV_ADDR : 352 case KEV_INET6_DEFROUTER : 353 if (dataLen < sizeof(*ev)) { 354 handled = FALSE; 355 break; 356 } 357 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name)); 358 interface_update_ipv6(NULL, ifr_name); 359 break; 360 361 default : 362 handled = FALSE; 363 break; 364 } 365 break; 366 } 367 case KEV_DL_SUBCLASS : { 368 struct net_event_data * ev; 369 370 eventName = dlEventNameString(ev_msg->event_code); 371 ev = (struct net_event_data *)event_data; 372 switch (ev_msg->event_code) { 373 case KEV_DL_IF_ATTACHED : 374 /* 375 * new interface added 376 */ 377 if (dataLen < sizeof(*ev)) { 378 handled = FALSE; 379 break; 380 } 381 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 382 link_add(ifr_name); 383 break; 384 385 case KEV_DL_IF_DETACHED : 386 /* 387 * interface removed 388 */ 389 if (dataLen < sizeof(*ev)) { 390 handled = FALSE; 391 break; 392 } 393 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 394 link_remove(ifr_name); 395 break; 396 397 case KEV_DL_IF_DETACHING : 398 /* 399 * interface detaching 400 */ 401 if (dataLen < sizeof(*ev)) { 402 handled = FALSE; 403 break; 404 } 405 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 406 interface_detaching(ifr_name); 407 break; 408 409 case KEV_DL_PROTO_ATTACHED : 410 case KEV_DL_PROTO_DETACHED : { 411 struct kev_dl_proto_data * protoEvent; 412 413 protoEvent = (struct kev_dl_proto_data *)event_data; 414 if (dataLen < sizeof(*protoEvent)) { 415 handled = FALSE; 416 break; 417 } 418 copy_if_name(&protoEvent->link_data, 419 ifr_name, sizeof(ifr_name)); 420 if (protoEvent->proto_remaining_count == 0) { 421 mark_if_down(ifr_name); 422 } else { 423 mark_if_up(ifr_name); 424 } 425 break; 426 } 427 428#ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT 429 case KEV_DL_IF_IDLE_ROUTE_REFCNT: { 430 /* 431 * interface route refcnt idle 432 */ 433 if (dataLen < sizeof(*ev)) { 434 handled = FALSE; 435 break; 436 } 437 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 438 interface_update_idle_state(ifr_name); 439 break; 440 } 441#endif // KEV_DL_IF_IDLE_ROUTE_REFCNT 442 443 case KEV_DL_LINK_OFF : 444 case KEV_DL_LINK_ON : 445 /* 446 * update the link status in the store 447 */ 448 if (dataLen < sizeof(*ev)) { 449 handled = FALSE; 450 break; 451 } 452 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 453 link_update_status(ifr_name, FALSE); 454 break; 455 456#ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED 457 case KEV_DL_LINK_QUALITY_METRIC_CHANGED: { 458 struct kev_dl_link_quality_metric_data * lqm_data; 459 lqm_data = (struct kev_dl_link_quality_metric_data *) event_data; 460 461 if (dataLen < sizeof(*ev)) { 462 handled = FALSE; 463 break; 464 } 465 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 466 interface_update_quality_metric(ifr_name, 467 lqm_data->link_quality_metric); 468 break; 469 } 470#endif // KEV_DL_LINK_QUALITY_METRIC_CHANGED 471 472#ifdef KEV_DL_ISSUES 473 case KEV_DL_ISSUES: { 474 struct kev_dl_issues *issues; 475 476 issues = (struct kev_dl_issues *)event_data; 477 if (dataLen < sizeof(*ev)) { 478 handled = FALSE; 479 break; 480 } 481 copy_if_name(ev, ifr_name, sizeof(ifr_name)); 482 interface_update_link_issues(ifr_name, 483 issues->timestamp, 484 issues->modid, 485 DLIL_MODIDLEN, 486 issues->info, 487 (bcmp(issues->info, info_zero, DLIL_MODIDLEN) != 0) 488 ?DLIL_MODARGLEN 489 :0); 490 break; 491 } 492#endif // KEV_DL_ISSUES 493 494 case KEV_DL_SIFFLAGS : 495 case KEV_DL_SIFMETRICS : 496 case KEV_DL_SIFMTU : 497 case KEV_DL_SIFPHYS : 498 case KEV_DL_SIFMEDIA : 499 case KEV_DL_SIFGENERIC : 500 case KEV_DL_ADDMULTI : 501 case KEV_DL_DELMULTI : 502 case KEV_DL_LINK_ADDRESS_CHANGED : 503 case KEV_DL_WAKEFLAGS_CHANGED : 504#ifdef KEV_DL_IFCAP_CHANGED 505 case KEV_DL_IFCAP_CHANGED : 506#endif // KEV_DL_IFCAP_CHANGED 507 break; 508 509 default : 510 handled = FALSE; 511 break; 512 } 513 break; 514 } 515#ifdef KEV_ND6_SUBCLASS 516 case KEV_ND6_SUBCLASS : { 517 eventName = nd6EventNameString(ev_msg->event_code); 518 switch (ev_msg->event_code) { 519 case KEV_KEV_ND6_RA : 520 break; 521 522 default : 523 handled = FALSE; 524 break; 525 } 526 break; 527 } 528#endif // KEV_ND6_SUBCLASS 529 case KEV_LOG_SUBCLASS : { 530 break; 531 } 532 default : 533 handled = FALSE; 534 break; 535 } 536 537 if (handled == FALSE) { 538 CFStringRef evStr; 539 540 evStr = CFStringCreateWithCString(NULL, 541 (eventName != NULL) ? eventName : "New Apple network subclass", 542 kCFStringEncodingASCII); 543 logEvent(evStr, ev_msg); 544 CFRelease(evStr); 545 } 546 return; 547} 548 549static void 550eventCallback(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) 551{ 552 int so = CFSocketGetNative(s); 553 int status; 554 union { 555 char bytes[1024]; 556 struct kern_event_msg ev_msg1; // first kernel event 557 } buf; 558 struct kern_event_msg *ev_msg = &buf.ev_msg1; 559 int offset = 0; 560 561 status = recv(so, &buf, sizeof(buf), 0); 562 if (status == -1) { 563 SCLog(TRUE, LOG_ERR, CFSTR("recv() failed: %s"), strerror(errno)); 564 goto error; 565 } 566 567 cache_open(); 568 569 while (offset < status) { 570 if ((offset + ev_msg->total_size) > status) { 571 SCLog(TRUE, LOG_NOTICE, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough")); 572 break; 573 } 574 575 switch (ev_msg->vendor_code) { 576 case KEV_VENDOR_APPLE : 577 switch (ev_msg->kev_class) { 578 case KEV_NETWORK_CLASS : 579 processEvent_Apple_Network(ev_msg); 580 break; 581 case KEV_IOKIT_CLASS : 582 case KEV_SYSTEM_CLASS : 583 case KEV_APPLESHARE_CLASS : 584 case KEV_FIREWALL_CLASS : 585 case KEV_IEEE80211_CLASS : 586 break; 587 default : 588 /* unrecognized (Apple) event class */ 589 logEvent(CFSTR("New (Apple) class"), ev_msg); 590 break; 591 } 592 break; 593 default : 594 /* unrecognized vendor code */ 595 logEvent(CFSTR("New vendor"), ev_msg); 596 break; 597 } 598 offset += ev_msg->total_size; 599 ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset]; 600 } 601 602 cache_write(store); 603 cache_close(); 604 post_network_changed(); 605 606 return; 607 608 error : 609 610 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled.")); 611 CFSocketInvalidate(s); 612 return; 613 614} 615 616__private_extern__ 617void 618prime_KernelEventMonitor() 619{ 620 struct ifaddrs *ifap = NULL; 621 struct ifaddrs *scan; 622 int sock = -1; 623 624 SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called")); 625 626 cache_open(); 627 628 sock = dgram_socket(AF_INET); 629 if (sock == -1) { 630 SCLog(TRUE, LOG_ERR, CFSTR("could not get interface list, socket() failed: %s"), strerror(errno)); 631 goto done; 632 } 633 634 if (getifaddrs(&ifap) == -1) { 635 SCLog(TRUE, 636 LOG_ERR, 637 CFSTR("could not get interface info, getifaddrs() failed: %s"), 638 strerror(errno)); 639 goto done; 640 } 641 642 /* update list of interfaces & link status */ 643 for (scan = ifap; scan != NULL; scan = scan->ifa_next) { 644 if (scan->ifa_addr == NULL 645 || scan->ifa_addr->sa_family != AF_LINK) { 646 continue; 647 } 648 /* get the per-interface link/media information */ 649 link_add(scan->ifa_name); 650 } 651 652 /* 653 * update IPv4 network addresses already assigned to 654 * the interfaces. 655 */ 656 interface_update_ipv4(ifap, NULL); 657 658 /* 659 * update IPv6 network addresses already assigned to 660 * the interfaces. 661 */ 662 interface_update_ipv6(ifap, NULL); 663 664 freeifaddrs(ifap); 665 666 done: 667 if (sock != -1) 668 close(sock); 669 670 cache_write(store); 671 cache_close(); 672 673 network_changed = TRUE; 674 post_network_changed(); 675 676 return; 677} 678 679static CFStringRef 680kevSocketCopyDescription(const void *info) 681{ 682 return CFStringCreateWithFormat(NULL, NULL, CFSTR("<kernel event socket>")); 683} 684 685__private_extern__ 686void 687load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose) 688{ 689 CFSocketContext context = { 0 690 , (void *)1 691 , NULL 692 , NULL 693 , kevSocketCopyDescription 694 }; 695 CFSocketRef es; 696 struct kev_request kev_req; 697 CFRunLoopSourceRef rls; 698 int so; 699 int status; 700 701 if (bundleVerbose) { 702 _verbose = TRUE; 703 } 704 705 SCLog(_verbose, LOG_DEBUG, CFSTR("load() called")); 706 SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle)); 707 708 /* open a "configd" session to allow cache updates */ 709 store = SCDynamicStoreCreate(NULL, 710 CFSTR("Kernel Event Monitor plug-in"), 711 NULL, 712 NULL); 713 if (store == NULL) { 714 SCLog(TRUE, LOG_ERR, CFSTR("SCDnamicStoreCreate() failed: %s"), SCErrorString(SCError())); 715 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled.")); 716 return; 717 } 718 719 /* Open an event socket */ 720 so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT); 721 if (so != -1) { 722 /* establish filter to return events of interest */ 723 kev_req.vendor_code = KEV_VENDOR_APPLE; 724 kev_req.kev_class = KEV_NETWORK_CLASS; 725 kev_req.kev_subclass = KEV_ANY_SUBCLASS; 726 status = ioctl(so, SIOCSKEVFILT, &kev_req); 727 if (status) { 728 SCLog(TRUE, LOG_ERR, CFSTR("could not establish event filter, ioctl() failed: %s"), strerror(errno)); 729 (void) close(so); 730 so = -1; 731 } 732 } else { 733 SCLog(TRUE, LOG_ERR, CFSTR("could not open event socket, socket() failed: %s"), strerror(errno)); 734 } 735 736 if (so != -1) { 737 int yes = 1; 738 739 status = ioctl(so, FIONBIO, &yes); 740 if (status) { 741 SCLog(TRUE, LOG_ERR, CFSTR("could not set non-blocking io, ioctl() failed: %s"), strerror(errno)); 742 (void) close(so); 743 so = -1; 744 } 745 } 746 747 if (so == -1) { 748 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled.")); 749 CFRelease(store); 750 return; 751 } 752 753 /* Create a CFSocketRef for the PF_SYSTEM kernel event socket */ 754 es = CFSocketCreateWithNative(NULL, 755 so, 756 kCFSocketReadCallBack, 757 eventCallback, 758 &context); 759 760 /* Create and add a run loop source for the event socket */ 761 rls = CFSocketCreateRunLoopSource(NULL, es, 0); 762 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 763 CFRelease(rls); 764 CFRelease(es); 765 766 return; 767} 768 769#ifdef MAIN 770 771#include "ev_dlil.c" 772 773#define appendAddress appendAddress_v4 774#define getIF getIF_v4 775#define updateStore updateStore_v4 776#include "ev_ipv4.c" 777#undef appendAddress 778#undef getIF 779#undef updateStore 780 781#define appendAddress appendAddress_v6 782#define getIF getIF_v6 783#define updateStore updateStore_v6 784#include "ev_ipv6.c" 785#undef appendAddress 786#undef getIF 787#undef updateStore 788 789int 790main(int argc, char **argv) 791{ 792 _sc_log = FALSE; 793 _sc_verbose = (argc > 1) ? TRUE : FALSE; 794 795 load_KernelEventMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE); 796 prime_KernelEventMonitor(); 797 CFRunLoopRun(); 798 /* not reached */ 799 exit(0); 800 return 0; 801} 802#endif 803