Return to farp_listener.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libcharon / plugins / farp |
1.1 misho 1: /* 2: * Copyright (C) 2019 Tobias Brunner 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * Copyright (C) 2010 Martin Willi 6: * Copyright (C) 2010 revosec AG 7: * 8: * This program is free software; you can redistribute it and/or modify it 9: * under the terms of the GNU General Public License as published by the 10: * Free Software Foundation; either version 2 of the License, or (at your 11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 12: * 13: * This program is distributed in the hope that it will be useful, but 14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16: * for more details. 17: */ 18: 19: #include "farp_listener.h" 20: 21: #include <collections/linked_list.h> 22: #include <threading/rwlock.h> 23: 24: typedef struct private_farp_listener_t private_farp_listener_t; 25: 26: /** 27: * Private data of an farp_listener_t object. 28: */ 29: struct private_farp_listener_t { 30: 31: /** 32: * Public farp_listener_t interface. 33: */ 34: farp_listener_t public; 35: 36: /** 37: * List with entry_t 38: */ 39: linked_list_t *entries; 40: 41: /** 42: * RWlock for IP list 43: */ 44: rwlock_t *lock; 45: }; 46: 47: /** 48: * Traffic selector cache entry 49: */ 50: typedef struct { 51: /** list of local selectors */ 52: linked_list_t *local; 53: /** list of remote selectors */ 54: linked_list_t *remote; 55: /** reqid of CHILD_SA */ 56: uint32_t reqid; 57: } entry_t; 58: 59: /** 60: * Destroy a cache entry 61: */ 62: static void destroy_entry(entry_t *this) 63: { 64: this->local->destroy_offset(this->local, 65: offsetof(traffic_selector_t, destroy)); 66: this->remote->destroy_offset(this->remote, 67: offsetof(traffic_selector_t, destroy)); 68: free(this); 69: } 70: 71: METHOD(listener_t, child_updown, bool, 72: private_farp_listener_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, 73: bool up) 74: { 75: enumerator_t *enumerator; 76: traffic_selector_t *ts; 77: entry_t *entry; 78: const chunk_t full_from = chunk_from_chars(0x00, 0x00, 0x00, 0x00), 79: full_to = chunk_from_chars(0xff, 0xff, 0xff, 0xff); 80: 81: if (up) 82: { 83: INIT(entry, 84: .local = linked_list_create(), 85: .remote = linked_list_create(), 86: .reqid = child_sa->get_reqid(child_sa), 87: ); 88: 89: enumerator = child_sa->create_ts_enumerator(child_sa, FALSE); 90: while (enumerator->enumerate(enumerator, &ts)) 91: { 92: if (ts->get_type(ts) != TS_IPV4_ADDR_RANGE) 93: { 94: continue; 95: } 96: /* ignore 0.0.0.0/0 remote TS because we don't want to 97: * reply to ARP requests for locally connected subnets */ 98: if (chunk_equals(ts->get_from_address(ts), full_from) && 99: chunk_equals(ts->get_to_address(ts), full_to)) 100: { 101: continue; 102: } 103: entry->remote->insert_last(entry->remote, ts->clone(ts)); 104: } 105: enumerator->destroy(enumerator); 106: 107: enumerator = child_sa->create_ts_enumerator(child_sa, TRUE); 108: while (enumerator->enumerate(enumerator, &ts)) 109: { 110: if (ts->get_type(ts) != TS_IPV4_ADDR_RANGE) 111: { 112: continue; 113: } 114: entry->local->insert_last(entry->local, ts->clone(ts)); 115: } 116: enumerator->destroy(enumerator); 117: 118: if (!entry->remote->get_count(entry->remote) || 119: !entry->local->get_count(entry->local)) 120: { 121: destroy_entry(entry); 122: return TRUE; 123: } 124: 125: this->lock->write_lock(this->lock); 126: this->entries->insert_last(this->entries, entry); 127: this->lock->unlock(this->lock); 128: } 129: else 130: { 131: this->lock->write_lock(this->lock); 132: enumerator = this->entries->create_enumerator(this->entries); 133: while (enumerator->enumerate(enumerator, &entry)) 134: { 135: if (entry->reqid == child_sa->get_reqid(child_sa)) 136: { 137: this->entries->remove_at(this->entries, enumerator); 138: destroy_entry(entry); 139: break; 140: } 141: } 142: enumerator->destroy(enumerator); 143: this->lock->unlock(this->lock); 144: } 145: return TRUE; 146: } 147: 148: METHOD(farp_listener_t, has_tunnel, bool, 149: private_farp_listener_t *this, host_t *local, host_t *remote) 150: { 151: enumerator_t *entries, *locals, *remotes; 152: traffic_selector_t *ts; 153: bool found = FALSE; 154: entry_t *entry; 155: 156: this->lock->read_lock(this->lock); 157: entries = this->entries->create_enumerator(this->entries); 158: while (!found && entries->enumerate(entries, &entry)) 159: { 160: remotes = entry->remote->create_enumerator(entry->remote); 161: while (!found && remotes->enumerate(remotes, &ts)) 162: { 163: if (ts->includes(ts, remote)) 164: { 165: locals = entry->local->create_enumerator(entry->local); 166: while (!found && locals->enumerate(locals, &ts)) 167: { 168: found = ts->includes(ts, local); 169: } 170: locals->destroy(locals); 171: } 172: } 173: remotes->destroy(remotes); 174: } 175: entries->destroy(entries); 176: this->lock->unlock(this->lock); 177: 178: return found; 179: } 180: 181: METHOD(farp_listener_t, destroy, void, 182: private_farp_listener_t *this) 183: { 184: this->entries->destroy(this->entries); 185: this->lock->destroy(this->lock); 186: free(this); 187: } 188: 189: /** 190: * See header 191: */ 192: farp_listener_t *farp_listener_create() 193: { 194: private_farp_listener_t *this; 195: 196: INIT(this, 197: .public = { 198: .listener = { 199: .child_updown = _child_updown, 200: }, 201: .has_tunnel = _has_tunnel, 202: .destroy = _destroy, 203: }, 204: .entries = linked_list_create(), 205: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), 206: ); 207: 208: return &this->public; 209: }