mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-20 05:37:57 +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
|
||||
serval.c
|
||||
servald
|
||||
directory_service
|
||||
*.so
|
||||
test.*.log
|
||||
testlog
|
||||
|
@ -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
5
Makefile.in
Normal file → Executable 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)
|
||||
|
@ -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
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
3
serval.h
3
serval.h
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user