Overhaul debug flags

Config debug flags are now represented as individual items, eg:
   servald config set debug.verbose yes
   servald config set debug.rhizome yes
instead of aggregated, eg:
   servald config set debug verbose,rhizome  <-- no longer works

Added a debug flag "debug.all" that can be set and cleared, over which
individual flag sets/clears take priority.

Slimmed down dna.c by moving some globals and functions to the files where they
are used.

Default command line (help message) is now the new style, not the deprecated
style.
This commit is contained in:
Andrew Bettison 2012-05-14 18:32:10 +09:30
parent b02e9b9ac4
commit d11258cefc
13 changed files with 406 additions and 292 deletions

View File

@ -43,6 +43,8 @@ LOCAL_SRC_FILES:= \
serval-dna/commandline.c \
serval-dna/dataformats.c \
serval-dna/dna.c \
serval-dna/log.c \
serval-dna/mkdir.c \
serval-dna/gateway.c \
serval-dna/overlay.c \
serval-dna/overlay_broadcast.c \

View File

@ -4,6 +4,8 @@ SRCS= batman.c \
commandline.c \
dataformats.c \
dna.c \
log.c \
mkdir.c \
dna_identity.c \
encode.c \
fifo.c \

View File

@ -19,6 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
int sock = -1;
/* Now that we are using the keyring, we only support a small subset of variables.
(VAR_NAME is not properly supported yet)
*/

View File

@ -19,10 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define _GNU_SOURCE // For asprintf()
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <math.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#include <time.h>
#include <unistd.h>
#include <stdarg.h>
@ -263,7 +265,7 @@ int parseCommandLine(int argc, const char *const *args)
}
/* Otherwise, make call */
setVerbosity(confValueGet("debug",""));
confSetDebugFlags();
int result=command_line_options[cli_call].function(argc, args, &command_line_options[cli_call]);
/* clean up after ourselves */
overlay_mdp_client_done();
@ -396,6 +398,8 @@ int app_echo(int argc, const char *const *argv, struct command_line_option *o)
{
int i;
for (i = 1; i < argc; ++i) {
if (debug & DEBUG_VERBOSE)
DEBUGF("echo:argv[%d]=%s", i, argv[i]);
cli_puts(argv[i]);
cli_delim(NULL);
}
@ -507,15 +511,15 @@ char *confValueGet(char *var,char *defaultValue)
char filename[1024];
if (!FORM_SERVAL_INSTANCE_PATH(filename, "serval.conf")) {
WHYF("Using default value of %s: %s", var, defaultValue);
WARNF("Using default value of %s: %s", var, defaultValue);
return defaultValue;
}
FILE *f = fopen(filename,"r");
if (!f) {
WHYF("Cannot open serval.conf, using default value of %s: %s", var, defaultValue);
WARNF("Cannot open serval.conf, using default value of %s: %s", var, defaultValue);
return defaultValue;
}
char line[1024];
line[0]=0; fgets(line,1024,f);
while(line[0]) {
@ -538,6 +542,64 @@ char *confValueGet(char *var,char *defaultValue)
return defaultValue;
}
void confSetDebugFlags()
{
char filename[1024];
if (FORM_SERVAL_INSTANCE_PATH(filename, "serval.conf")) {
FILE *f = fopen(filename, "r");
if (!f) {
WARN("Cannot open serval.conf");
} else {
long long setmask = 0;
long long clearmask = 0;
int setall = 0;
int clearall = 0;
char line[1024];
line[0] = '\0';
fgets(line, sizeof line, f);
while (line[0]) {
if (!strncasecmp(line, "debug.", 6)) {
char *flagname = line + 6;
char *p = flagname;
while (*p && *p != '=')
++p;
int flag;
if (*p) {
char *q = p + 1;
while (*q && *q != '\n')
++q;
*q = '\0';
if ((flag = confParseBoolean(p + 1)) != -1) {
*p = '\0';
long long mask = debugFlagMask(flagname);
if (mask == -1)
if (flag) setall = 1; else clearall = 1;
else
if (flag) setmask |= mask; else clearmask |= mask;
}
}
}
line[0] = '\0';
fgets(line, sizeof line, f);
}
fclose(f);
if (setall) debug = -1; else if (clearall) debug = 0;
debug &= ~clearmask;
debug |= setmask;
}
}
}
int confParseBoolean(const char *text)
{
if (!strcasecmp(text, "on") || !strcasecmp(text, "yes") || !strcasecmp(text, "true") || !strcmp(text, "1"))
return 1;
if (!strcasecmp(text, "off") || !strcasecmp(text, "no") || !strcasecmp(text, "false") || !strcmp(text, "0"))
return 0;
WARNF("Invalid boolean value '%s'", text);
return -1;
}
int cli_absolute_path(const char *arg)
{
return arg[0] == '/' && arg[1] != '\0';
@ -906,11 +968,13 @@ int cli_configvarname(const char *arg)
{
if (arg[0] == '\0')
return 0;
const char *s;
for (s = arg; *s; ++s)
if (!(isalnum(*s) || *s == '_'))
if (!(isalnum(arg[0]) || arg[0] == '_'))
return 0;
const char *s = arg + 1;
for (; *s; ++s)
if (!(isalnum(*s) || *s == '_' || (*s == '.' && s[-1] != '.')))
return 0;
return 1;
return s[-1] != '.';
}
int app_config_set(int argc, const char *const *argv, struct command_line_option *o)

View File

@ -19,6 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "serval.h"
int hexdigit[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
int extractDid(unsigned char *packet,int *ofs,char *did)
{
int d=0;
@ -134,6 +136,14 @@ int stowSid(unsigned char *packet, int ofs, const char *sid)
return 0;
}
int hexvalue(unsigned char c)
{
if (c>='0'&&c<='9') return c-'0';
if (c>='A'&&c<='F') return c-'A'+10;
if (c>='a'&&c<='f') return c-'a'+10;
return setReason("Invalid hex digit in SID");
}
int packetGetID(unsigned char *packet,int len,char *did,char *sid)
{
int ofs=HEADERFIELDS_LEN;

249
dna.c
View File

@ -21,126 +21,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "rhizome.h"
#include <signal.h>
#include <unistd.h>
#include <dirent.h>
#include <alloca.h>
char *gatewayspec=NULL;
char *outputtemplate=NULL;
char *instrumentation_file=NULL;
char *importFile=NULL;
int debug=0;
int timeout=3000; /* 3000ms request timeout */
int serverMode=0;
int clientMode=0;
int returnMultiVars=0;
int hexdigit[16]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
int sock=-1;
#ifndef HAVE_BZERO
/* OpenWRT doesn't have bzero */
void bzero(void *m,size_t len)
{
unsigned char *c=m;
int i;
for(i=0;i<len;i++) c[i]=0;
}
#endif
int dump(char *name,unsigned char *addr,int len)
{
int i,j;
fprintf(stderr,"Dump of %s\n",name);
for(i=0;i<len;i+=16)
{
fprintf(stderr," %04x :",i);
for(j=0;j<16&&(i+j)<len;j++) fprintf(stderr," %02x",addr[i+j]);
for(;j<16;j++) fprintf(stderr," ");
fprintf(stderr," ");
for(j=0;j<16&&(i+j)<len;j++) fprintf(stderr,"%c",addr[i+j]>=' '&&addr[i+j]<0x7f?addr[i+j]:'.');
fprintf(stderr,"\n");
}
return 0;
}
int dumpResponses(struct response_set *responses)
{
struct response *r;
if (!responses) {fprintf(stderr,"Response set is NULL\n"); return 0; }
fprintf(stderr,"Response set claims to contain %d entries.\n",responses->response_count);
r=responses->responses;
while(r)
{
fprintf(stderr," response code 0x%02x\n",r->code);
if (r->next)
if (r->next->prev!=r) fprintf(stderr," !! response chain is broken\n");
r=r->next;
}
return 0;
}
#ifdef ANDROID
#include <android/log.h>
#endif
void logMessage(int level, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vlogMessage(level, fmt, ap);
}
void vlogMessage(int level, char *fmt, va_list ap)
{
va_list ap2;
char buf[8192];
va_copy(ap2, ap);
vsnprintf(buf, sizeof buf, fmt, ap2);
va_end(ap);
buf[sizeof buf - 1] = '\0';
#ifdef ANDROID
int alevel = ANDROID_LOG_UNKNOWN;
switch (level) {
case LOG_LEVEL_FATAL: alevel = ANDROID_LOG_FATAL; break;
case LOG_LEVEL_ERROR: alevel = ANDROID_LOG_ERROR; break;
case LOG_LEVEL_INFO: alevel = ANDROID_LOG_INFO; break;
case LOG_LEVEL_WARN: alevel = ANDROID_LOG_WARN; break;
case LOG_LEVEL_DEBUG: alevel = ANDROID_LOG_DEBUG; break;
}
__android_log_print(alevel, "servald", "%s", buf);
#endif
const char *levelstr = "UNKNOWN";
switch (level) {
case LOG_LEVEL_FATAL: levelstr = "FATAL"; break;
case LOG_LEVEL_ERROR: levelstr = "ERROR"; break;
case LOG_LEVEL_INFO: levelstr = "INFO"; break;
case LOG_LEVEL_WARN: levelstr = "WARN"; break;
case LOG_LEVEL_DEBUG: levelstr = "DEBUG"; break;
}
fprintf(stderr, "%s: %s\n", levelstr, buf);
}
int setReason(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vlogMessage(LOG_LEVEL_ERROR, fmt, ap);
return -1;
}
int hexvalue(unsigned char c)
{
if (c>='0'&&c<='9') return c-'0';
if (c>='A'&&c<='F') return c-'A'+10;
if (c>='a'&&c<='f') return c-'a'+10;
return setReason("Invalid hex digit in SID");
}
int parseAssignment(unsigned char *text,int *var_id,unsigned char *value,int *value_len)
{
/* Parse an assignment.
@ -291,98 +180,7 @@ int form_serval_instance_path(char *buf, size_t bufsiz, const char *path)
}
int create_serval_instance_dir() {
const char *instancepath = serval_instancepath();
if (mkdir(instancepath, 0700) == -1) {
if (errno == EEXIST) {
DIR *d = opendir(instancepath);
if (!d) {
WHYF("Cannot access %s", instancepath);
return WHY_perror("opendir");
}
closedir(d);
return 0;
}
WHYF("Cannot mkdir %s", instancepath);
return WHY_perror("mkdir");
}
return 0;
}
int mkdirs(const char *path)
{
return mkdirsn(path, strlen(path));
}
int mkdirsn(const char *path, size_t len)
{
if (len == 0)
return WHY("Bug: empty path");
char *pathfrag = alloca(len + 1);
strncpy(pathfrag, path, len);
pathfrag[len] = '\0';
if (mkdir(pathfrag, 0700) != -1)
return 0;
if (errno == EEXIST) {
DIR *d = opendir(pathfrag);
if (!d) {
WHY_perror("opendir");
return WHYF("cannot access %s", pathfrag);
}
closedir(d);
return 0;
}
if (errno == ENOENT) {
const char *lastsep = path + len - 1;
while (lastsep != path && *--lastsep != '/')
;
while (lastsep != path && *--lastsep == '/')
;
if (lastsep != path) {
if (mkdirsn(path, lastsep - path + 1) == -1)
return -1;
if (mkdir(pathfrag, 0700) != -1)
return 0;
}
}
WHY_perror("mkdir");
return WHYF("cannot mkdir %s", pathfrag);
}
int setVerbosity(const char *optarg) {
long long old_debug=debug;
debug=strtoll(optarg,NULL,10);
if (strstr(optarg,"interfaces")) debug|=DEBUG_OVERLAYINTERFACES;
if (strstr(optarg,"rx")) debug|=DEBUG_PACKETRX;
if (strstr(optarg,"tx")) debug|=DEBUG_PACKETTX;
if (strstr(optarg,"verbose")) debug|=DEBUG_VERBOSE;
if (strstr(optarg,"verbio")) debug|=DEBUG_VERBOSE_IO;
if (strstr(optarg,"peers")) debug|=DEBUG_PEERS;
if (strstr(optarg,"dnaresponses")) debug|=DEBUG_DNARESPONSES;
if (strstr(optarg,"dnarequests")) debug|=DEBUG_DNAREQUESTS;
if (strstr(optarg,"simulation")) debug|=DEBUG_SIMULATION;
if (strstr(optarg,"dnavars")) debug|=DEBUG_DNAVARS;
if (strstr(optarg,"packetformats")) debug|=DEBUG_PACKETFORMATS;
if (strstr(optarg,"packetconstruction")) debug|=DEBUG_PACKETCONSTRUCTION;
if (strstr(optarg,"gateway")) debug|=DEBUG_GATEWAY;
if (strstr(optarg,"hlr")) debug|=DEBUG_HLR;
if (strstr(optarg,"sockio")) debug|=DEBUG_IO;
if (strstr(optarg,"frames")) debug|=DEBUG_OVERLAYFRAMES;
if (strstr(optarg,"abbreviations")) debug|=DEBUG_OVERLAYABBREVIATIONS;
if (strstr(optarg,"routing")) debug|=DEBUG_OVERLAYROUTING;
if (strstr(optarg,"security")) debug|=DEBUG_SECURITY;
if (strstr(optarg,"rhizome")) debug|=DEBUG_RHIZOME;
if (strstr(optarg,"norhizome"))
{ debug|=DEBUG_DISABLERHIZOME; debug&=~DEBUG_RHIZOME; }
if (strstr(optarg,"filesync")) debug|=DEBUG_RHIZOMESYNC;
if (strstr(optarg,"monitorroutes")) debug|=DEBUG_OVERLAYROUTEMONITOR;
if (strstr(optarg,"queues")) debug|=DEBUG_QUEUES;
if (strstr(optarg,"broadcasts")) debug|=DEBUG_BROADCASTS;
if (old_debug==debug && optarg[0]) {
fprintf(stderr,"WARNING: Option '%s' had no effect on existing debug/verbosity level.\n",
optarg);
}
return 0;
return mkdirs(serval_instancepath(), 0700);
}
int main(int argc, char **argv)
@ -394,6 +192,7 @@ int main(int argc, char **argv)
char *keyring_file=NULL;
int instance=-1;
int foregroundMode=0;
int clientMode=0;
#if defined WIN32
WSADATA wsa_data;
@ -405,19 +204,15 @@ int main(int argc, char **argv)
server_save_argv(argc, (const char*const*)argv);
if (argv[1]&&argv[1][0]!='-') {
/* First argument doesn't start with a dash, so assume it is for the new command line
parser. */
/* If first argument starts with a dash, we assume it is for the old command line parser. */
if (!argv[1] || argv[1][0] != '-') {
/* Don't include name of program in arguments */
int return_value = parseCommandLine(argc - 1, (const char*const*)&argv[1]);
#if defined WIN32
WSACleanup();
#endif
return return_value;
}
}
fprintf(stderr,
"WARNING: The use of the old command line structure is being deprecated.\n"
@ -507,7 +302,7 @@ int main(int argc, char **argv)
timeout=atoi(optarg);
break;
case 'v': /* set verbosity */
setVerbosity(optarg);
debug |= debugFlagMask(optarg);
break;
case 'A': /* get address (IP or otherwise) of a given peer */
peerAddress(did,sid,3 /* 1 = print list of addresses to stdout, 2 = set peer list to responders */);
@ -571,35 +366,3 @@ int main(int argc, char **argv)
return 0;
}
#endif
long long parse_quantity(char *q)
{
int m;
char units[80];
if (strlen(q)>=80) return WHY("quantity string >=80 characters");
if (sscanf(q,"%d%s",&m,units)==2)
{
if (units[1]) return WHY("Units should be single character");
switch(units[0])
{
case 'k': return m*1000LL;
case 'K': return m*1024LL;
case 'm': return m*1000LL*1000LL;
case 'M': return m*1024LL*1024LL;
case 'g': return m*1000LL*1000LL*1000LL;
case 'G': return m*1024LL*1024LL*1024LL;
default:
return WHY("Illegal unit: should be k,K,m,M,g, or G.");
}
}
if (sscanf(q,"%d",&m)==1)
{
return m;
}
else
{
return WHY("Could not parse quantity");
}
}

135
log.c Normal file
View File

@ -0,0 +1,135 @@
/*
Serval Distributed Numbering Architecture (DNA)
Copyright (C) 2010 Paul Gardner-Stephen
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "serval.h"
int debug = 0;
#ifdef ANDROID
#include <android/log.h>
#endif
void logMessage(int level, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vlogMessage(level, fmt, ap);
}
void vlogMessage(int level, char *fmt, va_list ap)
{
va_list ap2;
char buf[8192];
va_copy(ap2, ap);
vsnprintf(buf, sizeof buf, fmt, ap2);
va_end(ap);
buf[sizeof buf - 1] = '\0';
#ifdef ANDROID
int alevel = ANDROID_LOG_UNKNOWN;
switch (level) {
case LOG_LEVEL_FATAL: alevel = ANDROID_LOG_FATAL; break;
case LOG_LEVEL_ERROR: alevel = ANDROID_LOG_ERROR; break;
case LOG_LEVEL_INFO: alevel = ANDROID_LOG_INFO; break;
case LOG_LEVEL_WARN: alevel = ANDROID_LOG_WARN; break;
case LOG_LEVEL_DEBUG: alevel = ANDROID_LOG_DEBUG; break;
}
__android_log_print(alevel, "servald", "%s", buf);
#endif
const char *levelstr = "UNKNOWN";
switch (level) {
case LOG_LEVEL_FATAL: levelstr = "FATAL"; break;
case LOG_LEVEL_ERROR: levelstr = "ERROR"; break;
case LOG_LEVEL_INFO: levelstr = "INFO"; break;
case LOG_LEVEL_WARN: levelstr = "WARN"; break;
case LOG_LEVEL_DEBUG: levelstr = "DEBUG"; break;
}
fprintf(stderr, "%s: %s\n", levelstr, buf);
}
int setReason(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vlogMessage(LOG_LEVEL_ERROR, fmt, ap);
return -1;
}
int dump(char *name,unsigned char *addr,int len)
{
int i,j;
fprintf(stderr,"Dump of %s\n",name);
for(i=0;i<len;i+=16)
{
fprintf(stderr," %04x :",i);
for(j=0;j<16&&(i+j)<len;j++) fprintf(stderr," %02x",addr[i+j]);
for(;j<16;j++) fprintf(stderr," ");
fprintf(stderr," ");
for(j=0;j<16&&(i+j)<len;j++) fprintf(stderr,"%c",addr[i+j]>=' '&&addr[i+j]<0x7f?addr[i+j]:'.');
fprintf(stderr,"\n");
}
return 0;
}
int dumpResponses(struct response_set *responses)
{
struct response *r;
if (!responses) {fprintf(stderr,"Response set is NULL\n"); return 0; }
fprintf(stderr,"Response set claims to contain %d entries.\n",responses->response_count);
r=responses->responses;
while(r)
{
fprintf(stderr," response code 0x%02x\n",r->code);
if (r->next)
if (r->next->prev!=r) fprintf(stderr," !! response chain is broken\n");
r=r->next;
}
return 0;
}
long long debugFlagMask(const char *flagname) {
if (!strcasecmp(flagname,"all")) return -1;
else if (!strcasecmp(flagname,"interfaces")) return DEBUG_OVERLAYINTERFACES;
else if (!strcasecmp(flagname,"rx")) return DEBUG_PACKETRX;
else if (!strcasecmp(flagname,"tx")) return DEBUG_PACKETTX;
else if (!strcasecmp(flagname,"verbose")) return DEBUG_VERBOSE;
else if (!strcasecmp(flagname,"verbio")) return DEBUG_VERBOSE_IO;
else if (!strcasecmp(flagname,"peers")) return DEBUG_PEERS;
else if (!strcasecmp(flagname,"dnaresponses")) return DEBUG_DNARESPONSES;
else if (!strcasecmp(flagname,"dnarequests")) return DEBUG_DNAREQUESTS;
else if (!strcasecmp(flagname,"simulation")) return DEBUG_SIMULATION;
else if (!strcasecmp(flagname,"dnavars")) return DEBUG_DNAVARS;
else if (!strcasecmp(flagname,"packetformats")) return DEBUG_PACKETFORMATS;
else if (!strcasecmp(flagname,"packetconstruction")) return DEBUG_PACKETCONSTRUCTION;
else if (!strcasecmp(flagname,"gateway")) return DEBUG_GATEWAY;
else if (!strcasecmp(flagname,"hlr")) return DEBUG_HLR;
else if (!strcasecmp(flagname,"sockio")) return DEBUG_IO;
else if (!strcasecmp(flagname,"frames")) return DEBUG_OVERLAYFRAMES;
else if (!strcasecmp(flagname,"abbreviations")) return DEBUG_OVERLAYABBREVIATIONS;
else if (!strcasecmp(flagname,"routing")) return DEBUG_OVERLAYROUTING;
else if (!strcasecmp(flagname,"security")) return DEBUG_SECURITY;
else if (!strcasecmp(flagname,"rhizome")) return DEBUG_RHIZOME;
else if (!strcasecmp(flagname,"norhizome")) return DEBUG_DISABLERHIZOME;
else if (!strcasecmp(flagname,"filesync")) return DEBUG_RHIZOMESYNC;
else if (!strcasecmp(flagname,"monitorroutes")) return DEBUG_OVERLAYROUTEMONITOR;
else if (!strcasecmp(flagname,"queues")) return DEBUG_QUEUES;
else if (!strcasecmp(flagname,"broadcasts")) return DEBUG_BROADCASTS;
WARNF("Unsupported debug flag '%s'", flagname);
return 0;
}

64
mkdir.c Normal file
View File

@ -0,0 +1,64 @@
/*
Serval Distributed Numbering Architecture (DNA)
Copyright (C) 2010 Paul Gardner-Stephen
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, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <sys/types.h>
#include <alloca.h>
#include <dirent.h>
#include "serval.h"
int mkdirs(const char *path, mode_t mode)
{
return mkdirsn(path, strlen(path), mode);
}
int mkdirsn(const char *path, size_t len, mode_t mode)
{
if (len == 0)
return WHY("Bug: empty path");
char *pathfrag = alloca(len + 1);
strncpy(pathfrag, path, len);
pathfrag[len] = '\0';
if (mkdir(pathfrag, mode) != -1)
return 0;
if (errno == EEXIST) {
DIR *d = opendir(pathfrag);
if (!d) {
WHY_perror("opendir");
return WHYF("cannot access %s", pathfrag);
}
closedir(d);
return 0;
}
if (errno == ENOENT) {
const char *lastsep = path + len - 1;
while (lastsep != path && *--lastsep != '/')
;
while (lastsep != path && *--lastsep == '/')
;
if (lastsep != path) {
if (mkdirsn(path, lastsep - path + 1, mode) == -1)
return -1;
if (mkdir(pathfrag, mode) != -1)
return 0;
}
}
WHY_perror("mkdir");
return WHYF("cannot mkdir %s", pathfrag);
}

View File

@ -975,3 +975,35 @@ long long overlay_time_until_next_tick()
return nexttick;
}
long long parse_quantity(char *q)
{
int m;
char units[80];
if (strlen(q)>=80) return WHY("quantity string >=80 characters");
if (sscanf(q,"%d%s",&m,units)==2)
{
if (units[1]) return WHY("Units should be single character");
switch(units[0])
{
case 'k': return m*1000LL;
case 'K': return m*1024LL;
case 'm': return m*1000LL*1000LL;
case 'M': return m*1024LL*1024LL;
case 'g': return m*1000LL*1000LL*1000LL;
case 'G': return m*1024LL*1024LL*1024LL;
default:
return WHY("Illegal unit: should be k,K,m,M,g, or G.");
}
}
if (sscanf(q,"%d",&m)==1)
{
return m;
}
else
{
return WHY("Could not parse quantity");
}
}

View File

@ -56,7 +56,7 @@ int create_rhizome_datastore_dir()
WHY("Cannot create rhizome database -- no path specified");
return 0;
}
return mkdirs(rhizome_datastore_path);
return mkdirs(rhizome_datastore_path, 0700);
}
sqlite3 *rhizome_db=NULL;

View File

@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#endif
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#ifdef WIN32
#include "win32/win32.h"
@ -106,6 +107,9 @@ struct in_addr {
#define DEFAULT_INSTANCE_PATH "/var/serval-node"
#endif
/* bzero(3) is deprecated in favour of memset(3). */
#define bzero(addr,len) memset((addr), 0, (len))
/* UDP Port numbers for various Serval services.
The overlay mesh works over DNA */
#define PORT_DNA 4110
@ -384,6 +388,8 @@ extern int hexdigit[16];
extern int sock;
char *confValueGet(char *var,char *defaultValue);
void confSetDebugFlags();
int confParseBoolean(const const char *text);
int recvwithttl(int sock,unsigned char *buffer,int bufferlen,int *ttl,
struct sockaddr *recvaddr,unsigned int *recvaddrlen);
int validateSid(const char *sid);
@ -410,9 +416,7 @@ void serverCleanUp();
int isTransactionInCache(unsigned char *transaction_id);
void insertTransactionInCache(unsigned char *transaction_id);
int setReason(char *fmt, ...);
int hexvalue(unsigned char c);
int dump(char *name,unsigned char *addr,int len);
int packetOk(int interface,unsigned char *packet,int len,
unsigned char *transaction_id, int recvttl,
struct sockaddr *recvaddr,int recvaddrlen,int parseP);
@ -749,19 +753,25 @@ extern overlay_txqueue overlay_tx[OQ_MAX];
int setReason(char *fmt, ...);
void logMessage(int level, char *fmt, ...);
void vlogMessage(int level, char *fmt, va_list);
long long debugFlagMask(const char *flagname);
int dump(char *name,unsigned char *addr,int len);
#define FATALF(F,...) do { logMessage(LOG_LEVEL_FATAL, "%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__); exit(-1); } while(1)
#define FATAL(X) FATALF("%s", (X))
#define FATAL_perror(X) FATALF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define WHY(X) setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X)
#define WHYNULL(X) (setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X), NULL)
#define WHYF(F,...) setReason("%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define WHY_perror(X) setReason("%s:%d:%s() %s: %s [errno=%d]", __FILE__, __LINE__, __FUNCTION__, X, strerror(errno), errno)
#define WHY(X) setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X)
#define WHYNULL(X) (setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X), NULL)
#define WHYF(F,...) setReason("%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define WHY_perror(X) setReason("%s:%d:%s() %s: %s [errno=%d]", __FILE__, __LINE__, __FUNCTION__, X, strerror(errno), errno)
#define DEBUGF(F,...) logMessage(LOG_LEVEL_DEBUG, "%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define DEBUG(X) DEBUGF("%s", (X))
#define DEBUG_perror(X) DEBUGF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define WARNF(F,...) logMessage(LOG_LEVEL_WARN, "%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define WARN(X) WARNF("%s", (X))
#define WARN_perror(X) WARNF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define DEBUGF(F,...) logMessage(LOG_LEVEL_DEBUG, "%s:%d:%s() " F, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define DEBUG(X) DEBUGF("%s", (X))
#define DEBUG_perror(X) DEBUGF("%s: %s [errno=%d]", (X), strerror(errno), errno)
#define D DEBUG("D")
overlay_buffer *ob_new(int size);
@ -1023,32 +1033,31 @@ int overlay_saw_mdp_containing_frame(int interface,overlay_frame *f,long long no
#include "nacl.h"
#define DEBUG_OVERLAYINTERFACES 2
#define DEBUG_PACKETRX 1
#define DEBUG_VERBOSE 4
#define DEBUG_VERBOSE_IO 8
#define DEBUG_PEERS 16
#define DEBUG_DNARESPONSES 32
#define DEBUG_DNAREQUESTS 64
#define DEBUG_SIMULATION 128
#define DEBUG_DNAVARS 256
#define DEBUG_PACKETFORMATS 512
#define DEBUG_GATEWAY 1024
#define DEBUG_HLR 2048
#define DEBUG_IO 4096
#define DEBUG_OVERLAYFRAMES 8192
#define DEBUG_OVERLAYABBREVIATIONS 16384
#define DEBUG_OVERLAYROUTING 32768
#define DEBUG_SECURITY 65536
#define DEBUG_RHIZOME (1<<17)
#define DEBUG_OVERLAYROUTEMONITOR (1<<18)
#define DEBUG_QUEUES (1<<19)
#define DEBUG_BROADCASTS (1<<20)
#define DEBUG_RHIZOMESYNC (1<<21)
#define DEBUG_DISABLERHIZOME (1<<22)
#define DEBUG_PACKETTX (1<<23)
#define DEBUG_PACKETCONSTRUCTION (1<<24)
#define DEBUG_PACKETRX (1 << 0)
#define DEBUG_OVERLAYINTERFACES (1 << 1)
#define DEBUG_VERBOSE (1 << 2)
#define DEBUG_VERBOSE_IO (1 << 3)
#define DEBUG_PEERS (1 << 4)
#define DEBUG_DNARESPONSES (1 << 5)
#define DEBUG_DNAREQUESTS (1 << 6)
#define DEBUG_SIMULATION (1 << 7)
#define DEBUG_DNAVARS (1 << 8)
#define DEBUG_PACKETFORMATS (1 << 9)
#define DEBUG_GATEWAY (1 << 10)
#define DEBUG_HLR (1 << 11)
#define DEBUG_IO (1 << 12)
#define DEBUG_OVERLAYFRAMES (1 << 13)
#define DEBUG_OVERLAYABBREVIATIONS (1 << 14)
#define DEBUG_OVERLAYROUTING (1 << 15)
#define DEBUG_SECURITY (1 << 16)
#define DEBUG_RHIZOME (1 << 17)
#define DEBUG_OVERLAYROUTEMONITOR (1 << 18)
#define DEBUG_QUEUES (1 << 19)
#define DEBUG_BROADCASTS (1 << 20)
#define DEBUG_RHIZOMESYNC (1 << 21)
#define DEBUG_DISABLERHIZOME (1 << 22)
#define DEBUG_PACKETTX (1 << 23)
#define DEBUG_PACKETCONSTRUCTION (1 << 24)
int serval_packetvisualise(FILE *f,char *message,unsigned char *packet,int plen);
@ -1109,8 +1118,8 @@ const char *serval_instancepath();
int form_serval_instance_path(char * buf, size_t bufsiz, const char *path);
int create_serval_instance_dir();
int mkdirs(const char *path);
int mkdirsn(const char *path, size_t len);
int mkdirs(const char *path, mode_t mode);
int mkdirsn(const char *path, size_t len, mode_t mode);
/* Handy statement for forming a path to an instance file in a char buffer whose declaration
* is in scope (so that sizeof(buf) will work). Evaluates to true if the pathname fitted into
@ -1265,8 +1274,6 @@ typedef struct overlay_mdp_frame {
int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req);
int setVerbosity(const char *optarg);
/* Client-side MDP function */
extern int mdp_client_socket;
int overlay_mdp_client_init();

View File

@ -31,6 +31,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
char *exec_args[128];
int exec_argc = 0;
int serverMode=0;
int servalShutdown = 0;
static int server_getpid = 0;
@ -157,6 +158,8 @@ void server_save_argv(int argc, const char *const *argv)
int server(char *backing_file)
{
serverMode = 1;
/* Catch sigsegv and other crash signals so that we can relaunch ourselves */
signal(SIGSEGV, signal_handler);
signal(SIGFPE, signal_handler);

View File

@ -115,4 +115,34 @@ test_CaseInsensitive() {
assertStdoutGrep --stdout --stderr --matches=1 '^FOO=wah$'
}
doc_DotsInNames="Config item names can have internal dots"
test_DotsInNames() {
executeOk $dna config set foo.bar yes
executeOk $dna config get foo.bar
assertStdoutLineCount '==' 1
assertStdoutGrep --stdout --stderr --matches=1 '^foo\.bar=yes$'
execute $dna config set foo. yes
assertExitStatus '!=' 0
execute $dna config set .foo yes
assertExitStatus '!=' 0
execute $dna config set foo..bar yes
assertExitStatus '!=' 0
executeOk $dna config set foo.x.bar yes
executeOk $dna config get foo.x.bar
assertStdoutLineCount '==' 1
assertStdoutGrep --stdout --stderr --matches=1 '^foo\.x\.bar=yes$'
}
doc_DebugFlags="Debug flags affect verbosity"
test_DebugFlags() {
executeOk $dna echo one two three
assertStderrGrep --matches=0 '\<echo:argv\['
executeOk $dna config set debug.verbose true
executeOk $dna echo one two three
assertStderrGrep --matches=3 '\<echo:argv\['
executeOk $dna config set debug.verbose false
executeOk $dna echo one two three
assertStderrGrep --matches=0 '\<echo:argv\['
}
runTests "$@"