1/* 2 * Copyright (c) 2013, 2014 Apple Inc. 3 * All rights reserved. 4 */ 5#include <errno.h> 6#include <syslog.h> 7#include <xpc/xpc.h> 8 9#include "SNHelperPrivate.h" 10 11static xpc_connection_t 12create_connection(dispatch_queue_t queue) 13{ 14 xpc_connection_t new_connection; 15 16 new_connection = xpc_connection_create_mach_service(kSNHelperService, queue, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); 17 if (isa_xpc_connection(new_connection)) { 18 xpc_connection_set_event_handler(new_connection, 19 ^(xpc_object_t message) { 20 if (isa_xpc_error(message)) { 21 syslog(LOG_INFO, "Got an error on the snhelper connection"); 22 } else if (isa_xpc_dictionary(message)) { 23 syslog(LOG_INFO, "Got an unexpected message on the snhelper connection"); 24 } 25 }); 26 xpc_connection_resume(new_connection); 27 } 28 29 return new_connection; 30} 31 32static xpc_object_t 33copy_response(xpc_object_t request) 34{ 35 dispatch_queue_t conn_queue = dispatch_queue_create("snhelper request", NULL); 36 xpc_connection_t connection = create_connection(conn_queue); 37 xpc_object_t response = NULL; 38 39 if (connection) { 40 response = xpc_connection_send_message_with_reply_sync(connection, request); 41 xpc_connection_cancel(connection); 42 xpc_release(connection); 43 } 44 45 dispatch_release(conn_queue); 46 47 return response; 48} 49 50static int 51flow_divert_uuid_policy_operate(const uuid_t uuid, int operation) 52{ 53 int result = 0; 54 xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0); 55 xpc_object_t response; 56 57 xpc_dictionary_set_uint64(request, kSNHelperMessageType, operation); 58 xpc_dictionary_set_uuid(request, kSNHelperMessageUUID, uuid); 59 60 response = copy_response(request); 61 62 if (isa_xpc_dictionary(response)) { 63 result = (int)xpc_dictionary_get_int64(response, kSNHelperMessageResult); 64 } else { 65 result = EINVAL; 66 } 67 68 xpc_release(response); 69 xpc_release(request); 70 71 return result; 72} 73 74int 75snhelper_flow_divert_uuid_policy_add(const uuid_t uuid) 76{ 77 return flow_divert_uuid_policy_operate(uuid, kSNHelperMessageTypeFlowDivertUUIDAdd); 78} 79 80int 81snhelper_flow_divert_uuid_policy_remove(const uuid_t uuid) 82{ 83 return flow_divert_uuid_policy_operate(uuid, kSNHelperMessageTypeFlowDivertUUIDRemove); 84} 85 86int 87snhelper_flow_divert_uuid_policy_clear(void) 88{ 89 int result = 0; 90 xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0); 91 xpc_object_t response; 92 93 xpc_dictionary_set_uint64(request, kSNHelperMessageType, kSNHelperMessageTypeFlowDivertUUIDClear); 94 95 response = copy_response(request); 96 97 if (isa_xpc_dictionary(response)) { 98 result = (int)xpc_dictionary_get_int64(response, kSNHelperMessageResult); 99 } else { 100 result = EINVAL; 101 } 102 103 xpc_release(response); 104 xpc_release(request); 105 106 return result; 107} 108 109int 110snhelper_get_uuid_for_app(const char *appID, uuid_t uuid) 111{ 112 int result; 113 xpc_object_t request = xpc_dictionary_create(NULL, NULL, 0); 114 xpc_object_t response; 115 116 xpc_dictionary_set_uint64(request, kSNHelperMessageType, kSNHelperMessageTypeGetUUIDForApp); 117 xpc_dictionary_set_string(request, kSNHelperMessageAppID, appID); 118 119 response = copy_response(request); 120 121 if (isa_xpc_dictionary(response)) { 122 result = (int)xpc_dictionary_get_int64(response, kSNHelperMessageResult); 123 const uint8_t *uuidBytes = xpc_dictionary_get_uuid(response, kSNHelperMessageResultData); 124 if (result == 0 && uuid != NULL && uuidBytes != NULL) { 125 memcpy(uuid, uuidBytes, sizeof(uuid_t)); 126 } 127 } else { 128 result = EINVAL; 129 } 130 131 xpc_release(response); 132 xpc_release(request); 133 134 return result; 135} 136 137static bool 138isa_xpc_object_of_type(xpc_object_t obj, xpc_type_t type) 139{ 140 return (obj != NULL && xpc_get_type(obj) == type); 141} 142 143bool 144isa_xpc_connection(xpc_object_t obj) 145{ 146 return isa_xpc_object_of_type(obj, XPC_TYPE_CONNECTION); 147} 148 149bool 150isa_xpc_bool(xpc_object_t obj) 151{ 152 return isa_xpc_object_of_type(obj, XPC_TYPE_BOOL); 153} 154 155bool 156isa_xpc_dictionary(xpc_object_t obj) 157{ 158 return isa_xpc_object_of_type(obj, XPC_TYPE_DICTIONARY); 159} 160 161bool 162isa_xpc_error(xpc_object_t obj) 163{ 164 return isa_xpc_object_of_type(obj, XPC_TYPE_ERROR); 165} 166 167