/* * Copyright (C) 2012 Reto Guadagnini * HSR Hochschule fuer Technik Rapperswil * * 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 . * * 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 "ipseckey.h" #include #include #include typedef struct private_ipseckey_t private_ipseckey_t; /** * private data of the ipseckey */ struct private_ipseckey_t { /** * public functions */ ipseckey_t public; /** * Precedence */ uint8_t precedence; /** * Gateway type */ uint8_t gateway_type; /** * Algorithm */ uint8_t algorithm; /** * Gateway */ chunk_t gateway; /** * Public key */ chunk_t public_key; }; METHOD(ipseckey_t, get_precedence, uint8_t, private_ipseckey_t *this) { return this->precedence; } METHOD(ipseckey_t, get_gateway_type, ipseckey_gw_type_t, private_ipseckey_t *this) { return this->gateway_type; } METHOD(ipseckey_t, get_algorithm, ipseckey_algorithm_t, private_ipseckey_t *this) { return this->algorithm; } METHOD(ipseckey_t, get_gateway, chunk_t, private_ipseckey_t *this) { return this->gateway; } METHOD(ipseckey_t, get_public_key, chunk_t, private_ipseckey_t *this) { return this->public_key; } METHOD(ipseckey_t, destroy, void, private_ipseckey_t *this) { chunk_free(&this->gateway); chunk_free(&this->public_key); free(this); } /* * See header */ ipseckey_t *ipseckey_create_frm_rr(rr_t *rr) { private_ipseckey_t *this; bio_reader_t *reader = NULL; uint8_t label; chunk_t tmp; INIT(this, .public = { .get_precedence = _get_precedence, .get_gateway_type = _get_gateway_type, .get_algorithm = _get_algorithm, .get_gateway = _get_gateway, .get_public_key = _get_public_key, .destroy = _destroy, }, ); if (rr->get_type(rr) != RR_TYPE_IPSECKEY) { DBG1(DBG_CFG, "unable to create an ipseckey out of an RR " "whose type is not IPSECKEY"); free(this); return NULL; } /** Parse the content (RDATA field) of the RR */ reader = bio_reader_create(rr->get_rdata(rr)); if (!reader->read_uint8(reader, &this->precedence) || !reader->read_uint8(reader, &this->gateway_type) || !reader->read_uint8(reader, &this->algorithm)) { DBG1(DBG_CFG, "ipseckey RR has a wrong format"); reader->destroy(reader); free(this); return NULL; } switch (this->gateway_type) { case IPSECKEY_GW_TP_NOT_PRESENT: break; case IPSECKEY_GW_TP_IPV4: if (!reader->read_data(reader, 4, &this->gateway)) { DBG1(DBG_CFG, "ipseckey gateway field does not contain an " "IPv4 address as expected"); reader->destroy(reader); free(this); return NULL; } this->gateway = chunk_clone(this->gateway); break; case IPSECKEY_GW_TP_IPV6: if (!reader->read_data(reader, 16, &this->gateway)) { DBG1(DBG_CFG, "ipseckey gateway field does not contain an " "IPv6 address as expected"); reader->destroy(reader); free(this); return NULL; } this->gateway = chunk_clone(this->gateway); break; case IPSECKEY_GW_TP_WR_ENC_DNAME: /** * Uncompressed domain name as defined in RFC 1035 chapter 3. * * TODO: Currently we ignore wire encoded domain names. * */ while (reader->read_uint8(reader, &label) && label != 0 && label < 192) { if (!reader->read_data(reader, label, &tmp)) { DBG1(DBG_CFG, "wrong wire encoded domain name format " "in ipseckey gateway field"); reader->destroy(reader); free(this); return NULL; } } break; default: DBG1(DBG_CFG, "unable to parse ipseckey gateway field"); reader->destroy(reader); free(this); return NULL; } if (!reader->read_data(reader, reader->remaining(reader), &this->public_key)) { DBG1(DBG_CFG, "failed to read ipseckey public key field"); reader->destroy(reader); chunk_free(&this->gateway); free(this); return NULL; } this->public_key = chunk_clone(this->public_key); reader->destroy(reader); return &this->public; }