]> git.saurik.com Git - apple/configd.git/blob - Plugins/KernelEventMonitor/eventmon.c
configd-596.15.tar.gz
[apple/configd.git] / Plugins / KernelEventMonitor / eventmon.c
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
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 };
119
120 static 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
131 static 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__
142 int
143 dgram_socket(int domain)
144 {
145 return (socket(domain, SOCK_DGRAM, 0));
146 }
147
148 static int
149 ifflags_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
164 static int
165 ifflags_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
180 static void
181 mark_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
190 static void
191 mark_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
200 static void
201 post_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
217 static void
218 logEvent(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
241 static const char *
242 inetEventNameString(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
250 static const char *
251 inet6EventNameString(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
259 static const char *
260 dlEventNameString(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
268 static void
269 copy_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
275 static uint8_t info_zero[DLIL_MODARGLEN];
276
277 static void
278 processEvent_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
549 static void
550 eventCallback(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__
617 void
618 prime_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
679 static CFStringRef
680 kevSocketCopyDescription(const void *info)
681 {
682 return CFStringCreateWithFormat(NULL, NULL, CFSTR("<kernel event socket>"));
683 }
684
685 __private_extern__
686 void
687 load_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
789 int
790 main(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