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