Annotation of embedaddon/strongswan/src/libcharon/plugins/attr/attr_provider.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2010 Tobias Brunner
! 3: * Copyright (C) 2009 Martin Willi
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "attr_provider.h"
! 18:
! 19: #include <time.h>
! 20:
! 21: #include <daemon.h>
! 22: #include <utils/debug.h>
! 23: #include <collections/linked_list.h>
! 24: #include <threading/rwlock.h>
! 25:
! 26: #define SERVER_MAX 2
! 27:
! 28: typedef struct private_attr_provider_t private_attr_provider_t;
! 29: typedef struct attribute_entry_t attribute_entry_t;
! 30:
! 31: /**
! 32: * private data of attr_provider
! 33: */
! 34: struct private_attr_provider_t {
! 35:
! 36: /**
! 37: * public functions
! 38: */
! 39: attr_provider_t public;
! 40:
! 41: /**
! 42: * List of attributes, attribute_entry_t
! 43: */
! 44: linked_list_t *attributes;
! 45:
! 46: /**
! 47: * Lock for attribute list
! 48: */
! 49: rwlock_t *lock;
! 50: };
! 51:
! 52: struct attribute_entry_t {
! 53: /** type of attribute */
! 54: configuration_attribute_type_t type;
! 55: /** attribute value */
! 56: chunk_t value;
! 57: /** associated IKE version */
! 58: ike_version_t ike;
! 59: };
! 60:
! 61: /**
! 62: * Destroy an entry
! 63: */
! 64: static void attribute_destroy(attribute_entry_t *this)
! 65: {
! 66: free(this->value.ptr);
! 67: free(this);
! 68: }
! 69:
! 70: /**
! 71: * Data for attribute enumerator
! 72: */
! 73: typedef struct {
! 74: rwlock_t *lock;
! 75: ike_version_t ike;
! 76: } enumerator_data_t;
! 77:
! 78: CALLBACK(attr_enum_filter, bool,
! 79: enumerator_data_t *data, enumerator_t *orig, va_list args)
! 80: {
! 81: configuration_attribute_type_t *type;
! 82: attribute_entry_t *entry;
! 83: chunk_t *value;
! 84:
! 85: VA_ARGS_VGET(args, type, value);
! 86:
! 87: while (orig->enumerate(orig, &entry))
! 88: {
! 89: if (entry->ike == IKE_ANY || entry->ike == data->ike)
! 90: {
! 91: *type = entry->type;
! 92: *value = entry->value;
! 93: return TRUE;
! 94: }
! 95: }
! 96: return FALSE;
! 97: }
! 98:
! 99: CALLBACK(attr_enum_destroy, void,
! 100: enumerator_data_t *data)
! 101: {
! 102: data->lock->unlock(data->lock);
! 103: free(data);
! 104: }
! 105:
! 106: METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
! 107: private_attr_provider_t *this, linked_list_t *pools,
! 108: ike_sa_t *ike_sa, linked_list_t *vips)
! 109: {
! 110: enumerator_data_t *data;
! 111:
! 112: if (vips->get_count(vips))
! 113: {
! 114: INIT(data,
! 115: .lock = this->lock,
! 116: .ike = ike_sa->get_version(ike_sa),
! 117: );
! 118: this->lock->read_lock(this->lock);
! 119: return enumerator_create_filter(
! 120: this->attributes->create_enumerator(this->attributes),
! 121: attr_enum_filter, data, attr_enum_destroy);
! 122: }
! 123: return enumerator_create_empty();
! 124: }
! 125:
! 126: METHOD(attr_provider_t, destroy, void,
! 127: private_attr_provider_t *this)
! 128: {
! 129: this->attributes->destroy_function(this->attributes,
! 130: (void*)attribute_destroy);
! 131: this->lock->destroy(this->lock);
! 132: free(this);
! 133: }
! 134:
! 135: /**
! 136: * Add an attribute entry to the list
! 137: */
! 138: static void add_legacy_entry(private_attr_provider_t *this, char *key, int nr,
! 139: configuration_attribute_type_t type)
! 140: {
! 141: attribute_entry_t *entry;
! 142: host_t *host;
! 143: char *str;
! 144:
! 145: str = lib->settings->get_str(lib->settings, "%s.%s%d", NULL, lib->ns,
! 146: key, nr);
! 147: if (str)
! 148: {
! 149: host = host_create_from_string(str, 0);
! 150: if (host)
! 151: {
! 152: if (host->get_family(host) == AF_INET6)
! 153: {
! 154: switch (type)
! 155: {
! 156: case INTERNAL_IP4_DNS:
! 157: type = INTERNAL_IP6_DNS;
! 158: break;
! 159: case INTERNAL_IP4_NBNS:
! 160: type = INTERNAL_IP6_NBNS;
! 161: break;
! 162: default:
! 163: break;
! 164: }
! 165: }
! 166: INIT(entry,
! 167: .type = type,
! 168: .value = chunk_clone(host->get_address(host)),
! 169: .ike = IKE_ANY,
! 170: );
! 171: host->destroy(host);
! 172: DBG2(DBG_CFG, "loaded legacy entry attribute %N: %#B",
! 173: configuration_attribute_type_names, entry->type, &entry->value);
! 174: this->attributes->insert_last(this->attributes, entry);
! 175: }
! 176: }
! 177: }
! 178:
! 179: /**
! 180: * Key to attribute type mappings, for v4 and v6 attributes
! 181: */
! 182: typedef struct {
! 183: char *name;
! 184: configuration_attribute_type_t v4;
! 185: configuration_attribute_type_t v6;
! 186: ike_version_t ike;
! 187: } attribute_type_key_t;
! 188:
! 189: static attribute_type_key_t keys[] = {
! 190: {"address", INTERNAL_IP4_ADDRESS, INTERNAL_IP6_ADDRESS, IKE_ANY},
! 191: {"dns", INTERNAL_IP4_DNS, INTERNAL_IP6_DNS, IKE_ANY},
! 192: {"nbns", INTERNAL_IP4_NBNS, INTERNAL_IP6_NBNS, IKE_ANY},
! 193: {"dhcp", INTERNAL_IP4_DHCP, INTERNAL_IP6_DHCP, IKE_ANY},
! 194: {"netmask", INTERNAL_IP4_NETMASK, INTERNAL_IP6_NETMASK, IKE_ANY},
! 195: {"server", INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, IKE_ANY},
! 196: {"subnet", INTERNAL_IP4_SUBNET, INTERNAL_IP6_SUBNET, IKE_ANY},
! 197: {"p-cscf", P_CSCF_IP4_ADDRESS, P_CSCF_IP6_ADDRESS, IKEV2},
! 198: {"split-include", UNITY_SPLIT_INCLUDE, UNITY_SPLIT_INCLUDE, IKEV1},
! 199: {"split-exclude", UNITY_LOCAL_LAN, UNITY_LOCAL_LAN, IKEV1},
! 200: };
! 201:
! 202: /**
! 203: * Load (numerical) entries from the plugins.attr namespace
! 204: */
! 205: static void load_entries(private_attr_provider_t *this)
! 206: {
! 207: enumerator_t *enumerator, *tokens;
! 208: char *key, *value, *token;
! 209: int i;
! 210:
! 211: for (i = 1; i <= SERVER_MAX; i++)
! 212: {
! 213: add_legacy_entry(this, "dns", i, INTERNAL_IP4_DNS);
! 214: add_legacy_entry(this, "nbns", i, INTERNAL_IP4_NBNS);
! 215: }
! 216:
! 217: enumerator = lib->settings->create_key_value_enumerator(lib->settings,
! 218: "%s.plugins.attr", lib->ns);
! 219: while (enumerator->enumerate(enumerator, &key, &value))
! 220: {
! 221: configuration_attribute_type_t type;
! 222: attribute_type_key_t *mapped = NULL;
! 223: attribute_entry_t *entry;
! 224: chunk_t data;
! 225: host_t *host;
! 226: char *pos;
! 227: int i, mask = -1, family;
! 228:
! 229: if (streq(key, "load"))
! 230: {
! 231: continue;
! 232: }
! 233: type = atoi(key);
! 234: if (!type)
! 235: {
! 236: for (i = 0; i < countof(keys); i++)
! 237: {
! 238: if (streq(key, keys[i].name))
! 239: {
! 240: mapped = &keys[i];
! 241: break;
! 242: }
! 243: }
! 244: if (!mapped)
! 245: {
! 246: DBG1(DBG_CFG, "mapping attribute type %s failed", key);
! 247: continue;
! 248: }
! 249: }
! 250: tokens = enumerator_create_token(value, ",", " ");
! 251: while (tokens->enumerate(tokens, &token))
! 252: {
! 253: pos = strchr(token, '/');
! 254: if (pos)
! 255: {
! 256: *(pos++) = '\0';
! 257: mask = atoi(pos);
! 258: }
! 259: host = host_create_from_string(token, 0);
! 260: if (!host)
! 261: {
! 262: if (mapped)
! 263: {
! 264: DBG1(DBG_CFG, "invalid host in key %s: %s", key, token);
! 265: continue;
! 266: }
! 267: /* store numeric attributes that are no IP addresses as strings */
! 268: data = chunk_clone(chunk_from_str(token));
! 269: }
! 270: else
! 271: {
! 272: family = host->get_family(host);
! 273: if (mask == -1)
! 274: {
! 275: data = chunk_clone(host->get_address(host));
! 276: }
! 277: else
! 278: {
! 279: if (family == AF_INET)
! 280: { /* IPv4 attributes contain a subnet mask */
! 281: uint32_t netmask = 0;
! 282:
! 283: if (mask)
! 284: { /* shifting uint32_t by 32 or more is undefined */
! 285: mask = 32 - mask;
! 286: netmask = htonl((0xFFFFFFFF >> mask) << mask);
! 287: }
! 288: data = chunk_cat("cc", host->get_address(host),
! 289: chunk_from_thing(netmask));
! 290: }
! 291: else
! 292: { /* IPv6 addresses the prefix only */
! 293: data = chunk_cat("cc", host->get_address(host),
! 294: chunk_from_chars(mask));
! 295: }
! 296: }
! 297: host->destroy(host);
! 298: if (mapped)
! 299: {
! 300: switch (family)
! 301: {
! 302: case AF_INET:
! 303: type = mapped->v4;
! 304: break;
! 305: case AF_INET6:
! 306: type = mapped->v6;
! 307: break;
! 308: }
! 309: }
! 310: }
! 311: INIT(entry,
! 312: .type = type,
! 313: .value = data,
! 314: .ike = mapped ? mapped->ike : IKE_ANY,
! 315: );
! 316: DBG2(DBG_CFG, "loaded attribute %N: %#B",
! 317: configuration_attribute_type_names, entry->type, &entry->value);
! 318: this->attributes->insert_last(this->attributes, entry);
! 319: }
! 320: tokens->destroy(tokens);
! 321: }
! 322: enumerator->destroy(enumerator);
! 323: }
! 324:
! 325: METHOD(attr_provider_t, reload, void,
! 326: private_attr_provider_t *this)
! 327: {
! 328: this->lock->write_lock(this->lock);
! 329:
! 330: this->attributes->destroy_function(this->attributes, (void*)attribute_destroy);
! 331: this->attributes = linked_list_create();
! 332:
! 333: load_entries(this);
! 334:
! 335: DBG1(DBG_CFG, "loaded %d entr%s for attr plugin configuration",
! 336: this->attributes->get_count(this->attributes),
! 337: this->attributes->get_count(this->attributes) == 1 ? "y" : "ies");
! 338:
! 339: this->lock->unlock(this->lock);
! 340: }
! 341:
! 342: /*
! 343: * see header file
! 344: */
! 345: attr_provider_t *attr_provider_create()
! 346: {
! 347: private_attr_provider_t *this;
! 348:
! 349: INIT(this,
! 350: .public = {
! 351: .provider = {
! 352: .acquire_address = (void*)return_null,
! 353: .release_address = (void*)return_false,
! 354: .create_attribute_enumerator = _create_attribute_enumerator,
! 355: },
! 356: .reload = _reload,
! 357: .destroy = _destroy,
! 358: },
! 359: .attributes = linked_list_create(),
! 360: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
! 361: );
! 362:
! 363: load_entries(this);
! 364:
! 365: return &this->public;
! 366: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>