Import Upstream version 1.0.13

This commit is contained in:
Guus Sliepen 2019-08-26 13:44:40 +02:00
parent c54d214bf2
commit 3f0ae998e8
34 changed files with 861 additions and 375 deletions

View file

@ -26,6 +26,7 @@
#include "conf.h"
#include "logger.h"
#include "netutl.h" /* for str2address */
#include "protocol.h"
#include "utils.h" /* for cp */
#include "xalloc.h"
@ -206,111 +207,60 @@ bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
}
/*
Read exactly one line and strip the trailing newline if any. If the
file was on EOF, return NULL. Otherwise, return all the data in a
dynamically allocated buffer.
If line is non-NULL, it will be used as an initial buffer, to avoid
unnecessary mallocing each time this function is called. If buf is
given, and buf needs to be expanded, the var pointed to by buflen
will be increased.
Read exactly one line and strip the trailing newline if any.
*/
static char *readline(FILE * fp, char **buf, size_t *buflen) {
static char *readline(FILE * fp, char *buf, size_t buflen) {
char *newline = NULL;
char *p;
char *line; /* The array that contains everything that has been read so far */
char *idx; /* Read into this pointer, which points to an offset within line */
size_t size, newsize; /* The size of the current array pointed to by line */
size_t maxlen; /* Maximum number of characters that may be read with fgets. This is newsize - oldsize. */
if(feof(fp))
return NULL;
if(buf && buflen) {
size = *buflen;
line = *buf;
} else {
size = 100;
line = xmalloc(size);
}
p = fgets(buf, buflen, fp);
maxlen = size;
idx = line;
*idx = 0;
if(!p)
return NULL;
for(;;) {
errno = 0;
p = fgets(idx, maxlen, fp);
newline = strchr(p, '\n');
if(!p) { /* EOF or error */
if(feof(fp))
break;
if(!newline)
return NULL;
/* otherwise: error; let the calling function print an error message if applicable */
free(line);
return NULL;
}
*newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
newline[-1] = '\0';
newline = strchr(p, '\n');
if(!newline) { /* We haven't yet read everything to the end of the line */
newsize = size << 1;
line = xrealloc(line, newsize);
idx = &line[size - 1];
maxlen = newsize - size + 1;
size = newsize;
} else {
*newline = '\0'; /* kill newline */
if(newline > p && newline[-1] == '\r') /* and carriage return if necessary */
newline[-1] = '\0';
break; /* yay */
}
}
if(buf && buflen) {
*buflen = size;
*buf = line;
}
return line;
return buf;
}
/*
Parse a configuration file and put the results in the configuration tree
starting at *base.
*/
int read_config_file(avl_tree_t *config_tree, const char *fname) {
int err = -2; /* Parse error */
bool read_config_file(avl_tree_t *config_tree, const char *fname) {
FILE *fp;
char *buffer, *line;
char buffer[MAX_STRING_SIZE];
char *line;
char *variable, *value, *eol;
int lineno = 0;
int len;
bool ignore = false;
config_t *cfg;
size_t bufsize;
bool result = false;
fp = fopen(fname, "r");
if(!fp) {
logger(LOG_ERR, "Cannot open config file %s: %s", fname,
strerror(errno));
return -3;
logger(LOG_ERR, "Cannot open config file %s: %s", fname, strerror(errno));
return false;
}
bufsize = 100;
buffer = xmalloc(bufsize);
for(;;) {
if(feof(fp)) {
err = 0;
break;
}
line = readline(fp, &buffer, &bufsize);
line = readline(fp, buffer, sizeof buffer);
if(!line) {
err = -1;
if(feof(fp))
result = true;
break;
}
@ -361,46 +311,46 @@ int read_config_file(avl_tree_t *config_tree, const char *fname) {
config_add(config_tree, cfg);
}
free(buffer);
fclose(fp);
return err;
return result;
}
bool read_server_config() {
char *fname;
int x;
bool x;
xasprintf(&fname, "%s/tinc.conf", confbase);
x = read_config_file(config_tree, fname);
if(x == -1) { /* System error: complain */
if(!x) { /* System error: complain */
logger(LOG_ERR, "Failed to read `%s': %s", fname, strerror(errno));
}
free(fname);
return x == 0;
return x;
}
FILE *ask_and_open(const char *filename, const char *what) {
FILE *r;
char *directory;
char *fn;
char line[PATH_MAX];
const char *fn;
/* Check stdin and stdout */
if(!isatty(0) || !isatty(1)) {
/* Argh, they are running us from a script or something. Write
the files to the current directory and let them burn in hell
for ever. */
fn = xstrdup(filename);
fn = filename;
} else {
/* Ask for a file and/or directory name. */
fprintf(stdout, "Please enter a file to save %s to [%s]: ",
what, filename);
fflush(stdout);
fn = readline(stdin, NULL, NULL);
fn = readline(stdin, line, sizeof line);
if(!fn) {
fprintf(stderr, "Error while reading stdin: %s\n",
@ -410,7 +360,7 @@ FILE *ask_and_open(const char *filename, const char *what) {
if(!strlen(fn))
/* User just pressed enter. */
fn = xstrdup(filename);
fn = filename;
}
#ifdef HAVE_MINGW
@ -423,7 +373,6 @@ FILE *ask_and_open(const char *filename, const char *what) {
directory = get_current_dir_name();
xasprintf(&p, "%s/%s", directory, fn);
free(fn);
free(directory);
fn = p;
}
@ -437,12 +386,9 @@ FILE *ask_and_open(const char *filename, const char *what) {
if(!r) {
fprintf(stderr, "Error opening file `%s': %s\n",
fn, strerror(errno));
free(fn);
return NULL;
}
free(fn);
return r;
}

View file

@ -54,7 +54,7 @@ extern bool get_config_string(const config_t *, char **);
extern bool get_config_address(const config_t *, struct addrinfo **);
extern bool get_config_subnet(const config_t *, struct subnet_t **);
extern int read_config_file(avl_tree_t *, const char *);
extern bool read_config_file(avl_tree_t *, const char *);
extern bool read_server_config(void);
extern FILE *ask_and_open(const char *, const char *);
extern bool is_safe_path(const char *);

View file

@ -130,11 +130,11 @@ void dump_connections(void) {
bool read_connection_config(connection_t *c) {
char *fname;
int x;
bool x;
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
free(fname);
return x == 0;
return x;
}

View file

@ -68,9 +68,9 @@ static void purge(void) {
for(snode = n->subnet_tree->head; snode; snode = snext) {
snext = snode->next;
s = snode->data;
if(!tunnelserver)
send_del_subnet(broadcast, s);
subnet_del(n, s);
send_del_subnet(broadcast, s);
if(!strictsubnets)
subnet_del(n, s);
}
for(enode = n->edge_tree->head; enode; enode = enext) {
@ -98,7 +98,8 @@ static void purge(void) {
break;
}
if(!enode)
if(!enode && (!strictsubnets || !n->subnet_tree->head))
/* in strictsubnets mode do not delete nodes with subnets */
node_del(n);
}
}
@ -488,6 +489,36 @@ int main_loop(void) {
last_config_check = now;
/* If StrictSubnet is set, expire deleted Subnets and read new ones in */
if(strictsubnets) {
subnet_t *subnet;
for(node = subnet_tree->head; node; node = node->next) {
subnet = node->data;
subnet->expires = 1;
}
load_all_subnets();
for(node = subnet_tree->head; node; node = next) {
next = node->next;
subnet = node->data;
if(subnet->expires == 1) {
send_del_subnet(broadcast, subnet);
if(subnet->owner->status.reachable)
subnet_update(subnet->owner, subnet, false);
subnet_del(subnet->owner, subnet);
} else if(subnet->expires == -1) {
subnet->expires = 0;
} else {
send_add_subnet(broadcast, subnet);
if(subnet->owner->status.reachable)
subnet_update(subnet->owner, subnet, true);
}
}
}
/* Try to make outgoing connections */
try_outgoing_connections();

View file

@ -139,6 +139,7 @@ extern void terminate_connection(struct connection_t *, bool);
extern void flush_queue(struct node_t *);
extern bool read_rsa_public_key(struct connection_t *);
extern void send_mtu_probe(struct node_t *);
extern void load_all_subnets();
#ifndef HAVE_MINGW
#define closesocket(s) close(s)

View file

@ -26,8 +26,13 @@
#include <openssl/pem.h>
#include <openssl/hmac.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#ifdef HAVE_LZO
#include LZO1X_H
#endif
#include "avl_tree.h"
#include "conf.h"
@ -48,7 +53,9 @@
int keylifetime = 0;
int keyexpires = 0;
#ifdef HAVE_LZO
static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999_MEM_COMPRESS : LZO1X_1_MEM_COMPRESS];
#endif
static void send_udppacket(node_t *, vpn_packet_t *);
@ -147,40 +154,61 @@ void mtu_probe_h(node_t *n, vpn_packet_t *packet, length_t len) {
}
static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
if(level == 10) {
if(level == 0) {
memcpy(dest, source, len);
return len;
} else if(level == 10) {
#ifdef HAVE_LZO
lzo_uint lzolen = MAXSIZE;
lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem);
return lzolen;
#else
return -1;
#endif
} else if(level < 10) {
#ifdef HAVE_ZLIB
unsigned long destlen = MAXSIZE;
if(compress2(dest, &destlen, source, len, level) == Z_OK)
return destlen;
else
#endif
return -1;
} else {
#ifdef HAVE_LZO
lzo_uint lzolen = MAXSIZE;
lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem);
return lzolen;
#else
return -1;
#endif
}
return -1;
}
static length_t uncompress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) {
if(level > 9) {
if(level == 0) {
memcpy(dest, source, len);
return len;
} else if(level > 9) {
#ifdef HAVE_LZO
lzo_uint lzolen = MAXSIZE;
if(lzo1x_decompress_safe(source, len, dest, &lzolen, NULL) == LZO_E_OK)
return lzolen;
else
#endif
return -1;
} else {
}
#ifdef HAVE_ZLIB
else {
unsigned long destlen = MAXSIZE;
if(uncompress(dest, &destlen, source, len) == Z_OK)
return destlen;
else
return -1;
}
#endif
return -1;
}

View file

@ -201,6 +201,68 @@ bool read_rsa_private_key(void) {
return true;
}
/*
Read Subnets from all host config files
*/
void load_all_subnets(void) {
DIR *dir;
struct dirent *ent;
char *dname;
char *fname;
avl_tree_t *config_tree;
config_t *cfg;
subnet_t *s, *s2;
node_t *n;
bool result;
xasprintf(&dname, "%s/hosts", confbase);
dir = opendir(dname);
if(!dir) {
logger(LOG_ERR, "Could not open %s: %s", dname, strerror(errno));
free(dname);
return;
}
while((ent = readdir(dir))) {
if(!check_id(ent->d_name))
continue;
n = lookup_node(ent->d_name);
#ifdef _DIRENT_HAVE_D_TYPE
//if(ent->d_type != DT_REG)
// continue;
#endif
xasprintf(&fname, "%s/hosts/%s", confbase, ent->d_name);
init_configuration(&config_tree);
result = read_config_file(config_tree, fname);
free(fname);
if(!result)
continue;
if(!n) {
n = new_node();
n->name = xstrdup(ent->d_name);
node_add(n);
}
for(cfg = lookup_config(config_tree, "Subnet"); cfg; cfg = lookup_config_next(config_tree, cfg)) {
if(!get_config_subnet(cfg, &s))
continue;
if((s2 = lookup_subnet(n, s))) {
s2->expires = -1;
} else {
subnet_add(n, s);
}
}
exit_configuration(&config_tree);
}
closedir(dir);
}
/*
Configure node_t myself and set up the local sockets (listen only)
*/
@ -250,6 +312,16 @@ bool setup_myself(void) {
&& !get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport))
myport = xstrdup("655");
if(!atoi(myport)) {
struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
sockaddr_t sa;
if(!ai || !ai->ai_addr)
return false;
free(myport);
memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
sockaddr2str(&sa, NULL, &myport);
}
/* Read in all the subnets specified in the host configuration file */
cfg = lookup_config(myself->connection->config_tree, "Subnet");
@ -280,7 +352,10 @@ bool setup_myself(void) {
if(myself->options & OPTION_TCPONLY)
myself->options |= OPTION_INDIRECT;
get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
strictsubnets |= tunnelserver;
if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
if(!strcasecmp(mode, "router"))
@ -294,8 +369,21 @@ bool setup_myself(void) {
return false;
}
free(mode);
} else
routing_mode = RMODE_ROUTER;
}
if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
if(!strcasecmp(mode, "off"))
forwarding_mode = FMODE_OFF;
else if(!strcasecmp(mode, "internal"))
forwarding_mode = FMODE_INTERNAL;
else if(!strcasecmp(mode, "kernel"))
forwarding_mode = FMODE_KERNEL;
else {
logger(LOG_ERR, "Invalid forwarding mode!");
return false;
}
free(mode);
}
choice = true;
get_config_bool(lookup_config(myself->connection->config_tree, "PMTUDiscovery"), &choice);
@ -426,6 +514,9 @@ bool setup_myself(void) {
graph();
if(strictsubnets)
load_all_subnets();
/* Open device */
if(!setup_device())

View file

@ -102,8 +102,10 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
if(scopeid)
*scopeid = '\0'; /* Descope. */
*addrstr = xstrdup(address);
*portstr = xstrdup(port);
if(addrstr)
*addrstr = xstrdup(address);
if(portstr)
*portstr = xstrdup(port);
}
char *sockaddr2hostname(const sockaddr_t *sa) {

View file

@ -29,6 +29,7 @@
#include "xalloc.h"
bool tunnelserver = false;
bool strictsubnets = false;
/* Jumptable for the request handlers */

View file

@ -53,6 +53,7 @@ typedef struct past_request_t {
} past_request_t;
extern bool tunnelserver;
extern bool strictsubnets;
/* Maximum size of strings in a request.
* scanf terminates %2048s with a NUL character,

View file

@ -497,7 +497,7 @@ static void send_everything(connection_t *c) {
bool ack_h(connection_t *c) {
char hisport[MAX_STRING_SIZE];
char *hisaddress, *dummy;
char *hisaddress;
int weight, mtu;
uint32_t options;
node_t *n;
@ -566,10 +566,9 @@ bool ack_h(connection_t *c) {
c->edge = new_edge();
c->edge->from = myself;
c->edge->to = n;
sockaddr2str(&c->address, &hisaddress, &dummy);
sockaddr2str(&c->address, &hisaddress, NULL);
c->edge->address = str2sockaddr(hisaddress, hisport);
free(hisaddress);
free(dummy);
c->edge->weight = (weight + c->estimated_weight) / 2;
c->edge->connection = c;
c->edge->options = c->options;

View file

@ -104,29 +104,21 @@ bool add_subnet_h(connection_t *c) {
return true;
}
/* In tunnel server mode, check if the subnet matches one in the config file of this node */
/* In tunnel server mode, we should already know all allowed subnets */
if(tunnelserver) {
config_t *cfg;
subnet_t *allowed;
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
"ADD_SUBNET", c->name, c->hostname, subnetstr);
return true;
}
for(cfg = lookup_config(c->config_tree, "Subnet"); cfg; cfg = lookup_config_next(c->config_tree, cfg)) {
if(!get_config_subnet(cfg, &allowed))
continue;
/* Ignore if strictsubnets is true, but forward it to others */
if(!subnet_compare(&s, allowed))
break;
free_subnet(allowed);
}
if(!cfg) {
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
"ADD_SUBNET", c->name, c->hostname, subnetstr);
return true;
}
free_subnet(allowed);
if(strictsubnets) {
logger(LOG_WARNING, "Ignoring unauthorized %s from %s (%s): %s",
"ADD_SUBNET", c->name, c->hostname, subnetstr);
forward_request(c);
return true;
}
/* If everything is correct, add the subnet to the list of the owner */
@ -139,8 +131,7 @@ bool add_subnet_h(connection_t *c) {
/* Tell the rest */
if(!tunnelserver)
forward_request(c);
forward_request(c);
/* Fast handoff of roaming MAC addresses */
@ -216,6 +207,8 @@ bool del_subnet_h(connection_t *c) {
if(!find) {
ifdebug(PROTOCOL) logger(LOG_WARNING, "Got %s from %s (%s) for %s which does not appear in his subnet tree",
"DEL_SUBNET", c->name, c->hostname, name);
if(strictsubnets)
forward_request(c);
return true;
}
@ -228,10 +221,14 @@ bool del_subnet_h(connection_t *c) {
return true;
}
if(tunnelserver)
return true;
/* Tell the rest */
if(!tunnelserver)
forward_request(c);
forward_request(c);
if(strictsubnets)
return true;
/* Finally, delete it. */

View file

@ -33,6 +33,8 @@
#include "utils.h"
rmode_t routing_mode = RMODE_ROUTER;
fmode_t forwarding_mode = FMODE_INTERNAL;
bool directonly = false;
bool priorityinheritance = false;
int macexpire = 600;
bool overwrite_mac = false;
@ -48,7 +50,10 @@ static const size_t ip6_size = sizeof(struct ip6_hdr);
static const size_t icmp6_size = sizeof(struct icmp6_hdr);
static const size_t ns_size = sizeof(struct nd_neighbor_solicit);
static const size_t opt_size = sizeof(struct nd_opt_hdr);
#define max(a, b) ((a) > (b) ? (a) : (b))
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif
/* RFC 1071 */
@ -94,9 +99,13 @@ static bool checklength(node_t *source, vpn_packet_t *packet, length_t length) {
}
static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *packet) {
if(!via || via == myself || !(via->options & OPTION_CLAMP_MSS))
if(!source || !via || !(via->options & OPTION_CLAMP_MSS))
return;
uint16_t mtu = source->mtu;
if(via != myself && via->mtu < mtu)
mtu = via->mtu;
/* Find TCP header */
int start = 0;
uint16_t type = packet->data[12] << 8 | packet->data[13];
@ -140,7 +149,7 @@ static void clamp_mss(const node_t *source, const node_t *via, vpn_packet_t *pac
/* Found it */
uint16_t oldmss = packet->data[start + 22 + i] << 8 | packet->data[start + 23 + i];
uint16_t newmss = via->mtu - start - 20;
uint16_t newmss = mtu - start - 20;
uint16_t csum = packet->data[start + 16] << 8 | packet->data[start + 17];
if(oldmss <= newmss)
@ -379,17 +388,23 @@ static void route_ipv4_unicast(node_t *source, vpn_packet_t *packet) {
}
if(!subnet->owner->status.reachable)
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
if(priorityinheritance)
packet->priority = packet->data[15];
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(via && packet->len > max(via->mtu, 590) && via != myself) {
if(directonly && subnet->owner != via)
return route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_NET_ANO);
if(via && packet->len > MAX(via->mtu, 590) && via != myself) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
if(packet->data[20] & 0x40) {
packet->len = max(via->mtu, 590);
packet->len = MAX(via->mtu, 590);
route_ipv4_unreachable(source, packet, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED);
} else {
fragment_ipv4_packet(via, packet);
@ -527,13 +542,19 @@ static void route_ipv6_unicast(node_t *source, vpn_packet_t *packet) {
}
if(!subnet->owner->status.reachable)
route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE);
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(via && packet->len > max(via->mtu, 1294) && via != myself) {
if(directonly && subnet->owner != via)
return route_ipv6_unreachable(source, packet, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADMIN);
if(via && packet->len > MAX(via->mtu, 1294) && via != myself) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
packet->len = max(via->mtu, 1294);
packet->len = MAX(via->mtu, 1294);
route_ipv6_unreachable(source, packet, ICMP6_PACKET_TOO_BIG, 0);
return;
}
@ -792,9 +813,15 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
return;
}
if(forwarding_mode == FMODE_OFF && source != myself && subnet->owner != myself)
return;
// Handle packets larger than PMTU
node_t *via = (subnet->owner->via == myself) ? subnet->owner->nexthop : subnet->owner->via;
if(directonly && subnet->owner != via)
return;
if(via && packet->len > via->mtu && via != myself) {
ifdebug(TRAFFIC) logger(LOG_INFO, "Packet for %s (%s) length %d larger than MTU %d", subnet->owner->name, subnet->owner->hostname, packet->len, via->mtu);
@ -820,6 +847,11 @@ static void route_mac(node_t *source, vpn_packet_t *packet) {
}
void route(node_t *source, vpn_packet_t *packet) {
if(forwarding_mode == FMODE_KERNEL && source != myself) {
send_packet(myself, packet);
return;
}
if(!checklength(source, packet, ether_size))
return;

View file

@ -30,7 +30,15 @@ typedef enum rmode_t {
RMODE_ROUTER,
} rmode_t;
typedef enum fmode_t {
FMODE_OFF = 0,
FMODE_INTERNAL,
FMODE_KERNEL,
} fmode_t;
extern rmode_t routing_mode;
extern fmode_t forwarding_mode;
extern bool directonly;
extern bool overwrite_mac;
extern bool priorityinheritance;
extern int macexpire;

View file

@ -64,6 +64,8 @@ typedef struct subnet_t {
#define MAXNETSTR 64
extern avl_tree_t *subnet_tree;
extern int subnet_compare(const struct subnet_t *, const struct subnet_t *);
extern subnet_t *new_subnet(void) __attribute__ ((__malloc__));
extern void free_subnet(subnet_t *);

View file

@ -37,7 +37,9 @@
#include <openssl/evp.h>
#include <openssl/engine.h>
#ifdef HAVE_LZO
#include LZO1X_H
#endif
#ifndef HAVE_MINGW
#include <pwd.h>
@ -540,10 +542,12 @@ int main(int argc, char **argv) {
if(!read_server_config())
return 1;
#ifdef HAVE_LZO
if(lzo_init() != LZO_E_OK) {
logger(LOG_ERR, "Error initializing LZO compressor!");
return 1;
}
#endif
#ifdef HAVE_MINGW
if(WSAStartup(MAKEWORD(2, 2), &wsa_state)) {