]> git.saurik.com Git - apple/configd.git/blobdiff - IPMonitorControl/IPMonitorControl.c
configd-1061.141.1.tar.gz
[apple/configd.git] / IPMonitorControl / IPMonitorControl.c
index a85ebc2c8fd27ae4e2d043af8798a530db226423..39950ce9148380c98dcde49ee74e3096957d6dff 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 2013-2018 Apple Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  *
  *
  * @APPLE_LICENSE_HEADER_START@
  *
 #include <SystemConfiguration/SCPrivate.h>
 
 #ifdef TEST_IPMONITOR_CONTROL
 #include <SystemConfiguration/SCPrivate.h>
 
 #ifdef TEST_IPMONITOR_CONTROL
-#define my_log(__level, fmt, ...)      SCPrint(TRUE, stdout, CFSTR(fmt "\n"), ## __VA_ARGS__)
+
+#define        my_log(__level, __format, ...)  SCPrint(TRUE, stdout, CFSTR(__format "\n"), ## __VA_ARGS__)
 
 #else /* TEST_IPMONITOR_CONTROL */
 
 
 #else /* TEST_IPMONITOR_CONTROL */
 
-#define my_log(__level, fmt, ...)      SCLog(TRUE, __level, CFSTR(fmt), ## __VA_ARGS__)
-#endif /* TEST_IPMONITOR_CONTROL */
+#define        my_log(__level, __format, ...)  SC_log(__level, __format, ## __VA_ARGS__)
+
+#endif /* TEST_IPMONITOR_CONTROL */
 
 /**
  ** IPMonitorControl CF object glue
 
 /**
  ** IPMonitorControl CF object glue
@@ -60,7 +62,9 @@ struct IPMonitorControl {
 
     dispatch_queue_t           queue;
     xpc_connection_t           connection;
 
     dispatch_queue_t           queue;
     xpc_connection_t           connection;
+
     CFMutableDictionaryRef     assertions; /* ifname<string> = rank<number> */
     CFMutableDictionaryRef     assertions; /* ifname<string> = rank<number> */
+    CFMutableDictionaryRef     advisories; /* ifname<string> = adv<number> */
 };
 
 STATIC CFStringRef     __IPMonitorControlCopyDebugDesc(CFTypeRef cf);
 };
 
 STATIC CFStringRef     __IPMonitorControlCopyDebugDesc(CFTypeRef cf);
@@ -100,8 +104,10 @@ __IPMonitorControlDeallocate(CFTypeRef cf)
        xpc_release(control->connection);
     }
     if (control->queue != NULL) {
        xpc_release(control->connection);
     }
     if (control->queue != NULL) {
-       xpc_release(control->queue);
+       dispatch_release(control->queue);
     }
     }
+    my_CFRelease(&control->advisories);
+    my_CFRelease(&control->assertions);
     return;
 }
 
     return;
 }
 
@@ -131,10 +137,25 @@ __IPMonitorControlAllocate(CFAllocatorRef allocator)
     control = (IPMonitorControlRef)
        _CFRuntimeCreateInstance(allocator,
                                 __kIPMonitorControlTypeID, size, NULL);
     control = (IPMonitorControlRef)
        _CFRuntimeCreateInstance(allocator,
                                 __kIPMonitorControlTypeID, size, NULL);
-    bzero(((void *)control) + sizeof(CFRuntimeBase), size);
     return (control);
 }
 
     return (control);
 }
 
+STATIC xpc_object_t
+create_request_dictionary(void)
+{
+    const char *       progname;
+    xpc_object_t       request;
+
+    request = xpc_dictionary_create(NULL, NULL, 0);
+    progname = getprogname();
+    if (progname != NULL) {
+       xpc_dictionary_set_string(request,
+                                 kIPMonitorControlRequestKeyProcessName,
+                                 progname);
+    }
+    return (request);
+}
+
 STATIC Boolean
 IPMonitorControlHandleResponse(xpc_object_t event, Boolean async,
                               Boolean * retry_p)
 STATIC Boolean
 IPMonitorControlHandleResponse(xpc_object_t event, Boolean async,
                               Boolean * retry_p)
@@ -158,7 +179,7 @@ IPMonitorControlHandleResponse(xpc_object_t event, Boolean async,
                success = FALSE;
 #ifdef TEST_IPMONITOR_CONTROL
                my_log(LOG_NOTICE, "failure code %lld", error);
                success = FALSE;
 #ifdef TEST_IPMONITOR_CONTROL
                my_log(LOG_NOTICE, "failure code %lld", error);
-#endif /* TEST_IPMONITOR_CONTROL */
+#endif /* TEST_IPMONITOR_CONTROL */
            }
            else {
                success = TRUE;
            }
            else {
                success = TRUE;
@@ -169,7 +190,7 @@ IPMonitorControlHandleResponse(xpc_object_t event, Boolean async,
        if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
 #ifdef TEST_IPMONITOR_CONTROL
            my_log(LOG_NOTICE, "can retry");
        if (event == XPC_ERROR_CONNECTION_INTERRUPTED) {
 #ifdef TEST_IPMONITOR_CONTROL
            my_log(LOG_NOTICE, "can retry");
-#endif /* TEST_IPMONITOR_CONTROL */
+#endif /* TEST_IPMONITOR_CONTROL */
            retry = TRUE;
        }
        else {
            retry = TRUE;
        }
        else {
@@ -190,9 +211,9 @@ IPMonitorControlHandleResponse(xpc_object_t event, Boolean async,
 
 
 STATIC void
 
 
 STATIC void
-IPMonitorControlSetInterfaceRank(IPMonitorControlRef control,
-                                CFStringRef ifname_cf,
-                                SCNetworkServicePrimaryRank rank)
+_IPMonitorControlSetInterfacePrimaryRank(IPMonitorControlRef control,
+                                        CFStringRef ifname_cf,
+                                        SCNetworkServicePrimaryRank rank)
 {
     if (control->assertions == NULL) {
        if (rank == kSCNetworkServicePrimaryRankDefault) {
 {
     if (control->assertions == NULL) {
        if (rank == kSCNetworkServicePrimaryRankDefault) {
@@ -207,8 +228,7 @@ IPMonitorControlSetInterfaceRank(IPMonitorControlRef control,
     if (rank == kSCNetworkServicePrimaryRankDefault) {
        CFDictionaryRemoveValue(control->assertions, ifname_cf);
        if (CFDictionaryGetCount(control->assertions) == 0) {
     if (rank == kSCNetworkServicePrimaryRankDefault) {
        CFDictionaryRemoveValue(control->assertions, ifname_cf);
        if (CFDictionaryGetCount(control->assertions) == 0) {
-           CFRelease(control->assertions);
-           control->assertions = NULL;
+           my_CFRelease(&control->assertions);
        }
     }
     else {
        }
     }
     else {
@@ -229,14 +249,14 @@ ApplyInterfaceRank(const void * key, const void * value, void * context)
     SCNetworkServicePrimaryRank        rank;
     xpc_object_t               request;
 
     SCNetworkServicePrimaryRank        rank;
     xpc_object_t               request;
 
-    if (CFStringGetCString(key, ifname, sizeof(ifname),
-                          kCFStringEncodingUTF8) == FALSE) {
+    if (!CFStringGetCString(key, ifname, sizeof(ifname),
+                           kCFStringEncodingUTF8)) {
        return;
     }
        return;
     }
-    if (CFNumberGetValue(value, kCFNumberSInt32Type, &rank) == FALSE) {
+    if (!CFNumberGetValue(value, kCFNumberSInt32Type, &rank)) {
        return;
     }
        return;
     }
-    request = xpc_dictionary_create(NULL, NULL, 0);
+    request = create_request_dictionary();
     xpc_dictionary_set_uint64(request,
                              kIPMonitorControlRequestKeyType,
                              kIPMonitorControlRequestTypeSetInterfaceRank);
     xpc_dictionary_set_uint64(request,
                              kIPMonitorControlRequestKeyType,
                              kIPMonitorControlRequestTypeSetInterfaceRank);
@@ -252,6 +272,68 @@ ApplyInterfaceRank(const void * key, const void * value, void * context)
 }
 
 
 }
 
 
+STATIC void
+_IPMonitorControlSetInterfaceAdvisory(IPMonitorControlRef control,
+                                     CFStringRef ifname_cf,
+                                     SCNetworkInterfaceAdvisory advisory)
+{
+    if (control->advisories == NULL) {
+       if (advisory == kSCNetworkInterfaceAdvisoryNone) {
+           /* no advisories, no need to store advisory */
+           return;
+       }
+       control->advisories
+           = CFDictionaryCreateMutable(NULL, 0,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+    }
+    if (advisory == kSCNetworkInterfaceAdvisoryNone) {
+       CFDictionaryRemoveValue(control->advisories, ifname_cf);
+       if (CFDictionaryGetCount(control->advisories) == 0) {
+           my_CFRelease(&control->advisories);
+       }
+    }
+    else {
+       CFNumberRef     advisory_cf;
+
+       advisory_cf = CFNumberCreate(NULL, kCFNumberSInt32Type, &advisory);
+       CFDictionarySetValue(control->advisories, ifname_cf, advisory_cf);
+       CFRelease(advisory_cf);
+    }
+    return;
+}
+
+STATIC void
+ApplyInterfaceAdvisory(const void * key, const void * value, void * context)
+{
+    xpc_connection_t           connection = (xpc_connection_t)context;
+    char                       ifname[IF_NAMESIZE];
+    SCNetworkInterfaceAdvisory advisory;
+    xpc_object_t               request;
+
+    if (!CFStringGetCString(key, ifname, sizeof(ifname),
+                           kCFStringEncodingUTF8)) {
+       return;
+    }
+    if (!CFNumberGetValue(value, kCFNumberSInt32Type, &advisory)) {
+       return;
+    }
+    request = create_request_dictionary();
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyType,
+                             kIPMonitorControlRequestTypeSetInterfaceAdvisory);
+    xpc_dictionary_set_string(request,
+                             kIPMonitorControlRequestKeyInterfaceName,
+                             ifname);
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyAdvisory,
+                             advisory);
+    xpc_connection_send_message(connection, request);
+    xpc_release(request);
+    return;
+}
+
+
 /**
  ** IPMonitorControl SPI
  **/
 /**
  ** IPMonitorControl SPI
  **/
@@ -270,20 +352,21 @@ IPMonitorControlCreate(void)
        = xpc_connection_create_mach_service(kIPMonitorControlServerName,
                                             queue, flags);
     handler = ^(xpc_object_t event) {
        = xpc_connection_create_mach_service(kIPMonitorControlServerName,
                                             queue, flags);
     handler = ^(xpc_object_t event) {
-       os_activity_t   activity_id;
        Boolean         retry;
 
        Boolean         retry;
 
-       activity_id = os_activity_start("processing IPMonitor [rank] reply",
-                                       OS_ACTIVITY_FLAG_DEFAULT);
-
        (void)IPMonitorControlHandleResponse(event, TRUE, &retry);
        (void)IPMonitorControlHandleResponse(event, TRUE, &retry);
-       if (retry && control->assertions != NULL) {
-           CFDictionaryApplyFunction(control->assertions,
-                                     ApplyInterfaceRank,
-                                     control->connection);
+       if (retry) {
+           if (control->assertions != NULL) {
+               CFDictionaryApplyFunction(control->assertions,
+                                         ApplyInterfaceRank,
+                                         control->connection);
+           }
+           if (control->advisories != NULL) {
+               CFDictionaryApplyFunction(control->advisories,
+                                         ApplyInterfaceAdvisory,
+                                         control->connection);
+           }
        }
        }
-
-       os_activity_end(activity_id);
     };
     xpc_connection_set_event_handler(connection, handler);
     control->connection = connection;
     };
     xpc_connection_set_event_handler(connection, handler);
     control->connection = connection;
@@ -292,32 +375,15 @@ IPMonitorControlCreate(void)
     return (control);
 }
 
     return (control);
 }
 
-PRIVATE_EXTERN Boolean
-IPMonitorControlSetInterfacePrimaryRank(IPMonitorControlRef control,
-                                       CFStringRef ifname_cf,
-                                       SCNetworkServicePrimaryRank rank)
+STATIC xpc_object_t
+IPMonitorControlSendRequest(IPMonitorControlRef control,
+                           xpc_object_t request)
 {
 {
-    char               ifname[IF_NAMESIZE];
-    xpc_object_t       request;
-    Boolean            success = FALSE;
+    xpc_object_t       reply;
 
 
-    if (CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
-                          kCFStringEncodingUTF8) == FALSE) {
-       return (FALSE);
-    }
-    request = xpc_dictionary_create(NULL, NULL, 0);
-    xpc_dictionary_set_uint64(request,
-                             kIPMonitorControlRequestKeyType,
-                             kIPMonitorControlRequestTypeSetInterfaceRank);
-    xpc_dictionary_set_string(request,
-                             kIPMonitorControlRequestKeyInterfaceName,
-                             ifname);
-    xpc_dictionary_set_uint64(request,
-                             kIPMonitorControlRequestKeyPrimaryRank,
-                             rank);
     while (TRUE) {
     while (TRUE) {
-       xpc_object_t    reply;
        Boolean         retry_on_error = FALSE;
        Boolean         retry_on_error = FALSE;
+       Boolean         success;
 
        reply = xpc_connection_send_message_with_reply_sync(control->connection,
                                                            request);
 
        reply = xpc_connection_send_message_with_reply_sync(control->connection,
                                                            request);
@@ -327,26 +393,59 @@ IPMonitorControlSetInterfacePrimaryRank(IPMonitorControlRef control,
        }
        success = IPMonitorControlHandleResponse(reply, FALSE,
                                                 &retry_on_error);
        }
        success = IPMonitorControlHandleResponse(reply, FALSE,
                                                 &retry_on_error);
-       xpc_release(reply);
        if (success) {
            break;
        }
        if (success) {
            break;
        }
+       xpc_release(reply);
+       reply = NULL;
        if (retry_on_error) {
            continue;
        }
        my_log(LOG_NOTICE, "fatal error");
        break;
     }
        if (retry_on_error) {
            continue;
        }
        my_log(LOG_NOTICE, "fatal error");
        break;
     }
+    return (reply);
+}
+
+PRIVATE_EXTERN Boolean
+IPMonitorControlSetInterfacePrimaryRank(IPMonitorControlRef control,
+                                       CFStringRef ifname_cf,
+                                       SCNetworkServicePrimaryRank rank)
+{
+    char               ifname[IF_NAMESIZE];
+    xpc_object_t       reply;
+    xpc_object_t       request;
+    Boolean            success = FALSE;
+
+    if (!CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
+                           kCFStringEncodingUTF8)) {
+       return (FALSE);
+    }
+
+    request = create_request_dictionary();
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyType,
+                             kIPMonitorControlRequestTypeSetInterfaceRank);
+    xpc_dictionary_set_string(request,
+                             kIPMonitorControlRequestKeyInterfaceName,
+                             ifname);
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyPrimaryRank,
+                             rank);
+    reply = IPMonitorControlSendRequest(control, request);
     xpc_release(request);
     xpc_release(request);
-    if (success) {
+    if (reply != NULL) {
+       success = TRUE;
+       xpc_release(reply);
+
        /* sync our state */
        CFRetain(ifname_cf);
        CFRetain(control);
        dispatch_async(control->queue,
                       ^{
        /* sync our state */
        CFRetain(ifname_cf);
        CFRetain(control);
        dispatch_async(control->queue,
                       ^{
-                          IPMonitorControlSetInterfaceRank(control,
-                                                           ifname_cf,
-                                                           rank);
+                          _IPMonitorControlSetInterfacePrimaryRank(control,
+                                                                   ifname_cf,
+                                                                   rank);
                           CFRelease(ifname_cf);
                           CFRelease(control);
                       });
                           CFRelease(ifname_cf);
                           CFRelease(control);
                       });
@@ -354,55 +453,153 @@ IPMonitorControlSetInterfacePrimaryRank(IPMonitorControlRef control,
     return (success);
 }
 
     return (success);
 }
 
-SCNetworkServicePrimaryRank
+PRIVATE_EXTERN SCNetworkServicePrimaryRank
 IPMonitorControlGetInterfacePrimaryRank(IPMonitorControlRef control,
                                        CFStringRef ifname_cf)
 {
 IPMonitorControlGetInterfacePrimaryRank(IPMonitorControlRef control,
                                        CFStringRef ifname_cf)
 {
-    char                       ifname[IF_NAMESIZE];
-    SCNetworkServicePrimaryRank rank;
-    xpc_object_t               request;
+    char                               ifname[IF_NAMESIZE];
+    SCNetworkServicePrimaryRank                rank;
+    xpc_object_t                       reply;
+    xpc_object_t                       request;
 
     rank = kSCNetworkServicePrimaryRankDefault;
 
     rank = kSCNetworkServicePrimaryRankDefault;
-    if (CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
-                          kCFStringEncodingUTF8) == FALSE) {
-       goto done;
+    if (!CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
+                          kCFStringEncodingUTF8)) {
+       return rank;
     }
     }
-    request = xpc_dictionary_create(NULL, NULL, 0);
+
+    request = create_request_dictionary();
     xpc_dictionary_set_uint64(request,
                              kIPMonitorControlRequestKeyType,
                              kIPMonitorControlRequestTypeGetInterfaceRank);
     xpc_dictionary_set_string(request,
                              kIPMonitorControlRequestKeyInterfaceName,
                              ifname);
     xpc_dictionary_set_uint64(request,
                              kIPMonitorControlRequestKeyType,
                              kIPMonitorControlRequestTypeGetInterfaceRank);
     xpc_dictionary_set_string(request,
                              kIPMonitorControlRequestKeyInterfaceName,
                              ifname);
-    while (TRUE) {
-       xpc_object_t    reply;
-       Boolean         retry_on_error = FALSE;
-       Boolean         success;
+    reply = IPMonitorControlSendRequest(control, request);
+    if (reply != NULL) {
+       rank = (SCNetworkServicePrimaryRank)
+           xpc_dictionary_get_uint64(reply,
+                                     kIPMonitorControlResponseKeyPrimaryRank);
+       xpc_release(reply);
+    }
+    xpc_release(request);
+    return (rank);
+}
 
 
-       reply = xpc_connection_send_message_with_reply_sync(control->connection,
-                                                           request);
-       if (reply == NULL) {
-           my_log(LOG_NOTICE, "failed to send message");
-           break;
-       }
-       success = IPMonitorControlHandleResponse(reply, FALSE, &retry_on_error);
-       if (success) {
-           rank = (SCNetworkServicePrimaryRank)
-               xpc_dictionary_get_uint64(reply,
-                                         kIPMonitorControlResponseKeyPrimaryRank);
-       }
+PRIVATE_EXTERN Boolean
+IPMonitorControlSetInterfaceAdvisory(IPMonitorControlRef control,
+                                    CFStringRef ifname_cf,
+                                    SCNetworkInterfaceAdvisory advisory,
+                                    CFStringRef reason)
+{
+    char               ifname[IF_NAMESIZE];
+    char *             reason_str = NULL;
+    xpc_object_t       reply;
+    xpc_object_t       request;
+    Boolean            success = FALSE;
+
+    if (!CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
+                           kCFStringEncodingUTF8)) {
+       return (FALSE);
+    }
+    if (reason != NULL) {
+       reason_str
+           = _SC_cfstring_to_cstring(reason, NULL, 0, kCFStringEncodingUTF8);
+    }
+    request = create_request_dictionary();
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyType,
+                             kIPMonitorControlRequestTypeSetInterfaceAdvisory);
+    xpc_dictionary_set_string(request,
+                             kIPMonitorControlRequestKeyInterfaceName,
+                             ifname);
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyAdvisory,
+                             advisory);
+    if (reason_str != NULL) {
+       xpc_dictionary_set_string(request,
+                                 kIPMonitorControlRequestKeyReason,
+                                 reason_str);
+       CFAllocatorDeallocate(NULL, reason_str);
+    }
+    reply = IPMonitorControlSendRequest(control, request);
+    xpc_release(request);
+    if (reply != NULL) {
        xpc_release(reply);
        xpc_release(reply);
-       if (success) {
-           break;
-       }
-       if (retry_on_error) {
-           continue;
-       }
-       break;
+       success = TRUE;
+
+       /* sync our state */
+       CFRetain(ifname_cf);
+       CFRetain(control);
+       dispatch_async(control->queue,
+                      ^{
+                          _IPMonitorControlSetInterfaceAdvisory(control,
+                                                                ifname_cf,
+                                                                advisory);
+                          CFRelease(ifname_cf);
+                          CFRelease(control);
+                      });
+    }
+    return (success);
+}
+
+PRIVATE_EXTERN Boolean
+IPMonitorControlInterfaceAdvisoryIsSet(IPMonitorControlRef control,
+                                      CFStringRef ifname_cf)
+{
+    char               ifname[IF_NAMESIZE];
+    xpc_object_t       reply;
+    xpc_object_t       request;
+    Boolean            is_set = FALSE;
+
+    if (!CFStringGetCString(ifname_cf, ifname, sizeof(ifname),
+                           kCFStringEncodingUTF8)) {
+       return (FALSE);
     }
     }
+    request = create_request_dictionary();
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyType,
+                             kIPMonitorControlRequestTypeInterfaceAdvisoryIsSet);
+    xpc_dictionary_set_string(request,
+                             kIPMonitorControlRequestKeyInterfaceName,
+                             ifname);
+    reply = IPMonitorControlSendRequest(control, request);
     xpc_release(request);
     xpc_release(request);
+    if (reply != NULL) {
+       if (xpc_dictionary_get_bool(reply,
+                                   kIPMonitorControlResponseKeyAdvisoryIsSet)) {
+           is_set = TRUE;
+       }
+       xpc_release(reply);
+    }
+    return (is_set);
+}
 
 
- done:
-    return (rank);
+PRIVATE_EXTERN Boolean
+IPMonitorControlAnyInterfaceAdvisoryIsSet(IPMonitorControlRef control)
+{
+    xpc_object_t       reply;
+    xpc_object_t       request;
+    Boolean            is_set = FALSE;
+
+    request = create_request_dictionary();
+    xpc_dictionary_set_uint64(request,
+                             kIPMonitorControlRequestKeyType,
+                             kIPMonitorControlRequestTypeAnyInterfaceAdvisoryIsSet);
+    reply = IPMonitorControlSendRequest(control, request);
+    xpc_release(request);
+    if (reply != NULL) {
+       if (xpc_dictionary_get_bool(reply,
+                                   kIPMonitorControlResponseKeyAdvisoryIsSet)) {
+           is_set = TRUE;
+       }
+       xpc_release(reply);
+    }
+    return (is_set);
 }
 
 }
 
+PRIVATE_EXTERN CFStringRef
+IPMonitorControlCopyInterfaceAdvisoryNotificationKey(CFStringRef ifname)
+{
+    return (_IPMonitorControlCopyInterfaceAdvisoryNotificationKey(ifname));
+}