]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/eventmon.c
configd-699.30.1.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / eventmon.c
1 /*
2 * Copyright (c) 2000-2014 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
66 static 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
78 static 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 #ifdef KEV_DL_IFDELEGATE_CHANGED
119 "KEV_DL_IFDELEGATE_CHANGED",
120 #endif
121 };
122
123 static const char *inet6EventName[] = {
124 "",
125 "KEV_INET6_NEW_USER_ADDR",
126 "KEV_INET6_CHANGED_ADDR",
127 "KEV_INET6_ADDR_DELETED",
128 "KEV_INET6_NEW_LL_ADDR",
129 "KEV_INET6_NEW_RTADV_ADDR",
130 "KEV_INET6_DEFROUTER"
131 };
132
133 #ifdef KEV_ND6_SUBCLASS
134 static const char *nd6EventNameString[] = {
135 "",
136 "KEV_ND6_RA"
137 };
138 #endif // KEV_ND6_SUBCLASS
139
140 static dispatch_queue_t S_kev_queue;
141 static dispatch_source_t S_kev_source;
142 __private_extern__ Boolean network_changed = FALSE;
143 __private_extern__ SCDynamicStoreRef store = NULL;
144 __private_extern__ Boolean _verbose = FALSE;
145
146 __private_extern__
147 int
148 dgram_socket(int domain)
149 {
150 return (socket(domain, SOCK_DGRAM, 0));
151 }
152
153 static int
154 ifflags_set(int s, char * name, short flags)
155 {
156 struct ifreq ifr;
157 int ret;
158
159 bzero(&ifr, sizeof(ifr));
160 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
161 ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
162 if (ret == -1) {
163 return (ret);
164 }
165 ifr.ifr_flags |= flags;
166 return (ioctl(s, SIOCSIFFLAGS, &ifr));
167 }
168
169 static int
170 ifflags_clear(int s, char * name, short flags)
171 {
172 struct ifreq ifr;
173 int ret;
174
175 bzero(&ifr, sizeof(ifr));
176 strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
177 ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
178 if (ret == -1) {
179 return (ret);
180 }
181 ifr.ifr_flags &= ~flags;
182 return (ioctl(s, SIOCSIFFLAGS, &ifr));
183 }
184
185 static void
186 mark_if_up(char * name)
187 {
188 int s = dgram_socket(AF_INET);
189 if (s == -1)
190 return;
191 ifflags_set(s, name, IFF_UP);
192 close(s);
193 }
194
195 static void
196 mark_if_down(char * name)
197 {
198 int s = dgram_socket(AF_INET);
199 if (s == -1)
200 return;
201 ifflags_clear(s, name, IFF_UP);
202 close(s);
203 }
204
205 static void
206 post_network_changed(void)
207 {
208 if (network_changed) {
209 uint32_t status;
210
211 status = notify_post(_SC_NOTIFY_NETWORK_CHANGE);
212 if (status != NOTIFY_STATUS_OK) {
213 SCLog(TRUE, LOG_ERR, CFSTR("notify_post() failed: error=%u"), status);
214 }
215
216 network_changed = FALSE;
217 }
218
219 return;
220 }
221
222 static void
223 logEvent(CFStringRef evStr, struct kern_event_msg *ev_msg)
224 {
225 int i;
226 int j;
227
228 if (!_verbose) {
229 return;
230 }
231
232 SCLog(TRUE, LOG_DEBUG, CFSTR("%@ event:"), evStr);
233 SCLog(TRUE, LOG_DEBUG,
234 CFSTR(" Event size=%d, id=%d, vendor=%d, class=%d, subclass=%d, code=%d"),
235 ev_msg->total_size,
236 ev_msg->id,
237 ev_msg->vendor_code,
238 ev_msg->kev_class,
239 ev_msg->kev_subclass,
240 ev_msg->event_code);
241 for (i = 0, j = KEV_MSG_HEADER_SIZE; j < ev_msg->total_size; i++, j+=4) {
242 SCLog(TRUE, LOG_DEBUG, CFSTR(" Event data[%2d] = %08x"), i, ev_msg->event_data[i]);
243 }
244 }
245
246 static const char *
247 inetEventNameString(uint32_t event_code)
248 {
249 if (event_code < sizeof(inetEventName) / sizeof(inetEventName[0])) {
250 return (inetEventName[event_code]);
251 }
252 return ("New Apple network INET subcode");
253 }
254
255 static const char *
256 inet6EventNameString(uint32_t event_code)
257 {
258 if (event_code < sizeof(inet6EventName) / sizeof(inet6EventName[0])) {
259 return (inet6EventName[event_code]);
260 }
261 return ("New Apple network INET6 subcode");
262 }
263
264 static const char *
265 dlEventNameString(uint32_t event_code)
266 {
267 if (event_code < sizeof(dlEventName) / sizeof(dlEventName[0])) {
268 return (dlEventName[event_code]);
269 }
270 return ("New Apple network DL subcode");
271 }
272
273 static void
274 copy_if_name(const struct net_event_data * ev, char * ifr_name, int ifr_len)
275 {
276 snprintf(ifr_name, ifr_len, "%s%d", ev->if_name, ev->if_unit);
277 return;
278 }
279
280 static uint8_t info_zero[DLIL_MODARGLEN];
281
282 static void
283 processEvent_Apple_Network(struct kern_event_msg *ev_msg)
284 {
285 const char * eventName = NULL;
286 int dataLen = (ev_msg->total_size - KEV_MSG_HEADER_SIZE);
287 void * event_data = &ev_msg->event_data[0];
288 Boolean handled = TRUE;
289 char ifr_name[IFNAMSIZ];
290
291 switch (ev_msg->kev_subclass) {
292 case KEV_INET_SUBCLASS : {
293 eventName = inetEventNameString(ev_msg->event_code);
294 switch (ev_msg->event_code) {
295 case KEV_INET_NEW_ADDR :
296 case KEV_INET_CHANGED_ADDR :
297 case KEV_INET_ADDR_DELETED :
298 case KEV_INET_SIFDSTADDR :
299 case KEV_INET_SIFBRDADDR :
300 case KEV_INET_SIFNETMASK : {
301 struct kev_in_data * ev;
302
303 ev = (struct kev_in_data *)event_data;
304 if (dataLen < sizeof(*ev)) {
305 handled = FALSE;
306 break;
307 }
308 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
309 ipv4_interface_update(NULL, ifr_name);
310 break;
311 }
312 case KEV_INET_ARPCOLLISION : {
313 struct kev_in_collision * ev;
314
315 ev = (struct kev_in_collision *)event_data;
316 if ((dataLen < sizeof(*ev))
317 || (dataLen < (sizeof(*ev) + ev->hw_len))) {
318 handled = FALSE;
319 break;
320 }
321 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
322 ipv4_arp_collision(ifr_name,
323 ev->ia_ipaddr,
324 ev->hw_len,
325 ev->hw_addr);
326 break;
327 }
328 #if !TARGET_OS_IPHONE
329 case KEV_INET_PORTINUSE : {
330 struct kev_in_portinuse * ev;
331 ev = (struct kev_in_portinuse *)event_data;
332 if (dataLen < sizeof(*ev)) {
333 handled = FALSE;
334 break;
335 }
336 ipv4_port_in_use(ev->port, ev->req_pid);
337 break;
338 }
339 #endif /* !TARGET_OS_IPHONE */
340 case KEV_INET_ARPRTRFAILURE: {
341 const struct kev_in_arpfailure * ev;
342
343 ev = (const struct kev_in_arpfailure *)event_data;
344 if (dataLen < sizeof(*ev)) {
345 handled = FALSE;
346 break;
347 }
348 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
349 ipv4_router_arp_failure(ifr_name);
350 break;
351 }
352 case KEV_INET_ARPRTRALIVE: {
353 const struct kev_in_arpalive * ev;
354
355 ev = (const struct kev_in_arpalive *)event_data;
356 if (dataLen < sizeof(*ev)) {
357 handled = FALSE;
358 break;
359 }
360 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
361 ipv4_router_arp_alive(ifr_name);
362 break;
363 }
364 default :
365 handled = FALSE;
366 break;
367 }
368 break;
369 }
370 case KEV_INET6_SUBCLASS : {
371 struct kev_in6_data * ev;
372
373 eventName = inet6EventNameString(ev_msg->event_code);
374 ev = (struct kev_in6_data *)event_data;
375 switch (ev_msg->event_code) {
376 case KEV_INET6_NEW_USER_ADDR :
377 case KEV_INET6_CHANGED_ADDR :
378 case KEV_INET6_ADDR_DELETED :
379 case KEV_INET6_NEW_LL_ADDR :
380 case KEV_INET6_NEW_RTADV_ADDR :
381 case KEV_INET6_DEFROUTER :
382 if (dataLen < sizeof(*ev)) {
383 handled = FALSE;
384 break;
385 }
386 copy_if_name(&ev->link_data, ifr_name, sizeof(ifr_name));
387 interface_update_ipv6(NULL, ifr_name);
388 break;
389
390 default :
391 handled = FALSE;
392 break;
393 }
394 break;
395 }
396 case KEV_DL_SUBCLASS : {
397 struct net_event_data * ev;
398
399 eventName = dlEventNameString(ev_msg->event_code);
400 ev = (struct net_event_data *)event_data;
401 switch (ev_msg->event_code) {
402 case KEV_DL_IF_ATTACHED :
403 /*
404 * new interface added
405 */
406 if (dataLen < sizeof(*ev)) {
407 handled = FALSE;
408 break;
409 }
410 copy_if_name(ev, ifr_name, sizeof(ifr_name));
411 link_add(ifr_name);
412 break;
413
414 case KEV_DL_IF_DETACHED :
415 /*
416 * interface removed
417 */
418 if (dataLen < sizeof(*ev)) {
419 handled = FALSE;
420 break;
421 }
422 copy_if_name(ev, ifr_name, sizeof(ifr_name));
423 link_remove(ifr_name);
424 break;
425
426 case KEV_DL_IF_DETACHING :
427 /*
428 * interface detaching
429 */
430 if (dataLen < sizeof(*ev)) {
431 handled = FALSE;
432 break;
433 }
434 copy_if_name(ev, ifr_name, sizeof(ifr_name));
435 interface_detaching(ifr_name);
436 break;
437
438 case KEV_DL_PROTO_ATTACHED :
439 case KEV_DL_PROTO_DETACHED : {
440 struct kev_dl_proto_data * protoEvent;
441
442 protoEvent = (struct kev_dl_proto_data *)event_data;
443 if (dataLen < sizeof(*protoEvent)) {
444 handled = FALSE;
445 break;
446 }
447 copy_if_name(&protoEvent->link_data,
448 ifr_name, sizeof(ifr_name));
449 if (protoEvent->proto_remaining_count == 0) {
450 mark_if_down(ifr_name);
451 } else {
452 mark_if_up(ifr_name);
453 }
454 break;
455 }
456
457 #ifdef KEV_DL_IF_IDLE_ROUTE_REFCNT
458 case KEV_DL_IF_IDLE_ROUTE_REFCNT: {
459 /*
460 * interface route refcnt idle
461 */
462 if (dataLen < sizeof(*ev)) {
463 handled = FALSE;
464 break;
465 }
466 copy_if_name(ev, ifr_name, sizeof(ifr_name));
467 interface_update_idle_state(ifr_name);
468 break;
469 }
470 #endif // KEV_DL_IF_IDLE_ROUTE_REFCNT
471
472 case KEV_DL_LINK_OFF :
473 case KEV_DL_LINK_ON :
474 /*
475 * update the link status in the store
476 */
477 if (dataLen < sizeof(*ev)) {
478 handled = FALSE;
479 break;
480 }
481 copy_if_name(ev, ifr_name, sizeof(ifr_name));
482 link_update_status(ifr_name, FALSE);
483 break;
484
485 #ifdef KEV_DL_LINK_QUALITY_METRIC_CHANGED
486 case KEV_DL_LINK_QUALITY_METRIC_CHANGED: {
487 struct kev_dl_link_quality_metric_data * lqm_data;
488 lqm_data = (struct kev_dl_link_quality_metric_data *) event_data;
489
490 if (dataLen < sizeof(*ev)) {
491 handled = FALSE;
492 break;
493 }
494 copy_if_name(ev, ifr_name, sizeof(ifr_name));
495 interface_update_quality_metric(ifr_name,
496 lqm_data->link_quality_metric);
497 break;
498 }
499 #endif // KEV_DL_LINK_QUALITY_METRIC_CHANGED
500
501 #ifdef KEV_DL_ISSUES
502 case KEV_DL_ISSUES: {
503 struct kev_dl_issues *issues;
504
505 issues = (struct kev_dl_issues *)event_data;
506 if (dataLen < sizeof(*ev)) {
507 handled = FALSE;
508 break;
509 }
510 copy_if_name(ev, ifr_name, sizeof(ifr_name));
511 interface_update_link_issues(ifr_name,
512 issues->timestamp,
513 issues->modid,
514 DLIL_MODIDLEN,
515 issues->info,
516 (bcmp(issues->info, info_zero, DLIL_MODIDLEN) != 0)
517 ?DLIL_MODARGLEN
518 :0);
519 break;
520 }
521 #endif // KEV_DL_ISSUES
522
523 case KEV_DL_SIFFLAGS :
524 case KEV_DL_SIFMETRICS :
525 case KEV_DL_SIFMTU :
526 case KEV_DL_SIFPHYS :
527 case KEV_DL_SIFMEDIA :
528 case KEV_DL_SIFGENERIC :
529 case KEV_DL_ADDMULTI :
530 case KEV_DL_DELMULTI :
531 case KEV_DL_LINK_ADDRESS_CHANGED :
532 case KEV_DL_WAKEFLAGS_CHANGED :
533 #ifdef KEV_DL_IFCAP_CHANGED
534 case KEV_DL_IFCAP_CHANGED :
535 #endif // KEV_DL_IFCAP_CHANGED
536 break;
537
538 default :
539 handled = FALSE;
540 break;
541 }
542 break;
543 }
544 #ifdef KEV_ND6_SUBCLASS
545 case KEV_ND6_SUBCLASS : {
546 eventName = nd6EventNameString(ev_msg->event_code);
547 switch (ev_msg->event_code) {
548 case KEV_KEV_ND6_RA :
549 break;
550
551 default :
552 handled = FALSE;
553 break;
554 }
555 break;
556 }
557 #endif // KEV_ND6_SUBCLASS
558 case KEV_LOG_SUBCLASS : {
559 break;
560 }
561 default :
562 handled = FALSE;
563 break;
564 }
565
566 if (handled == FALSE) {
567 CFStringRef evStr;
568
569 evStr = CFStringCreateWithCString(NULL,
570 (eventName != NULL) ? eventName : "New Apple network subclass",
571 kCFStringEncodingASCII);
572 logEvent(evStr, ev_msg);
573 CFRelease(evStr);
574 }
575 return;
576 }
577
578 static Boolean
579 eventCallback(int so)
580 {
581 ssize_t status;
582 union {
583 char bytes[1024];
584 struct kern_event_msg ev_msg1; // first kernel event
585 } buf;
586 struct kern_event_msg *ev_msg = &buf.ev_msg1;
587 ssize_t offset = 0;
588
589 status = recv(so, &buf, sizeof(buf), 0);
590 if (status == -1) {
591 SCLog(TRUE, LOG_ERR, CFSTR("recv() failed: %s"), strerror(errno));
592 return FALSE;
593 }
594
595 cache_open();
596
597 while (offset < status) {
598 if ((offset + ev_msg->total_size) > status) {
599 SCLog(TRUE, LOG_NOTICE, CFSTR("missed SYSPROTO_EVENT event, buffer not big enough"));
600 break;
601 }
602
603 switch (ev_msg->vendor_code) {
604 case KEV_VENDOR_APPLE :
605 switch (ev_msg->kev_class) {
606 case KEV_NETWORK_CLASS :
607 processEvent_Apple_Network(ev_msg);
608 break;
609 case KEV_IOKIT_CLASS :
610 case KEV_SYSTEM_CLASS :
611 case KEV_APPLESHARE_CLASS :
612 case KEV_FIREWALL_CLASS :
613 case KEV_IEEE80211_CLASS :
614 break;
615 default :
616 /* unrecognized (Apple) event class */
617 logEvent(CFSTR("New (Apple) class"), ev_msg);
618 break;
619 }
620 break;
621 default :
622 /* unrecognized vendor code */
623 logEvent(CFSTR("New vendor"), ev_msg);
624 break;
625 }
626 offset += ev_msg->total_size;
627 ev_msg = (struct kern_event_msg *)(void *)&buf.bytes[offset];
628 }
629
630 cache_write(store);
631 cache_close();
632 post_network_changed();
633
634 return TRUE;
635 }
636
637
638 static void
639 prime(void)
640 {
641 struct ifaddrs *ifap = NULL;
642 struct ifaddrs *scan;
643 int sock = -1;
644
645 SCLog(_verbose, LOG_DEBUG, CFSTR("prime() called"));
646
647 cache_open();
648
649 sock = dgram_socket(AF_INET);
650 if (sock == -1) {
651 SCLog(TRUE, LOG_ERR, CFSTR("could not get interface list, socket() failed: %s"), strerror(errno));
652 goto done;
653 }
654
655 if (getifaddrs(&ifap) == -1) {
656 SCLog(TRUE,
657 LOG_ERR,
658 CFSTR("could not get interface info, getifaddrs() failed: %s"),
659 strerror(errno));
660 goto done;
661 }
662
663 /* update list of interfaces & link status */
664 for (scan = ifap; scan != NULL; scan = scan->ifa_next) {
665 if (scan->ifa_addr == NULL
666 || scan->ifa_addr->sa_family != AF_LINK) {
667 continue;
668 }
669 /* get the per-interface link/media information */
670 link_add(scan->ifa_name);
671 }
672
673 /*
674 * update IPv4 network addresses already assigned to
675 * the interfaces.
676 */
677 ipv4_interface_update(ifap, NULL);
678
679 /*
680 * update IPv6 network addresses already assigned to
681 * the interfaces.
682 */
683 interface_update_ipv6(ifap, NULL);
684
685 freeifaddrs(ifap);
686
687 done:
688 if (sock != -1)
689 close(sock);
690
691 cache_write(store);
692 cache_close();
693
694 network_changed = TRUE;
695 post_network_changed();
696
697 /* start handling kernel events */
698 dispatch_resume(S_kev_source);
699
700 return;
701 }
702
703
704 __private_extern__
705 void
706 prime_KernelEventMonitor()
707 {
708 dispatch_async(S_kev_queue, ^{ prime(); });
709 return;
710 }
711
712 __private_extern__
713 void
714 load_KernelEventMonitor(CFBundleRef bundle, Boolean bundleVerbose)
715 {
716 struct kev_request kev_req;
717 int so;
718 int status;
719
720 if (bundleVerbose) {
721 _verbose = TRUE;
722 }
723
724 SCLog(_verbose, LOG_DEBUG, CFSTR("load() called"));
725 SCLog(_verbose, LOG_DEBUG, CFSTR(" bundle ID = %@"), CFBundleGetIdentifier(bundle));
726
727 /* open a "configd" session to allow cache updates */
728 store = SCDynamicStoreCreate(NULL,
729 CFSTR("Kernel Event Monitor plug-in"),
730 NULL,
731 NULL);
732 if (store == NULL) {
733 SCLog(TRUE, LOG_ERR, CFSTR("SCDnamicStoreCreate() failed: %s"), SCErrorString(SCError()));
734 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
735 return;
736 }
737
738 /* Open an event socket */
739 so = socket(PF_SYSTEM, SOCK_RAW, SYSPROTO_EVENT);
740 if (so != -1) {
741 /* establish filter to return events of interest */
742 kev_req.vendor_code = KEV_VENDOR_APPLE;
743 kev_req.kev_class = KEV_NETWORK_CLASS;
744 kev_req.kev_subclass = KEV_ANY_SUBCLASS;
745 status = ioctl(so, SIOCSKEVFILT, &kev_req);
746 if (status) {
747 SCLog(TRUE, LOG_ERR, CFSTR("could not establish event filter, ioctl() failed: %s"), strerror(errno));
748 (void) close(so);
749 so = -1;
750 }
751 } else {
752 SCLog(TRUE, LOG_ERR, CFSTR("could not open event socket, socket() failed: %s"), strerror(errno));
753 }
754
755 if (so != -1) {
756 int yes = 1;
757
758 status = ioctl(so, FIONBIO, &yes);
759 if (status) {
760 SCLog(TRUE, LOG_ERR, CFSTR("could not set non-blocking io, ioctl() failed: %s"), strerror(errno));
761 (void) close(so);
762 so = -1;
763 }
764 }
765
766 if (so == -1) {
767 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
768 CFRelease(store);
769 return;
770 }
771
772 S_kev_queue = dispatch_queue_create("com.apple.SystemConfiguration.KernelEventMonitor", NULL);
773 S_kev_source
774 = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, so, 0, S_kev_queue);
775 dispatch_source_set_cancel_handler(S_kev_source, ^{
776 close(so);
777 });
778 dispatch_source_set_event_handler(S_kev_source, ^{
779 Boolean ok;
780
781 ok = eventCallback(so);
782 if (!ok) {
783 SCLog(TRUE, LOG_ERR, CFSTR("kernel event monitor disabled."));
784 dispatch_source_cancel(S_kev_source);
785 }
786
787 });
788 // NOTE: dispatch_resume() will be called in prime()
789
790 return;
791 }
792
793 #ifdef MAIN
794
795 #include "ev_dlil.c"
796
797 #define appendAddress appendAddress_v4
798 #define getIF getIF_v4
799 #define updateStore updateStore_v4
800 #include "ev_ipv4.c"
801 #undef appendAddress
802 #undef getIF
803 #undef updateStore
804
805 #define appendAddress appendAddress_v6
806 #define getIF getIF_v6
807 #define updateStore updateStore_v6
808 #include "ev_ipv6.c"
809 #undef appendAddress
810 #undef getIF
811 #undef updateStore
812
813 int
814 main(int argc, char **argv)
815 {
816 _sc_log = FALSE;
817 _sc_verbose = (argc > 1) ? TRUE : FALSE;
818
819 load_KernelEventMonitor(CFBundleGetMainBundle(), (argc > 1) ? TRUE : FALSE);
820 prime_KernelEventMonitor();
821 dispatch_main();
822 /* not reached */
823 exit(0);
824 return 0;
825 }
826 #endif