+STATIC const char *
+get_advisory_str(SCNetworkInterfaceAdvisory advisory)
+{
+ const char * str = NULL;
+
+ switch (advisory) {
+ case kSCNetworkInterfaceAdvisoryNone:
+ str = "None";
+ break;
+ case kSCNetworkInterfaceAdvisoryLinkLayerIssue:
+ str = "LinkLayerIssue";
+ break;
+ case kSCNetworkInterfaceAdvisoryUplinkIssue:
+ str = "UplinkIssue";
+ break;
+ default:
+ break;
+ }
+ return (str);
+}
+
+STATIC int
+HandleSetInterfaceAdvisory(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(reply)
+ SCNetworkInterfaceAdvisory advisory;
+ const char * advisory_str;
+ const char * ifname;
+ const char * reason;
+ ControlSessionRef session;
+
+#define ENTITLEMENT "com.apple.SystemConfiguration.SCNetworkInterfaceSetAdvisory"
+ if (!IPMonitorControlServerConnectionIsRoot(connection)
+ && !IPMonitorControlServerConnectionHasEntitlement(connection,
+ ENTITLEMENT)) {
+ my_log(LOG_INFO, "connection %p pid %d permission denied",
+ connection, xpc_connection_get_pid(connection));
+ return (EPERM);
+ }
+ ifname
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyInterfaceName);
+ if (ifname == NULL) {
+ return (EINVAL);
+ }
+ reason
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyReason);
+ advisory = (SCNetworkInterfaceAdvisory)
+ xpc_dictionary_get_uint64(request, kIPMonitorControlRequestKeyAdvisory);
+
+ /* validate the advisory code */
+ advisory_str = get_advisory_str(advisory);
+ if (advisory_str == NULL) {
+ return (EINVAL);
+ }
+ session = ControlSessionForConnection(connection);
+ ControlSessionSetInterfaceAdvisory(session, ifname, advisory);
+ my_log(LOG_NOTICE, "%s[%d] SetInterfaceAdvisory(%s) = %s (%u) reason='%s'",
+ get_process_name(request),
+ xpc_connection_get_pid(connection), ifname, advisory_str, advisory,
+ reason != NULL ? reason : "" );
+ return (0);
+}
+
+STATIC int
+HandleInterfaceAdvisoryIsSet(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(connection)
+ const char * ifname;
+ CFStringRef ifname_cf;
+
+ if (reply == NULL) {
+ /* no point in processing the request if we can't provide an answer */
+ return (EINVAL);
+ }
+ ifname
+ = xpc_dictionary_get_string(request,
+ kIPMonitorControlRequestKeyInterfaceName);
+ if (ifname == NULL) {
+ return (EINVAL);
+ }
+ ifname_cf = CFStringCreateWithCString(NULL, ifname,
+ kCFStringEncodingUTF8);
+ xpc_dictionary_set_bool(reply,
+ kIPMonitorControlResponseKeyAdvisoryIsSet,
+ InterfaceHasAdvisories(ifname_cf));
+ CFRelease(ifname_cf);
+ return (0);
+}
+
+STATIC int
+HandleAnyInterfaceAdvisoryIsSet(xpc_connection_t connection,
+ xpc_object_t request,
+ xpc_object_t reply)
+{
+#pragma unused(connection)
+#pragma unused(request)
+ if (reply == NULL) {
+ /* no point in processing the request if we can't provide an answer */
+ return (EINVAL);
+ }
+ xpc_dictionary_set_bool(reply,
+ kIPMonitorControlResponseKeyAdvisoryIsSet,
+ AnyInterfaceHasAdvisories());
+ return (0);
+}
+