/* * Copyright (C) 2014 Red Hat * * 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. * * 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. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include struct find_ip_st { struct sockaddr_storage *sockaddr; unsigned sockaddr_size; unsigned found_ips; }; struct find_sid_st { const uint8_t *sid; unsigned sid_size; }; static size_t rehash_ip(const void* _p, void* unused) { const struct proc_st * proc = _p; return hash_any( SA_IN_P_GENERIC(&proc->remote_addr, proc->remote_addr_len), SA_IN_SIZE(proc->remote_addr_len), 0); } static size_t rehash_sid(const void* _p, void* unused) { const struct proc_st * proc = _p; return hash_any(proc->dtls_session_id, proc->dtls_session_id_size, 0); } void proc_table_init(main_server_st *s) { s->proc_table.db_ip = talloc(s, struct htable); s->proc_table.db_sid = talloc(s, struct htable); htable_init(s->proc_table.db_ip, rehash_ip, NULL); htable_init(s->proc_table.db_sid, rehash_sid, NULL); s->proc_table.total = 0; } void proc_table_deinit(main_server_st *s) { htable_clear(s->proc_table.db_ip); htable_clear(s->proc_table.db_sid); talloc_free(s->proc_table.db_sid); talloc_free(s->proc_table.db_ip); } void proc_table_add(main_server_st *s, struct proc_st *proc) { size_t ip_hash = rehash_ip(proc, NULL); if (htable_add(s->proc_table.db_ip, ip_hash, proc) == 0) { return; } if (htable_add(s->proc_table.db_sid, rehash_sid(proc, NULL), proc) == 0) { htable_del(s->proc_table.db_ip, ip_hash, proc); return; } s->proc_table.total++; return; } void proc_table_del(main_server_st *s, struct proc_st *proc) { htable_del(s->proc_table.db_ip, rehash_ip(proc, NULL), proc); htable_del(s->proc_table.db_sid, rehash_sid(proc, NULL), proc); } static bool local_ip_cmp(const void* _c1, void* _c2) { const struct proc_st* c1 = _c1; struct find_ip_st* c2 = _c2; if (c1->remote_addr_len != c2->sockaddr_size) return 0; if (memcmp(SA_IN_P_GENERIC(&c1->remote_addr, c1->remote_addr_len), SA_IN_P_GENERIC(c2->sockaddr, c2->sockaddr_size), SA_IN_SIZE(c1->remote_addr_len)) == 0) { c2->found_ips++; return 1; } return 0; } struct proc_st *proc_search_ip(struct main_server_st *s, struct sockaddr_storage *sockaddr, unsigned sockaddr_size) { struct proc_st *proc; struct find_ip_st fip; size_t h; fip.sockaddr = sockaddr; fip.sockaddr_size = sockaddr_size; fip.found_ips = 0; h = hash_any(SA_IN_P_GENERIC(sockaddr, sockaddr_size), SA_IN_SIZE(sockaddr_size), 0); proc = htable_get(s->proc_table.db_ip, h, local_ip_cmp, &fip); if (fip.found_ips > 1) return NULL; return proc; } static bool sid_cmp(const void* _c1, void* _c2) { const struct proc_st* c1 = _c1; struct find_sid_st* c2 = _c2; if (c1->dtls_session_id_size != c2->sid_size) return 0; if (memcmp(c1->dtls_session_id, c2->sid, c1->dtls_session_id_size) == 0) { return 1; } return 0; } struct proc_st *proc_search_sid(struct main_server_st *s, const uint8_t *id, unsigned id_size) { struct find_sid_st fsid; fsid.sid = id; fsid.sid_size = id_size; return htable_get(s->proc_table.db_sid, hash_any(id, id_size, 0), sid_cmp, &fsid); }