/* Serval Daemon Copyright (C) 2010-2012 Paul Gardner-Stephen Copyright (C) 2012 Serval Project Inc. 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. */ #ifndef __SERVALD_SERVALD_H #define __SERVALD_SERVALD_H // #define MALLOC_PARANOIA #include #include #include #include #ifdef HAVE_STRINGS_H #include #endif #include #include #include #ifdef WIN32 #include "win32/win32.h" #else #include #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_NET_ROUTE_H #include #endif #ifdef HAVE_LINUX_IF_H #include #else #ifdef HAVE_NET_IF_H #include #endif #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_LINUX_NETLINK_H #include #endif #ifdef HAVE_LINUX_RTNETLINK_H #include #endif #ifdef HAVE_IFADDRS_H #include #endif #ifdef HAVE_SYS_UCRED_H #include #endif #endif #if !defined(FORASTERISK) && !defined(s_addr) #ifdef HAVE_ARPA_INET_H #include #else typedef unsigned int in_addr_t; struct in_addr { in_addr_t s_addr; }; #endif #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #ifdef HAVE_SYS_MMAN_H #include #endif #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_POLL_H #include #endif #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #ifndef WIN32 #include #include #endif #include #include #include #include "constants.h" #include "xprintf.h" #include "log.h" #include "net.h" #include "conf.h" /* All wall clock times in the Serval daemon are represented in milliseconds * since the Unix epoch. The gettime_ms() function uses gettimeofday(2) to * return this value when called. The time_ms_t typedef should be used * wherever this time value is handled or stored. * * This type could perfectly well be unsigned, but is defined as signed to * avoid the need to cast or define a special signed timedelta_ms_t type at ** * (1): * * static time_ms_t then = 0; * time_ms_t now = gettime_ms(); * time_ms_t ago = now - then; // ** (1) * if (then && ago < 0) { * ... time going backwards ... * } else { * ... time has advanced ... * then = now; * } */ typedef long long time_ms_t; /* bzero(3) is deprecated in favour of memset(3). */ #define bzero(addr,len) memset((addr), 0, (len)) /* UDP Port numbers for various Serval services. The overlay mesh works over DNA */ #define PORT_DNA 4110 /* 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 double simulatedBER; extern int serverMode; extern int servalShutdown; extern char *gatewayspec; int rhizome_enabled(); int rhizome_http_server_running(); const char *rhizome_datastore_path(); extern struct in_addr client_addr; extern int client_port; #define MAX_PEERS 1024 extern int peer_count; extern struct in_addr peers[MAX_PEERS]; extern char *outputtemplate; extern char *instrumentation_file; extern char *batman_socket; extern char *batman_peerfile; typedef struct keypair { int type; unsigned char *private_key; int private_key_len; unsigned char *public_key; int public_key_len; } keypair; /* Contains just the list of private:public key pairs and types, the pin used to extract them, and the slot in the keyring file (so that it can be replaced/rewritten as required). */ #define PKR_MAX_KEYPAIRS 64 #define PKR_SALT_BYTES 32 #define PKR_MAC_BYTES 64 typedef struct keyring_identity { char *PKRPin; unsigned int slot; int keypair_count; keypair *keypairs[PKR_MAX_KEYPAIRS]; } keyring_identity; /* 64K identities, can easily be increased should the need arise, but keep it low-ish for now so that the 64K pointers don't eat too much ram on a small device. Should probably think about having small and large device settings for some of these things */ #define KEYRING_MAX_IDENTITIES 65536 typedef struct keyring_context { char *KeyRingPin; unsigned char *KeyRingSalt; int KeyRingSaltLen; int identity_count; keyring_identity *identities[KEYRING_MAX_IDENTITIES]; } keyring_context; #define KEYRING_PAGE_SIZE 4096LL #define KEYRING_BAM_BYTES 2048LL #define KEYRING_BAM_BITS (KEYRING_BAM_BYTES<<3) #define KEYRING_SLAB_SIZE (KEYRING_PAGE_SIZE*KEYRING_BAM_BITS) typedef struct keyring_bam { off_t file_offset; unsigned char bitmap[KEYRING_BAM_BYTES]; struct keyring_bam *next; } keyring_bam; #define KEYRING_MAX_CONTEXTS 256 typedef struct keyring_file { int context_count; keyring_bam *bam; keyring_context *contexts[KEYRING_MAX_CONTEXTS]; FILE *file; off_t file_size; } keyring_file; void keyring_free(keyring_file *k); void keyring_free_context(keyring_context *c); void keyring_free_identity(keyring_identity *id); void keyring_free_keypair(keypair *kp); int keyring_identity_mac(keyring_context *c,keyring_identity *id, unsigned char *pkrsalt,unsigned char *mac); #define KEYTYPE_CRYPTOBOX 0x01 #define KEYTYPE_CRYPTOSIGN 0x02 #define KEYTYPE_RHIZOME 0x03 /* DIDs aren't really keys, but the keyring is a real handy place to keep them, and keep them private if people so desire */ #define KEYTYPE_DID 0x04 /* handle to keyring file for use in running instance */ extern keyring_file *keyring; /* Public calls to keyring management */ keyring_file *keyring_open(char *file); keyring_file *keyring_open_with_pins(const char *pinlist); int keyring_enter_pin(keyring_file *k, const char *pin); int keyring_enter_pins(keyring_file *k, const char *pinlist); int keyring_set_did(keyring_identity *id,char *did,char *name); int keyring_sanitise_position(const keyring_file *k,int *cn,int *in,int *kp); int keyring_next_keytype(const keyring_file *k, int *cn, int *in, int *kp, int keytype); int keyring_next_identity(const keyring_file *k,int *cn,int *in,int *kp); int keyring_identity_find_keytype(const keyring_file *k, int cn, int in, int keytype); int keyring_find_did(const keyring_file *k,int *cn,int *in,int *kp,char *did); int keyring_find_sid(const keyring_file *k,int *cn,int *in,int *kp, const unsigned char *sid); unsigned char *keyring_find_sas_private(keyring_file *k,unsigned char *sid, unsigned char **sas_public); unsigned char *keyring_find_sas_public(keyring_file *k,unsigned char *sid); int keyring_commit(keyring_file *k); keyring_identity *keyring_create_identity(keyring_file *k,keyring_context *c, const char *pin); int keyring_seed(keyring_file *k); void keyring_identity_extract(const keyring_identity *id, const unsigned char **sidp, const char **didp, const char **namep); /* 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) { return WHY("Packet composition ran out of space."); } } extern int sock; struct profile_total { struct profile_total *_next; int _initialised; const char *name; time_ms_t max_time; time_ms_t total_time; time_ms_t child_time; int calls; }; struct call_stats{ time_ms_t enter_time; time_ms_t child_time; struct profile_total *totals; struct call_stats *prev; }; struct sched_ent; typedef void (*ALARM_FUNCP) (struct sched_ent *alarm); struct sched_ent{ struct sched_ent *_next; struct sched_ent *_prev; ALARM_FUNCP function; void *context; struct pollfd poll; // when we should first consider the alarm time_ms_t alarm; // the order we will prioritise the alarm time_ms_t deadline; struct profile_total *stats; int _poll_index; }; struct overlay_buffer; struct subscriber; #define STRUCT_SCHED_ENT_UNUSED ((struct sched_ent){NULL, NULL, NULL, NULL, {-1, 0, 0}, 0LL, 0LL, NULL, -1}) extern int overlayMode; #define INTERFACE_STATE_FREE 0 #define INTERFACE_STATE_UP 1 #define INTERFACE_STATE_DOWN 2 #define INTERFACE_STATE_DETECTING 3 typedef struct overlay_interface { struct sched_ent alarm; char name[80]; int recv_offset; int fileP; 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; /* milliseconds per tick */ int send_broadcasts; /* The time of the last tick on this interface in milli seconds */ time_ms_t last_tick_ms; /* How many times have we abbreviated our address since we last announced it in full? */ int ticks_since_sent_full_address; /* sequence number of last packet sent on this interface. Used to allow NACKs that can request retransmission of recent packets. */ int sequence_number; /* XXX need recent packet buffers to support the above */ /* We need to make sure that interface name and broadcast address is unique for all interfaces that are UP. We bind a separate socket per interface / broadcast address Broadcast address and netmask, if known We really only case about distinct broadcast addresses on interfaces. Also simplifies aliases on interfaces. */ struct sockaddr_in address; struct sockaddr_in broadcast_address; struct in_addr 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; /* Use one of the INTERFACE_STATE_* constants to indicate the state of this interface. If the interface stops working or disappears, it will be marked as DOWN and the socket closed. But if it comes back up again, we should try to reuse this structure, even if the broadcast address has changed. */ int state; } 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. */ extern overlay_interface overlay_interfaces[OVERLAY_MAX_INTERFACES]; extern int overlay_last_interface_number; // used to remember where a packet came from extern unsigned int overlay_sequence_number; 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_txqueue { struct overlay_frame *first; struct overlay_frame *last; int length; /* # frames in queue */ int maxLength; /* max # frames in queue before we consider ourselves congested */ /* wait until first->enqueued_at+transmit_delay before trying to force the transmission of a packet */ int transmit_delay; /* if servald is busy, wait this long before trying to force the transmission of a packet */ int grace_period; /* 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[OQ_MAX]; ssize_t recvwithttl(int sock, unsigned char *buffer, size_t bufferlen, int *ttl, struct sockaddr *recvaddr, socklen_t *recvaddrlen); int is_xsubstring(const char *text, int len); int is_xstring(const char *text, int len); char *tohex(char *dstHex, const unsigned char *srcBinary, size_t bytes); size_t fromhex(unsigned char *dstBinary, const char *srcHex, size_t bytes); int fromhexstr(unsigned char *dstBinary, const char *srcHex, size_t bytes); int hexvalue(char c); char *str_toupper_inplace(char *s); int is_all_matching(unsigned char *ptr, int len, int value); int str_is_subscriber_id(const char *sid); int strn_is_subscriber_id(const char *sid, size_t *lenp); int str_is_did(const char *did); int strn_is_did(const char *did, size_t *lenp); int str_is_uri(const char *uri); int stowSid(unsigned char *packet, int ofs, const char *sid); int stowDid(unsigned char *packet,int *ofs,char *did); int isFieldZeroP(unsigned char *packet,int start,int count); void srandomdev(); int respondSimple(keyring_identity *id, int action,unsigned char *action_text,int action_len, unsigned char *transaction_id,int recvttl, struct sockaddr *recvaddr,int cryptoFlags); time_ms_t gettime_ms(); time_ms_t sleep_ms(time_ms_t milliseconds); int server_pid(); void server_save_argv(int argc, const char *const *argv); int server(char *backing_file); int server_create_stopfile(); int server_remove_stopfile(); int server_check_stopfile(); void serverCleanUp(); int isTransactionInCache(unsigned char *transaction_id); void insertTransactionInCache(unsigned char *transaction_id); int packetOk(struct overlay_interface *interface,unsigned char *packet, size_t len, unsigned char *transaction_id, int recvttl, struct sockaddr *recvaddr, size_t recvaddrlen,int parseP); int process_packet(unsigned char *packet, size_t len, int recvttl,struct sockaddr *sender, size_t sender_len); int packetMakeHeader(unsigned char *packet,int packet_maxlen,int *packet_len,unsigned char *transaction_id,int cryptoflags); int packetSetDid(unsigned char *packet,int packet_maxlen,int *packet_len,char *did); int packetSetSidFromId(unsigned char *packet,int packet_maxlen,int *packet_len, keyring_identity *id); int packetFinalise(unsigned char *packet,int packet_maxlen,int recvttl, int *packet_len,int cryptoflags); int packetGetID(unsigned char *packet,int len,char *did,char *sid); int getPeerList(); struct response { int code; unsigned char sid[SID_SIZE]; struct in_addr sender; int recvttl; 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; }; int clearResponse(struct response **response); int clearResponses(struct response_set *responses); int fixResponses(struct response_set *responses); int dumpResponses(struct response_set *responses); int eraseLastResponse(struct response_set *responses); int responseFromPeerP(struct response_set *responses,int peerId); int responseFromPeer(struct response_set *responses,int peerId); int extractResponses(struct in_addr sender,unsigned char *buffer,int len,struct response_set *responses); 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,struct sockaddr *recvaddr,int timeout); int packageVariableSegment(unsigned char *data, int *dlen, struct response *h, int offset, int buffer_size); int unpackageVariableSegment(unsigned char *data, int dlen, int flags, struct response *r); int packetDecipher(unsigned char *packet,int len,int cipher); int safeZeroField(unsigned char *packet,int start,int count); int extractSid(const unsigned char *packet,int *ofs, char *sid); int extractDid(unsigned char *packet,int *ofs,char *did); int processRequest(unsigned char *packet,int len,struct sockaddr *sender,int sender_len, unsigned char *transaction_id,int recvttl,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 dropPacketP(size_t packet_len); int additionalPeer(char *peer); int readRoutingTable(struct in_addr peers[],int *peer_count,int peer_max); 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); int asteriskObtainGateway(char *requestor_sid,char *did,char *uri_out); int packetOkDNA(unsigned char *packet,int len,unsigned char *transaction_id, int recvttl,struct sockaddr *recvaddr, size_t recvaddrlen,int parseP); int overlay_forward_payload(struct overlay_frame *f); int packetOkOverlay(struct overlay_interface *interface,unsigned char *packet, size_t len, unsigned char *transaction_id,int recvttl, struct sockaddr *recvaddr, size_t recvaddrlen,int parseP); int prepareGateway(char *gatewayspec); int packetSendRequest(int method,unsigned char *packet,int packet_len,int batchP, unsigned char *transaction_id,struct sockaddr *recvaddr, struct response_set *responses); int readArpTable(struct in_addr peers[],int *peer_count,int peer_max); int overlay_frame_process(struct overlay_interface *interface, struct overlay_frame *f); int overlay_frame_resolve_addresses(struct overlay_frame *f); #define alloca_tohex(buf,len) tohex((char *)alloca((len)*2+1), (buf), (len)) #define alloca_tohex_sid(sid) alloca_tohex((sid), SID_SIZE) #define alloca_tohex_sas(sas) alloca_tohex((sas), SAS_SIZE) time_ms_t overlay_time_until_next_tick(); int overlay_rx_messages(); #define DEBUG_packet_visualise(M,P,N) logServalPacket(LOG_LEVEL_DEBUG, __HERE__, (M), (P), (N)) int overlay_add_selfannouncement(); int overlay_frame_append_payload(overlay_interface *interface, struct overlay_frame *p, struct subscriber *next_hop, struct overlay_buffer *b); int overlay_interface_args(const char *arg); int overlay_sendto(struct sockaddr_in *recipientaddr,unsigned char *bytes,int len); int overlay_rhizome_add_advertisements(int interface_number,struct overlay_buffer *e); int overlay_add_local_identity(unsigned char *s); void overlay_update_queue_schedule(overlay_txqueue *queue, struct overlay_frame *frame); void overlay_send_packet(struct sched_ent *alarm); extern int overlay_interface_count; extern int overlay_local_identity_count; extern unsigned char *overlay_local_identities[OVERLAY_MAX_LOCAL_IDENTITIES]; int rfs_length(int l); int rfs_encode(int l,unsigned char *b); int rfs_decode(unsigned char *b,int *offset); typedef struct overlay_node_observation { unsigned char observed_score; /* serves as validty check also */ unsigned char corrected_score; unsigned char gateways_en_route; unsigned char RESERVED; /* for alignment */ unsigned char interface; time_ms_t rx_time; struct subscriber *sender; } overlay_node_observation; typedef struct overlay_node { struct subscriber *subscriber; int neighbour_id; /* 0=not a neighbour */ int most_recent_observation_id; int best_link_score; int best_observation; unsigned int last_first_hand_observation_time_millisec; time_ms_t last_observation_time_ms; /* When did we last advertise this node on each interface, and what score did we advertise? */ time_ms_t most_recent_advertisment_ms[OVERLAY_MAX_INTERFACES]; unsigned char most_recent_advertised_score[OVERLAY_MAX_INTERFACES]; overlay_node_observation observations[OVERLAY_MAX_OBSERVATIONS]; } overlay_node; int overlay_route_saw_selfannounce_ack(struct overlay_frame *f, time_ms_t now); int overlay_route_saw_selfannounce(struct overlay_frame *f, time_ms_t now); overlay_node *overlay_route_find_node(const unsigned char *sid,int prefixLen,int createP); unsigned int overlay_route_hash_sid(const unsigned char *sid); int packetEncipher(unsigned char *packet,int maxlen,int *len,int cryptoflags); int overlayServerMode(); int overlay_payload_enqueue(int q, struct overlay_frame *p); int overlay_route_record_link( time_ms_t now,unsigned char *to, unsigned char *via,int sender_interface, unsigned int s1,unsigned int s2,int score,int gateways_en_route); int overlay_route_dump(); int overlay_route_add_advertisements(overlay_interface *interface, struct overlay_buffer *e); int ovleray_route_please_advertise(overlay_node *n); int overlay_route_saw_advertisements(int i, struct overlay_frame *f, time_ms_t now); int overlay_rhizome_saw_advertisements(int i, struct overlay_frame *f, time_ms_t now); int overlay_route_please_advertise(overlay_node *n); int rhizome_server_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int rhizome_saw_voice_traffic(); int overlay_saw_mdp_containing_frame(struct overlay_frame *f, time_ms_t now); #include "nacl.h" int serval_packetvisualise(XPRINTF xpf, const char *message, const unsigned char *packet, size_t len); int rhizome_fetching_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int rhizome_opendb(); typedef struct dna_identity_status { char sid[SID_STRLEN]; char did[64+1]; char name[255+1]; int initialisedP; time_t startofvalidity; time_t endofvalidity; int verifier_count; /* Dynamically allocate these so that we don't waste a memory (well, if we are talking about running on a feature phone, 4KB per entry (16*256 bytes) is best avoided if we can.) */ unsigned char *verifiers[MAX_SIGNATURES]; int verificationStatus; /* Set if we know that there are no duplicates of this DID/name combination, as it allows us to avoid a database lookup. */ int uniqueDidAndName; } dna_identity_status; int parseCommandLine(const char *argv0, int argc, const char *const *argv); dna_identity_status *dnacache_lookup(char *did,char *name,char *sid); dna_identity_status *dnacache_lookup_next(); int dnacache_update_verification(char *did,char *sid,char *name, char *signature,int revokeVerificationP); int dnacache_vouch_for_identity(char *did,char *sid,char *name); #undef DEBUG_MEM_ABUSE #ifdef DEBUG_MEM_ABUSE int memabuseInit(); int _memabuseCheck(const char *func,const char *file,const int line); #define memabuseCheck() _memabuseCheck(__FUNCTION__,__FILE__,__LINE__) #else #define memabuseInit() /* */ #define memabuseCheck() /* */ #endif int form_serval_instance_path(char * buf, size_t bufsiz, const char *path); int create_serval_instance_dir(); int overlay_mdp_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int overlay_mdp_reply_error(int sock, struct sockaddr_un *recvaddr,int recvaddrlen, int error_number,char *message); extern struct sched_ent mdp_abstract; extern struct sched_ent mdp_named; typedef struct sockaddr_mdp { unsigned char sid[SID_SIZE]; unsigned int port; } sockaddr_mdp; unsigned char *keyring_get_nm_bytes(sockaddr_mdp *priv,sockaddr_mdp *pub); typedef struct overlay_mdp_data_frame { sockaddr_mdp src; sockaddr_mdp dst; unsigned short payload_length; unsigned char payload[MDP_MTU-100]; } overlay_mdp_data_frame; typedef struct overlay_mdp_bind_request { unsigned int port_number; unsigned char sid[SID_SIZE]; } overlay_mdp_bind_request; typedef struct overlay_mdp_error { unsigned int error; char message[128]; } overlay_mdp_error; typedef struct overlay_mdp_addrlist { int mode; unsigned int server_sid_count; unsigned int first_sid; unsigned int last_sid; unsigned int frame_sid_count; /* how many of the following 59 slots are populated */ unsigned char sids[MDP_MAX_SID_REQUEST][SID_SIZE]; } overlay_mdp_addrlist; /* elements sorted by size for alignment */ typedef struct overlay_mdp_vompevent { /* Once a call has been established, this is how the MDP/VoMP server and user-end process talk about the call. */ unsigned int call_session_token; unsigned int audio_sample_endtime; unsigned int audio_sample_starttime; time_ms_t last_activity; unsigned int flags; unsigned short audio_sample_bytes; unsigned char audio_sample_codec; unsigned char local_state; unsigned char remote_state; /* list of codecs the registering party is willing to support (for VOMPEVENT_REGISTERINTEREST) */ unsigned char supported_codecs[257]; union { struct { /* Used to precisely define the call end points during call setup. */ char local_did[64]; char remote_did[64]; unsigned char local_sid[SID_SIZE]; unsigned char remote_sid[SID_SIZE]; /* session numbers of other calls in progress (for VOMPEVENT_CALLINFO) */ unsigned int other_calls_sessions[VOMP_MAX_CALLS]; unsigned char other_calls_states[VOMP_MAX_CALLS]; }; unsigned char audio_bytes[MAX_AUDIO_BYTES]; }; } overlay_mdp_vompevent; typedef struct overlay_mdp_nodeinfo { unsigned char sid[SID_SIZE]; int sid_prefix_length; /* must be long enough to be unique */ char did[64]; char name[64]; int foundP; int localP; int neighbourP; int score; int interface_number; int resolve_did; time_ms_t time_since_last_observation; } overlay_mdp_nodeinfo; typedef struct overlay_mdp_frame { unsigned int packetTypeAndFlags; union { overlay_mdp_data_frame out; overlay_mdp_data_frame in; overlay_mdp_bind_request bind; overlay_mdp_addrlist addrlist; overlay_mdp_vompevent vompevent; overlay_mdp_nodeinfo nodeinfo; overlay_mdp_error error; /* 2048 is too large (causes EMSGSIZE errors on OSX, but probably fine on Linux) */ char raw[MDP_MTU]; }; } overlay_mdp_frame; int keyring_mapping_request(keyring_file *k,overlay_mdp_frame *req); /* Server-side MDP functions */ int overlay_saw_mdp_frame(overlay_mdp_frame *mdp, time_ms_t now); int overlay_mdp_swap_src_dst(overlay_mdp_frame *mdp); int overlay_mdp_reply(int sock,struct sockaddr_un *recvaddr,int recvaddrlen, overlay_mdp_frame *mdpreply); int overlay_mdp_dispatch(overlay_mdp_frame *mdp,int userGeneratedFrameP, struct sockaddr_un *recvaddr,int recvaddlen); int overlay_mdp_dnalookup_reply(const sockaddr_mdp *dstaddr, const unsigned char *resolved_sid, const char *uri, const char *did, const char *name); int dump_payload(struct overlay_frame *p, char *message); int urandombytes(unsigned char *x,unsigned long long xlen); #ifdef MALLOC_PARANOIA #define malloc(X) _serval_debug_malloc(X,__HERE__) #define calloc(X,Y) _serval_debug_calloc(X,Y,__HERE__) #define free(X) _serval_debug_free(X,__HERE__) void *_serval_debug_malloc(unsigned int bytes, struct __sourceloc where); void *_serval_debug_calloc(unsigned int bytes, unsigned int count, struct __sourceloc where); void _serval_debug_free(void *p, struct __sourceloc where); #endif struct vomp_call_state; struct vomp_call_state *vomp_find_call_by_session(int session_token); int vomp_mdp_received(overlay_mdp_frame *mdp); int vomp_tick_interval(); int vomp_sample_size(int c); int vomp_codec_timespan(int c); int vomp_parse_dtmf_digit(char c); int vomp_dial(unsigned char *local_sid, unsigned char *remote_sid, char *local_did, char *remote_did); int vomp_pickup(struct vomp_call_state *call); int vomp_hangup(struct vomp_call_state *call); int vomp_ringing(struct vomp_call_state *call); int vomp_received_audio(struct vomp_call_state *call, int audio_codec, const unsigned char *audio, int audio_length); typedef struct command_line_option { int (*function)(int argc, const char *const *argv, struct command_line_option *o); const char *words[32]; // 32 words should be plenty! unsigned long long flags; #define CLIFLAG_NONOVERLAY (1<<0) /* Uses a legacy IPv4 DNA call instead of overlay mnetwork */ #define CLIFLAG_STANDALONE (1<<1) /* Cannot be issued to a running instance */ const char *description; // describe this invocation } command_line_option; extern command_line_option command_line_options[]; int cli_arg(int argc, const char *const *argv, command_line_option *o, char *argname, const char **dst, int (*validator)(const char *arg), char *defaultvalue); int cli_putchar(char c); int cli_puts(const char *str); int cli_printf(const char *fmt, ...); int cli_delim(const char *opt); int is_configvarname(const char *arg); int overlay_mdp_getmyaddr(int index,unsigned char *sid); int overlay_mdp_bind(unsigned char *localaddr,int port); int overlay_route_node_info(overlay_mdp_frame *mdp, struct sockaddr_un *addr,int addrlen); 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_registration(); int directory_service_init(); #ifdef HAVE_VOIPTEST int app_pa_phone(int argc, const char *const *argv, struct command_line_option *o); #endif int app_monitor_cli(int argc, const char *const *argv, struct command_line_option *o); int monitor_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int monitor_setup_sockets(); int monitor_get_fds(struct pollfd *fds,int *fdcount,int fdmax); int monitor_announce_peer(const unsigned char *sid); int monitor_announce_unreachable_peer(const unsigned char *sid); int monitor_tell_clients(char *msg, int msglen, int mask); int monitor_tell_formatted(int mask, char *fmt, ...); int monitor_client_interested(int mask); extern int monitor_socket_count; typedef struct monitor_audio { char name[128]; int (*start)(); int (*stop)(); int (*poll_fds)(struct pollfd *,int); int (*read)(unsigned char *,int); int (*write)(unsigned char *,int); } monitor_audio; extern monitor_audio *audev; monitor_audio *audio_msm_g1_detect(); monitor_audio *audio_alsa_detect(); monitor_audio *audio_reflector_detect(); int detectAudioDevice(); int getAudioPlayFd(); int getAudioRecordFd(); int getAudioBytes(unsigned char *buffer, int offset, int bufferSize); int encodeAndDispatchRecordedAudio(int fd,int callSessionToken, int recordCodec, unsigned char *sampleData, int sampleBytes); int scrapeProcNetRoute(); int lsif(); int doifaddrs(); int bufferAudioForPlayback(int codec, time_ms_t start_time, time_ms_t end_time, unsigned char *data,int dataLen); int startAudio(); int stopAudio(); #define SERVER_UNKNOWN 1 #define SERVER_NOTRESPONDING 2 #define SERVER_NOTRUNNING 3 #define SERVER_RUNNING 4 int server_probe(int *pid); int dna_helper_start(); int dna_helper_shutdown(); int dna_helper_enqueue(overlay_mdp_frame *mdp, const char *did, const unsigned char *requestorSid); int dna_return_resolution(overlay_mdp_frame *mdp, unsigned char *fromSid, const char *did,const char *name,const char *uri); int parseDnaReply(const char *buf, size_t len, char *token, char *did, char *name, char *uri, const char **bufp); extern int sigPipeFlag; extern int sigIoFlag; void sigPipeHandler(int signal); void sigIoHandler(int signal); int rhizome_http_server_start(); int overlay_mdp_setup_sockets(); int schedule(struct sched_ent *alarm); int unschedule(struct sched_ent *alarm); int watch(struct sched_ent *alarm); int unwatch(struct sched_ent *alarm); int fd_poll(); void overlay_interface_discover(struct sched_ent *alarm); void overlay_dummy_poll(struct sched_ent *alarm); void overlay_route_tick(struct sched_ent *alarm); void rhizome_enqueue_suggestions(struct sched_ent *alarm); void server_shutdown_check(struct sched_ent *alarm); void overlay_mdp_poll(struct sched_ent *alarm); void fd_periodicstats(struct sched_ent *alarm); void rhizome_check_connections(struct sched_ent *alarm); void monitor_client_poll(struct sched_ent *alarm); void monitor_poll(struct sched_ent *alarm); void rhizome_client_poll(struct sched_ent *alarm); void rhizome_fetch_poll(struct sched_ent *alarm); void rhizome_server_poll(struct sched_ent *alarm); /* function timing routines */ int fd_clearstats(); int fd_showstats(); int fd_checkalarms(); int fd_func_exit(struct call_stats *this_call); int fd_func_enter(struct call_stats *this_call); void dump_stack(); #define IN() static struct profile_total _aggregate_stats={NULL,0,__FUNCTION__,0,0,0}; \ struct call_stats _this_call; \ _this_call.totals=&_aggregate_stats; \ fd_func_enter(&_this_call); #define OUT() fd_func_exit(&_this_call); #define RETURN(X) { OUT() return(X); } int olsr_init_socket(void); int olsr_send(struct overlay_frame *frame); #endif // __SERVALD_SERVALD_H