diff options
author | Martin Willi <martin@revosec.ch> | 2013-05-15 15:56:17 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-06-21 17:03:22 +0200 |
commit | 45dcf4df575ba44879a0858a333938788406900b (patch) | |
tree | ee120d948e8a576117ee06a1af98662e2c76d4d8 /src/libcharon/plugins/osx_attr/osx_attr_handler.c | |
parent | 12488efa78bd42c41684236266d64631830012d0 (diff) | |
download | strongswan-45dcf4df575ba44879a0858a333938788406900b.tar.bz2 strongswan-45dcf4df575ba44879a0858a333938788406900b.tar.xz |
osx-attr: add plugin installing config attributes using SystemConfiguration
Currently installs DNS servers only, by prepending IP addresses to the
DNS configuration of the primary networking service.
Diffstat (limited to 'src/libcharon/plugins/osx_attr/osx_attr_handler.c')
-rw-r--r-- | src/libcharon/plugins/osx_attr/osx_attr_handler.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.c b/src/libcharon/plugins/osx_attr/osx_attr_handler.c new file mode 100644 index 000000000..9a3b2701d --- /dev/null +++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.c @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "osx_attr_handler.h" + +#include <networking/host.h> +#include <utils/debug.h> + +#include <SystemConfiguration/SCDynamicStore.h> + +typedef struct private_osx_attr_handler_t private_osx_attr_handler_t; + +/** + * Private data of an osx_attr_handler_t object. + */ +struct private_osx_attr_handler_t { + + /** + * Public interface + */ + osx_attr_handler_t public; +}; + +/** + * Create a path to the DNS configuration of the Primary IPv4 Service + */ +static CFStringRef create_dns_path(SCDynamicStoreRef store) +{ + CFStringRef service, path = NULL; + CFDictionaryRef dict; + + /* get primary service */ + dict = SCDynamicStoreCopyValue(store, CFSTR("State:/Network/Global/IPv4")); + if (dict) + { + service = CFDictionaryGetValue(dict, CFSTR("PrimaryService")); + if (service) + { + path = CFStringCreateWithFormat(NULL, NULL, + CFSTR("State:/Network/Service/%@/DNS"), service); + } + else + { + DBG1(DBG_CFG, "SystemConfiguration PrimaryService not known"); + } + CFRelease(dict); + } + else + { + DBG1(DBG_CFG, "getting global IPv4 SystemConfiguration failed"); + } + return path; +} + +/** + * Create a mutable dictionary from path, a new one if not found + */ +static CFMutableDictionaryRef get_dictionary(SCDynamicStoreRef store, + CFStringRef path) +{ + CFDictionaryRef dict; + CFMutableDictionaryRef mut = NULL; + + dict = SCDynamicStoreCopyValue(store, path); + if (dict) + { + if (CFGetTypeID(dict) == CFDictionaryGetTypeID()) + { + mut = CFDictionaryCreateMutableCopy(NULL, 0, dict); + } + CFRelease(dict); + } + if (!mut) + { + mut = CFDictionaryCreateMutable(NULL, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + } + return mut; +} + +/** + * Create a mutable array from dictionary path, a new one if not found + */ +static CFMutableArrayRef get_array_from_dict(CFDictionaryRef dict, + CFStringRef name) +{ + CFArrayRef arr; + + arr = CFDictionaryGetValue(dict, name); + if (arr && CFGetTypeID(arr) == CFArrayGetTypeID()) + { + return CFArrayCreateMutableCopy(NULL, 0, arr); + } + return CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); +} + +/** + * Add/Remove a DNS server to the configuration + */ +static bool manage_dns(int family, chunk_t data, bool add) +{ + SCDynamicStoreRef store; + CFStringRef path, dns; + CFMutableArrayRef arr; + CFMutableDictionaryRef dict; + CFIndex i; + host_t *server; + char buf[64]; + bool success = FALSE; + + server = host_create_from_chunk(family, data, 0); + if (!server) + { + return FALSE; + } + snprintf(buf, sizeof(buf), "%H", server); + server->destroy(server); + + store = SCDynamicStoreCreate(NULL, CFSTR("osx-attr"), NULL, NULL); + path = create_dns_path(store); + if (path) + { + dict = get_dictionary(store, path); + arr = get_array_from_dict(dict, CFSTR("ServerAddresses")); + dns = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8); + if (add) + { + DBG1(DBG_CFG, "installing %s as DNS server", buf); + CFArrayInsertValueAtIndex(arr, 0, dns); + } + else + { + i = CFArrayGetFirstIndexOfValue(arr, + CFRangeMake(0, CFArrayGetCount(arr)), dns); + if (i >= 0) + { + DBG1(DBG_CFG, "removing %s from DNS servers (%d)", buf, i); + CFArrayRemoveValueAtIndex(arr, i); + } + } + CFRelease(dns); + CFDictionarySetValue(dict, CFSTR("ServerAddresses"), arr); + CFRelease(arr); + + success = SCDynamicStoreSetValue(store, path, dict); + CFRelease(dict); + CFRelease(path); + } + CFRelease(store); + + if (!success) + { + DBG1(DBG_CFG, "adding DNS server to SystemConfiguration failed"); + } + return success; +} + +METHOD(attribute_handler_t, handle, bool, + private_osx_attr_handler_t *this, identification_t *id, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case INTERNAL_IP4_DNS: + return manage_dns(AF_INET, data, TRUE); + default: + return FALSE; + } +} + +METHOD(attribute_handler_t, release, void, + private_osx_attr_handler_t *this, identification_t *server, + configuration_attribute_type_t type, chunk_t data) +{ + switch (type) + { + case INTERNAL_IP4_DNS: + manage_dns(AF_INET, data, FALSE); + break; + default: + break; + } +} + +METHOD(enumerator_t, enumerate_dns, bool, + enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data) +{ + *type = INTERNAL_IP4_DNS; + *data = chunk_empty; + /* stop enumeration */ + this->enumerate = (void*)return_false; + return TRUE; +} + +METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, + private_osx_attr_handler_t *this, identification_t *id, + linked_list_t *vips) +{ + enumerator_t *enumerator; + + INIT(enumerator, + .enumerate = (void*)_enumerate_dns, + .destroy = (void*)free, + ); + return enumerator; +} + +METHOD(osx_attr_handler_t, destroy, void, + private_osx_attr_handler_t *this) +{ + free(this); +} + +/** + * See header + */ +osx_attr_handler_t *osx_attr_handler_create() +{ + private_osx_attr_handler_t *this; + + INIT(this, + .public = { + .handler = { + .handle = _handle, + .release = _release, + .create_attribute_enumerator = _create_attribute_enumerator, + }, + .destroy = _destroy, + }, + ); + + return &this->public; +} |