mirror of
https://gitlab.com/openconnect/ocserv.git
synced 2026-02-10 16:57:00 +08:00
Avoid many system calls when sending serialized data.
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#include <gnutls/crypto.h>
|
||||
#include <tlslib.h>
|
||||
#include "ipc.h"
|
||||
#include "str.h"
|
||||
|
||||
#include <vpn.h>
|
||||
#include <cookies.h>
|
||||
@@ -61,23 +62,22 @@ void main_auth_init(main_server_st *s)
|
||||
}
|
||||
}
|
||||
|
||||
static int send_str_value_length(main_server_st* s, struct proc_st* proc, char* data)
|
||||
static int send_value_length(main_server_st* s, struct proc_st* proc, const void* data, size_t _len)
|
||||
{
|
||||
uint8_t len;
|
||||
uint16_t len = _len;
|
||||
int ret;
|
||||
|
||||
if (data != NULL) {
|
||||
len = strlen(data);
|
||||
ret = force_write(proc->fd, &len, 1);
|
||||
if (len > 0) {
|
||||
ret = force_write(proc->fd, &len, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = force_write(proc->fd, proc->config.ipv4_dns, len);
|
||||
ret = force_write(proc->fd, data, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
len = 0;
|
||||
ret = force_write(proc->fd, &len, 1);
|
||||
ret = force_write(proc->fd, &len, 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
@@ -91,69 +91,75 @@ int serialize_additional_data(main_server_st* s, struct proc_st* proc)
|
||||
int ret;
|
||||
unsigned i;
|
||||
uint8_t len;
|
||||
str_st buffer;
|
||||
|
||||
str_init(&buffer);
|
||||
|
||||
/* IPv4 DNS */
|
||||
if (proc->config.ipv4_dns)
|
||||
mslog(s, proc, LOG_DEBUG, "sending DNS '%s'", proc->config.ipv4_dns);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv4_dns);
|
||||
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv4_dns);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPv6 DNS */
|
||||
if (proc->config.ipv6_dns)
|
||||
mslog(s, proc, LOG_DEBUG, "sending DNS '%s'", proc->config.ipv6_dns);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv6_dns);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv6_dns);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPv4 NBNS */
|
||||
if (proc->config.ipv4_nbns)
|
||||
mslog(s, proc, LOG_DEBUG, "sending NBNS '%s'", proc->config.ipv4_nbns);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv4_nbns);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv4_nbns);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPv6 NBNS */
|
||||
if (proc->config.ipv6_nbns)
|
||||
mslog(s, proc, LOG_DEBUG, "sending NBNS '%s'", proc->config.ipv6_nbns);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv6_nbns);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv6_nbns);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPv4 netmask */
|
||||
if (proc->config.ipv4_netmask)
|
||||
mslog(s, proc, LOG_DEBUG, "sending netmask '%s'", proc->config.ipv4_netmask);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv4_netmask);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv4_netmask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPv6 netmask */
|
||||
if (proc->config.ipv6_netmask)
|
||||
mslog(s, proc, LOG_DEBUG, "sending netmask '%s'", proc->config.ipv6_netmask);
|
||||
ret = send_str_value_length(s, proc, proc->config.ipv6_netmask);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.ipv6_netmask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* routes */
|
||||
len = proc->config.routes_size;
|
||||
ret = force_write(proc->fd, &len, 1);
|
||||
ret = str_append_data(&buffer, &len, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
for (i=0;i<proc->config.routes_size;i++) {
|
||||
len = strlen(proc->config.routes[i]);
|
||||
|
||||
mslog(s, proc, LOG_DEBUG, "sending route '%s'", proc->config.routes[i]);
|
||||
ret = force_write(proc->fd, &len, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = force_write(proc->fd, proc->config.routes[i], len);
|
||||
ret = str_append_str_prefix1(&buffer, proc->config.routes[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = send_value_length(s, proc, buffer.data, buffer.length);
|
||||
if (ret < 0)
|
||||
goto cleanup;
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
str_clear(&buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int send_auth_reply(main_server_st* s, struct proc_st* proc,
|
||||
|
||||
83
src/str.c
83
src/str.c
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2013 Nikos Mavrogiannopoulos
|
||||
*
|
||||
* Author: Nikos Mavrogiannopoulos
|
||||
*
|
||||
@@ -43,9 +44,9 @@ void str_clear(str_st * str)
|
||||
}
|
||||
|
||||
#define MIN_CHUNK 64
|
||||
/* This function always null terminates the string in dest.
|
||||
/* This function makes sure there is an additional byte in dest;
|
||||
*/
|
||||
int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
int str_append_size(str_st * dest, size_t data_size)
|
||||
{
|
||||
size_t tot_len = data_size + dest->length;
|
||||
|
||||
@@ -62,9 +63,6 @@ int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
|
||||
dest->data = dest->allocd;
|
||||
}
|
||||
memmove(&dest->data[dest->length], data, data_size);
|
||||
dest->length = tot_len;
|
||||
dest->data[dest->length] = 0;
|
||||
|
||||
return tot_len;
|
||||
} else {
|
||||
@@ -83,14 +81,40 @@ int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
memmove(dest->allocd, dest->data, dest->length);
|
||||
dest->data = dest->allocd;
|
||||
|
||||
memcpy(&dest->data[dest->length], data, data_size);
|
||||
dest->length = tot_len;
|
||||
dest->data[dest->length] = 0;
|
||||
|
||||
return tot_len;
|
||||
}
|
||||
}
|
||||
|
||||
/* This function always null terminates the string in dest.
|
||||
*/
|
||||
int str_append_data(str_st * dest, const void *data, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = str_append_size(dest, data_size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
memcpy(&dest->data[dest->length], data, data_size);
|
||||
dest->length = data_size + dest->length;
|
||||
dest->data[dest->length] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int str_append_data_prefix1(str_st * dest, const void *data, size_t data_size)
|
||||
{
|
||||
int ret;
|
||||
uint8_t prefix = data_size;
|
||||
|
||||
ret = str_append_data(dest, &prefix, 1);
|
||||
if (ret >= 0) {
|
||||
ret = str_append_data(dest, data, data_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Appends the provided string. The null termination byte is appended
|
||||
* but not included in length.
|
||||
*/
|
||||
@@ -103,3 +127,44 @@ int str_append_str(str_st * dest, const char *src)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Makes sure that the data read are null terminated (but not counted in *data_size)
|
||||
* If the size of the data is zero then *data will be null;
|
||||
*/
|
||||
int str_read_data_prefix1(str_st * src, char **data, size_t *data_size)
|
||||
{
|
||||
uint8_t prefix;
|
||||
|
||||
if (src->length < 1)
|
||||
return ERR_MEM;
|
||||
|
||||
prefix = src->data[0];
|
||||
|
||||
if (src->length < prefix)
|
||||
return ERR_MEM;
|
||||
|
||||
src->data++;
|
||||
src->length--;
|
||||
|
||||
if (prefix == 0) {
|
||||
if (data_size)
|
||||
*data_size = 0;
|
||||
*data = NULL;
|
||||
|
||||
} else {
|
||||
|
||||
if (data_size)
|
||||
*data_size = prefix + 1;
|
||||
|
||||
*data = malloc(((int)prefix)+1);
|
||||
if (*data == NULL)
|
||||
return ERR_MEM;
|
||||
|
||||
memcpy(*data, src->data, prefix);
|
||||
(*data)[prefix] = 0;
|
||||
|
||||
src->data += prefix;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,10 @@ inline static void str_reset(str_st * buf)
|
||||
|
||||
int str_append_str(str_st *, const char *str);
|
||||
int str_append_data(str_st *, const void *data, size_t data_size);
|
||||
int str_append_size(str_st *, size_t data_size);
|
||||
int str_append_data_prefix1(str_st *, const void *data, size_t data_size);
|
||||
int str_read_data_prefix1(str_st * src, char **data, size_t *data_size);
|
||||
|
||||
#define str_append_str_prefix1(s, str) (((str)==NULL)?str_append_data_prefix1(s, NULL, 0):str_append_data_prefix1(s, str, strlen(str)))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -196,11 +196,6 @@ const char *human_addr(const struct sockaddr *sa, socklen_t salen,
|
||||
#define SA_IN_SIZE(size) ((size==sizeof(struct sockaddr_in))?sizeof(struct in_addr):sizeof(struct in6_addr))
|
||||
|
||||
/* Helper structures */
|
||||
struct route_st {
|
||||
uint8_t size;
|
||||
char *route;
|
||||
};
|
||||
|
||||
enum option_types { OPTION_NUMERIC, OPTION_STRING, OPTION_BOOLEAN, OPTION_MULTI_LINE };
|
||||
|
||||
#endif
|
||||
|
||||
@@ -253,28 +253,29 @@ static int send_auth_cookie_req(int fd, const struct cmd_auth_cookie_req_st* r)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int read_str_value_length(worker_st *ws, char** res)
|
||||
static int recv_value_length(worker_st *ws, str_st* b)
|
||||
{
|
||||
int ret;
|
||||
uint8_t len;
|
||||
uint16_t len;
|
||||
|
||||
ret = force_read(ws->cmd_fd, &len, 1);
|
||||
if (ret != 1) {
|
||||
ret = force_read(ws->cmd_fd, &len, 2);
|
||||
if (ret != 2) {
|
||||
oclog(ws, LOG_ERR, "Error receiving length-value from main (%d)", ret);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
*res = malloc(((int)len)+1);
|
||||
if (*res == NULL)
|
||||
return ERR_MEM;
|
||||
|
||||
ret = force_read(ws->cmd_fd, *res, len);
|
||||
ret = str_append_size(b, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = force_read(ws->cmd_fd, b->data, len);
|
||||
if (ret != len) {
|
||||
oclog(ws, LOG_ERR, "Error receiving value from main (%d)", ret);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
(*res)[len] = 0;
|
||||
b->length += len;
|
||||
b->data[len] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -284,68 +285,69 @@ static
|
||||
int deserialize_additional_data(worker_st* ws)
|
||||
{
|
||||
int ret;
|
||||
uint8_t len;
|
||||
unsigned i;
|
||||
str_st b;
|
||||
|
||||
/* IPV4 DNS */
|
||||
ret = read_str_value_length(ws, &ws->ipv4_dns);
|
||||
str_init(&b);
|
||||
|
||||
ret = recv_value_length(ws, &b);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPV4 DNS */
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv4_dns, NULL);
|
||||
if (ret < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* IPV6 DNS */
|
||||
ret = read_str_value_length(ws, &ws->ipv6_dns);
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv6_dns, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPV4 NBNS */
|
||||
ret = read_str_value_length(ws, &ws->ipv4_nbns);
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv4_nbns, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPV6 NBNS */
|
||||
ret = read_str_value_length(ws, &ws->ipv6_nbns);
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv6_nbns, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPV4 netmask */
|
||||
ret = read_str_value_length(ws, &ws->ipv4_netmask);
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv4_netmask, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* IPV6 netmask */
|
||||
ret = read_str_value_length(ws, &ws->ipv6_netmask);
|
||||
ret = str_read_data_prefix1(&b, &ws->ipv6_netmask, NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto cleanup;
|
||||
|
||||
/* number of routes */
|
||||
ret = force_read(ws->cmd_fd, &len, 1);
|
||||
if (ret != 1) {
|
||||
oclog(ws, LOG_ERR, "Error receiving length-value from main (%d)", ret);
|
||||
return ERR_BAD_COMMAND;
|
||||
if (b.length < 1) {
|
||||
oclog(ws, LOG_ERR, "Error in received length-value from main");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
ws->routes_size = len;
|
||||
ws->routes_size = b.data[0];
|
||||
b.length--;
|
||||
b.data++;
|
||||
|
||||
/* routes */
|
||||
for (i=0;i<ws->routes_size;i++) {
|
||||
ret = force_read(ws->cmd_fd, &ws->routes[i].size, 1);
|
||||
if (ret != 1) {
|
||||
oclog(ws, LOG_ERR, "Error received route size from main (%d)", ret);
|
||||
return ERR_BAD_COMMAND;
|
||||
ret = str_read_data_prefix1(&b, &ws->routes[i], NULL);
|
||||
if (ret < 0) {
|
||||
oclog(ws, LOG_ERR, "Error receiving private routes from main");
|
||||
ret = ERR_BAD_COMMAND;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ws->routes[i].route = malloc(ws->routes[i].size+1);
|
||||
if (ws->routes[i].route == NULL)
|
||||
return ERR_MEM;
|
||||
|
||||
ret = force_read(ws->cmd_fd, ws->routes[i].route, ws->routes[i].size);
|
||||
if (ret != ws->routes[i].size) {
|
||||
oclog(ws, LOG_ERR, "Error received routes from main (%d)", ret);
|
||||
return ERR_BAD_COMMAND;
|
||||
}
|
||||
ws->routes[i].route[ws->routes[i].size] = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
ret = 0;
|
||||
cleanup:
|
||||
str_clear(&b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int recv_auth_reply(worker_st *ws, struct cmd_auth_reply_msg_st* mresp)
|
||||
|
||||
@@ -899,13 +899,13 @@ socklen_t sl;
|
||||
}
|
||||
|
||||
for (i=0;i<ws->routes_size;i++) {
|
||||
if (req->no_ipv6 != 0 && strchr(ws->routes[i].route, ':') != 0)
|
||||
if (req->no_ipv6 != 0 && strchr(ws->routes[i], ':') != 0)
|
||||
continue;
|
||||
if (req->no_ipv4 != 0 && strchr(ws->routes[i].route, '.') != 0)
|
||||
if (req->no_ipv4 != 0 && strchr(ws->routes[i], '.') != 0)
|
||||
continue;
|
||||
oclog(ws, LOG_DEBUG, "adding route %s", ws->routes[i].route);
|
||||
oclog(ws, LOG_DEBUG, "adding private route %s", ws->routes[i]);
|
||||
ret = tls_printf(ws->session,
|
||||
"X-CSTP-Split-Include: %s\r\n", ws->routes[i].route);
|
||||
"X-CSTP-Split-Include: %s\r\n", ws->routes[i]);
|
||||
SEND_ERR(ret);
|
||||
}
|
||||
ret = tls_printf(ws->session, "X-CSTP-Keepalive: %u\r\n", ws->config->keepalive);
|
||||
|
||||
@@ -126,7 +126,7 @@ typedef struct worker_st {
|
||||
char *ipv4_netmask;
|
||||
char *ipv6_netmask;
|
||||
unsigned routes_size;
|
||||
struct route_st routes[MAX_ROUTES];
|
||||
char* routes[MAX_ROUTES];
|
||||
|
||||
struct http_req_st req;
|
||||
} worker_st;
|
||||
|
||||
Reference in New Issue
Block a user