2010-07-13 12:15:46 +00:00
|
|
|
/*
|
|
|
|
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 <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
#include <strings.h>
|
|
|
|
#endif
|
|
|
|
#include <string.h>
|
2011-03-30 05:04:23 +00:00
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
#include "win32/win32.h"
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
2011-07-08 05:06:54 +00:00
|
|
|
#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
|
2011-03-30 05:04:23 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(FORASTERISK) && !defined(s_addr)
|
2010-07-13 12:15:46 +00:00
|
|
|
#ifdef HAVE_ARPA_INET_H
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#else
|
|
|
|
typedef unsigned int in_addr_t;
|
|
|
|
struct in_addr {
|
|
|
|
in_addr_t s_addr;
|
|
|
|
};
|
|
|
|
#endif
|
2011-03-21 02:38:35 +00:00
|
|
|
#endif
|
2011-03-30 05:04:23 +00:00
|
|
|
|
2010-07-13 12:15:46 +00:00
|
|
|
#ifdef HAVE_SYS_SOCKET_H
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_MMAN_H
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TIME_H
|
|
|
|
#include <sys/time.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_POLL_H
|
|
|
|
#include <poll.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_NETDB_H
|
|
|
|
#include <netdb.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_CTYPE_H
|
|
|
|
#include <ctype.h>
|
|
|
|
#endif
|
2011-03-30 05:04:23 +00:00
|
|
|
|
|
|
|
#ifndef WIN32
|
2010-07-13 12:15:46 +00:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <net/if.h>
|
2011-03-30 05:04:23 +00:00
|
|
|
#endif
|
|
|
|
|
2010-07-13 12:15:46 +00:00
|
|
|
#include <fcntl.h>
|
2011-03-30 05:04:23 +00:00
|
|
|
//FIXME #include <getopt.h>
|
2010-07-13 12:15:46 +00:00
|
|
|
#include <ctype.h>
|
|
|
|
|
2011-08-08 14:41:46 +00:00
|
|
|
/* UDP Port numbers for various Serval services.
|
|
|
|
The overlay mesh works over DNA */
|
2011-04-27 11:48:09 +00:00
|
|
|
#define PORT_DNA 4110
|
2010-07-13 12:15:46 +00:00
|
|
|
|
|
|
|
/* OpenWRT libc doesn't have bcopy, but has memmove */
|
|
|
|
#define bcopy(A,B,C) memmove(B,A,C)
|
|
|
|
|
|
|
|
#define BATCH 1
|
|
|
|
#define NONBATCH 0
|
|
|
|
|
|
|
|
#define REQ_SERIAL 0
|
|
|
|
#define REQ_PARALLEL -1
|
|
|
|
#define REQ_FIRSTREPLY -2
|
|
|
|
#define REQ_REPLY -101
|
|
|
|
|
|
|
|
|
|
|
|
#define SET_NOREPLACE 1
|
|
|
|
#define SET_REPLACE 2
|
|
|
|
#define SET_NOCREATE 3
|
|
|
|
#define SET_FRAGMENT 0x80
|
|
|
|
|
|
|
|
#define WITHDATA 1
|
|
|
|
#define WITHOUTDATA 0
|
|
|
|
|
|
|
|
/* Limit packet payloads to minimise packet loss of big packets in mesh networks */
|
|
|
|
#define MAX_DATA_BYTES 256
|
|
|
|
|
|
|
|
extern int debug;
|
|
|
|
extern int timeout;
|
|
|
|
extern int hlr_size;
|
|
|
|
extern unsigned char *hlr;
|
|
|
|
|
|
|
|
double simulatedBER;
|
|
|
|
|
|
|
|
extern int serverMode;
|
|
|
|
|
2011-08-10 13:38:59 +00:00
|
|
|
extern char *gatewayspec;
|
2011-05-06 02:27:33 +00:00
|
|
|
|
2010-07-13 12:15:46 +00:00
|
|
|
extern struct sockaddr recvaddr;
|
|
|
|
extern struct in_addr client_addr;
|
|
|
|
extern int client_port;
|
|
|
|
|
|
|
|
#define MAX_PEERS 1024
|
|
|
|
extern int peer_count;
|
2011-04-27 11:48:09 +00:00
|
|
|
extern struct in_addr peers[MAX_PEERS];
|
2010-07-13 12:15:46 +00:00
|
|
|
|
|
|
|
struct mphlr_variable {
|
|
|
|
unsigned char id;
|
|
|
|
char *name;
|
|
|
|
char *desc;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern char *outputtemplate;
|
2011-05-05 09:10:38 +00:00
|
|
|
extern char *instrumentation_file;
|
2010-07-13 12:15:46 +00:00
|
|
|
extern char *batman_socket;
|
2011-03-21 02:38:35 +00:00
|
|
|
extern char *batman_peerfile;
|
2010-07-13 12:15:46 +00:00
|
|
|
|
|
|
|
/* HLR records can be upto 4GB, so 4x8bits are needed to encode the size */
|
|
|
|
#define HLR_RECORD_LEN_SIZE 4
|
|
|
|
|
|
|
|
/* Packet format:
|
|
|
|
|
|
|
|
16 bit - Magic value 0x4110
|
|
|
|
16 bit - Version number (0001 initially)
|
|
|
|
16 bit - Payload length
|
|
|
|
16 bit - Cipher method (0000 = clear text)
|
|
|
|
|
|
|
|
Ciphered payload follows:
|
|
|
|
(needs to have no predictable data to protect against known plain-text attacks)
|
|
|
|
|
|
|
|
64bit transaction id (random)
|
|
|
|
8bit - payload rotation (random, to help protect encryption from cribs)
|
|
|
|
|
|
|
|
Remainder of payload, after correcting for rotation:
|
|
|
|
|
|
|
|
33byte did|subscriber id
|
|
|
|
16byte salt
|
|
|
|
16byte hash of PIN+salt
|
|
|
|
|
|
|
|
Remainder of packet is interpretted as a series of operations
|
|
|
|
|
|
|
|
8 bit operation:
|
|
|
|
00 = get, 01 = set, 02 = delete, 03 = update,
|
|
|
|
80 = decline, 81 = okay (+optional result),
|
|
|
|
f0 = xfer HLR record
|
|
|
|
fe = random padding follows (to help protect cryptography from cribs)
|
|
|
|
ff = end of transaction
|
|
|
|
|
|
|
|
get - 8 bit variable value
|
|
|
|
|
|
|
|
*/
|
|
|
|
#define SID_SIZE 32
|
|
|
|
#define DID_MAXSIZE 32
|
|
|
|
#define SIDDIDFIELD_LEN (SID_SIZE+1)
|
|
|
|
#define PINFIELD_LEN 32
|
|
|
|
#define HEADERFIELDS_LEN (2+2+2+2+8+1)
|
|
|
|
#define OFS_TRANSIDFIELD (2+2+2+2)
|
|
|
|
#define TRANSID_SIZE 8
|
|
|
|
#define OFS_ROTATIONFIELD (OFS_TRANSIDFIELD+TRANSID_SIZE)
|
|
|
|
#define OFS_SIDDIDFIELD HEADERFIELDS_LEN
|
|
|
|
#define OFS_PINFIELD (OFS_SIDDIDFIELD+SIDDIDFIELD_LEN)
|
|
|
|
#define OFS_PAYLOAD (OFS_PINFIELD+16+16)
|
|
|
|
|
|
|
|
struct response {
|
|
|
|
int code;
|
|
|
|
unsigned char sid[32];
|
|
|
|
struct in_addr sender;
|
|
|
|
unsigned char *response;
|
|
|
|
int response_len;
|
|
|
|
int var_id;
|
|
|
|
int var_instance;
|
|
|
|
int value_len;
|
|
|
|
int value_offset;
|
|
|
|
int value_bytes;
|
|
|
|
struct response *next,*prev;
|
|
|
|
|
|
|
|
/* who sent it? */
|
|
|
|
unsigned short peer_id;
|
|
|
|
/* have we checked it to see if it allows us to stop requesting? */
|
|
|
|
unsigned char checked;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct response_set {
|
|
|
|
struct response *responses;
|
|
|
|
struct response *last_response;
|
|
|
|
int response_count;
|
|
|
|
|
|
|
|
/* Bit mask of peers who have replied */
|
|
|
|
unsigned char *reply_bitmask;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct hlrentry_handle {
|
|
|
|
int record_length;
|
|
|
|
unsigned char *hlr;
|
|
|
|
int hlr_offset;
|
|
|
|
|
|
|
|
int var_id;
|
|
|
|
int var_instance;
|
|
|
|
unsigned char *value;
|
|
|
|
int value_len;
|
|
|
|
|
|
|
|
int entry_offset;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Array of variables that can be placed in an MPHLR */
|
|
|
|
#define VAR_EOR 0x00
|
|
|
|
#define VAR_CREATETIME 0x01
|
|
|
|
#define VAR_CREATOR 0x02
|
|
|
|
#define VAR_REVISION 0x03
|
|
|
|
#define VAR_REVISOR 0x04
|
|
|
|
#define VAR_PIN 0x05
|
|
|
|
#define VAR_VOICESIG 0x08
|
|
|
|
#define VAR_HLRMASTER 0x0f
|
|
|
|
#define VAR_DIDS 0x80
|
|
|
|
#define VAR_LOCATIONS 0x81
|
|
|
|
#define VAR_IEMIS 0x82
|
|
|
|
#define VAR_TEMIS 0x83
|
|
|
|
#define VAR_CALLS_IN 0x90
|
|
|
|
#define VAR_CALLS_MISSED 0x91
|
|
|
|
#define VAR_CALLS_OUT 0x92
|
|
|
|
#define VAR_SMESSAGES 0xa0
|
|
|
|
#define VAR_DID2SUBSCRIBER 0xb0
|
|
|
|
#define VAR_HLRBACKUPS 0xf0
|
|
|
|
#define VAR_NOTE 0xff
|
|
|
|
extern struct mphlr_variable vars[];
|
|
|
|
|
|
|
|
#define ACTION_GET 0x00
|
|
|
|
#define ACTION_SET 0x01
|
|
|
|
#define ACTION_DEL 0x02
|
|
|
|
#define ACTION_INSERT 0x03
|
2011-05-23 11:35:15 +00:00
|
|
|
#define ACTION_DIGITALTELEGRAM 0x04
|
2010-07-13 12:15:46 +00:00
|
|
|
#define ACTION_CREATEHLR 0x0f
|
|
|
|
|
2011-05-02 13:02:38 +00:00
|
|
|
#define ACTION_STATS 0x40
|
|
|
|
|
2010-07-13 12:15:46 +00:00
|
|
|
#define ACTION_DONE 0x7e
|
|
|
|
#define ACTION_ERROR 0x7f
|
|
|
|
|
|
|
|
#define ACTION_DECLINED 0x80
|
|
|
|
#define ACTION_OKAY 0x81
|
|
|
|
#define ACTION_DATA 0x82
|
|
|
|
#define ACTION_WROTE 0x83
|
|
|
|
|
|
|
|
#define ACTION_XFER 0xf0
|
|
|
|
#define ACTION_PAD 0xfe
|
|
|
|
#define ACTION_EOT 0xff
|
|
|
|
|
|
|
|
extern int hexdigit[16];
|
|
|
|
|
|
|
|
/* Make sure we have space to put bytes of the packet as we go along */
|
|
|
|
#define CHECK_PACKET_LEN(B) {if (((*packet_len)+(B))>=packet_maxlen) { setReason("Packet composition ran out of space."); return -1; } }
|
|
|
|
|
|
|
|
extern int sock;
|
|
|
|
|
|
|
|
int stowSid(unsigned char *packet,int ofs,char *sid);
|
|
|
|
int stowDid(unsigned char *packet,int *ofs,char *did);
|
|
|
|
int isFieldZeroP(unsigned char *packet,int start,int count);
|
|
|
|
void srandomdev();
|
|
|
|
int respondSimple(char *sid,int action,unsigned char *action_text,int action_len,
|
2011-05-16 07:28:25 +00:00
|
|
|
unsigned char *transaction_id,int cryptoFlags);
|
2010-07-13 12:15:46 +00:00
|
|
|
int requestItem(char *did,char *sid,char *item,int instance,unsigned char *buffer,int buffer_length,int *len,
|
|
|
|
unsigned char *transaction_id);
|
|
|
|
int requestNewHLR(char *did,char *pin,char *sid);
|
|
|
|
int server(char *backing_file,int size,int foregroundMode);
|
|
|
|
|
2011-05-06 02:27:33 +00:00
|
|
|
int setReason(char *fmt, ...);
|
2010-07-13 12:15:46 +00:00
|
|
|
int hexvalue(unsigned char c);
|
|
|
|
int dump(char *name,unsigned char *addr,int len);
|
|
|
|
int packetOk(unsigned char *packet,int len,unsigned char *transaction_id);
|
|
|
|
int process_packet(unsigned char *packet,int len,struct sockaddr *sender,int sender_len);
|
|
|
|
int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len,unsigned char *transaction_id);
|
|
|
|
int packetSetDid(unsigned char *packet,int packet_maxlen,int *packet_len,char *did);
|
|
|
|
int packetSetSid(unsigned char *packet,int packet_maxlen,int *packet_len,char *sid);
|
|
|
|
int packetFinalise(unsigned char *packet,int packet_maxlen,int *packet_len);
|
|
|
|
int packetAddHLRCreateRequest(unsigned char *packet,int packet_maxlen,int *packet_len);
|
|
|
|
int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct response_set *responses);
|
|
|
|
int packetAddVariableRequest(unsigned char *packet,int packet_maxlen,int *packet_len,
|
|
|
|
char *item,int instance,int start_offset,int max_offset);
|
|
|
|
int packetGetID(unsigned char *packet,int len,char *did,char *sid);
|
|
|
|
int getPeerList();
|
|
|
|
int sendToPeers(unsigned char *packet,int packet_len,int method,int peerId,struct response_set *responses);
|
|
|
|
int getReplyPackets(int method,int peer,int batchP,
|
|
|
|
struct response_set *responses,
|
|
|
|
unsigned char *transaction_id,int timeout);
|
|
|
|
int clearResponse(struct response **response);
|
|
|
|
int nextHlr(unsigned char *hlr,int *ofs);
|
|
|
|
int findHlr(unsigned char *hlr,int *ofs,char *sid,char *did);
|
|
|
|
int createHlr(char *did,char *sid);
|
|
|
|
struct hlrentry_handle *openhlrentry(unsigned char *hlr,int hofs);
|
|
|
|
struct hlrentry_handle *hlrentrygetent(struct hlrentry_handle *h);
|
|
|
|
int hlrStowValue(unsigned char *hlr,int hofs,int hlr_offset,
|
|
|
|
int varid,int varinstance,unsigned char *value,int len);
|
|
|
|
int hlrMakeSpace(unsigned char *hlr,int hofs,int hlr_offset,int bytes);
|
|
|
|
int packageVariableSegment(unsigned char *data,int *dlen,struct hlrentry_handle *h,
|
|
|
|
int offset,int buffer_size);
|
|
|
|
int packetDecipher(unsigned char *packet,int len,int cipher);
|
|
|
|
int safeZeroField(unsigned char *packet,int start,int count);
|
|
|
|
int unpackageVariableSegment(unsigned char *data,int dlen,int flags,struct response *r);
|
|
|
|
int extractSid(unsigned char *packet,int *ofs,char *sid);
|
|
|
|
int hlrSetVariable(unsigned char *hlr,int hofs,int varid,int varinstance,
|
|
|
|
unsigned char *value,int len);
|
|
|
|
int extractDid(unsigned char *packet,int *ofs,char *did);
|
|
|
|
char *hlrSid(unsigned char *hlr,int ofs);
|
|
|
|
int parseAssignment(unsigned char *text,int *var_id,unsigned char *value,int *value_len);
|
|
|
|
int writeItem(char *id,int var_id,int instance,unsigned char *value,int value_start,int value_len,int policy);
|
|
|
|
int packetAddVariableWrite(unsigned char *packet,int packet_maxlen,int *packet_len,
|
|
|
|
int itemId,int instance,unsigned char *value,int start_offset,int value_len,int flags);
|
|
|
|
int processRequest(unsigned char *packet,int len,struct sockaddr *sender,int sender_len,
|
|
|
|
unsigned char *transaction_id,char *did,char *sid);
|
|
|
|
|
|
|
|
int extractRequest(unsigned char *packet,int *packet_ofs,int packet_len,
|
|
|
|
int *itemId,int *instance,unsigned char *value,
|
|
|
|
int *start_offset,int *max_offset,int *flags);
|
|
|
|
int hlrGetVariable(unsigned char *hlr,int hofs,int varid,int varinstance,
|
|
|
|
unsigned char *value,int *len);
|
|
|
|
int packetSendRequest(int method,unsigned char *packet,int packet_len,int batchP,
|
|
|
|
unsigned char *transaction_id,struct response_set *responses);
|
|
|
|
int dumpResponses(struct response_set *responses);
|
|
|
|
int eraseLastResponse(struct response_set *responses);
|
|
|
|
int dropPacketP(int packet_len);
|
|
|
|
int clearResponses(struct response_set *responses);
|
|
|
|
int responseFromPeerP(struct response_set *responses,int peerId);
|
|
|
|
int responseFromPeer(struct response_set *responses,int peerId);
|
|
|
|
int additionalPeer(char *peer);
|
2011-06-04 03:59:26 +00:00
|
|
|
int readRoutingTable(struct in_addr peers[],int *peer_count,int peer_max);
|
2011-04-27 11:48:09 +00:00
|
|
|
int readBatmanPeerFile(char *file_path,struct in_addr peers[],int *peer_count,int peer_max);
|
|
|
|
int getBatmanPeerList(char *socket_path,struct in_addr peers[],int *peer_count,int peer_max);
|
2010-07-13 12:15:46 +00:00
|
|
|
int hlrDump(unsigned char *hlr,int hofs);
|
2011-03-22 06:01:02 +00:00
|
|
|
int peerAddress(char *did,char *sid,int flags);
|
2011-03-30 13:39:42 +00:00
|
|
|
int fixResponses(struct response_set *responses);
|
2011-05-06 02:27:33 +00:00
|
|
|
int importHlr(char *textfile);
|
|
|
|
int exportHlr(unsigned char *hlr,char *text);
|
|
|
|
int openHlrFile(char *backing_file,int size);
|
2011-05-23 21:52:43 +00:00
|
|
|
int runCommand(char *cmd);
|
|
|
|
int asteriskObtainGateway(char *requestor_sid,char *did,char *uri_out);
|
2011-05-16 07:28:25 +00:00
|
|
|
|
|
|
|
#define CRYPT_CIPHERED 1
|
|
|
|
#define CRYPT_SIGNED 2
|
|
|
|
#define CRYPT_PUBLIC 4
|
2011-08-08 06:41:05 +00:00
|
|
|
|
2011-08-08 14:41:46 +00:00
|
|
|
extern int overlayMode;
|
2011-08-08 06:41:05 +00:00
|
|
|
#define OVERLAY_INTERFACE_UNKNOWN 0
|
|
|
|
#define OVERLAY_INTERFACE_ETHERNET 1
|
|
|
|
#define OVERLAY_INTERFACE_WIFI 2
|
|
|
|
#define OVERLAY_INTERFACE_PACKETRADIO 3
|
|
|
|
typedef struct overlay_interface {
|
2011-08-12 07:47:29 +00:00
|
|
|
char name[80];
|
2011-08-08 06:41:05 +00:00
|
|
|
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;
|
2011-08-08 14:41:46 +00:00
|
|
|
/* The time of the last tick on this interface in milli seconds */
|
|
|
|
long long last_tick_ms;
|
|
|
|
|
2011-08-12 06:34:56 +00:00
|
|
|
/* Sequence number of last tick. Sent with announcments to help keep track of the reliability of
|
|
|
|
getting traffic to/from us. */
|
|
|
|
int sequence_number;
|
|
|
|
|
2011-08-08 14:41:46 +00:00
|
|
|
/* Broadcast address and netmask, if known */
|
2011-08-12 07:47:29 +00:00
|
|
|
struct sockaddr_in local_address;
|
2011-08-08 14:41:46 +00:00
|
|
|
struct sockaddr_in broadcast_address;
|
|
|
|
struct sockaddr_in netmask;
|
|
|
|
|
|
|
|
/* Not necessarily the real MTU, but the largest frame size we are willing to TX on this interface.
|
|
|
|
For radio links the actual maximum and the maximum that is likely to be delivered reliably are
|
|
|
|
potentially two quite different values. */
|
|
|
|
int mtu;
|
2011-08-12 07:47:29 +00:00
|
|
|
|
|
|
|
/* If the interface still exists on the local machine.
|
|
|
|
If not, it we keep track of it for a few seconds before purging it, incase of flapping, e.g.,
|
|
|
|
due to DHCP renewal */
|
|
|
|
int observed;
|
2011-08-08 06:41:05 +00:00
|
|
|
} 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;
|
2011-08-08 14:41:46 +00:00
|
|
|
|
|
|
|
/* time this frame was enqueued */
|
|
|
|
long long enqueued_at;
|
2011-08-08 06:41:05 +00:00
|
|
|
} 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);
|
|
|
|
|
2011-08-08 14:41:46 +00:00
|
|
|
int op_free(overlay_payload *p);
|
|
|
|
|
2011-08-08 06:41:05 +00:00
|
|
|
long long parse_quantity(char *q);
|
|
|
|
|
2011-08-12 07:47:29 +00:00
|
|
|
int overlay_interface_init(char *name,struct sockaddr_in src_addr,struct sockaddr_in broadcast,
|
|
|
|
struct sockaddr_in netmask,int speed_in_bits,int port,int type);
|
|
|
|
int overlay_interface_init_socket(int i,struct sockaddr_in src_addr,struct sockaddr_in broadcast,
|
|
|
|
struct sockaddr_in netmask);
|
2011-08-08 14:41:46 +00:00
|
|
|
int overlay_interface_discover();
|
|
|
|
int overlay_interface_discover();
|
|
|
|
long long overlay_time_until_next_tick();
|
|
|
|
int overlay_rx_messages();
|
|
|
|
int overlay_check_ticks();
|
|
|
|
int overlay_add_selfannouncement();
|
|
|
|
int overlay_payload_package_fmt1(overlay_payload *p,overlay_buffer *b);
|
|
|
|
|
|
|
|
extern int overlay_interface_count;
|
2011-08-12 06:15:26 +00:00
|
|
|
|
|
|
|
/* Userland overlay mesh packet codes */
|
|
|
|
#define OF_SELFANNOUNCE 0x01
|