mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 13:43:12 +00:00
Add stub directory service
This commit is contained in:
parent
7b8885fd96
commit
ac8d9b93e6
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,6 +18,7 @@ nacl/naclinc.txt
|
|||||||
nacl/nacllib.txt
|
nacl/nacllib.txt
|
||||||
serval.c
|
serval.c
|
||||||
servald
|
servald
|
||||||
|
directory_service
|
||||||
*.so
|
*.so
|
||||||
test.*.log
|
test.*.log
|
||||||
testlog
|
testlog
|
||||||
|
@ -16,6 +16,7 @@ SERVALD_SRC_FILES = \
|
|||||||
serval-dna/commandline.c \
|
serval-dna/commandline.c \
|
||||||
serval-dna/conf.c \
|
serval-dna/conf.c \
|
||||||
serval-dna/dataformats.c \
|
serval-dna/dataformats.c \
|
||||||
|
serval-dna/directory_client.c \
|
||||||
serval-dna/xprintf.c \
|
serval-dna/xprintf.c \
|
||||||
serval-dna/log.c \
|
serval-dna/log.c \
|
||||||
serval-dna/net.c \
|
serval-dna/net.c \
|
||||||
|
5
Makefile.in
Normal file → Executable file
5
Makefile.in
Normal file → Executable file
@ -10,6 +10,7 @@ SRCS= \
|
|||||||
commandline.c \
|
commandline.c \
|
||||||
conf.c \
|
conf.c \
|
||||||
dataformats.c \
|
dataformats.c \
|
||||||
|
directory_client.c \
|
||||||
dna_helper.c \
|
dna_helper.c \
|
||||||
dna_identity.c \
|
dna_identity.c \
|
||||||
encode.c \
|
encode.c \
|
||||||
@ -132,6 +133,10 @@ servald: $(OBJS)
|
|||||||
@echo LINK $@
|
@echo LINK $@
|
||||||
@$(CC) $(CFLAGS) -Wall -o $@ $(OBJS) $(LDFLAGS)
|
@$(CC) $(CFLAGS) -Wall -o $@ $(OBJS) $(LDFLAGS)
|
||||||
|
|
||||||
|
directory_service: $(MDPCLIENTOBJS) directory_service.o
|
||||||
|
@echo LINK $@
|
||||||
|
@$(CC) $(CFLAGS) -Wall -o $@ $(MDPCLIENTOBJS) directory_service.o $(LDFLAGS)
|
||||||
|
|
||||||
# This does not build on 64 bit elf platforms as NaCL isn't built with -fPIC
|
# This does not build on 64 bit elf platforms as NaCL isn't built with -fPIC
|
||||||
# DOC 20120615
|
# DOC 20120615
|
||||||
libservald.so: $(OBJS)
|
libservald.so: $(OBJS)
|
||||||
|
@ -246,6 +246,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||||||
#define MDP_PORT_VOMP 0x10000002
|
#define MDP_PORT_VOMP 0x10000002
|
||||||
#define MDP_PORT_DNALOOKUP 0x10000003
|
#define MDP_PORT_DNALOOKUP 0x10000003
|
||||||
#define MDP_PORT_NOREPLY 0x10000000
|
#define MDP_PORT_NOREPLY 0x10000000
|
||||||
|
#define MDP_PORT_DIRECTORY 10
|
||||||
|
|
||||||
#define MDP_TYPE_MASK 0xff
|
#define MDP_TYPE_MASK 0xff
|
||||||
#define MDP_FLAG_MASK 0xff00
|
#define MDP_FLAG_MASK 0xff00
|
||||||
|
88
directory_client.c
Normal file
88
directory_client.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Serval Directory Service client
|
||||||
|
|
||||||
|
When servald starts, load the SID, IP (or domain name) & port of a directory server.
|
||||||
|
When an interface comes up with a route to this server, and periodically thereafter,
|
||||||
|
send our SID name and number to the configured server.
|
||||||
|
|
||||||
|
When we perform a lookup, send an additional copy of the request to the directory server.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "serval.h"
|
||||||
|
#include "overlay_address.h"
|
||||||
|
|
||||||
|
#define MDP_DIRECTORY 999
|
||||||
|
|
||||||
|
struct subscriber *directory_service;
|
||||||
|
|
||||||
|
// send a registration packet
|
||||||
|
static void directory_send(struct subscriber *directory_service, const unsigned char *sid, const char *did, const char *name){
|
||||||
|
overlay_mdp_frame request;
|
||||||
|
|
||||||
|
memset(&request, 0, sizeof(overlay_mdp_frame));
|
||||||
|
|
||||||
|
bcopy(sid, request.out.src.sid, SID_SIZE);
|
||||||
|
request.out.src.port=MDP_PORT_NOREPLY;
|
||||||
|
|
||||||
|
bcopy(request.out.dst.sid, directory_service->sid, SID_SIZE);
|
||||||
|
request.out.dst.port=MDP_DIRECTORY;
|
||||||
|
request.out.payload_length = snprintf((char *)request.out.payload, sizeof(request.out.payload),
|
||||||
|
"%s|%s", did, name);
|
||||||
|
|
||||||
|
overlay_mdp_dispatch(&request, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send a registration packet for each unlocked identity
|
||||||
|
static void directory_send_keyring(struct subscriber *directory_service){
|
||||||
|
int cn=0, in=0, kp=0, k2;
|
||||||
|
|
||||||
|
for (; !keyring_sanitise_position(keyring, &cn, &in, &kp); ++kp){
|
||||||
|
keyring_identity *i = keyring->contexts[cn]->identities[in];
|
||||||
|
|
||||||
|
if (i->keypairs[kp]->type == KEYTYPE_CRYPTOBOX){
|
||||||
|
const unsigned char *packedSid = i->keypairs[0]->public_key;
|
||||||
|
|
||||||
|
for(k2=0; k2 < i->keypair_count; k2++){
|
||||||
|
if (i->keypairs[k2]->type==KEYTYPE_DID){
|
||||||
|
const char *unpackedDid = (const char *) i->keypairs[kp]->private_key;
|
||||||
|
const char *name = (const char *) i->keypairs[kp]->public_key;
|
||||||
|
|
||||||
|
directory_send(directory_service, packedSid, unpackedDid, name);
|
||||||
|
// send the first DID only
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int load_directory_config(){
|
||||||
|
const char *sid_hex = confValueGet("directory.service", NULL);
|
||||||
|
if (!sid_hex)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unsigned char sid[SID_SIZE];
|
||||||
|
if (stowSid(sid, 0, sid_hex)==-1)
|
||||||
|
return WHYF("Invalid directory server SID %s", sid_hex);
|
||||||
|
|
||||||
|
directory_service = find_subscriber(sid, SID_SIZE, 1);
|
||||||
|
if (!directory_service)
|
||||||
|
return WHYF("Failed to create subscriber record");
|
||||||
|
|
||||||
|
return load_subscriber_address(directory_service);
|
||||||
|
}
|
||||||
|
|
||||||
|
int directory_interface_up(overlay_interface *interface){
|
||||||
|
// reload config, now that an interface is up
|
||||||
|
load_directory_config();
|
||||||
|
|
||||||
|
if (directory_service && subscriber_is_reachable(directory_service) != REACHABLE_NONE){
|
||||||
|
directory_send_keyring(directory_service);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
124
directory_service.c
Normal file
124
directory_service.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
#include "constants.h"
|
||||||
|
#include "mdp_client.h"
|
||||||
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
char last_add[256]="dummy";
|
||||||
|
|
||||||
|
void store(char *key, char *value){
|
||||||
|
fprintf(stderr,"Adding; \"%s\" = \"%s\"\n", key, value);
|
||||||
|
strncpy(value, last_add, sizeof(last_add));
|
||||||
|
last_add[255]=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *retrieve(char *key){
|
||||||
|
fprintf(stderr, "Looking for; \"%s\"\n", key);
|
||||||
|
|
||||||
|
// dummy code, just reply with the last record we've heard
|
||||||
|
return last_add;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void add_record(){
|
||||||
|
int ttl;
|
||||||
|
overlay_mdp_frame mdp;
|
||||||
|
|
||||||
|
if (!overlay_mdp_recv(&mdp, &ttl))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// make sure the payload is a NULL terminated string
|
||||||
|
mdp.in.payload[mdp.in.payload_length]=0;
|
||||||
|
|
||||||
|
char *did=(char *)mdp.in.payload;
|
||||||
|
int i=0;
|
||||||
|
while(i<mdp.in.payload_length && mdp.in.payload[i] && mdp.in.payload[i]!='|')
|
||||||
|
i++;
|
||||||
|
mdp.in.payload[i]=0;
|
||||||
|
char *name = mdp.in.payload+i+1;
|
||||||
|
char *sid = alloca_to_hex_sid(mdp.in.src.sid);
|
||||||
|
|
||||||
|
// TODO check that did is a valid phone number
|
||||||
|
|
||||||
|
char url[256];
|
||||||
|
snprintf(url, sizeof(url), "sid://%s/%s|%s|%s", sid, did, did, name);
|
||||||
|
store(did, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_line(char *line){
|
||||||
|
char *token=line;
|
||||||
|
char *p=line;
|
||||||
|
while(*p && *p!='|') p++;
|
||||||
|
*p++=0;
|
||||||
|
char *did = p;
|
||||||
|
while(*p && *p!='|') p++;
|
||||||
|
*p++=0;
|
||||||
|
|
||||||
|
const char *response = retrieve(did);
|
||||||
|
if (response)
|
||||||
|
printf("%s|%s|\n",token,response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resolve_request(){
|
||||||
|
static char line_buff[1024];
|
||||||
|
static int line_pos=0;
|
||||||
|
|
||||||
|
int bytes = read(STDIN_FILENO, line_buff + line_pos, sizeof(line_buff) - line_pos);
|
||||||
|
int i = line_pos;
|
||||||
|
int processed=0;
|
||||||
|
line_pos+=bytes;
|
||||||
|
char *line_start=line_buff;
|
||||||
|
|
||||||
|
for (;i<line_pos;i++){
|
||||||
|
if (line_buff[i]=='\n'){
|
||||||
|
line_buff[i]=0;
|
||||||
|
if (*line_start)
|
||||||
|
process_line(line_start);
|
||||||
|
processed=i+1;
|
||||||
|
line_start = line_buff + processed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processed){
|
||||||
|
// squash unprocessed data back to the start of the buffer
|
||||||
|
line_pos -= processed;
|
||||||
|
bcopy(line_buff, line_start, line_pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
struct pollfd fds[2];
|
||||||
|
|
||||||
|
// bind for incoming directory updates
|
||||||
|
unsigned char srcsid[SID_SIZE];
|
||||||
|
if (overlay_mdp_getmyaddr(0,srcsid)) return WHY("Could not get local address");
|
||||||
|
if (overlay_mdp_bind(srcsid,MDP_PORT_DIRECTORY)) return WHY("Could not bind to MDP socket");
|
||||||
|
|
||||||
|
set_nonblock(STDIN_FILENO);
|
||||||
|
|
||||||
|
fds[0].fd = STDIN_FILENO;
|
||||||
|
fds[0].events = POLLIN;
|
||||||
|
fds[1].fd = mdp_client_socket;
|
||||||
|
fds[1].events = POLLIN;
|
||||||
|
|
||||||
|
fprintf(stderr, "Hello\n");
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
int r = poll(fds, 2, 10000);
|
||||||
|
if (r>0){
|
||||||
|
if (fds[0].revents & POLLIN)
|
||||||
|
resolve_request();
|
||||||
|
if (fds[1].revents & POLLIN)
|
||||||
|
add_record();
|
||||||
|
|
||||||
|
if (fds[0].revents & (POLLHUP | POLLERR))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(stderr,".");
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Bye\n");
|
||||||
|
overlay_mdp_client_done();
|
||||||
|
return 0;
|
||||||
|
}
|
@ -215,6 +215,38 @@ int reachable_unicast(struct subscriber *subscriber, overlay_interface *interfac
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load a unicast address from configuration, replace with database??
|
||||||
|
int load_subscriber_address(struct subscriber *subscriber){
|
||||||
|
char buff[80];
|
||||||
|
const char *sid_hex = alloca_tohex_sid(subscriber->sid);
|
||||||
|
|
||||||
|
snprintf(buff, sizeof(buff), "%s.interface", sid_hex);
|
||||||
|
const char *interface_name = confValueGet(buff, NULL);
|
||||||
|
if (!interface_name)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
snprintf(buff, sizeof(buff), "%s.address", sid_hex);
|
||||||
|
const char *address = confValueGet(buff, NULL);
|
||||||
|
if (!address)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
snprintf(buff, sizeof(buff), "%s.port", sid_hex);
|
||||||
|
int port = confValueGetInt64Range(buff, PORT_DNA, 1, 65535);
|
||||||
|
|
||||||
|
overlay_interface *interface = overlay_interface_find_name(interface_name);
|
||||||
|
if (!interface){
|
||||||
|
WARNF("Interface %s is not UP", interface_name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct in_addr addr;
|
||||||
|
if (!inet_aton(address, &addr)){
|
||||||
|
return WHYF("%s doesn't look like an IP address", address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reachable_unicast(subscriber, interface, addr, port);
|
||||||
|
}
|
||||||
|
|
||||||
// generate a new random broadcast address
|
// generate a new random broadcast address
|
||||||
int overlay_broadcast_generate_address(struct broadcast *addr)
|
int overlay_broadcast_generate_address(struct broadcast *addr)
|
||||||
{
|
{
|
||||||
|
@ -103,6 +103,7 @@ struct subscriber *find_subscriber(const unsigned char *sid, int len, int create
|
|||||||
void enum_subscribers(struct subscriber *start, int(*callback)(struct subscriber *, void *), void *context);
|
void enum_subscribers(struct subscriber *start, int(*callback)(struct subscriber *, void *), void *context);
|
||||||
int subscriber_is_reachable(struct subscriber *subscriber);
|
int subscriber_is_reachable(struct subscriber *subscriber);
|
||||||
int reachable_unicast(struct subscriber *subscriber, overlay_interface *interface, struct in_addr addr, int port);
|
int reachable_unicast(struct subscriber *subscriber, overlay_interface *interface, struct in_addr addr, int port);
|
||||||
|
int load_subscriber_address(struct subscriber *subscriber);
|
||||||
|
|
||||||
int overlay_broadcast_drop_check(struct broadcast *addr);
|
int overlay_broadcast_drop_check(struct broadcast *addr);
|
||||||
int overlay_broadcast_generate_address(struct broadcast *addr);
|
int overlay_broadcast_generate_address(struct broadcast *addr);
|
||||||
|
@ -266,6 +266,18 @@ overlay_interface * overlay_interface_find(struct in_addr addr){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overlay_interface * overlay_interface_find_name(const char *name){
|
||||||
|
int i;
|
||||||
|
for (i=0;i<OVERLAY_MAX_INTERFACES;i++){
|
||||||
|
if (overlay_interfaces[i].state!=INTERFACE_STATE_UP)
|
||||||
|
continue;
|
||||||
|
if (strcasecmp(name, overlay_interfaces[i].name)==0){
|
||||||
|
return &overlay_interfaces[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// OSX doesn't recieve broadcast packets on sockets bound to an interface's address
|
// OSX doesn't recieve broadcast packets on sockets bound to an interface's address
|
||||||
// So we have to bind a socket to INADDR_ANY to receive these packets.
|
// So we have to bind a socket to INADDR_ANY to receive these packets.
|
||||||
static void
|
static void
|
||||||
@ -406,6 +418,10 @@ overlay_interface_init_socket(int interface_index)
|
|||||||
// mark our sid to be sent in full
|
// mark our sid to be sent in full
|
||||||
if (my_subscriber)
|
if (my_subscriber)
|
||||||
my_subscriber->send_full = 1;
|
my_subscriber->send_full = 1;
|
||||||
|
|
||||||
|
// try to register ourselves with a directory service
|
||||||
|
directory_interface_up(interface);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
serval.h
3
serval.h
@ -863,6 +863,9 @@ int overlay_interface_register(char *name,
|
|||||||
struct in_addr addr,
|
struct in_addr addr,
|
||||||
struct in_addr mask);
|
struct in_addr mask);
|
||||||
overlay_interface * overlay_interface_find(struct in_addr addr);
|
overlay_interface * overlay_interface_find(struct in_addr addr);
|
||||||
|
overlay_interface * overlay_interface_find_name(const char *name);
|
||||||
|
|
||||||
|
int directory_interface_up(overlay_interface *interface);
|
||||||
|
|
||||||
#ifdef HAVE_VOIPTEST
|
#ifdef HAVE_VOIPTEST
|
||||||
int app_pa_phone(int argc, const char *const *argv, struct command_line_option *o);
|
int app_pa_phone(int argc, const char *const *argv, struct command_line_option *o);
|
||||||
|
Loading…
Reference in New Issue
Block a user