Compare commits

..

9 Commits

Author SHA1 Message Date
angt
e5eb30598d Code cleanup 2015-12-24 17:38:08 +01:00
angt
c81ad0a7c6 One more time 2015-12-24 17:35:01 +01:00
angt
97641d6dda Reserve exclam for very bad message 2015-12-24 17:32:32 +01:00
angt
e48dac775c The statefile option needs an absolute path and a fifo 2015-12-24 17:29:41 +01:00
angt
6282f36ac7 Add statefile option 2015-12-24 16:53:50 +01:00
angt
cf022af4a9 Simplify the db by merging size and mask 2015-12-24 13:13:43 +01:00
angt
597c586657 Don't free data in db_remove() 2015-12-23 22:26:53 +01:00
angt
fc7f9aa0c8 Add a very simple low cost database 2015-12-23 17:11:20 +01:00
angt
7492f977b6 Define a simple proto 2015-12-21 12:34:24 +01:00
7 changed files with 232 additions and 20 deletions

View File

@@ -13,7 +13,9 @@ glorytun_SOURCES = \
src/option.c \
src/option.h \
src/tun.c \
src/tun.h
src/tun.h \
src/db.c \
src/db.h
EXTRA_DIST = \
LICENSE \

View File

@@ -50,16 +50,18 @@ static inline int str_empty (const char *restrict str)
}
_pure_
static inline int str_cmp (const char *restrict sa, const char *restrict sb)
static inline size_t str_cmp (const char *restrict sa, const char *restrict sb)
{
if (!sa || !sb)
return 1;
while (*sa==*sb++)
if (!*sa++)
return 0;
size_t i = 0;
return 1;
while (sa[i]==sb[i])
if (!sa[i++])
return 0;
return i+1;
}
_pure_

View File

@@ -36,7 +36,7 @@ void gt_fatal (const char *fmt, ...)
void gt_na (const char *name)
{
gt_log("%s is not available on your platform!\n", name);
gt_log("%s is not available on your platform\n", name);
}
int gt_tohex (char *dst, size_t dst_size, const uint8_t *src, size_t src_size)

View File

@@ -17,12 +17,14 @@
#define _1_(x) (__builtin_expect((x), 1))
#define _0_(x) (__builtin_expect((x), 0))
#define _printf_(A,B) __attribute__((format(printf,A,B)))
#define _noreturn_ __attribute__((noreturn))
#define _unused_ __attribute__((unused))
#define _pure_ __attribute__((pure))
#define _const_ __attribute__((const))
#define _align_(...) __attribute__((aligned(__VA_ARGS__)))
#define CLZ(x) (__builtin_clz(x))
#define _printf_(A,B) __attribute__ ((format(printf,A,B)))
#define _noreturn_ __attribute__ ((noreturn))
#define _unused_ __attribute__ ((unused))
#define _pure_ __attribute__ ((pure))
#define _const_ __attribute__ ((const))
#define _align_(...) __attribute__ ((aligned(__VA_ARGS__)))
typedef struct buffer buffer_t;

153
src/db.c Normal file
View File

@@ -0,0 +1,153 @@
#include "db.h"
#include "common-static.h"
#define CBIT(X) (1&(intptr_t)(X))
#define CBIT_PTR(X) (uint8_t *)(1|(intptr_t)(X))
#define CBIT_NODE(X) (struct node *)(1^(intptr_t)(X))
struct node {
uint8_t *child[2];
uint32_t point;
};
_pure_
static inline size_t db_size (const uint8_t *a)
{
return (a[0]?:str_len((char *)a+1))+1;
}
_pure_
static inline size_t db_cmp (const uint8_t *a, const uint8_t *b)
{
const size_t size = a[0];
if (size!=b[0])
return 1;
if (!size) {
size_t i = str_cmp((char *)a+1, (char *)b+1);
return i?i+1:0;
}
for (size_t i=1; i<=size; i++) {
if (a[i]!=b[i])
return i+1;
}
return 0;
}
_pure_
static inline int db_dir (const uint32_t point, uint8_t *data, const size_t size)
{
const size_t pos = point>>8;
if (pos>=size)
return 0;
return ((point|data[pos])&255)==255;
}
uint8_t *db_search (uint8_t **p, uint8_t *data)
{
if _0_(!*p)
return NULL;
uint8_t *r = *p;
const size_t size = db_size(data);
while (CBIT(r)) {
struct node *node = CBIT_NODE(r);
r = node->child[db_dir(node->point, data, size)];
}
if (!db_cmp(r, data))
return r;
return NULL;
}
uint8_t *db_insert (uint8_t **p, uint8_t *data)
{
if _0_(CBIT(data))
return NULL;
if _0_(!*p) {
*p = data;
return data;
}
uint8_t *r = *p;
size_t size = db_size(data);
while (CBIT(r)) {
struct node *node = CBIT_NODE(r);
r = node->child[db_dir(node->point, data, size)];
}
const size_t diff = db_cmp(r, data);
if _0_(!diff)
return r;
const size_t pos = diff-1;
const uint8_t mask = ~((1u<<31)>>CLZ(r[pos]^data[pos]));
const size_t point = (pos<<8)|mask;
while (CBIT(*p)) {
struct node *node = CBIT_NODE(*p);
if (node->point>point)
break;
p = node->child+db_dir(node->point, data, size);
}
struct node *node = malloc(sizeof(struct node));
if _0_(!node)
return NULL;
const int dir = (mask|r[pos])==255;
node->child[dir] = *p;
node->child[1-dir] = data;
node->point = point;
*p = CBIT_PTR(node);
return data;
}
uint8_t *db_remove (uint8_t **p, uint8_t *data)
{
if _0_(!*p)
return NULL;
const size_t size = db_size(data);
uint8_t **p_old = NULL;
struct node *node = NULL;
int dir = 0;
while (CBIT(*p)) {
p_old = p;
node = CBIT_NODE(*p);
dir = db_dir(node->point, data, size);
p = node->child+dir;
}
if _0_(db_cmp(data, *p))
return NULL;
uint8_t *r = *p;
if (p_old) {
*p_old = node->child[1-dir];
free(node);
} else {
*p = NULL;
}
return r;
}

7
src/db.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <stdint.h>
uint8_t *db_search (uint8_t **, uint8_t *);
uint8_t *db_insert (uint8_t **, uint8_t *);
uint8_t *db_remove (uint8_t **, uint8_t *);

View File

@@ -2,9 +2,11 @@
#include <limits.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#ifndef __FAVOR_BSD
#define __FAVOR_BSD
@@ -41,6 +43,9 @@
#define GT_TUNR_SIZE (0x7FFF-16)
#define GT_TUNW_SIZE (0x7FFF)
#define GT_STARTED "STARTED\n"
#define GT_STOPPED "STOPPED\n"
struct fdbuf {
int fd;
buffer_t read;
@@ -341,7 +346,7 @@ static void gt_set_signal (void)
static ssize_t fd_read (int fd, void *data, size_t size)
{
if (!size)
if ((fd==-1) || !size)
return -1;
ssize_t ret = read(fd, data, size);
@@ -361,7 +366,7 @@ static ssize_t fd_read (int fd, void *data, size_t size)
static ssize_t fd_write (int fd, const void *data, size_t size)
{
if (!size)
if ((fd==-1) || !size)
return -1;
ssize_t ret = write(fd, data, size);
@@ -610,10 +615,11 @@ static int gt_setup_secretkey (struct crypto_ctx *ctx, char *keyfile)
static int gt_setup_crypto (struct crypto_ctx *ctx, int fd, int listener)
{
const size_t size = 96;
const size_t hash_size = 32;
const size_t nonce_size = crypto_aead_aes256gcm_NPUBBYTES;
const size_t public_size = crypto_scalarmult_SCALARBYTES;
const size_t hash_size = crypto_generichash_BYTES;
const size_t size = nonce_size + public_size + hash_size;
uint8_t secret[crypto_scalarmult_SCALARBYTES];
uint8_t shared[crypto_scalarmult_BYTES];
@@ -625,10 +631,14 @@ static int gt_setup_crypto (struct crypto_ctx *ctx, int fd, int listener)
crypto_generichash_state state;
byte_set(data_w, 0, size);
randombytes_buf(data_w, nonce_size);
randombytes_buf(secret, sizeof(secret));
crypto_scalarmult_base(&data_w[nonce_size], secret);
byte_cpy(&data_w[size-hash_size-4], "GT\0\0", 4);
crypto_generichash(&data_w[size-hash_size], hash_size,
data_w, size-hash_size, ctx->skey, sizeof(ctx->skey));
@@ -638,6 +648,9 @@ static int gt_setup_crypto (struct crypto_ctx *ctx, int fd, int listener)
if (fd_read_all(fd, data_r, size)!=size)
return -1;
if (memcmp(&data_r[size-hash_size-4], &data_w[size-hash_size-4], 4))
return -2;
crypto_generichash(hash, hash_size,
data_r, size-hash_size, ctx->skey, sizeof(ctx->skey));
@@ -698,6 +711,7 @@ int main (int argc, char **argv)
char *dev = NULL;
char *keyfile = NULL;
char *congestion = NULL;
char *statefile = NULL;
long buffer_size = GT_BUFFER_SIZE;
@@ -739,6 +753,7 @@ int main (int argc, char **argv)
{ "noquickack", NULL, option_option },
{ "retry", &retry_opts, option_option },
{ "daemon", NULL, option_option },
{ "statefile", &statefile, option_str },
{ "debug", NULL, option_option },
{ "version", NULL, option_option },
{ NULL },
@@ -760,7 +775,7 @@ int main (int argc, char **argv)
if (buffer_size < 2048) {
buffer_size = 2048;
gt_log("buffer size must be greater than 2048!\n");
gt_log("buffer size must be greater than 2048\n");
}
if (!listener) {
@@ -773,8 +788,13 @@ int main (int argc, char **argv)
retry_count = 0;
}
if (statefile && statefile[0]!='/') {
gt_log("statefile must be an absolute path\n");
return 1;
}
if (sodium_init()==-1) {
gt_log("libsodium initialization has failed!\n");
gt_log("libsodium initialization has failed\n");
return 1;
}
@@ -844,6 +864,30 @@ int main (int argc, char **argv)
chdir("/");
}
int state_fd = -1;
if (statefile) {
state_fd = open(statefile, O_WRONLY);
if (state_fd==-1) {
if (errno!=EINTR)
perror("open statefile");
return 1;
}
struct stat st = {0};
if (fstat(state_fd, &st)==-1) {
perror("stat statefile");
return 1;
}
if (!S_ISFIFO(st.st_mode)) {
gt_log("`%s' is not a fifo\n", statefile);
return 1;
}
}
long retry = 0;
while (!gt_close) {
@@ -911,7 +955,7 @@ int main (int argc, char **argv)
retry = 0;
gt_log("%s: running\n", sockname);
fd_write(state_fd, GT_STARTED, sizeof(GT_STARTED)-1);
fd_set rfds;
FD_ZERO(&rfds);
@@ -1084,6 +1128,8 @@ int main (int argc, char **argv)
}
restart:
fd_write(state_fd, GT_STOPPED, sizeof(GT_STOPPED)-1);
if (sockname) {
free(sockname);
sockname = NULL;