mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 00:37:00 +08:00
use hash tables to locate proc entries
That would avoid a walk on all connected clients, when a new UDP session starts.
This commit is contained in:
@@ -77,6 +77,7 @@ ocserv_SOURCES = main.c main-auth.c worker-vpn.c worker-auth.c tlslib.c \
|
||||
sup-config/file.c sup-config/file.h \
|
||||
worker-bandwidth.c worker-bandwidth.h ctl.h main-ctl.h \
|
||||
vasprintf.c vasprintf.h \
|
||||
proc-search.c proc-search.h \
|
||||
str.c str.h gettime.h $(CCAN_SOURCES) $(HTTP_PARSER_SOURCES) \
|
||||
$(PROTOBUF_SOURCES)
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <tlslib.h>
|
||||
#include <script-list.h>
|
||||
#include <ip-lease.h>
|
||||
#include <proc-search.h>
|
||||
#include <main-sup-config.h>
|
||||
#include "str.h"
|
||||
|
||||
@@ -287,6 +288,9 @@ struct cookie_entry_st *old;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* add the links to proc hash */
|
||||
proc_table_add(s, proc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include <sec-mod.h>
|
||||
#include <route-add.h>
|
||||
#include <ip-lease.h>
|
||||
#include <proc-search.h>
|
||||
#include <ipc.pb-c.h>
|
||||
#include <script-list.h>
|
||||
#include <main-sup-config.h>
|
||||
@@ -294,6 +295,7 @@ void remove_proc(main_server_st * s, struct proc_st *proc, unsigned k)
|
||||
}
|
||||
|
||||
close_tun(s, proc);
|
||||
proc_table_del(s, proc);
|
||||
|
||||
talloc_free(proc);
|
||||
}
|
||||
|
||||
31
src/main.c
31
src/main.c
@@ -56,6 +56,7 @@
|
||||
#include <route-add.h>
|
||||
#include <worker.h>
|
||||
#include <cookies.h>
|
||||
#include <proc-search.h>
|
||||
#include <tun.h>
|
||||
#include <grp.h>
|
||||
#include <ip-lease.h>
|
||||
@@ -625,6 +626,7 @@ void clear_lists(main_server_st *s)
|
||||
|
||||
tls_cache_deinit(&s->tls_db);
|
||||
ip_lease_deinit(&s->ip_leases);
|
||||
proc_table_deinit(s);
|
||||
ctl_handler_deinit(s);
|
||||
cookie_db_deinit(&s->cookies);
|
||||
}
|
||||
@@ -664,7 +666,7 @@ static int forward_udp_to_owner(main_server_st* s, struct listener_st *listener)
|
||||
{
|
||||
int ret, e;
|
||||
struct sockaddr_storage cli_addr;
|
||||
struct proc_st *ctmp = NULL, *proc_to_send = NULL;
|
||||
struct proc_st *proc_to_send = NULL;
|
||||
socklen_t cli_addr_size;
|
||||
uint8_t buffer[1024];
|
||||
char tbuf[64];
|
||||
@@ -672,7 +674,7 @@ uint8_t *session_id = NULL;
|
||||
int session_id_size = 0;
|
||||
ssize_t buffer_size;
|
||||
int connected = 0;
|
||||
int match_ip_only = 0, matching_ips;
|
||||
int match_ip_only = 0;
|
||||
time_t now;
|
||||
|
||||
/* first receive from the correct client and connect socket */
|
||||
@@ -723,32 +725,16 @@ time_t now;
|
||||
|
||||
/* search for the IP and the session ID in all procs */
|
||||
now = time(0);
|
||||
matching_ips = 0;
|
||||
|
||||
list_for_each(&s->proc_list.head, ctmp, list) {
|
||||
if (match_ip_only == 0 && session_id_size == ctmp->dtls_session_id_size &&
|
||||
memcmp(session_id, ctmp->dtls_session_id, session_id_size) == 0) {
|
||||
|
||||
proc_to_send = ctmp;
|
||||
break;
|
||||
} else if (match_ip_only != 0 && cli_addr_size == ctmp->remote_addr_len &&
|
||||
memcmp(SA_IN_P_GENERIC(&cli_addr, cli_addr_size),
|
||||
SA_IN_P_GENERIC(&ctmp->remote_addr, ctmp->remote_addr_len),
|
||||
SA_IN_SIZE(ctmp->remote_addr_len)) == 0) {
|
||||
matching_ips++;
|
||||
proc_to_send = ctmp;
|
||||
}
|
||||
if (match_ip_only == 0) {
|
||||
proc_to_send = proc_search_sid(s, session_id, session_id_size);
|
||||
} else {
|
||||
proc_to_send = proc_search_ip(s, &cli_addr, cli_addr_size);
|
||||
}
|
||||
|
||||
if (proc_to_send != 0) {
|
||||
UdpFdMsg msg = UDP_FD_MSG__INIT;
|
||||
|
||||
if (matching_ips > 1) {
|
||||
mslog(s, proc_to_send, LOG_INFO, "cannot associate with a client; more than a single clients from %s",
|
||||
human_addr((struct sockaddr*)&cli_addr, cli_addr_size, tbuf, sizeof(tbuf)));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (now - proc_to_send->udp_fd_receive_time <= UDP_FD_RESEND_TIME) {
|
||||
mslog(s, proc_to_send, LOG_INFO, "received UDP connection too soon from %s",
|
||||
human_addr((struct sockaddr*)&cli_addr, cli_addr_size, tbuf, sizeof(tbuf)));
|
||||
@@ -921,6 +907,7 @@ int main(int argc, char** argv)
|
||||
tls_cache_init(s, &s->tls_db);
|
||||
cookie_db_init(s, &s->cookies);
|
||||
ip_lease_init(&s->ip_leases);
|
||||
proc_table_init(s);
|
||||
|
||||
sigemptyset(&blockset);
|
||||
sigemptyset(&emptyset);
|
||||
|
||||
@@ -179,6 +179,12 @@ struct cookie_entry_db_st {
|
||||
unsigned total;
|
||||
};
|
||||
|
||||
struct proc_hash_db_st {
|
||||
struct htable *db_ip;
|
||||
struct htable *db_sid;
|
||||
unsigned total;
|
||||
};
|
||||
|
||||
typedef struct main_server_st {
|
||||
struct cfg_st *config;
|
||||
|
||||
@@ -193,6 +199,8 @@ typedef struct main_server_st {
|
||||
struct listen_list_st listen_list;
|
||||
struct proc_list_st proc_list;
|
||||
struct script_list_st script_list;
|
||||
/* maps DTLS session IDs to proc entries */
|
||||
struct proc_hash_db_st proc_table;
|
||||
|
||||
char socket_file[_POSIX_PATH_MAX];
|
||||
char full_socket_file[_POSIX_PATH_MAX];
|
||||
|
||||
160
src/proc-search.c
Normal file
160
src/proc-search.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <proc-search.h>
|
||||
#include <main.h>
|
||||
#include <common.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
40
src/proc-search.h
Normal file
40
src/proc-search.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* Author: Nikos Mavrogiannopoulos
|
||||
*
|
||||
* This file is part of ocserv.
|
||||
*
|
||||
* The GnuTLS is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
#ifndef PROC_SEARCH_H
|
||||
# define PROC_SEARCH_H
|
||||
|
||||
#include <vpn.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ccan/hash/hash.h>
|
||||
#include <main.h>
|
||||
|
||||
struct proc_st *proc_search_ip(struct main_server_st *s,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
unsigned sockaddr_size);
|
||||
struct proc_st *proc_search_sid(struct main_server_st *s, const uint8_t *id, unsigned id_size);
|
||||
|
||||
void proc_table_init(main_server_st *s);
|
||||
void proc_table_deinit(main_server_st *s);
|
||||
void proc_table_add(main_server_st *s, struct proc_st *proc);
|
||||
void proc_table_del(main_server_st *s, struct proc_st *proc);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user