Add stub directory service

This commit is contained in:
Jeremy Lakeman 2012-09-14 11:50:45 +09:30
parent 7b8885fd96
commit ac8d9b93e6
10 changed files with 272 additions and 0 deletions

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ nacl/naclinc.txt
nacl/nacllib.txt
serval.c
servald
directory_service
*.so
test.*.log
testlog

View File

@ -16,6 +16,7 @@ SERVALD_SRC_FILES = \
serval-dna/commandline.c \
serval-dna/conf.c \
serval-dna/dataformats.c \
serval-dna/directory_client.c \
serval-dna/xprintf.c \
serval-dna/log.c \
serval-dna/net.c \

5
Makefile.in Normal file → Executable file
View File

@ -10,6 +10,7 @@ SRCS= \
commandline.c \
conf.c \
dataformats.c \
directory_client.c \
dna_helper.c \
dna_identity.c \
encode.c \
@ -132,6 +133,10 @@ servald: $(OBJS)
@echo LINK $@
@$(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
# DOC 20120615
libservald.so: $(OBJS)

View File

@ -246,6 +246,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define MDP_PORT_VOMP 0x10000002
#define MDP_PORT_DNALOOKUP 0x10000003
#define MDP_PORT_NOREPLY 0x10000000
#define MDP_PORT_DIRECTORY 10
#define MDP_TYPE_MASK 0xff
#define MDP_FLAG_MASK 0xff00

88
directory_client.c Normal file
View 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
View 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;
}

View File

@ -215,6 +215,38 @@ int reachable_unicast(struct subscriber *subscriber, overlay_interface *interfac
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
int overlay_broadcast_generate_address(struct broadcast *addr)
{

View File

@ -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);
int subscriber_is_reachable(struct subscriber *subscriber);
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_generate_address(struct broadcast *addr);

View File

@ -266,6 +266,18 @@ overlay_interface * overlay_interface_find(struct in_addr addr){
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
// So we have to bind a socket to INADDR_ANY to receive these packets.
static void
@ -406,6 +418,10 @@ overlay_interface_init_socket(int interface_index)
// mark our sid to be sent in full
if (my_subscriber)
my_subscriber->send_full = 1;
// try to register ourselves with a directory service
directory_interface_up(interface);
return 0;
}

View File

@ -863,6 +863,9 @@ int overlay_interface_register(char *name,
struct in_addr addr,
struct in_addr mask);
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
int app_pa_phone(int argc, const char *const *argv, struct command_line_option *o);