mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-18 20:57:56 +00:00
Fixed broadcast address discovery to work on Mac.
Fixed Linux assumptions. Added parsing of overlay mesh interface specification from command line. Separated overlay mesh code out into several files. Overlay mesh is still far from working, but the infrastructure is coming together.
This commit is contained in:
parent
67eec6c3ff
commit
6e172c76c9
15
Makefile
15
Makefile
@ -1,19 +1,22 @@
|
||||
SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c dataformats.c \
|
||||
hlrdata.c srandomdev.c simulate.c batman.c overlay.c export.c gateway.c
|
||||
hlrdata.c srandomdev.c simulate.c batman.c export.c gateway.c \
|
||||
overlay.c overlay_buffer.c overlay_interface.c
|
||||
|
||||
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
|
||||
hlrdata.o srandomdev.o simulate.o batman.o overlay.o export.o gateway.o
|
||||
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
|
||||
overlay.o overlay_buffer.o overlay_interface.o
|
||||
HDRS= Makefile mphlr.h
|
||||
LDFLAGS=
|
||||
DEFS= -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DHAVE_LIBC=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDIO_H=1 -DHAVE_ERRNO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRINGS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_POLL_H=1 -DHAVE_NETDB_H=1
|
||||
LDFLAGS= -L/Developer/SDKs/MacOSX10.6.sdk/usr/lib
|
||||
CFLAGS= -I/Developer/SDKs/MacOSX10.6.sdk/usr/include
|
||||
DEFS= -DPACKAGE_NAME=\"\" -DPACKAGE_TARNAME=\"\" -DPACKAGE_VERSION=\"\" -DPACKAGE_STRING=\"\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DHAVE_LIBC=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDIO_H=1 -DHAVE_ERRNO_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRINGS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRING_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_SYS_MMAN_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_POLL_H=1 -DHAVE_NETDB_H=1 -DHAVE_NETINET_IN_H=1 -DHAVE_IFADDRS_H=1 -DHAVE_NET_IF_H
|
||||
|
||||
all: serval.c dna
|
||||
|
||||
%.o: %.c $(HDRS)
|
||||
$(CC) $(DEFS) -Os -g -Wall -c $<
|
||||
$(CC) $(CFLAGS) $(DEFS) -Os -g -Wall -c $<
|
||||
|
||||
dna: $(OBJS)
|
||||
$(CC) -Os -g -Wall -o dna $(OBJS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -Os -g -Wall -o dna $(OBJS) $(LDFLAGS)
|
||||
|
||||
serval.c: $(SRCS) $(HDRS)
|
||||
cat mphlr.h > serval.c
|
||||
|
11
Makefile.in
11
Makefile.in
@ -1,19 +1,22 @@
|
||||
SRCS= dna.c server.c client.c peers.c ciphers.c responses.c packetformats.c dataformats.c \
|
||||
hlrdata.c srandomdev.c simulate.c batman.c overlay.c export.c gateway.c
|
||||
hlrdata.c srandomdev.c simulate.c batman.c export.c gateway.c \
|
||||
overlay.c overlay_buffer.c overlay_interface.c
|
||||
|
||||
OBJS= dna.o server.o client.o peers.o ciphers.o responses.o packetformats.o dataformats.o \
|
||||
hlrdata.o srandomdev.o simulate.o batman.o overlay.o export.o gateway.o
|
||||
hlrdata.o srandomdev.o simulate.o batman.o export.o gateway.o \
|
||||
overlay.o overlay_buffer.o overlay_interface.o
|
||||
HDRS= Makefile mphlr.h
|
||||
LDFLAGS= @LDFLAGS@
|
||||
CFLAGS= @CFLAGS@
|
||||
DEFS= @DEFS@
|
||||
|
||||
all: serval.c dna
|
||||
|
||||
%.o: %.c $(HDRS)
|
||||
$(CC) $(DEFS) -Os -g -Wall -c $<
|
||||
$(CC) $(CFLAGS) $(DEFS) -Os -g -Wall -c $<
|
||||
|
||||
dna: $(OBJS)
|
||||
$(CC) -Os -g -Wall -o dna $(OBJS) $(LDFLAGS)
|
||||
$(CC) $(CFLAGS) -Os -g -Wall -o dna $(OBJS) $(LDFLAGS)
|
||||
|
||||
serval.c: $(SRCS) $(HDRS)
|
||||
cat mphlr.h > serval.c
|
||||
|
2
batman.c
2
batman.c
@ -118,7 +118,7 @@ int readBatmanPeerFile(char *file_path,struct in_addr peers[],int *peer_count,in
|
||||
timestamp=ntohl(timestamp);
|
||||
|
||||
if (timestamp<(time(0)-3)) {
|
||||
if (debug>1) fprintf(stderr,"Ignoring stale BATMAN peer list (%d seconds old)\n",time(0)-timestamp);
|
||||
if (debug>1) fprintf(stderr,"Ignoring stale BATMAN peer list (%d seconds old)\n",(int)(time(0)-timestamp));
|
||||
fclose(f);
|
||||
return -1;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ AC_PROG_CC
|
||||
|
||||
AC_CHECK_LIB(c,srandomdev)
|
||||
|
||||
AC_CHECK_HEADERS(stdio.h errno.h stdlib.h strings.h unistd.h string.h arpa/inet.h sys/socket.h sys/mman.h sys/time.h poll.h netdb.h)
|
||||
AC_CHECK_HEADERS(stdio.h errno.h stdlib.h strings.h unistd.h string.h arpa/inet.h sys/socket.h sys/mman.h sys/time.h poll.h netdb.h linux/if.h linux/netlink.h linux/rtnetlink.h net/if.h netinet/in.h ifaddrs.h)
|
||||
|
||||
AC_CHECK_LIB(nsl,callrpc,[LDFLAGS="$LDFLAGS -lnsl"])
|
||||
AC_CHECK_LIB(socket,socket,[LDFLAGS="$LDFLAGS -lsocket"])
|
||||
|
46
dna.c
46
dna.c
@ -215,7 +215,7 @@ int usage(char *complaint)
|
||||
{
|
||||
fprintf(stderr,"dna: %s\n",complaint);
|
||||
fprintf(stderr,"usage:\n");
|
||||
fprintf(stderr," dna [-v ...] -S <hlr size in MB> [-f HLR backing file] [-I import.txt] [-G SIP gateway]\n");
|
||||
fprintf(stderr," dna [-v ...] -S <hlr size in MB> [-f HLR backing file] [-I import.txt] [-N interface,...] [-G SIP gateway]\n");
|
||||
fprintf(stderr,"or\n");
|
||||
fprintf(stderr," dna <-d|-s> id -A\n");
|
||||
fprintf(stderr,"or\n");
|
||||
@ -255,6 +255,13 @@ int usage(char *complaint)
|
||||
fprintf(stderr," @value means read value from file called value.\n");
|
||||
fprintf(stderr," -C - Request the creation of a new subscriber with the specified DID.\n");
|
||||
fprintf(stderr," -t - Specify the request timeout period.\n");
|
||||
fprintf(stderr," -N - Specify one or more interfaces for the DNA overlay mesh to operate.\n");
|
||||
fprintf(stderr," Interface specifications take the form IP[:speed[:type[:port]]], and\n");
|
||||
fprintf(stderr," multiple interfaces can be specified by comma separating them.\n");
|
||||
fprintf(stderr," Speed is the interface speed in bits per second (K,M or G suffixes allowed)\n");
|
||||
fprintf(stderr," Type is WiFi,ethernet,catear or other.\n");
|
||||
fprintf(stderr," Port specifies an alternate UDP port, otherwise %d is used.\n",PORT_DNA);
|
||||
fprintf(stderr," e.g., -N 10.1.2.3,10.1.130.45:2M:wifi\n");
|
||||
fprintf(stderr,"\n");
|
||||
exit(-1);
|
||||
}
|
||||
@ -277,10 +284,14 @@ int main(int argc,char **argv)
|
||||
|
||||
srandomdev();
|
||||
|
||||
while((c=getopt(argc,argv,"Ab:B:E:G:I:S:f:d:i:l:L:np:P:s:t:vR:W:U:D:CO:")) != -1 )
|
||||
while((c=getopt(argc,argv,"Ab:B:E:G:I:S:f:d:i:l:L:np:P:s:t:vR:W:U:D:CO:N:")) != -1 )
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'N': /* Ask for overlay network to setup one or more interfaces */
|
||||
if (overlay_interface_args(optarg))
|
||||
return WHY("Invalid interface specification(s) passed to -N");
|
||||
break;
|
||||
case 'G': /* Offer gateway services */
|
||||
gatewayuri=strdup(optarg);
|
||||
break;
|
||||
@ -409,3 +420,34 @@ int main(int argc,char **argv)
|
||||
}
|
||||
#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");
|
||||
}
|
||||
}
|
||||
|
4
macconfig
Executable file
4
macconfig
Executable file
@ -0,0 +1,4 @@
|
||||
export LDFLAGS=-L/Developer/SDKs/MacOSX10.6.sdk/usr/lib
|
||||
export CPPFLAGS=-I/Developer/SDKs/MacOSX10.6.sdk/usr/include
|
||||
export CFLAGS=-I/Developer/SDKs/MacOSX10.6.sdk/usr/include
|
||||
./configure $*
|
167
mphlr.h
167
mphlr.h
@ -350,3 +350,170 @@ int asteriskObtainGateway(char *requestor_sid,char *did,char *uri_out);
|
||||
#define CRYPT_CIPHERED 1
|
||||
#define CRYPT_SIGNED 2
|
||||
#define CRYPT_PUBLIC 4
|
||||
|
||||
#define OVERLAY_INTERFACE_UNKNOWN 0
|
||||
#define OVERLAY_INTERFACE_ETHERNET 1
|
||||
#define OVERLAY_INTERFACE_WIFI 2
|
||||
#define OVERLAY_INTERFACE_PACKETRADIO 3
|
||||
typedef struct overlay_interface {
|
||||
int socket;
|
||||
int bits_per_second;
|
||||
int port;
|
||||
int type;
|
||||
/* Number of milli-seconds per tick for this interface, which is basically related to the
|
||||
the typical TX range divided by the maximum expected speed of nodes in the network.
|
||||
This means that short-range communications has a higher bandwidth requirement than
|
||||
long-range communications because the tick interval has to be shorter to still allow
|
||||
fast-convergence time to allow for mobility.
|
||||
|
||||
For wifi (nominal range 100m) it is usually 500ms.
|
||||
For ~100K ISM915MHz (nominal range 1000m) it will probably be about 5000ms.
|
||||
For ~10K ISM915MHz (nominal range ~3000m) it will probably be about 15000ms.
|
||||
These figures will be refined over time, and we will allow people to set them per-interface.
|
||||
*/
|
||||
int tick_ms;
|
||||
} overlay_interface;
|
||||
|
||||
/* Maximum interface count is rather arbitrary.
|
||||
Memory consumption is O(n) with respect to this parameter, so let's not make it too big for now.
|
||||
*/
|
||||
#define OVERLAY_MAX_INTERFACES 16
|
||||
extern overlay_interface overlay_interfaces[OVERLAY_MAX_INTERFACES];
|
||||
|
||||
/*
|
||||
For each peer we need to keep track of the routes that we know to reach it.
|
||||
|
||||
We want to use static sized data structures as much as we can to keep things efficient by
|
||||
allowing computed memory address lookups instead of following linked lists and other
|
||||
non-deterministic means.
|
||||
|
||||
The tricky part of doing all this is that each interface may have a different maximum number
|
||||
of peers based on the bandwidth of the link, as we do not want mesh traffic to consume all
|
||||
available bandwidth. In particular, we need to reserve at least enough bandwidth for one
|
||||
call.
|
||||
|
||||
Related to this, if we are in a mesh larger than the per-interface limit allows, then we need to
|
||||
only track the highest-scoring peers. This sounds simple, but how to we tell when to replace a
|
||||
low-scoring peer with another one which has a better reachability score, if we are not tracking
|
||||
the reachability score of that node?
|
||||
|
||||
The answer to this is that we track as many nodes as we can, but only announce the highest
|
||||
scoring nodes on each interface as bandwidth allows.
|
||||
|
||||
This also keeps our memory usage fixed.
|
||||
|
||||
XXX - At present we are setting OVERLAY_MAX_PEERS at compile time.
|
||||
With a bit of work we can change this to be a run-time option.
|
||||
|
||||
Memory consumption of OVERLAY_MAX_PEERS=n is O(n^2).
|
||||
XXX We could and should improve this down the track by only monitoring the top k routes, and replacing the worst route
|
||||
option when a better one comes along. This would get the memory usage down to O(n).
|
||||
|
||||
*/
|
||||
#define OVERLAY_MAX_PEERS 500
|
||||
|
||||
typedef struct overlay_peer {
|
||||
unsigned char address[SIDDIDFIELD_LEN];
|
||||
|
||||
/* Scores and score update times for reaching this node via various interfaces */
|
||||
int known_routes[OVERLAY_MAX_INTERFACES];
|
||||
unsigned short scores[OVERLAY_MAX_INTERFACES][OVERLAY_MAX_PEERS];
|
||||
|
||||
/* last_regeneration is the time that this peer was created/replaced with another peer.
|
||||
lastupdate[] indicates the time that another peer's reachability report
|
||||
caused us to update our score to reach via that peer.
|
||||
If lastupdate[x][y] is older than last_regeneration[y], then we must
|
||||
ignore the entry, because the lastupdate[x][y] entry references a previous
|
||||
generation of that peer, i.e., not to the peer we think it does.
|
||||
|
||||
This slight convolution allows us to replace peers without having to touch the
|
||||
records of every other peer in our list.
|
||||
*/
|
||||
int last_regeneration;
|
||||
unsigned int lastupdate[OVERLAY_MAX_INTERFACES][OVERLAY_MAX_PEERS];
|
||||
} overlay_peer;
|
||||
|
||||
extern overlay_peer overlay_peers[OVERLAY_MAX_PEERS];
|
||||
|
||||
typedef struct overlay_buffer {
|
||||
unsigned char *bytes;
|
||||
int length;
|
||||
int allocSize;
|
||||
int checkpointLength;
|
||||
int sizeLimit;
|
||||
} overlay_buffer;
|
||||
|
||||
int ob_unlimitsize(overlay_buffer *b);
|
||||
|
||||
typedef struct overlay_payload {
|
||||
struct overlay_payload *prev;
|
||||
struct overlay_payload *next;
|
||||
|
||||
/* We allows 256 bit addresses and 32bit port numbers */
|
||||
char src[SIDDIDFIELD_LEN];
|
||||
char dst[SIDDIDFIELD_LEN];
|
||||
int srcPort;
|
||||
int dstPort;
|
||||
|
||||
/* Hops before packet is dropped */
|
||||
unsigned char ttl;
|
||||
unsigned char trafficClass;
|
||||
|
||||
unsigned char srcAddrType;
|
||||
unsigned char dstAddrType;
|
||||
|
||||
/* Method of encryption if any employed */
|
||||
unsigned char cipher;
|
||||
|
||||
/* Payload flags */
|
||||
unsigned char flags;
|
||||
|
||||
/* Size and Pointer to the payload itself */
|
||||
int payloadLength;
|
||||
/* make the payload pointer be at the end, so that we can conveniently have the data follow this structure if necessary.
|
||||
(this lets us change the char * to a char payload[1] down the track to simplify this) */
|
||||
unsigned char *payload;
|
||||
} overlay_payload;
|
||||
|
||||
typedef struct overlay_txqueue {
|
||||
overlay_payload *first;
|
||||
overlay_payload *last;
|
||||
int length;
|
||||
int maxLength;
|
||||
/* Latency target in ms for this traffic class.
|
||||
Frames older than the latency target will get dropped. */
|
||||
int latencyTarget;
|
||||
|
||||
/* XXX Need to initialise these:
|
||||
Real-time queue for voice (<200ms ?)
|
||||
Real-time queue for video (<200ms ?) (lower priority than voice)
|
||||
Ordinary service queue (<3 sec ?)
|
||||
Rhizome opportunistic queue (infinity)
|
||||
|
||||
(Mesh management doesn't need a queue, as each overlay packet is tagged with some mesh management information)
|
||||
*/
|
||||
} overlay_txqueue;
|
||||
|
||||
extern overlay_txqueue overlay_tx[4];
|
||||
#define OVERLAY_ISOCHRONOUS_VOICE 0
|
||||
#define OVERLAY_ISOCHRONOUS_VIDEO 1
|
||||
#define OVERLAY_ORDINARY 2
|
||||
#define OVERLAY_OPPORTUNISTIC 3
|
||||
|
||||
int setReason(char *fmt, ...);
|
||||
#define WHY(X) setReason("%s:%d:%s() %s",__FILE__,__LINE__,__FUNCTION__,X)
|
||||
|
||||
overlay_buffer *ob_new(int size);
|
||||
int ob_free(overlay_buffer *b);
|
||||
int ob_checkpoint(overlay_buffer *b);
|
||||
int ob_rewind(overlay_buffer *b);
|
||||
int ob_limitsize(overlay_buffer *b,int bytes);
|
||||
int ob_unlimitsize(overlay_buffer *b);
|
||||
int ob_makespace(overlay_buffer *b,int bytes);
|
||||
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count);
|
||||
int ob_append_short(overlay_buffer *b,unsigned short v);
|
||||
int ob_append_int(overlay_buffer *b,unsigned int v);
|
||||
|
||||
long long parse_quantity(char *q);
|
||||
|
||||
int overlay_init_interface(in_addr_t src_addr,int speed_in_bits,int port,int type);
|
||||
|
309
overlay.c
309
overlay.c
@ -6,246 +6,61 @@
|
||||
Each overlay packet can contain one or more encapsulated packets each addressed using Serval DNA SIDs, with source,
|
||||
destination and next-hop addresses.
|
||||
|
||||
The use of long (relative to IPv4) ECC160 addresses means that it is a really good idea to have neighbouring nodes
|
||||
exchange lists of peer aliases so that addresses can be summarised, possibly using less space than IPv4 would have.
|
||||
The use of an overlay also lets us be a bit clever about using irregular transports, such as an ISM915 modem attached via ethernet
|
||||
(which we are planning to build in coming months), by paring off the IP and UDP headers that would otherwise dominate. Even on
|
||||
regular WiFi and ethernet we can aggregate packets in a way similar to IAX, but not just for voice frames.
|
||||
|
||||
The use of long (relative to IPv4 or even IPv6) 256 bit Curve25519 addresses means that it is a really good idea to
|
||||
have neighbouring nodes exchange lists of peer aliases so that addresses can be summarised, possibly using less space than IPv4
|
||||
would have.
|
||||
|
||||
One approach to handle address shortening is to have the periodic TTL=255 BATMAN-style hello packets include an epoch number.
|
||||
This epoch number can be used by immediate neighbours of the originator to reference the neighbours listed in that packet by
|
||||
their ordinal position in the packet instead of by their full address. This gets us address shortening to 1 byte in most cases
|
||||
in return for no new packets, but the periodic hello packets will now be larger. We might deal with this issue by having these
|
||||
hello packets reference the previous epoch for common neighbours. Unresolved neighbour addresses could be resolved by a simple
|
||||
DNA request, which should only need to occur ocassionally, and other link-local neighbours could sniff and cache the responses
|
||||
to avoid duplicated traffic. Indeed, during quiet times nodes could preemptively advertise address resolutions if they wished,
|
||||
or similarly advertise the full address of a few (possibly randomly selected) neighbours in each epoch.
|
||||
|
||||
Byzantine Robustness is a goal, so we have to think about all sorts of malicious failure modes.
|
||||
|
||||
One approach to help byzantine robustness is to have multiple signature shells for each hop for mesh topology packets.
|
||||
Thus forging a report of closeness requires forging a signature. As such frames are forwarded, the outermost signature
|
||||
shell is removed.
|
||||
shell is removed. This is really only needed for more paranoid uses.
|
||||
|
||||
We want to have different traffic classes for voice/video calls versus regular traffic, e.g., MeshMS frames. Thus we need to have
|
||||
separate traffic queues for these items. Aside from allowing us to prioritise isochronous data, it also allows us to expire old
|
||||
isochronous frames that are in-queue once there is no longer any point delivering them (e.g after holding them more than 200ms).
|
||||
We can also be clever about round-robin fair-sharing or even prioritising among isochronous streams. Since we also know about the
|
||||
DNA isochronous protocols and the forward error correction and other redundancy measures we also get smart about dropping, say, 1 in 3
|
||||
frames from every call if we know that this can be safely done. That is, when traffic is low, we maximise redundancy, and when we
|
||||
start to hit the limit of traffic, we start to throw away some of the redundancy. This of course relies on us knowing when the
|
||||
network channel is getting too full.
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_socket=-1;
|
||||
|
||||
typedef struct overlay_buffer {
|
||||
unsigned char *bytes;
|
||||
int length;
|
||||
int allocSize;
|
||||
int checkpointLength;
|
||||
int sizeLimit;
|
||||
} overlay_buffer;
|
||||
|
||||
int ob_unlimitsize(overlay_buffer *b);
|
||||
|
||||
typedef struct overlay_payload {
|
||||
struct overlay_payload *prev;
|
||||
struct overlay_payload *next;
|
||||
|
||||
/* We allows 256 bit addresses and 32bit port numbers */
|
||||
char src[SIDDIDFIELD_LEN];
|
||||
char dst[SIDDIDFIELD_LEN];
|
||||
int srcPort;
|
||||
int dstPort;
|
||||
|
||||
/* Hops before packet is dropped */
|
||||
unsigned char ttl;
|
||||
unsigned char trafficClass;
|
||||
|
||||
unsigned char srcAddrType;
|
||||
unsigned char dstAddrType;
|
||||
|
||||
/* Method of encryption if any employed */
|
||||
unsigned char cipher;
|
||||
|
||||
/* Payload flags */
|
||||
unsigned char flags;
|
||||
|
||||
/* Pointer to the payload itself */
|
||||
unsigned char *payload;
|
||||
int payloadLength;
|
||||
} overlay_payload;
|
||||
|
||||
typedef struct overlay_txqueue {
|
||||
overlay_payload *first;
|
||||
overlay_payload *last;
|
||||
int length;
|
||||
int maxLength;
|
||||
/* Latency target in ms for this traffic class */
|
||||
int latencyTarget;
|
||||
} overlay_txqueue;
|
||||
|
||||
/* XXX Need to initialise these:
|
||||
Real-time queue for voice
|
||||
Real-time queue for video (lower priority than voice)
|
||||
Ordinary service queue
|
||||
Rhizome opportunistic queue
|
||||
|
||||
(Mesh management doesn't need a queue, as each overlay packet is tagged with some mesh management information)
|
||||
*/
|
||||
overlay_txqueue overlay_tx[4];
|
||||
|
||||
int overlay_sock=-1;
|
||||
|
||||
int overlay_init()
|
||||
{
|
||||
struct sockaddr_in bind_addr;
|
||||
|
||||
overlay_sock=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (overlay_sock<0) {
|
||||
fprintf(stderr,"Could not create overlay UDP socket.\n");
|
||||
perror("socket");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons( PORT_DNA );
|
||||
bind_addr.sin_addr.s_addr = htonl( INADDR_ANY );
|
||||
if(bind(sock,(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
|
||||
fprintf(stderr,"MP HLR server could not bind to UDP port %d\n", PORT_DNA);
|
||||
perror("bind");
|
||||
exit(-3);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_rx_messages()
|
||||
{
|
||||
if (overlay_socket==-1) overlay_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_tx_messages()
|
||||
{
|
||||
if (overlay_socket==-1) overlay_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_broadcast_ensemble(char *bytes,int len)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
memset(&s, '\0', sizeof(struct sockaddr_in));
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons( PORT_OVERLAY );
|
||||
s.sin_addr.s_addr = htonl( INADDR_BROADCAST );
|
||||
|
||||
if(sendto(overlay_socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
|
||||
/* Failed to send */
|
||||
return -1;
|
||||
else
|
||||
/* Sent okay */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_payload_verify()
|
||||
{
|
||||
/* Make sure that an incoming payload has a valid signature from the sender.
|
||||
This is used to prevent spoofing */
|
||||
|
||||
return -1;
|
||||
return WHY("function not implemented");
|
||||
}
|
||||
|
||||
|
||||
overlay_buffer *ob_new(int size)
|
||||
{
|
||||
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1);
|
||||
if (!ret) return NULL;
|
||||
|
||||
ob_unlimitsize(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_free(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return -1;
|
||||
if (b->bytes) free(b->bytes);
|
||||
b->bytes=NULL;
|
||||
b->allocSize=0;
|
||||
b->sizeLimit=0;
|
||||
free(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_checkpoint(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return -1;
|
||||
b->checkpointLength=b->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rewind(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return -1;
|
||||
b->length=b->checkpointLength;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_limitsize(overlay_buffer *b,int bytes)
|
||||
{
|
||||
if (!b) return -1;
|
||||
if (b->length>bytes) return -1;
|
||||
if (b->checkpointLength>bytes) return -1;
|
||||
if (bytes<0) return -1;
|
||||
b->sizeLimit=bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_unlimitsize(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return -1;
|
||||
b->sizeLimit=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_makespace(overlay_buffer *b,int bytes)
|
||||
{
|
||||
if (b->sizeLimit!=-1) {
|
||||
if (b->length+bytes>b->sizeLimit) return -1;
|
||||
}
|
||||
if (b->length+bytes<b->allocSize)
|
||||
{
|
||||
int newSize=b->length+bytes;
|
||||
if (newSize<64) newSize=64;
|
||||
if (newSize&63) newSize+=64-(newSize&63);
|
||||
if (newSize>1024) {
|
||||
if (newSize&1023) newSize+=1024-(newSize&1023);
|
||||
}
|
||||
if (newSize>65536) {
|
||||
if (newSize&65535) newSize+=65536-(newSize&65535);
|
||||
}
|
||||
unsigned char *r=realloc(b->bytes,newSize);
|
||||
if (!r) return -1;
|
||||
b->bytes=r;
|
||||
b->allocSize=newSize;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count)
|
||||
{
|
||||
if (ob_makespace(b,count)) return -1;
|
||||
|
||||
bcopy(bytes,&b->bytes[b->length],count);
|
||||
b->length+=count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_append_short(overlay_buffer *b,unsigned short v)
|
||||
{
|
||||
unsigned short s=htons(v);
|
||||
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned short));
|
||||
}
|
||||
|
||||
int ob_append_int(overlay_buffer *b,unsigned int v)
|
||||
{
|
||||
unsigned int s=htonl(v);
|
||||
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned int));
|
||||
}
|
||||
|
||||
int overlay_get_nexthop(overlay_payload *p,unsigned char *hopout,int *hopaddrlen)
|
||||
{
|
||||
return -1;
|
||||
return WHY("function not implemented");
|
||||
}
|
||||
|
||||
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
|
||||
@ -258,9 +73,9 @@ int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
|
||||
|
||||
overlay_buffer *headers=ob_new(256);
|
||||
|
||||
if (!headers) return -1;
|
||||
if (!p) return -1;
|
||||
if (!b) return -1;
|
||||
if (!headers) return WHY("could not allocate overlay buffer for headers");
|
||||
if (!p) return WHY("p is NULL");
|
||||
if (!b) return WHY("b is NULL");
|
||||
|
||||
/* Build header */
|
||||
int fail=0;
|
||||
@ -268,37 +83,71 @@ int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b)
|
||||
if (overlay_get_nexthop(p,nexthop,&nexthoplen)) fail++;
|
||||
if (ob_append_bytes(headers,nexthop,nexthoplen)) fail++;
|
||||
|
||||
/* XXX Can use shorter fields for different address types */
|
||||
/* XXX Can use shorter fields for different address types, and if we know that the next hop
|
||||
knows a short-hand for the address.
|
||||
XXX Need a prefix byte for the type of address being used.
|
||||
BETTER - We just insist that the first byte of Curve25519 addresses be >0x0f, and use
|
||||
the low numbers for special cases:
|
||||
|
||||
*/
|
||||
if (p->src[0]<0x10||p->dst[0]<0x10) {
|
||||
// Make sure that addresses do not overload the special address spaces of 0x00*-0x0f*
|
||||
fail++;
|
||||
return WHY("address begins with reserved value 0x00-0x0f");
|
||||
}
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->src,SIDDIDFIELD_LEN)) fail++;
|
||||
if (ob_append_bytes(headers,(unsigned char *)p->dst,SIDDIDFIELD_LEN)) fail++;
|
||||
|
||||
if (fail) {
|
||||
ob_free(headers);
|
||||
return -1;
|
||||
return WHY("failure count was non-zero");
|
||||
}
|
||||
|
||||
/* Write payload format plus total length of header bits */
|
||||
if (ob_makespace(b,2+headers->length+p->payloadLength)) {
|
||||
/* Not enough space free in output buffer */
|
||||
ob_free(headers);
|
||||
return -1;
|
||||
return WHY("Could not make enough space free in output buffer");
|
||||
}
|
||||
|
||||
|
||||
/* Package up headers and payload */
|
||||
ob_checkpoint(b);
|
||||
if (ob_append_short(b,0x1000|(p->payloadLength+headers->length))) fail++;
|
||||
if (ob_append_bytes(b,headers->bytes,headers->length)) fail++;
|
||||
if (ob_append_bytes(b,p->payload,p->payloadLength)) fail++;
|
||||
|
||||
/* XXX SIGNATURE! */
|
||||
|
||||
if (ob_append_short(b,0x1000|(p->payloadLength+headers->length)))
|
||||
{ fail++; WHY("could not append version and length bytes"); }
|
||||
if (ob_append_bytes(b,headers->bytes,headers->length))
|
||||
{ fail++; WHY("could not append header"); }
|
||||
if (ob_append_bytes(b,p->payload,p->payloadLength))
|
||||
{ fail++; WHY("could not append payload"); }
|
||||
|
||||
/* XXX SIGN &/or ENCRYPT */
|
||||
|
||||
ob_free(headers);
|
||||
|
||||
if (fail) { ob_rewind(b); return -1; } else return 0;
|
||||
|
||||
if (fail) { ob_rewind(b); return WHY("failure count was non-zero"); } else return 0;
|
||||
}
|
||||
|
||||
|
||||
overlay_payload *overlay_payload_unpackage(overlay_buffer *b) {
|
||||
/* Extract the payload at the current location in the buffer. */
|
||||
|
||||
|
||||
WHY("not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int overlay_payload_enqueue(int q,overlay_payload *p,int urgentP)
|
||||
{
|
||||
/* Add payload p to queue q.
|
||||
If urgentP is set, then ask for the payload queue to be sent now.
|
||||
*/
|
||||
|
||||
return WHY("not implemented");
|
||||
if (urgentP) overlay_push_queued();
|
||||
}
|
||||
|
||||
int overlay_push_queued()
|
||||
{
|
||||
/* Try to send frames.
|
||||
The trick here is that we need to aggregate payloads based on which interface they need to go to */
|
||||
|
||||
return WHY("not implemented");
|
||||
}
|
||||
|
||||
|
101
overlay_buffer.c
Normal file
101
overlay_buffer.c
Normal file
@ -0,0 +1,101 @@
|
||||
#include "mphlr.h"
|
||||
|
||||
|
||||
overlay_buffer *ob_new(int size)
|
||||
{
|
||||
overlay_buffer *ret=calloc(sizeof(overlay_buffer),1);
|
||||
if (!ret) return NULL;
|
||||
|
||||
ob_unlimitsize(ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ob_free(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return WHY("Asked to free NULL");
|
||||
if (b->bytes) free(b->bytes);
|
||||
b->bytes=NULL;
|
||||
b->allocSize=0;
|
||||
b->sizeLimit=0;
|
||||
free(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_checkpoint(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return WHY("Asked to checkpoint NULL");
|
||||
b->checkpointLength=b->length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_rewind(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return WHY("Asked to rewind NULL");
|
||||
b->length=b->checkpointLength;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_limitsize(overlay_buffer *b,int bytes)
|
||||
{
|
||||
if (!b) return WHY("Asked to limit size of NULL");
|
||||
if (b->length>bytes) return WHY("Length of data in buffer already exceeds size limit");
|
||||
if (b->checkpointLength>bytes) return WHY("Checkpointed length of data in buffer already exceeds size limit");
|
||||
if (bytes<0) return WHY("Cant limit buffer to a negative size");
|
||||
b->sizeLimit=bytes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_unlimitsize(overlay_buffer *b)
|
||||
{
|
||||
if (!b) return WHY("b is NULL");
|
||||
b->sizeLimit=-1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_makespace(overlay_buffer *b,int bytes)
|
||||
{
|
||||
if (b->sizeLimit!=-1) {
|
||||
if (b->length+bytes>b->sizeLimit) return WHY("Asked to make space beyond size limit");
|
||||
}
|
||||
if (b->length+bytes<b->allocSize)
|
||||
{
|
||||
int newSize=b->length+bytes;
|
||||
if (newSize<64) newSize=64;
|
||||
if (newSize&63) newSize+=64-(newSize&63);
|
||||
if (newSize>1024) {
|
||||
if (newSize&1023) newSize+=1024-(newSize&1023);
|
||||
}
|
||||
if (newSize>65536) {
|
||||
if (newSize&65535) newSize+=65536-(newSize&65535);
|
||||
}
|
||||
unsigned char *r=realloc(b->bytes,newSize);
|
||||
if (!r) return WHY("realloc() failed");
|
||||
b->bytes=r;
|
||||
b->allocSize=newSize;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_append_bytes(overlay_buffer *b,unsigned char *bytes,int count)
|
||||
{
|
||||
if (ob_makespace(b,count)) return WHY("ob_makespace() failed");
|
||||
|
||||
bcopy(bytes,&b->bytes[b->length],count);
|
||||
b->length+=count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ob_append_short(overlay_buffer *b,unsigned short v)
|
||||
{
|
||||
unsigned short s=htons(v);
|
||||
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned short));
|
||||
}
|
||||
|
||||
int ob_append_int(overlay_buffer *b,unsigned int v)
|
||||
{
|
||||
unsigned int s=htonl(v);
|
||||
return ob_append_bytes(b,(unsigned char *)&s,sizeof(unsigned int));
|
||||
}
|
165
overlay_interface.c
Normal file
165
overlay_interface.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include "mphlr.h"
|
||||
|
||||
int overlay_ready=0;
|
||||
int overlay_interface_count=0;
|
||||
overlay_interface overlay_interfaces[OVERLAY_MAX_INTERFACES];
|
||||
|
||||
int overlay_interface_type(char *s)
|
||||
{
|
||||
if (!strcasecmp(s,"ethernet")) return OVERLAY_INTERFACE_ETHERNET;
|
||||
if (!strcasecmp(s,"wifi")) return OVERLAY_INTERFACE_WIFI;
|
||||
if (!strcasecmp(s,"other")) return OVERLAY_INTERFACE_UNKNOWN;
|
||||
if (!strcasecmp(s,"catear")) return OVERLAY_INTERFACE_PACKETRADIO;
|
||||
return WHY("Invalid interface type -- consider using 'wifi','ethernet' or 'other'");
|
||||
}
|
||||
|
||||
int overlay_interface_arg(char *arg)
|
||||
{
|
||||
/* Parse an interface argument, of the form:
|
||||
|
||||
address[:speed[:type[:port]]]
|
||||
*/
|
||||
|
||||
char address[80];
|
||||
char speed[80]="2m";
|
||||
char typestring[80]="wifi";
|
||||
int port=PORT_DNA;
|
||||
int type=OVERLAY_INTERFACE_UNKNOWN;
|
||||
int n=0;
|
||||
|
||||
/* Too long */
|
||||
if (strlen(arg)>79) return WHY("interface specification was >79 characters");
|
||||
|
||||
if (sscanf(arg,"%[^:]%n:%[^:]%n:%[^:]%n:%d%n",
|
||||
address,&n,speed,&n,typestring,&n,&port,&n)>=1)
|
||||
{
|
||||
int speed_in_bits=parse_quantity(speed);
|
||||
if (speed_in_bits<=1) {
|
||||
fprintf(stderr,"speed='%s'\n",speed);
|
||||
return WHY("Interfaces must be capable of at least 1 bit per second");
|
||||
}
|
||||
if (n<strlen(arg)) return WHY("Extra stuff at end of interface specification");
|
||||
|
||||
type=overlay_interface_type(typestring);
|
||||
if (type<0) return WHY("Invalid interface type in specification");
|
||||
|
||||
/* Okay, register the interface */
|
||||
in_addr_t src_addr=inet_addr(address);
|
||||
if (overlay_init_interface(src_addr,speed_in_bits,port,type))
|
||||
return WHY("Could not initialise interface");
|
||||
|
||||
}
|
||||
else return WHY("Bad interface specification");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_interface_args(char *arg)
|
||||
{
|
||||
/* Parse series of comma-separated interface definitions from a single argument
|
||||
*/
|
||||
int i=0;
|
||||
char interface[80];
|
||||
int len=0;
|
||||
|
||||
for(i=0;arg[i];i++)
|
||||
{
|
||||
if (arg[i]==',') {
|
||||
interface[len]=0;
|
||||
if (overlay_interface_arg(interface)) return WHY("Could not add interface");
|
||||
len=0;
|
||||
} else {
|
||||
if (len<79) {
|
||||
interface[len++]=arg[i];
|
||||
interface[len]=0;
|
||||
} else
|
||||
return WHY("Interface definition is too long (each must be <80 characters)");
|
||||
}
|
||||
}
|
||||
if (len) if (overlay_interface_arg(interface)) return WHY("Could not add final interface");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_init_interface(in_addr_t src_addr,int speed_in_bits,int port,int type)
|
||||
{
|
||||
struct sockaddr_in bind_addr;
|
||||
|
||||
/* Too many interfaces */
|
||||
if (overlay_interface_count>=OVERLAY_MAX_INTERFACES) return WHY("Too many interfaces -- Increase OVERLAY_MAX_INTERFACES");
|
||||
|
||||
#define I(X) overlay_interfaces[overlay_interface_count].X
|
||||
|
||||
I(socket)=socket(PF_INET,SOCK_DGRAM,0);
|
||||
if (I(socket)<0) {
|
||||
return WHY("Could not create UDP socket for interface");
|
||||
}
|
||||
|
||||
bind_addr.sin_family = AF_INET;
|
||||
bind_addr.sin_port = htons( port<0?PORT_DNA:port );
|
||||
/* XXX Is this right? Are we really setting the local side address?
|
||||
I was in a plane when at the time, so couldn't Google it.
|
||||
*/
|
||||
fprintf(stderr,"src_addr=%08x\n",(unsigned int)src_addr);
|
||||
bind_addr.sin_addr.s_addr = htonl( src_addr );
|
||||
if(bind(I(socket),(struct sockaddr *)&bind_addr,sizeof(bind_addr))) {
|
||||
perror("bind()");
|
||||
return WHY("MP HLR server could not bind to requested UDP port (bind() failed)");
|
||||
}
|
||||
|
||||
I(bits_per_second)=speed_in_bits;
|
||||
I(port)=bind_addr.sin_port;
|
||||
I(type)=type;
|
||||
|
||||
overlay_interface_count++;
|
||||
#undef I(X)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_rx_messages()
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Grab packets, unpackage and dispatch frames to consumers */
|
||||
/* XXX Okay, so how are we managing out-of-process consumers?
|
||||
They need some way to register their interest in listening to a port.
|
||||
*/
|
||||
for(i=0;i<overlay_interface_count;i++)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_tx_messages()
|
||||
{
|
||||
/* Check out the various queues, and add payloads to a new frame and send it out. */
|
||||
/* XXX We may want to throttle the maximum packets/sec or KB/sec */
|
||||
|
||||
/* How are we going to pick and choose things from the various priority queues?
|
||||
We could simply pick the top item from each queue in round-robin until the
|
||||
frame is filled. That would be a start. We could certainly get more intelligent
|
||||
and stuff lots of little frames from a high priority queue in if that makes sense,
|
||||
especially if they look like getting delayed a bit. Perhaps we just reserve the first
|
||||
n bytes for the first queue, the first n+k bytes for the first two queues and so on?
|
||||
*/
|
||||
|
||||
/* XXX Go through queue and separate into per-interface queues? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int overlay_broadcast_ensemble(int interface_number,char *bytes,int len)
|
||||
{
|
||||
struct sockaddr_in s;
|
||||
|
||||
memset(&s, '\0', sizeof(struct sockaddr_in));
|
||||
s.sin_family = AF_INET;
|
||||
s.sin_port = htons( PORT_OVERLAY );
|
||||
s.sin_addr.s_addr = htonl( INADDR_BROADCAST );
|
||||
|
||||
if(sendto(overlay_interfaces[interface_number].socket, bytes, len, 0, (struct sockaddr *)&s, sizeof(struct sockaddr_in)) < 0)
|
||||
/* Failed to send */
|
||||
return WHY("sendto() failed");
|
||||
else
|
||||
/* Sent okay */
|
||||
return 0;
|
||||
}
|
53
peers.c
53
peers.c
@ -19,13 +19,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#include "mphlr.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_IF_H
|
||||
#include <linux/if.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_NETLINK_H
|
||||
#include <linux/netlink.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINUX_RTNETLINK_H
|
||||
#include <linux/rtnetlink.h>
|
||||
#endif
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
char *batman_socket=NULL;
|
||||
char *batman_peerfile=NULL;
|
||||
@ -50,8 +61,13 @@ int additionalPeer(char *peer)
|
||||
}
|
||||
|
||||
int getBroadcastAddresses(struct in_addr peers[],int *peer_count,int peer_max){
|
||||
#ifndef WIN32
|
||||
// android ndk doesn't have ifaddrs.h, so we have to use the netlink interface
|
||||
/* The Android ndk doesn't have ifaddrs.h, so we have to use the netlink interface.
|
||||
However, netlink is only available on Linux, so for BSD systems, e.g., Mac, we
|
||||
need to use the ifaddrs method.
|
||||
|
||||
Also, ifaddrs will work on non-linux systems which is considered critical.
|
||||
*/
|
||||
#ifdef HAVE_LINUX_NETLINK_H
|
||||
|
||||
// Ask for the address information.
|
||||
struct {
|
||||
@ -102,6 +118,37 @@ int getBroadcastAddresses(struct in_addr peers[],int *peer_count,int peer_max){
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifdef HAVE_IFADDRS_H
|
||||
struct ifaddrs *ifaddr,*ifa;
|
||||
int family, s;
|
||||
char host[NI_MAXHOST];
|
||||
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
perror("getifaddr()");
|
||||
return WHY("getifaddrs() failed");
|
||||
}
|
||||
|
||||
for (ifa=ifaddr;ifa!=NULL;ifa=ifa->ifa_next) {
|
||||
family=ifa->ifa_addr->sa_family;
|
||||
switch(family) {
|
||||
case AF_INET:
|
||||
/* Add our local address and computed broadcast address to the list of peers.
|
||||
XXX - ifa->ifa_broadaddr should give us the broadcast address, but doesn't seem to
|
||||
on mac osx. So we have resorted computing the normal (ceiling) broadcast address.
|
||||
*/
|
||||
peers[(*peer_count)++].s_addr=((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr;
|
||||
{
|
||||
struct sockaddr_in broadcast;
|
||||
unsigned int local=(((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr.s_addr);
|
||||
unsigned int netmask=(((struct sockaddr_in *)(ifa->ifa_netmask))->sin_addr.s_addr);
|
||||
peers[(*peer_count)++].s_addr=local|~netmask;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user