macos-realtime-ip-updates-20070618
authorDerrick Brashear <shadow@dementia.org>
Mon, 18 Jun 2007 19:48:33 +0000 (19:48 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 18 Jun 2007 19:48:33 +0000 (19:48 +0000)
notice and deal with IP address changes

src/afs/afs_call.c
src/afsd/afsd.c
src/cf/osconf.m4

index 5d1978b..c6cd0eb 100644 (file)
@@ -846,6 +846,8 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
     } else if (parm == AFSOP_ADVISEADDR) {
        /* pass in the host address to the rx package */
        int rxbind = 0;
+       int refresh = 0;
+
        afs_int32 count = parm2;
        afs_int32 *buffer =
            afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
@@ -855,6 +857,14 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
            afs_osi_Alloc(sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
        int i;
 
+       /* This is a refresh */
+       if (count & 0x40000000) {
+           count &= ~0x40000000;
+           /* Can't bind after we start. Fix? */
+           count &= ~0x80000000;
+           refresh = 1;
+       }
+
        /* Bind, but only if there's only one address configured */ 
        if ( count & 0x80000000) {
            count &= ~0x80000000;
@@ -895,14 +905,21 @@ afs_syscall_call(parm, parm2, parm3, parm4, parm5, parm6)
 #endif
        }
        rxi_setaddr(buffer[0]);
-       if (rxbind)
-           rx_bindhost = buffer[0];
-       else
-           rx_bindhost = htonl(INADDR_ANY);
+       if (!refresh) {
+           if (rxbind)
+               rx_bindhost = buffer[0];
+           else
+               rx_bindhost = htonl(INADDR_ANY);
+       }
 
        afs_osi_Free(buffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
        afs_osi_Free(maskbuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
        afs_osi_Free(mtubuffer, sizeof(afs_int32) * AFS_MAX_INTERFACE_ADDR);
+
+       if (refresh) {
+           afs_CheckServers(1, NULL);     /* check down servers */
+           afs_CheckServers(0, NULL);     /* check down servers */
+       }
     }
 #ifdef AFS_SGI53_ENV
     else if (parm == AFSOP_NFSSTATICADDR) {
index 5db5625..e39a9b0 100644 (file)
@@ -164,6 +164,36 @@ kern_return_t DiskArbStart(mach_port_t *);
 kern_return_t DiskArbDiskAppearedWithMountpointPing_auto(char *, unsigned int,
                                                         char *);
 #define DISK_ARB_NETWORK_DISK_FLAG 8
+
+#include <mach/mach_port.h>
+#include <mach/mach_interface.h>
+#include <mach/mach_init.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <SystemConfiguration/SystemConfiguration.h>
+#include <SystemConfiguration/SCDynamicStore.h>
+
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#include <IOKit/IOMessage.h>
+
+#include <dns_sd.h>
+
+typedef struct DNSSDState
+{
+    DNSServiceRef       service;
+    CFRunLoopSourceRef  source;
+    CFSocketRef         socket;
+} DNSSDState;
+
+static io_connect_t root_port;
+static IONotificationPortRef notify;
+static io_object_t iterator;
+static CFRunLoopSourceRef source;
+static DNSSDState dnsstate;
+
+static int event_pid;
+
 #endif /* AFS_DARWIN_ENV */
 
 #ifndef MOUNT_AFS
@@ -314,6 +344,162 @@ struct afs_cacheParams cparams;   /* params passed to cache manager */
 
 static int HandleMTab();
 
+#ifdef AFS_DARWIN_ENV
+static void
+afsd_sleep_callback(void * refCon, io_service_t service, 
+                   natural_t messageType, void * messageArgument )
+{
+    afs_int32 code;
+    
+    switch (messageType) {
+    case kIOMessageCanSystemSleep:
+       /* Idle sleep is about to kick in; can 
+          prevent sleep by calling IOCancelPowerChange, otherwise 
+          if we don't ack in 30s the system sleeps anyway */
+       
+       /* allow it */
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillSleep:
+       /* The system WILL go to sleep. Ack or suffer delay */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillRestart:
+       /* The system WILL restart. Ack or suffer delay */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    case kIOMessageSystemWillPowerOn:
+    case kIOMessageSystemHasPoweredOn:
+       /* coming back from sleep */
+       
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+       
+    default:
+       IOAllowPowerChange(root_port, (long)messageArgument);
+       break;
+    }
+}
+
+static void
+afsd_update_addresses(CFRunLoopTimerRef timer, void *info)
+{
+    /* parse multihomed address files */
+    afs_int32 addrbuf[MAXIPADDRS], maskbuf[MAXIPADDRS],
+       mtubuf[MAXIPADDRS];
+    char reason[1024];
+    afs_int32 code;
+
+    code =
+       parseNetFiles(addrbuf, maskbuf, mtubuf, MAXIPADDRS, reason,
+                     AFSDIR_CLIENT_NETINFO_FILEPATH,
+                     AFSDIR_CLIENT_NETRESTRICT_FILEPATH);
+
+    if (code > 0) {
+       /* Note we're refreshing */
+       code = code | 0x40000000;
+       call_syscall(AFSOP_ADVISEADDR, code, addrbuf, maskbuf, mtubuf);
+    } else
+       printf("ADVISEADDR: Error in specifying interface addresses:%s\n",
+              reason);
+}
+
+/* This function is called when the system's ip addresses may have changed. */
+static void
+afsd_ipaddr_callback (SCDynamicStoreRef store, CFArrayRef changed_keys, void *info)
+{
+      CFRunLoopTimerRef timer;
+
+      timer = CFRunLoopTimerCreate (NULL, CFAbsoluteTimeGetCurrent () + 1.0,
+                                   0.0, 0, 0, afsd_update_addresses, NULL);
+      CFRunLoopAddTimer (CFRunLoopGetCurrent (), timer,
+                        kCFRunLoopDefaultMode);
+      CFRelease (timer);
+}
+
+static void 
+afsd_event_cleanup(int signo) {
+    DNSSDState *query = &dnsstate;
+
+    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
+    CFRelease (source);
+    IODeregisterForSystemPower(iterator);
+    IOServiceClose(root_port);
+    IONotificationPortDestroy(notify);
+
+    exit(0);
+}
+
+/* Adapted from "Living in a Dynamic TCP/IP Environment" technote. */
+static Boolean
+afsd_install_events(void)
+{
+    SCDynamicStoreContext ctx = {0};
+    SCDynamicStoreRef store;
+
+    root_port = IORegisterForSystemPower(0,&notify,afsd_sleep_callback,&iterator);
+    
+    if (root_port) {
+       CFRunLoopAddSource(CFRunLoopGetCurrent(),
+                          IONotificationPortGetRunLoopSource(notify),
+                          kCFRunLoopDefaultMode);
+    }
+    
+    
+    store = SCDynamicStoreCreate (NULL,
+                                 CFSTR ("AddIPAddressListChangeCallbackSCF"),
+                                 afsd_ipaddr_callback, &ctx);
+    
+    if (store) {
+       const void *keys[1];
+       
+       /* Request IPV4 address change notification */
+       keys[0] = (SCDynamicStoreKeyCreateNetworkServiceEntity
+                  (NULL, kSCDynamicStoreDomainState,
+                   kSCCompAnyRegex, kSCEntNetIPv4));
+       
+#if 0
+       /* This should tell us when the hostname(s) change. do we care? */
+       keys[N] = SCDynamicStoreKeyCreateHostNames (NULL);
+#endif
+       
+       if (keys[0] != NULL) {
+           CFArrayRef pattern_array;
+           
+           pattern_array = CFArrayCreate (NULL, keys, 1,
+                                          &kCFTypeArrayCallBacks);
+           
+           if (pattern_array != NULL)
+           {
+               SCDynamicStoreSetNotificationKeys (store, NULL, pattern_array);
+               source = SCDynamicStoreCreateRunLoopSource (NULL, store, 0);
+               
+               CFRelease (pattern_array);
+           }
+           
+           if (keys[0] != NULL)
+               CFRelease (keys[0]);
+       }
+       
+       CFRelease (store); 
+    }
+    
+    if (source != NULL) {
+       CFRunLoopAddSource (CFRunLoopGetCurrent(),
+                           source, kCFRunLoopDefaultMode);
+    }
+    
+    signal(SIGTERM, afsd_event_cleanup);
+
+    CFRunLoopRun();
+}
+#endif
+
 /* ParseArgs is now obsolete, being handled by cmd */
 
 /*------------------------------------------------------------------------------
@@ -1251,6 +1437,16 @@ AfsdbLookupHandler()
     kernelMsg[1] = 0;
     acellName[0] = '\0';
 
+#ifdef AFS_DARWIN_ENV
+    /* Fork the event handler also. */
+    code = fork();
+    if (code == 0) {
+       afsd_install_events();
+       exit(1);
+    } else if (code != -1) {
+       event_pid = code;
+    }
+#endif
     while (1) {
        /* On some platforms you only get 4 args to an AFS call */
        int sizeArg = ((sizeof acellName) << 16) | (sizeof kernelMsg);
@@ -1280,7 +1476,7 @@ AfsdbLookupHandler()
            acellName[sizeof(acellName) - 1] = '\0';
        }
     }
-
+    kill(event_pid, SIGTERM);
     exit(1);
 }
 #endif
@@ -1758,10 +1954,6 @@ mainproc(struct cmd_syndesc *as, char *arock)
        exit(1);
 #endif
     }
-#if 0
-    fputs(AFS_GOVERNMENT_MESSAGE, stdout);
-    fflush(stdout);
-#endif
 
     /*
      * Set up all the kernel processes needed for AFS.
index 835b991..d0468b2 100644 (file)
@@ -475,7 +475,7 @@ case $AFS_SYSNAME in
                ;;
 
        *_darwin_80)
-               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
                LEX="lex -l"
                MT_CFLAGS='-DAFS_PTHREAD_ENV -D_REENTRANT ${XCFLAGS} ${ARCHFLAGS}'
                KROOT=
@@ -491,7 +491,7 @@ case $AFS_SYSNAME in
                ;;
 
        *_darwin_90)
-               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration"
+               AFSD_LDFLAGS="-F/System/Library/PrivateFrameworks -framework DiskArbitration -framework SystemConfiguration -framework IOKit -framework CoreFoundation"
                LEX="lex -l"
                MT_CFLAGS='-DAFS_PTHREAD_ENV -D_REENTRANT ${XCFLAGS} ${ARCHFLAGS}'
                KROOT=