diff options
Diffstat (limited to 'src/libipsec/ipsec_policy.c')
-rw-r--r-- | src/libipsec/ipsec_policy.c | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/libipsec/ipsec_policy.c b/src/libipsec/ipsec_policy.c new file mode 100644 index 000000000..af8ea9f9d --- /dev/null +++ b/src/libipsec/ipsec_policy.c @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012 Giuliano Grassi + * Copyright (C) 2012 Ralf Sager + * 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 <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 "ipsec_policy.h" + +#include <debug.h> + +typedef struct private_ipsec_policy_t private_ipsec_policy_t; + +/** + * Private additions to ipsec_policy_t. + */ +struct private_ipsec_policy_t { + + /** + * Public members + */ + ipsec_policy_t public; + + /** + * SA source address + */ + host_t *src; + + /** + * SA destination address + */ + host_t *dst; + + /** + * Source traffic selector + */ + traffic_selector_t *src_ts; + + /** + * Destination traffic selector + */ + traffic_selector_t *dst_ts; + + /** + * If any of the two TS has a protocol selector we cache it here + */ + u_int8_t protocol; + + /** + * Traffic direction + */ + policy_dir_t direction; + + /** + * Policy type + */ + policy_type_t type; + + /** + * SA configuration + */ + ipsec_sa_cfg_t sa; + + /** + * Mark + */ + mark_t mark; + + /** + * Policy priority + */ + policy_priority_t priority; + + /** + * Reference counter + */ + refcount_t refcount; + +}; + +METHOD(ipsec_policy_t, match, bool, + private_ipsec_policy_t *this, traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, policy_dir_t direction, u_int32_t reqid, + mark_t mark, policy_priority_t priority) +{ + return (this->direction == direction && + this->priority == priority && + this->sa.reqid == reqid && + memeq(&this->mark, &mark, sizeof(mark_t)) && + this->src_ts->equals(this->src_ts, src_ts) && + this->dst_ts->equals(this->dst_ts, dst_ts)); +} + +METHOD(ipsec_policy_t, match_packet, bool, + private_ipsec_policy_t *this, ip_packet_t *packet) +{ + u_int8_t proto = packet->get_next_header(packet); + host_t *src = packet->get_source(packet), + *dst = packet->get_destination(packet); + + return (!this->protocol || this->protocol == proto) && + this->src_ts->includes(this->src_ts, src) && + this->dst_ts->includes(this->dst_ts, dst); +} + +METHOD(ipsec_policy_t, get_source_ts, traffic_selector_t*, + private_ipsec_policy_t *this) +{ + return this->src_ts; +} + +METHOD(ipsec_policy_t, get_destination_ts, traffic_selector_t*, + private_ipsec_policy_t *this) +{ + return this->dst_ts; +} + +METHOD(ipsec_policy_t, get_reqid, u_int32_t, + private_ipsec_policy_t *this) +{ + return this->sa.reqid; +} + +METHOD(ipsec_policy_t, get_direction, policy_dir_t, + private_ipsec_policy_t *this) +{ + return this->direction; +} + +METHOD(ipsec_policy_t, get_priority, policy_priority_t, + private_ipsec_policy_t *this) +{ + return this->priority; +} + +METHOD(ipsec_policy_t, get_type, policy_type_t, + private_ipsec_policy_t *this) +{ + return this->type; +} + +METHOD(ipsec_policy_t, get_ref, ipsec_policy_t*, + private_ipsec_policy_t *this) +{ + ref_get(&this->refcount); + return &this->public; +} + +METHOD(ipsec_policy_t, destroy, void, + private_ipsec_policy_t *this) +{ + if (ref_put(&this->refcount)) + { + this->src->destroy(this->src); + this->dst->destroy(this->dst); + this->src_ts->destroy(this->src_ts); + this->dst_ts->destroy(this->dst_ts); + free(this); + } +} + +/** + * Described in header. + */ +ipsec_policy_t *ipsec_policy_create(host_t *src, host_t *dst, + traffic_selector_t *src_ts, + traffic_selector_t *dst_ts, + policy_dir_t direction, policy_type_t type, + ipsec_sa_cfg_t *sa, mark_t mark, + policy_priority_t priority) +{ + private_ipsec_policy_t *this; + + INIT(this, + .public = { + .match = _match, + .match_packet = _match_packet, + .get_source_ts = _get_source_ts, + .get_destination_ts = _get_destination_ts, + .get_direction = _get_direction, + .get_priority = _get_priority, + .get_reqid = _get_reqid, + .get_type = _get_type, + .get_ref = _get_ref, + .destroy = _destroy, + }, + .src = src->clone(src), + .dst = dst->clone(dst), + .src_ts = src_ts->clone(src_ts), + .dst_ts = dst_ts->clone(dst_ts), + .protocol = max(src_ts->get_protocol(src_ts), + dst_ts->get_protocol(dst_ts)), + .direction = direction, + .type = type, + .sa = *sa, + .mark = mark, + .priority = priority, + .refcount = 1, + ); + + return &this->public; +} |