Browse Source

Merge pull request #355 from fengdaolong/dev

Added DHCP function embedded in sn.
pull/357/head
Luca Deri 4 years ago
committed by GitHub
parent
commit
9928ccaeea
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 172
      include/n2n.h
  2. 9
      include/n2n_define.h
  3. 93
      include/n2n_wire.h
  4. 76
      src/edge.c
  5. 152
      src/edge_utils.c
  6. 4
      src/example_edge_embed.c
  7. 58
      src/n2n.c
  8. 165
      src/sn.c
  9. 337
      src/sn_utils.c
  10. 260
      src/wire.c
  11. 15
      win32/n2n_win32.h
  12. 7
      win32/winconfig.h

172
include/n2n.h

@ -36,8 +36,6 @@
/* Moved here to define _CRT_SECURE_NO_WARNINGS before all the including takes place */ /* Moved here to define _CRT_SECURE_NO_WARNINGS before all the including takes place */
#ifdef WIN32 #ifdef WIN32
#include "win32/n2n_win32.h"
#ifdef _MSC_VER #ifdef _MSC_VER
#include "config.h" /* Visual C++ */ #include "config.h" /* Visual C++ */
#else #else
@ -171,12 +169,13 @@ typedef struct ether_hdr ether_hdr_t;
#ifndef WIN32 #ifndef WIN32
typedef struct tuntap_dev { typedef struct tuntap_dev {
int fd; int fd;
int if_idx; int if_idx;
uint8_t mac_addr[6]; n2n_mac_t mac_addr;
uint32_t ip_addr, device_mask; uint32_t ip_addr;
uint16_t mtu; uint32_t device_mask;
char dev_name[N2N_IFNAMSIZ]; uint16_t mtu;
char dev_name[N2N_IFNAMSIZ];
} tuntap_dev; } tuntap_dev;
#define SOCKET int #define SOCKET int
@ -192,26 +191,31 @@ typedef char ipstr_t[32];
/** Common type used to hold stringified MAC addresses. */ /** Common type used to hold stringified MAC addresses. */
#define N2N_MACSTR_SIZE 32 #define N2N_MACSTR_SIZE 32
typedef char macstr_t[N2N_MACSTR_SIZE]; typedef char macstr_t[N2N_MACSTR_SIZE];
typedef char dec_ip_str_t[N2N_NETMASK_STR_SIZE];
typedef char dec_ip_bit_str_t[N2N_NETMASK_STR_SIZE + 4];
struct peer_info {
n2n_mac_t mac_addr;
n2n_sock_t sock;
int timeout;
time_t last_seen;
time_t last_p2p;
time_t last_sent_query;
uint64_t last_valid_time_stamp;
UT_hash_handle hh; /* makes this structure hashable */ struct peer_info {
n2n_mac_t mac_addr;
n2n_ip_subnet_t dev_addr;
n2n_sock_t sock;
int timeout;
time_t last_seen;
time_t last_p2p;
time_t last_sent_query;
uint64_t last_valid_time_stamp;
UT_hash_handle hh; /* makes this structure hashable */
}; };
typedef struct speck_context_t he_context_t; typedef struct speck_context_t he_context_t;
typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE];
typedef struct n2n_route { typedef struct n2n_route {
in_addr_t net_addr; in_addr_t net_addr;
int net_bitlen; uint8_t net_bitlen;
in_addr_t gateway; in_addr_t gateway;
} n2n_route_t; } n2n_route_t;
typedef struct n2n_edge n2n_edge_t; typedef struct n2n_edge n2n_edge_t;
@ -253,8 +257,8 @@ typedef struct n2n_edge_callbacks {
typedef struct n2n_tuntap_priv_config { typedef struct n2n_tuntap_priv_config {
char tuntap_dev_name[N2N_IFNAMSIZ]; char tuntap_dev_name[N2N_IFNAMSIZ];
char ip_mode[N2N_IF_MODE_SIZE]; char ip_mode[N2N_IF_MODE_SIZE];
char ip_addr[N2N_NETMASK_STR_SIZE]; dec_ip_str_t ip_addr;
char netmask[N2N_NETMASK_STR_SIZE]; dec_ip_str_t netmask;
char device_mac[N2N_MACNAMSIZ]; char device_mac[N2N_MACNAMSIZ];
int mtu; int mtu;
uint8_t got_s; uint8_t got_s;
@ -267,30 +271,32 @@ typedef struct n2n_tuntap_priv_config {
/* *************************************************** */ /* *************************************************** */
typedef struct n2n_edge_conf { typedef struct n2n_edge_conf {
n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES];
n2n_route_t *routes; /**< Networks to route through n2n */ n2n_route_t *routes; /**< Networks to route through n2n */
n2n_community_t community_name; /**< The community. 16 full octets. */ n2n_community_t community_name; /**< The community. 16 full octets. */
uint8_t header_encryption; /**< Header encryption indicator. */ uint8_t header_encryption; /**< Header encryption indicator. */
he_context_t *header_encryption_ctx; /**< Header encryption cipher context. */ he_context_t *header_encryption_ctx; /**< Header encryption cipher context. */
he_context_t *header_iv_ctx; /**< Header IV ecnryption cipher context, REMOVE as soon as seperte fileds for checksum and replay protection available */ he_context_t *header_iv_ctx; /**< Header IV ecnryption cipher context, REMOVE as soon as seperte fileds for checksum and replay protection available */
n2n_transform_t transop_id; /**< The transop to use. */ n2n_transform_t transop_id; /**< The transop to use. */
uint16_t compression; /**< Compress outgoing data packets before encryption */ uint16_t compression; /**< Compress outgoing data packets before encryption */
uint16_t num_routes; /**< Number of routes in routes */ uint16_t num_routes; /**< Number of routes in routes */
uint8_t dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */ uint8_t tuntap_ip_mode; /**< Interface IP address allocated mode, eg. DHCP. */
uint8_t allow_routing; /**< Accept packet no to interface address. */ uint8_t allow_routing; /**< Accept packet no to interface address. */
uint8_t drop_multicast; /**< Multicast ethernet addresses. */ uint8_t drop_multicast; /**< Multicast ethernet addresses. */
uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */ uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */
uint8_t allow_p2p; /**< Allow P2P connection */ uint8_t allow_p2p; /**< Allow P2P connection */
uint8_t sn_num; /**< Number of supernode addresses defined. */ uint8_t sn_num; /**< Number of supernode addresses defined. */
uint8_t tos; /** TOS for sent packets */ uint8_t tos; /** TOS for sent packets */
char *encrypt_key; char *encrypt_key;
int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */ int register_interval; /**< Interval for supernode registration, also used for UDP NAT hole punching. */
int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */ int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */
int local_port; int local_port;
int mgmt_port; int mgmt_port;
} n2n_edge_conf_t; } n2n_edge_conf_t;
struct n2n_edge_stats { struct n2n_edge_stats {
uint32_t tx_p2p; uint32_t tx_p2p;
uint32_t rx_p2p; uint32_t rx_p2p;
@ -304,44 +310,45 @@ struct n2n_edge {
n2n_edge_conf_t conf; n2n_edge_conf_t conf;
/* Status */ /* Status */
uint8_t sn_idx; /**< Currently active supernode. */ uint8_t sn_idx; /**< Currently active supernode. */
uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */ uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */
size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ size_t sup_attempts; /**< Number of remaining attempts to this supernode. */
tuntap_dev device; /**< All about the TUNTAP device */ tuntap_dev device; /**< All about the TUNTAP device */
n2n_trans_op_t transop; /**< The transop to use when encoding */ n2n_trans_op_t transop; /**< The transop to use when encoding */
n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */ n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */
n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */ n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */
n2n_edge_callbacks_t cb; /**< API callbacks */ n2n_edge_callbacks_t cb; /**< API callbacks */
void *user_data; /**< Can hold user data */ void *user_data; /**< Can hold user data */
uint64_t sn_last_valid_time_stamp;/*< last valid time stamp from supernode */ uint64_t sn_last_valid_time_stamp;/**< last valid time stamp from supernode */
/* Sockets */ /* Sockets */
n2n_sock_t supernode; n2n_sock_t supernode;
int udp_sock; int udp_sock;
int udp_mgmt_sock; /**< socket for status info. */ int udp_mgmt_sock; /**< socket for status info. */
#ifndef SKIP_MULTICAST_PEERS_DISCOVERY #ifndef SKIP_MULTICAST_PEERS_DISCOVERY
n2n_sock_t multicast_peer; /**< Multicast peer group (for local edges) */ n2n_sock_t multicast_peer; /**< Multicast peer group (for local edges) */
int udp_multicast_sock; /**< socket for local multicast registrations. */ int udp_multicast_sock; /**< socket for local multicast registrations. */
int multicast_joined; /**< 1 if the group has been joined.*/ int multicast_joined; /**< 1 if the group has been joined.*/
#endif #endif
/* Peers */ /* Peers */
struct peer_info * known_peers; /**< Edges we are connected to. */ struct peer_info * known_peers; /**< Edges we are connected to. */
struct peer_info * pending_peers; /**< Edges we have tried to register with. */ struct peer_info * pending_peers; /**< Edges we have tried to register with. */
/* Timers */ /* Timers */
time_t last_register_req; /**< Check if time to re-register with super*/ time_t last_register_req; /**< Check if time to re-register with super*/
time_t last_p2p; /**< Last time p2p traffic was received. */ time_t last_p2p; /**< Last time p2p traffic was received. */
time_t last_sup; /**< Last time a packet arrived from supernode. */ time_t last_sup; /**< Last time a packet arrived from supernode. */
time_t start_time; /**< For calculating uptime */ time_t start_time; /**< For calculating uptime */
/* Statistics */
struct n2n_edge_stats stats; struct n2n_edge_stats stats; /**< Statistics */
/* Tuntap config */
n2n_tuntap_priv_config_t tuntap_priv_conf; n2n_tuntap_priv_config_t tuntap_priv_conf; /**< Tuntap config */
}; };
typedef struct sn_stats typedef struct sn_stats
{ {
size_t errors; /* Number of errors encountered. */ size_t errors; /* Number of errors encountered. */
@ -365,21 +372,21 @@ struct sn_community
UT_hash_handle hh; /* makes this structure hashable */ UT_hash_handle hh; /* makes this structure hashable */
}; };
typedef struct n2n_sn typedef struct n2n_sn {
{ time_t start_time; /* Used to measure uptime. */
time_t start_time; /* Used to measure uptime. */ sn_stats_t stats;
sn_stats_t stats; int daemon; /* If non-zero then daemonise. */
int daemon; /* If non-zero then daemonise. */ uint16_t lport; /* Local UDP port to bind to. */
uint16_t lport; /* Local UDP port to bind to. */ uint16_t mport; /* Management UDP port to bind to. */
uint16_t mport; /* Management UDP port to bind to. */ int sock; /* Main socket for UDP traffic with edges. */
int sock; /* Main socket for UDP traffic with edges. */ int mgmt_sock; /* management socket. */
int mgmt_sock; /* management socket. */ n2n_ip_subnet_t dhcp_addr; /* Address range of dhcp service. */
#ifndef WIN32 #ifndef WIN32
uid_t userid; uid_t userid;
gid_t groupid; gid_t groupid;
#endif #endif
int lock_communities; /* If true, only loaded communities can be used. */ int lock_communities; /* If true, only loaded communities can be used. */
struct sn_community *communities; struct sn_community *communities;
} n2n_sn_t; } n2n_sn_t;
/* ************************************** */ /* ************************************** */
@ -426,6 +433,8 @@ void tuntap_get_address(struct tuntap_dev *tuntap);
/* Utils */ /* Utils */
char* intoa(uint32_t addr, char* buf, uint16_t buf_len); char* intoa(uint32_t addr, char* buf, uint16_t buf_len);
uint32_t bitlen2mask(uint8_t bitlen);
uint8_t mask2bitlen(uint32_t mask);
char* macaddr_str(macstr_t buf, const n2n_mac_t mac); char* macaddr_str(macstr_t buf, const n2n_mac_t mac);
int str2mac( uint8_t * outmac /* 6 bytes */, const char * s ); int str2mac( uint8_t * outmac /* 6 bytes */, const char * s );
uint8_t is_multi_broadcast(const uint8_t * dest_mac); uint8_t is_multi_broadcast(const uint8_t * dest_mac);
@ -438,6 +447,7 @@ void print_edge_stats(const n2n_edge_t *eee);
/* Sockets */ /* Sockets */
char* sock_to_cstr( n2n_sock_str_t out, char* sock_to_cstr( n2n_sock_str_t out,
const n2n_sock_t * sock ); const n2n_sock_t * sock );
char * ip_subnet_to_str(dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr);
SOCKET open_socket(int local_port, int bind_any); SOCKET open_socket(int local_port, int bind_any);
int sock_equal( const n2n_sock_t * a, int sock_equal( const n2n_sock_t * a,
const n2n_sock_t * b ); const n2n_sock_t * b );
@ -461,7 +471,9 @@ const n2n_edge_conf_t* edge_get_conf(const n2n_edge_t *eee);
void edge_term_conf(n2n_edge_conf_t *conf); void edge_term_conf(n2n_edge_conf_t *conf);
/* Public functions */ /* Public functions */
n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *rv); n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv);
void update_supernode_reg(n2n_edge_t * eee, time_t nowTime);
void readFromIPSocket(n2n_edge_t * eee, int in_sock);
void edge_term(n2n_edge_t *eee); void edge_term(n2n_edge_t *eee);
void edge_set_callbacks(n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks); void edge_set_callbacks(n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks);
void edge_set_userdata(n2n_edge_t *eee, void *user_data); void edge_set_userdata(n2n_edge_t *eee, void *user_data);

9
include/n2n_define.h

@ -97,6 +97,15 @@
#define N2N_SN_PKTBUF_SIZE 2048 #define N2N_SN_PKTBUF_SIZE 2048
/* The way TUNTAP allocated IP. */
#define TUNTAP_IP_MODE_SN_ASSIGN 0
#define TUNTAP_IP_MODE_STATIC 1
#define TUNTAP_IP_MODE_DHCP 2
/* Default network segment of the dhcp service provided by sn. */
#define N2N_SN_DHCP_NET_ADDR_DEFAULT "172.17.12.0"
#define N2N_SN_DHCP_NET_BIT_DEFAULT 24
/* ************************************** */ /* ************************************** */
#define SUPERNODE_IP "127.0.0.1" #define SUPERNODE_IP "127.0.0.1"

93
include/n2n_wire.h

@ -20,19 +20,10 @@
#define N2N_WIRE_H_ #define N2N_WIRE_H_
#include <stdlib.h> #include <stdlib.h>
#ifndef _MSC_VER
#if defined(WIN32) /* Not included in Visual Studio 2008 */
#include "win32/n2n_win32.h"
#if defined(__MINGW32__)
#include <stdint.h>
#endif /* #ifdef __MINGW32__ */
#else /* #if defined(WIN32) */
#include <stdint.h> #include <stdint.h>
#include <netinet/in.h> #endif
#include <sys/socket.h> /* AF_INET and AF_INET6 */
#endif /* #if defined(WIN32) */
#define N2N_PKT_VERSION 2 #define N2N_PKT_VERSION 2
#define N2N_DEFAULT_TTL 2 /* can be forwarded twice at most */ #define N2N_DEFAULT_TTL 2 /* can be forwarded twice at most */
@ -51,6 +42,13 @@ typedef uint8_t n2n_cookie_t[N2N_COOKIE_SIZE];
typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */ typedef char n2n_sock_str_t[N2N_SOCKBUF_SIZE]; /* tracing string buffer */
#if defined(WIN32)
#include "win32/n2n_win32.h"
#else /* #if defined(WIN32) */
#include <netinet/in.h>
#include <sys/socket.h> /* AF_INET and AF_INET6 */
#endif /* #if defined(WIN32) */
typedef enum n2n_pc typedef enum n2n_pc
{ {
n2n_ping=0, /* Not used */ n2n_ping=0, /* Not used */
@ -86,6 +84,12 @@ typedef enum n2n_pc
#define N2N_EINVAL -3 #define N2N_EINVAL -3
#define N2N_ENOSPACE -4 #define N2N_ENOSPACE -4
typedef struct n2n_ip_subnet {
uint32_t net_addr; /* Host order IP address. */
uint8_t net_bitlen; /* Subnet prefix. */
} n2n_ip_subnet_t;
typedef struct n2n_sock typedef struct n2n_sock
{ {
uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */ uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */
@ -117,18 +121,18 @@ typedef struct n2n_common
typedef struct n2n_REGISTER typedef struct n2n_REGISTER
{ {
n2n_cookie_t cookie; /* Link REGISTER and REGISTER_ACK */ n2n_cookie_t cookie; /**< Link REGISTER and REGISTER_ACK */
n2n_mac_t srcMac; /* MAC of registering party */ n2n_mac_t srcMac; /**< MAC of registering party */
n2n_mac_t dstMac; /* MAC of target edge */ n2n_mac_t dstMac; /**< MAC of target edge */
n2n_sock_t sock; /* REVISIT: unused? */ n2n_sock_t sock; /**< REVISIT: unused? */
} n2n_REGISTER_t; } n2n_REGISTER_t;
typedef struct n2n_REGISTER_ACK typedef struct n2n_REGISTER_ACK
{ {
n2n_cookie_t cookie; /* Return cookie from REGISTER */ n2n_cookie_t cookie; /**< Return cookie from REGISTER */
n2n_mac_t srcMac; /* MAC of acknowledging party (supernode or edge) */ n2n_mac_t srcMac; /**< MAC of acknowledging party (supernode or edge) */
n2n_mac_t dstMac; /* Reflected MAC of registering edge from REGISTER */ n2n_mac_t dstMac; /**< Reflected MAC of registering edge from REGISTER */
n2n_sock_t sock; /* Supernode's view of edge socket (IP Addr, port) */ n2n_sock_t sock; /**< Supernode's view of edge socket (IP Addr, port) */
} n2n_REGISTER_ACK_t; } n2n_REGISTER_ACK_t;
typedef struct n2n_PACKET typedef struct n2n_PACKET
@ -141,30 +145,30 @@ typedef struct n2n_PACKET
} n2n_PACKET_t; } n2n_PACKET_t;
/* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */ /* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */
typedef struct n2n_REGISTER_SUPER typedef struct n2n_REGISTER_SUPER {
{ n2n_cookie_t cookie; /**< Link REGISTER_SUPER and REGISTER_SUPER_ACK */
n2n_cookie_t cookie; /* Link REGISTER_SUPER and REGISTER_SUPER_ACK */ n2n_mac_t edgeMac; /**< MAC to register with edge sending socket */
n2n_mac_t edgeMac; /* MAC to register with edge sending socket */ n2n_ip_subnet_t dev_addr; /**< IP address of the tuntap adapter. */
n2n_auth_t auth; /* Authentication scheme and tokens */ n2n_auth_t auth; /**< Authentication scheme and tokens */
} n2n_REGISTER_SUPER_t; } n2n_REGISTER_SUPER_t;
/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */ /* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */
typedef struct n2n_REGISTER_SUPER_ACK typedef struct n2n_REGISTER_SUPER_ACK {
{ n2n_cookie_t cookie; /**< Return cookie from REGISTER_SUPER */
n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_mac_t edgeMac; /**< MAC registered to edge sending socket */
n2n_mac_t edgeMac; /* MAC registered to edge sending socket */ n2n_ip_subnet_t dev_addr; /**< Assign an IP address to the tuntap adapter of edge. */
uint16_t lifetime; /* How long the registration will live */ uint16_t lifetime; /**< How long the registration will live */
n2n_sock_t sock; /* Sending sockets associated with edgeMac */ n2n_sock_t sock; /**< Sending sockets associated with edgeMac */
/* The packet format provides additional supernode definitions here. /** The packet format provides additional supernode definitions here.
* uint8_t count, then for each count there is one * uint8_t count, then for each count there is one
* n2n_sock_t. * n2n_sock_t.
*/ */
uint8_t num_sn; /* Number of supernodes that were send uint8_t num_sn; /**< Number of supernodes that were send
* even if we cannot store them all. If * even if we cannot store them all. If
* non-zero then sn_bak is valid. */ * non-zero then sn_bak is valid. */
n2n_sock_t sn_bak; /* Socket of the first backup supernode */ n2n_sock_t sn_bak; /**< Socket of the first backup supernode */
} n2n_REGISTER_SUPER_ACK_t; } n2n_REGISTER_SUPER_ACK_t;
@ -174,13 +178,14 @@ typedef struct n2n_REGISTER_SUPER_NAK
n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */ n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */
} n2n_REGISTER_SUPER_NAK_t; } n2n_REGISTER_SUPER_NAK_t;
typedef struct n2n_PEER_INFO
{ typedef struct n2n_PEER_INFO {
uint16_t aflags; uint16_t aflags;
n2n_mac_t mac; n2n_mac_t mac;
n2n_sock_t sock; n2n_sock_t sock;
} n2n_PEER_INFO_t; } n2n_PEER_INFO_t;
typedef struct n2n_QUERY_PEER typedef struct n2n_QUERY_PEER
{ {
n2n_mac_t srcMac; n2n_mac_t srcMac;

76
src/edge.c

@ -450,7 +450,7 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec
char cidr_net[64], gateway[64]; char cidr_net[64], gateway[64];
n2n_route_t route; n2n_route_t route;
if(sscanf(optargument, "%63[^/]/%d:%63s", cidr_net, &route.net_bitlen, gateway) != 3) { if(sscanf(optargument, "%63[^/]/%hhd:%63s", cidr_net, &route.net_bitlen, gateway) != 3) {
traceEvent(TRACE_WARNING, "Bad cidr/gateway format '%d'. See -h.", optargument); traceEvent(TRACE_WARNING, "Bad cidr/gateway format '%d'. See -h.", optargument);
break; break;
} }
@ -818,7 +818,6 @@ int main(int argc, char* argv[]) {
#else #else
snprintf(ec.tuntap_dev_name, sizeof(ec.tuntap_dev_name), "edge0"); snprintf(ec.tuntap_dev_name, sizeof(ec.tuntap_dev_name), "edge0");
#endif #endif
snprintf(ec.ip_mode, sizeof(ec.ip_mode), "static");
snprintf(ec.netmask, sizeof(ec.netmask), "255.255.255.0"); snprintf(ec.netmask, sizeof(ec.netmask), "255.255.255.0");
if((argc >= 2) && (argv[1][0] != '-')) { if((argc >= 2) && (argv[1][0] != '-')) {
@ -861,21 +860,6 @@ int main(int argc, char* argv[]) {
/* Random seed */ /* Random seed */
n2n_srand (n2n_seed()); n2n_srand (n2n_seed());
if(0 == strcmp("dhcp", ec.ip_mode)) {
traceEvent(TRACE_NORMAL, "Dynamic IP address assignment enabled.");
conf.dyn_ip_mode = 1;
} else
traceEvent(TRACE_NORMAL, "ip_mode='%s'", ec.ip_mode);
if(!(
#ifdef __linux__
(ec.tuntap_dev_name[0] != 0) &&
#endif
(ec.ip_addr[0] != 0)
))
help();
#ifndef WIN32 #ifndef WIN32
/* If running suid root then we need to setuid before using the force. */ /* If running suid root then we need to setuid before using the force. */
if(setuid(0) != 0) if(setuid(0) != 0)
@ -886,17 +870,51 @@ int main(int argc, char* argv[]) {
if(conf.encrypt_key && !strcmp((char*)conf.community_name, conf.encrypt_key)) if(conf.encrypt_key && !strcmp((char*)conf.community_name, conf.encrypt_key))
traceEvent(TRACE_WARNING, "Community and encryption key must differ, otherwise security will be compromised"); traceEvent(TRACE_WARNING, "Community and encryption key must differ, otherwise security will be compromised");
if(tuntap_open(&tuntap, ec.tuntap_dev_name, ec.ip_mode, ec.ip_addr, ec.netmask, ec.device_mac, ec.mtu) < 0) if((eee = edge_init(&conf, &rc)) == NULL) {
exit(1);
if((eee = edge_init(&tuntap, &conf, &rc)) == NULL) {
traceEvent(TRACE_ERROR, "Failed in edge_init"); traceEvent(TRACE_ERROR, "Failed in edge_init");
exit(1); exit(1);
} }
memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec)); memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec));
if ((0 == strcmp("static", eee->tuntap_priv_conf.ip_mode)) ||
((eee->tuntap_priv_conf.ip_mode[0] == '\0') && (eee->tuntap_priv_conf.ip_addr[0] != '\0'))) {
traceEvent(TRACE_NORMAL, "Use manually set IP address.");
eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_STATIC;
} else if (0 == strcmp("dhcp", eee->tuntap_priv_conf.ip_mode)) {
traceEvent(TRACE_NORMAL, "Obtain IP from other edge DHCP services.");
eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_DHCP;
} else {
traceEvent(TRACE_NORMAL, "Automatically assign IP address by supernode.");
eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN;
do {
fd_set socket_mask;
struct timeval wait_time;
update_supernode_reg(eee, time(NULL));
FD_ZERO(&socket_mask);
FD_SET(eee->udp_sock, &socket_mask);
wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS;
wait_time.tv_usec = 0;
if (select(eee->udp_sock + 1, &socket_mask, NULL, NULL, &wait_time) > 0) {
if (FD_ISSET(eee->udp_sock, &socket_mask)) {
readFromIPSocket(eee, eee->udp_sock);
}
}
} while (eee->sn_wait);
eee->last_register_req = 0;
}
if (tuntap_open(&tuntap, eee->tuntap_priv_conf.tuntap_dev_name, eee->tuntap_priv_conf.ip_mode,
eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask,
eee->tuntap_priv_conf.device_mac, eee->tuntap_priv_conf.mtu) < 0) exit(1);
traceEvent(TRACE_NORMAL, "Local tuntap IP: %s, Mask: %s",
eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask);
memcpy(&eee->device, &tuntap, sizeof(tuntap));
// hexdump((unsigned char*)&tuntap,sizeof(tuntap_dev));
#ifndef WIN32 #ifndef WIN32
if(ec.daemon) { if(eee->tuntap_priv_conf.daemon) {
setUseSyslog(1); /* traceEvent output now goes to syslog. */ setUseSyslog(1); /* traceEvent output now goes to syslog. */
daemonize(); daemonize();
} }
@ -919,13 +937,13 @@ int main(int argc, char* argv[]) {
#endif #endif
#endif /* HAVE_LIBCAP */ #endif /* HAVE_LIBCAP */
if((ec.userid != 0) || (ec.groupid != 0)) { if((eee->tuntap_priv_conf.userid != 0) || (eee->tuntap_priv_conf.groupid != 0)) {
traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d", traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d",
(signed int)ec.userid, (signed int)ec.groupid); (signed int)eee->tuntap_priv_conf.userid, (signed int)eee->tuntap_priv_conf.groupid);
/* Finished with the need for root privileges. Drop to unprivileged user. */ /* Finished with the need for root privileges. Drop to unprivileged user. */
if((setgid(ec.groupid) != 0) if((setgid(eee->tuntap_priv_conf.groupid) != 0)
|| (setuid(ec.userid) != 0)) { || (setuid(eee->tuntap_priv_conf.userid) != 0)) {
traceEvent(TRACE_ERROR, "Unable to drop privileges [%u/%s]", errno, strerror(errno)); traceEvent(TRACE_ERROR, "Unable to drop privileges [%u/%s]", errno, strerror(errno));
exit(1); exit(1);
} }
@ -961,10 +979,8 @@ int main(int argc, char* argv[]) {
/* Cleanup */ /* Cleanup */
edge_term(eee); edge_term(eee);
edge_term_conf(&conf); edge_term_conf(&eee->conf);
tuntap_close(&tuntap); tuntap_close(&eee->device);
if(conf.encrypt_key) free(conf.encrypt_key);
return(rc); return(rc);
} }

152
src/edge_utils.c

@ -167,7 +167,7 @@ static int is_ip6_discovery(const void * buf, size_t bufsize) {
* *
* This also initialises the NULL transform operation opstruct. * This also initialises the NULL transform operation opstruct.
*/ */
n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *rv) { n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) {
n2n_transform_t transop_id = conf->transop_id; n2n_transform_t transop_id = conf->transop_id;
n2n_edge_t *eee = calloc(1, sizeof(n2n_edge_t)); n2n_edge_t *eee = calloc(1, sizeof(n2n_edge_t));
int rc = -1, i; int rc = -1, i;
@ -187,7 +187,6 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
#endif #endif
memcpy(&eee->conf, conf, sizeof(*conf)); memcpy(&eee->conf, conf, sizeof(*conf));
memcpy(&eee->device, dev, sizeof(*dev));
eee->start_time = time(NULL); eee->start_time = time(NULL);
eee->known_peers = NULL; eee->known_peers = NULL;
@ -207,11 +206,11 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
// zstd does not require initialization. if it were required, this would be a good place // zstd does not require initialization. if it were required, this would be a good place
#endif #endif
for(i=0; i<conf->sn_num; ++i) for(i=0; i<eee->conf.sn_num; ++i)
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i])); traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee->conf.sn_ip_array[i]));
/* Set the active supernode */ /* Set the active supernode */
supernode2addr(&(eee->supernode), conf->sn_ip_array[eee->sn_idx]); supernode2addr(&(eee->supernode), eee->conf.sn_ip_array[eee->sn_idx]);
/* Set active transop */ /* Set active transop */
switch(transop_id) { switch(transop_id) {
@ -243,18 +242,18 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
/* Set the key schedule (context) for header encryption if enabled */ /* Set the key schedule (context) for header encryption if enabled */
if(conf->header_encryption == HEADER_ENCRYPTION_ENABLED) { if(conf->header_encryption == HEADER_ENCRYPTION_ENABLED) {
traceEvent(TRACE_NORMAL, "Header encryption is enabled."); traceEvent(TRACE_NORMAL, "Header encryption is enabled.");
packet_header_setup_key ((char *)(conf->community_name), &(eee->conf.header_encryption_ctx),&(eee->conf.header_iv_ctx)); packet_header_setup_key ((char *)(eee->conf.community_name), &(eee->conf.header_encryption_ctx),&(eee->conf.header_iv_ctx));
} }
if(eee->transop.no_encryption) if(eee->transop.no_encryption)
traceEvent(TRACE_WARNING, "Encryption is disabled in edge"); traceEvent(TRACE_WARNING, "Encryption is disabled in edge");
if(edge_init_sockets(eee, conf->local_port, conf->mgmt_port, conf->tos) < 0) { if(edge_init_sockets(eee, eee->conf.local_port, eee->conf.mgmt_port, eee->conf.tos) < 0) {
traceEvent(TRACE_ERROR, "socket setup failed"); traceEvent(TRACE_ERROR, "socket setup failed");
goto edge_init_error; goto edge_init_error;
} }
if(edge_init_routes(eee, conf->routes, conf->num_routes) < 0) { if(edge_init_routes(eee, eee->conf.routes, eee->conf.num_routes) < 0) {
traceEvent(TRACE_ERROR, "routes setup failed"); traceEvent(TRACE_ERROR, "routes setup failed");
goto edge_init_error; goto edge_init_error;
} }
@ -389,7 +388,7 @@ static const int definitely_from_supernode = 1;
* and verify it (and also update, if applicable). * and verify it (and also update, if applicable).
*/ */
static int find_peer_time_stamp_and_verify (n2n_edge_t * eee, static int find_peer_time_stamp_and_verify (n2n_edge_t * eee,
int from_supernode, n2n_mac_t mac, int from_supernode, const n2n_mac_t mac,
uint64_t stamp) { uint64_t stamp) {
uint64_t * previous_stamp = NULL; uint64_t * previous_stamp = NULL;
@ -628,8 +627,8 @@ int is_empty_ip_address(const n2n_sock_t * sock) {
/* ************************************** */ /* ************************************** */
static n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; static const n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; static const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0};
/** Check if a known peer socket has changed and possibly register again. /** Check if a known peer socket has changed and possibly register again.
*/ */
@ -736,41 +735,44 @@ static void check_join_multicast_group(n2n_edge_t *eee) {
/** Send a REGISTER_SUPER packet to the current supernode. */ /** Send a REGISTER_SUPER packet to the current supernode. */
static void send_register_super(n2n_edge_t *eee, const n2n_sock_t *supernode, int sn_idx) { static void send_register_super(n2n_edge_t *eee, const n2n_sock_t *supernode, int sn_idx) {
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0}; uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
size_t idx; size_t idx;
/* ssize_t sent; */ /* ssize_t sent; */
n2n_common_t cmn; n2n_common_t cmn;
n2n_REGISTER_SUPER_t reg; n2n_REGISTER_SUPER_t reg;
n2n_sock_str_t sockbuf; n2n_sock_str_t sockbuf;
memset(&cmn, 0, sizeof(cmn)); memset(&cmn, 0, sizeof(cmn));
memset(&reg, 0, sizeof(reg)); memset(&reg, 0, sizeof(reg));
cmn.ttl=N2N_DEFAULT_TTL;
cmn.pc = n2n_register_super;
cmn.flags = 0;
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
for (idx = 0; (sn_idx==0) && (idx < N2N_COOKIE_SIZE); ++idx) cmn.ttl = N2N_DEFAULT_TTL;
eee->last_cookie[idx] = n2n_rand() % 0xff; cmn.pc = n2n_register_super;
cmn.flags = 0;
memcpy(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE);
memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE); for (idx = 0; (sn_idx==0) && (idx < N2N_COOKIE_SIZE); ++idx)
reg.auth.scheme=0; /* No auth yet */ eee->last_cookie[idx] = n2n_rand() % 0xff;
idx=0; memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE);
encode_mac(reg.edgeMac, &idx, eee->device.mac_addr); reg.dev_addr.net_addr = ntohl(eee->device.ip_addr);
reg.dev_addr.net_bitlen = mask2bitlen(ntohl(eee->device.device_mask));
reg.auth.scheme = 0; /* No auth yet */
idx=0; idx = 0;
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, &reg); encode_mac(reg.edgeMac, &idx, eee->device.mac_addr);
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", idx = 0;
sock_to_cstr(sockbuf, supernode)); encode_REGISTER_SUPER(pktbuf, &idx, &cmn, &reg);
if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, sock_to_cstr(sockbuf, supernode));
eee->conf.header_iv_ctx,
time_stamp (), pearson_hash_16 (pktbuf, idx));
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED)
packet_header_encrypt(pktbuf, idx, eee->conf.header_encryption_ctx,
eee->conf.header_iv_ctx,
time_stamp(), pearson_hash_16(pktbuf, idx));
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode);
} }
/* ************************************** */ /* ************************************** */
@ -904,7 +906,7 @@ static void send_register_ack(n2n_edge_t * eee,
* *
* This is frequently called by the main loop. * This is frequently called by the main loop.
*/ */
static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) { void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {
u_int sn_idx; u_int sn_idx;
if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->conf.register_interval/10)))) { if(eee->sn_wait && (nowTime > (eee->last_register_req + (eee->conf.register_interval/10)))) {
@ -1588,7 +1590,7 @@ void edge_read_from_tap(n2n_edge_t * eee) {
/* ************************************** */ /* ************************************** */
/** Read a datagram from the main UDP socket to the internet. */ /** Read a datagram from the main UDP socket to the internet. */
static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
n2n_common_t cmn; /* common fields in the packet header */ n2n_common_t cmn; /* common fields in the packet header */
n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf1;
@ -1750,14 +1752,14 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
* to double check this. * to double check this.
*/ */
traceEvent(TRACE_DEBUG, "Got P2P register"); traceEvent(TRACE_DEBUG, "Got P2P register");
traceEvent(TRACE_NORMAL, "[P2P] Rx REGISTER from %s", sock_to_cstr(sockbuf1, &sender)); traceEvent(TRACE_INFO, "[P2P] Rx REGISTER from %s", sock_to_cstr(sockbuf1, &sender));
find_and_remove_peer(&eee->pending_peers, reg.srcMac); find_and_remove_peer(&eee->pending_peers, reg.srcMac);
/* NOTE: only ACK to peers */ /* NOTE: only ACK to peers */
send_register_ack(eee, orig_sender, &reg); send_register_ack(eee, orig_sender, &reg);
} }
else { else {
traceEvent(TRACE_NORMAL, "[PsP] Rx REGISTER src=%s dst=%s from sn=%s (edge:%s)", traceEvent(TRACE_INFO, "[PsP] Rx REGISTER src=%s dst=%s from sn=%s (edge:%s)",
macaddr_str(mac_buf1, reg.srcMac), macaddr_str(mac_buf2, reg.dstMac), macaddr_str(mac_buf1, reg.srcMac), macaddr_str(mac_buf2, reg.dstMac),
sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender)); sock_to_cstr(sockbuf1, &sender), sock_to_cstr(sockbuf2, orig_sender));
} }
@ -1793,7 +1795,13 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
} }
case MSG_TYPE_REGISTER_SUPER_ACK: case MSG_TYPE_REGISTER_SUPER_ACK:
{ {
// Indicates successful connection between the edge and SN nodes in_addr_t net;
char * ip_str = NULL;
n2n_REGISTER_SUPER_ACK_t ra;
memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
// Indicates successful connection between the edge and SN nodes
static int bTrace = 1; static int bTrace = 1;
if (bTrace) if (bTrace)
{ {
@ -1801,7 +1809,6 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
bTrace = 0; bTrace = 0;
} }
n2n_REGISTER_SUPER_ACK_t ra;
if(eee->sn_wait) if(eee->sn_wait)
{ {
@ -1839,6 +1846,20 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
eee->last_sup = now; eee->last_sup = now;
eee->sn_wait=0; eee->sn_wait=0;
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */
if (eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_SN_ASSIGN) {
if ((ra.dev_addr.net_addr != 0) && (ra.dev_addr.net_bitlen != 0)) {
net = htonl(ra.dev_addr.net_addr);
if ((ip_str = inet_ntoa(*(struct in_addr *) &net)) != NULL) {
strncpy(eee->tuntap_priv_conf.ip_addr, ip_str,
N2N_NETMASK_STR_SIZE);
}
net = htonl(bitlen2mask(ra.dev_addr.net_bitlen));
if ((ip_str = inet_ntoa(*(struct in_addr *) &net)) != NULL) {
strncpy(eee->tuntap_priv_conf.netmask, ip_str,
N2N_NETMASK_STR_SIZE);
}
}
}
if(eee->cb.sn_registration_updated) if(eee->cb.sn_registration_updated)
eee->cb.sn_registration_updated(eee, now, &sender); eee->cb.sn_registration_updated(eee, now, &sender);
@ -1857,7 +1878,8 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER.");
} }
break; break;
} case MSG_TYPE_PEER_INFO: { }
case MSG_TYPE_PEER_INFO: {
n2n_PEER_INFO_t pi; n2n_PEER_INFO_t pi;
struct peer_info * scan; struct peer_info * scan;
decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx ); decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx );
@ -2024,7 +2046,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
HASH_COUNT(eee->known_peers)); HASH_COUNT(eee->known_peers));
} }
if(eee->conf.dyn_ip_mode && if((eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_DHCP) &&
((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) { ((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) {
uint32_t old_ip = eee->device.ip_addr; uint32_t old_ip = eee->device.ip_addr;
@ -2535,28 +2557,30 @@ static void edge_cleanup_routes(n2n_edge_t *eee) {
/* ************************************** */ /* ************************************** */
void edge_init_conf_defaults(n2n_edge_conf_t *conf) { void edge_init_conf_defaults(n2n_edge_conf_t *conf) {
memset(conf, 0, sizeof(*conf)); memset(conf, 0, sizeof(*conf));
conf->local_port = 0 /* any port */; conf->local_port = 0 /* any port */;
conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */
conf->transop_id = N2N_TRANSFORM_ID_NULL; conf->transop_id = N2N_TRANSFORM_ID_NULL;
conf->header_encryption = HEADER_ENCRYPTION_NONE; conf->header_encryption = HEADER_ENCRYPTION_NONE;
conf->compression = N2N_COMPRESSION_ID_NONE; conf->compression = N2N_COMPRESSION_ID_NONE;
conf->drop_multicast = 1; conf->drop_multicast = 1;
conf->allow_p2p = 1; conf->allow_p2p = 1;
conf->disable_pmtu_discovery = 1; conf->disable_pmtu_discovery = 1;
conf->register_interval = REGISTER_SUPER_INTERVAL_DFL; conf->register_interval = REGISTER_SUPER_INTERVAL_DFL;
conf->tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN;
if(getenv("N2N_KEY")) {
conf->encrypt_key = strdup(getenv("N2N_KEY")); if (getenv("N2N_KEY")) {
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH; conf->encrypt_key = strdup(getenv("N2N_KEY"));
} conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
}
} }
/* ************************************** */ /* ************************************** */
void edge_term_conf(n2n_edge_conf_t *conf) { void edge_term_conf(n2n_edge_conf_t *conf) {
if(conf->routes) free(conf->routes); if (conf->routes) free(conf->routes);
if (conf->encrypt_key) free(conf->encrypt_key);
} }
/* ************************************** */ /* ************************************** */
@ -2608,7 +2632,7 @@ int quick_edge_init(char *device_name, char *community_name,
return(-2); return(-2);
/* Init edge */ /* Init edge */
if((eee = edge_init(&tuntap, &conf, &rv)) == NULL) if((eee = edge_init(&conf, &rv)) == NULL)
goto quick_edge_init_end; goto quick_edge_init_end;
rv = run_edge_loop(eee, keep_on_running); rv = run_edge_loop(eee, keep_on_running);

4
src/example_edge_embed.c

@ -33,7 +33,7 @@ int main()
snprintf((char *)conf.community_name, sizeof(conf.community_name), "%s", "mycommunity"); // Community to connect to snprintf((char *)conf.community_name, sizeof(conf.community_name), "%s", "mycommunity"); // Community to connect to
conf.disable_pmtu_discovery = 1; // Whether to disable the path MTU discovery conf.disable_pmtu_discovery = 1; // Whether to disable the path MTU discovery
conf.drop_multicast = 0; // Whether to disable multicast conf.drop_multicast = 0; // Whether to disable multicast
conf.dyn_ip_mode = 0; // Whether the IP address is set dynamically (see IP mode; 0 if static, 1 if dynamic) conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; // How to set the IP address
conf.encrypt_key = "mysecret"; // Secret to decrypt & encrypt with conf.encrypt_key = "mysecret"; // Secret to decrypt & encrypt with
conf.local_port = 0; // What port to use (0 = any port) conf.local_port = 0; // What port to use (0 = any port)
conf.mgmt_port = N2N_EDGE_MGMT_PORT; // Edge management port (5644 by default) conf.mgmt_port = N2N_EDGE_MGMT_PORT; // Edge management port (5644 by default)
@ -59,7 +59,7 @@ int main()
return -1; return -1;
} }
eee = edge_init(&tuntap, &conf, &rc); eee = edge_init(&conf, &rc);
if (eee == NULL) if (eee == NULL)
{ {
exit(1); exit(1);

58
src/n2n.c

@ -185,6 +185,29 @@ char* intoa(uint32_t /* host order */ addr, char* buf, uint16_t buf_len) {
return(retStr); return(retStr);
} }
/** Convert subnet prefix bit length to host order subnet mask. */
uint32_t bitlen2mask(uint8_t bitlen) {
uint8_t i;
uint32_t mask = 0;
for (i = 1; i <= bitlen; ++i) {
mask |= 1 << (32 - i);
}
return mask;
}
/** Convert host order subnet mask to subnet prefix bit length. */
uint8_t mask2bitlen(uint32_t mask) {
uint8_t i, bitlen = 0;
for (i = 0; i < 32; ++i) {
if ((mask << i) & 0x80000000) ++bitlen;
else break;
}
return bitlen;
}
/* *********************************************** */ /* *********************************************** */
char * macaddr_str(macstr_t buf, char * macaddr_str(macstr_t buf,
@ -231,21 +254,21 @@ char* msg_type2str(uint16_t msg_type) {
/* *********************************************** */ /* *********************************************** */
void hexdump(const uint8_t * buf, size_t len) void hexdump(const uint8_t *buf, size_t len) {
{ size_t i;
size_t i;
if(0 == len) { return; }
for(i=0; i<len; i++) if (0 == len) { return; }
{
if((i > 0) &&((i % 16) == 0)) { printf("\n"); }
printf("%02X ", buf[i] & 0xFF);
}
printf("\n"); printf("-----------------------------------------------\n");
for (i = 0; i < len; i++) {
if ((i > 0) && ((i % 16) == 0)) { printf("\n"); }
printf("%02X ", buf[i] & 0xFF);
}
printf("\n");
printf("-----------------------------------------------\n");
} }
/* *********************************************** */ /* *********************************************** */
void print_n2n_version() { void print_n2n_version() {
@ -360,6 +383,17 @@ extern char * sock_to_cstr(n2n_sock_str_t out,
} }
} }
char *ip_subnet_to_str(dec_ip_bit_str_t buf, const n2n_ip_subnet_t *ipaddr) {
snprintf(buf, sizeof(dec_ip_bit_str_t), "%hhu.%hhu.%hhu.%hhu/%hhu",
(uint8_t) ((ipaddr->net_addr >> 24) & 0xFF),
(uint8_t) ((ipaddr->net_addr >> 16) & 0xFF),
(uint8_t) ((ipaddr->net_addr >> 8) & 0xFF),
(uint8_t) (ipaddr->net_addr & 0xFF),
ipaddr->net_bitlen);
return buf;
}
/* @return 1 if the two sockets are equivalent. */ /* @return 1 if the two sockets are equivalent. */
int sock_equal(const n2n_sock_t * a, int sock_equal(const n2n_sock_t * a,
const n2n_sock_t * b) { const n2n_sock_t * b) {
@ -383,7 +417,7 @@ int sock_equal(const n2n_sock_t * a,
/* *********************************************** */ /* *********************************************** */
#if defined(WIN32) && !defined(__GNUC__) #if defined(WIN32)
int gettimeofday(struct timeval *tp, void *tzp) { int gettimeofday(struct timeval *tp, void *tzp) {
time_t clock; time_t clock;
struct tm tm; struct tm tm;

165
src/sn.c

@ -92,100 +92,137 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) {
/** Help message to print if the command line arguments are not valid. */ /** Help message to print if the command line arguments are not valid. */
static void help() { static void help() {
print_n2n_version(); print_n2n_version();
printf("supernode <config file> (see supernode.conf)\n" printf("supernode <config file> (see supernode.conf)\n"
"or\n" "or\n"
); );
printf("supernode "); printf("supernode ");
printf("-l <local port> "); printf("-l <local port> ");
printf("-c <path> "); printf("-c <path> ");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("[-f] "); printf("[-f] ");
#endif #endif
#ifndef WIN32 #ifndef WIN32
printf("[-u <uid> -g <gid>] "); printf("[-u <uid> -g <gid>] ");
#endif /* ifndef WIN32 */ #endif /* ifndef WIN32 */
printf("[-t <mgmt port>] "); printf("[-t <mgmt port>] ");
printf("[-v] "); printf("[-d <net/bit>] ");
printf("\n\n"); printf("[-v] ");
printf("\n\n");
printf("-l <port>\tSet UDP main listen port to <port>\n"); printf("-l <port> | Set UDP main listen port to <port>\n");
printf("-c <path>\tFile containing the allowed communities.\n"); printf("-c <path> | File containing the allowed communities.\n");
#if defined(N2N_HAVE_DAEMON) #if defined(N2N_HAVE_DAEMON)
printf("-f \tRun in foreground.\n"); printf("-f | Run in foreground.\n");
#endif /* #if defined(N2N_HAVE_DAEMON) */ #endif /* #if defined(N2N_HAVE_DAEMON) */
#ifndef WIN32 #ifndef WIN32
printf("-u <UID>\tUser ID (numeric) to use when privileges are dropped.\n"); printf("-u <UID> | User ID (numeric) to use when privileges are dropped.\n");
printf("-g <GID>\tGroup ID (numeric) to use when privileges are dropped.\n"); printf("-g <GID> | Group ID (numeric) to use when privileges are dropped.\n");
#endif /* ifndef WIN32 */ #endif /* ifndef WIN32 */
printf("-t <port>\tManagement UDP Port (for multiple supernodes on a machine).\n"); printf("-t <port> | Management UDP Port (for multiple supernodes on a machine).\n");
printf("-v \tIncrease verbosity. Can be used multiple times.\n"); printf("-d <net/bit> | Subnet that provides dhcp service for edge. eg. -d 172.17.12.0/24\n");
printf("-h \tThis help message.\n"); printf("-v | Increase verbosity. Can be used multiple times.\n");
printf("\n"); printf("-h | This help message.\n");
printf("\n");
exit(1); exit(1);
} }
/* *************************************************** */ /* *************************************************** */
static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) { static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
switch(optkey) { switch (optkey) {
case 'l': /* local-port */ case 'l': /* local-port */
sss->lport = atoi(_optarg); sss->lport = atoi(_optarg);
break; break;
case 't': /* mgmt-port */ case 't': /* mgmt-port */
sss->mport = atoi(_optarg); sss->mport = atoi(_optarg);
break; break;
case 'd': {
dec_ip_str_t ip_str = {'\0'};
in_addr_t net;
uint8_t bitlen;
if (sscanf(_optarg, "%15[^/]/%hhu", ip_str, &bitlen) != 2) {
traceEvent(TRACE_WARNING, "Bad net/bit format '%s'. See -h.", _optarg);
break;
}
net = inet_addr(ip_str);
if ((net < 0) || (net == INADDR_NONE) || (net == INADDR_ANY)) {
traceEvent(TRACE_WARNING, "Bad network '%s' in '%s', Use default: '%s/%d'",
ip_str, _optarg,
N2N_SN_DHCP_NET_ADDR_DEFAULT, N2N_SN_DHCP_NET_BIT_DEFAULT);
break;
}
if (bitlen > 32) {
traceEvent(TRACE_WARNING, "Bad prefix '%hhu' in '%s', Use default: '%s/%d'",
bitlen, _optarg,
N2N_SN_DHCP_NET_ADDR_DEFAULT, N2N_SN_DHCP_NET_BIT_DEFAULT);
break;
}
traceEvent(TRACE_NORMAL, "The subnet of DHCP service is: '%s/%hhu'.", ip_str, bitlen);
sss->dhcp_addr.net_addr = ntohl(net);
sss->dhcp_addr.net_bitlen = bitlen;
break;
}
#ifndef WIN32 #ifndef WIN32
case 'u': /* unprivileged uid */ case 'u': /* unprivileged uid */
sss->userid = atoi(_optarg); sss->userid = atoi(_optarg);
break; break;
case 'g': /* unprivileged uid */ case 'g': /* unprivileged uid */
sss->groupid = atoi(_optarg); sss->groupid = atoi(_optarg);
break; break;
#endif #endif
case 'c': /* community file */ case 'c': /* community file */
load_allowed_sn_community(sss, _optarg); load_allowed_sn_community(sss, _optarg);
break; break;
case 'f': /* foreground */ case 'f': /* foreground */
sss->daemon = 0; sss->daemon = 0;
break; break;
case 'h': /* help */ case 'h': /* help */
help(); help();
break; break;
case 'v': /* verbose */ case 'v': /* verbose */
setTraceLevel(getTraceLevel() + 1); setTraceLevel(getTraceLevel() + 1);
break; break;
default: default:
traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey); traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char) optkey);
return(-1); return (-1);
} }
return(0); return (0);
} }
/* *********************************************** */ /* *********************************************** */
static const struct option long_options[] = { static const struct option long_options[] = {
{ "communities", required_argument, NULL, 'c' }, {"communities", required_argument, NULL, 'c'},
{ "foreground", no_argument, NULL, 'f' }, {"foreground", no_argument, NULL, 'f'},
{ "local-port", required_argument, NULL, 'l' }, {"local-port", required_argument, NULL, 'l'},
{ "mgmt-port", required_argument, NULL, 't' }, {"mgmt-port", required_argument, NULL, 't'},
{ "help" , no_argument, NULL, 'h' }, {"dhcp", required_argument, NULL, 'd'},
{ "verbose", no_argument, NULL, 'v' }, {"help", no_argument, NULL, 'h'},
{ NULL, 0, NULL, 0 } {"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
}; };
/* *************************************************** */ /* *************************************************** */
@ -194,7 +231,7 @@ static const struct option long_options[] = {
static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) { static int loadFromCLI(int argc, char * const argv[], n2n_sn_t *sss) {
u_char c; u_char c;
while((c = getopt_long(argc, argv, "fl:u:g:t:c:vh", while((c = getopt_long(argc, argv, "fl:u:g:t:d:c:vh",
long_options, NULL)) != '?') { long_options, NULL)) != '?') {
if(c == 255) break; if(c == 255) break;
setOption(c, optarg, sss); setOption(c, optarg, sss);

337
src/sn_utils.c

@ -47,7 +47,7 @@ static int try_broadcast(n2n_sn_t * sss,
static uint16_t reg_lifetime(n2n_sn_t *sss); static uint16_t reg_lifetime(n2n_sn_t *sss);
static int update_edge(n2n_sn_t *sss, static int update_edge(n2n_sn_t *sss,
const n2n_mac_t edgeMac, const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm, struct sn_community *comm,
const n2n_sock_t *sender_sock, const n2n_sock_t *sender_sock,
time_t now); time_t now);
@ -204,23 +204,25 @@ static int try_broadcast(n2n_sn_t * sss,
/** Initialise the supernode structure */ /** Initialise the supernode structure */
int sn_init(n2n_sn_t *sss) int sn_init(n2n_sn_t *sss) {
{
#ifdef WIN32 #ifdef WIN32
initWin32(); initWin32();
#endif #endif
pearson_hash_init(); pearson_hash_init();
memset(sss, 0, sizeof(n2n_sn_t)); memset(sss, 0, sizeof(n2n_sn_t));
sss->daemon = 1; /* By defult run as a daemon. */ sss->daemon = 1; /* By defult run as a daemon. */
sss->lport = N2N_SN_LPORT_DEFAULT; sss->lport = N2N_SN_LPORT_DEFAULT;
sss->mport = N2N_SN_MGMT_PORT; sss->mport = N2N_SN_MGMT_PORT;
sss->sock = -1; sss->sock = -1;
sss->mgmt_sock = -1; sss->mgmt_sock = -1;
sss->dhcp_addr.net_addr = inet_addr(N2N_SN_DHCP_NET_ADDR_DEFAULT);
sss->dhcp_addr.net_addr = ntohl(sss->dhcp_addr.net_addr);
sss->dhcp_addr.net_bitlen = N2N_SN_DHCP_NET_BIT_DEFAULT;
return 0; /* OK */ return 0; /* OK */
} }
/** Deinitialise the supernode structure and deallocate any memory owned by /** Deinitialise the supernode structure and deallocate any memory owned by
@ -265,61 +267,101 @@ static uint16_t reg_lifetime(n2n_sn_t *sss)
/** Update the edge table with the details of the edge which contacted the /** Update the edge table with the details of the edge which contacted the
* supernode. */ * supernode. */
static int update_edge(n2n_sn_t *sss, static int update_edge(n2n_sn_t *sss,
const n2n_mac_t edgeMac, const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm, struct sn_community *comm,
const n2n_sock_t *sender_sock, const n2n_sock_t *sender_sock,
time_t now) time_t now) {
{ macstr_t mac_buf;
macstr_t mac_buf; n2n_sock_str_t sockbuf;
n2n_sock_str_t sockbuf; struct peer_info *scan;
struct peer_info *scan;
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]",
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]", macaddr_str(mac_buf, reg->edgeMac),
macaddr_str(mac_buf, edgeMac), sock_to_cstr(sockbuf, sender_sock));
sock_to_cstr(sockbuf, sender_sock));
HASH_FIND_PEER(comm->edges, reg->edgeMac, scan);
HASH_FIND_PEER(comm->edges, edgeMac, scan);
if (NULL == scan) {
if (NULL == scan) /* Not known */
{
/* Not known */ scan = (struct peer_info *) calloc(1,
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */
scan = (struct peer_info *)calloc(1,
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */ memcpy(&(scan->mac_addr), reg->edgeMac, sizeof(n2n_mac_t));
scan->dev_addr.net_addr = reg->dev_addr.net_addr;
memcpy(&(scan->mac_addr), edgeMac, sizeof(n2n_mac_t)); scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen;
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
scan->last_valid_time_stamp = initial_time_stamp (); scan->last_valid_time_stamp = initial_time_stamp();
HASH_ADD_PEER(comm->edges, scan);
traceEvent(TRACE_INFO, "update_edge created %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
} else {
/* Known */
if (!sock_equal(sender_sock, &(scan->sock))) {
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
traceEvent(TRACE_INFO, "update_edge updated %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
} else {
traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
}
}
scan->last_seen = now;
return 0;
}
HASH_ADD_PEER(comm->edges, scan);
traceEvent(TRACE_INFO, "update_edge created %s ==> %s", static signed int peer_tap_ip_sort(struct peer_info *a, struct peer_info *b) {
macaddr_str(mac_buf, edgeMac), uint32_t a_host_id = a->dev_addr.net_addr & (~bitlen2mask(a->dev_addr.net_bitlen));
sock_to_cstr(sockbuf, sender_sock)); uint32_t b_host_id = b->dev_addr.net_addr & (~bitlen2mask(b->dev_addr.net_bitlen));
} return ((signed int)a_host_id - (signed int)b_host_id);
else }
{
/* Known */
if (!sock_equal(sender_sock, &(scan->sock)))
{
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
traceEvent(TRACE_INFO, "update_edge updated %s ==> %s",
macaddr_str(mac_buf, edgeMac),
sock_to_cstr(sockbuf, sender_sock));
}
else
{
traceEvent(TRACE_DEBUG, "update_edge unchanged %s ==> %s",
macaddr_str(mac_buf, edgeMac),
sock_to_cstr(sockbuf, sender_sock));
}
}
scan->last_seen = now; /** The IP address assigned to the edge by the DHCP function of sn. */
return 0; static int assign_one_ip_addr(n2n_sn_t *sss,
struct sn_community *comm,
n2n_ip_subnet_t *ipaddr) {
struct peer_info *peer, *tmpPeer;
uint32_t net_id, mask, max_host, host_id = 1;
dec_ip_bit_str_t ip_bit_str = {'\0'};
mask = bitlen2mask(sss->dhcp_addr.net_bitlen);
net_id = sss->dhcp_addr.net_addr & mask;
max_host = ~mask;
HASH_SORT(comm->edges, peer_tap_ip_sort);
HASH_ITER(hh, comm->edges, peer, tmpPeer) {
if ((peer->dev_addr.net_addr & bitlen2mask(peer->dev_addr.net_bitlen)) == net_id) {
if (host_id >= max_host) {
traceEvent(TRACE_WARNING, "No assignable IP to edge tap adapter.");
return -1;
}
if (peer->dev_addr.net_addr == 0) {
continue;
}
if ((peer->dev_addr.net_addr & max_host) == host_id) {
++host_id;
} else {
break;
}
}
}
ipaddr->net_addr = net_id | host_id;
ipaddr->net_bitlen = sss->dhcp_addr.net_bitlen;
traceEvent(TRACE_INFO, "Assign IP %s to tap adapter of edge.", ip_subnet_to_str(ip_bit_str, ipaddr));
return 0;
} }
/*** /***
* *
* For a given packet, find the apporopriate internal last valid time stamp for lookup * For a given packet, find the apporopriate internal last valid time stamp for lookup
@ -409,89 +451,89 @@ static int process_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock, const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf, const uint8_t *mgmt_buf,
size_t mgmt_size, size_t mgmt_size,
time_t now) time_t now) {
{ char resbuf[N2N_SN_PKTBUF_SIZE];
char resbuf[N2N_SN_PKTBUF_SIZE]; size_t ressize = 0;
size_t ressize = 0; uint32_t num_edges = 0;
uint32_t num_edges = 0; uint32_t num = 0;
uint32_t num = 0; struct sn_community *community, *tmp;
struct sn_community *community, *tmp; struct peer_info *peer, *tmpPeer;
struct peer_info * peer, *tmpPeer; macstr_t mac_buf;
macstr_t mac_buf; n2n_sock_str_t sockbuf;
n2n_sock_str_t sockbuf; dec_ip_bit_str_t ip_bit_str = {'\0'};
traceEvent(TRACE_DEBUG, "process_mgmt"); traceEvent(TRACE_DEBUG, "process_mgmt");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"----------------\n"); "\tid tun_tap MAC edge last_seen\n");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "-------------------------------------------------------------------------------------\n");
"uptime %lu\n", (now - sss->start_time)); HASH_ITER(hh, sss->communities, community, tmp) {
num_edges += HASH_COUNT(community->edges);
HASH_ITER(hh, sss->communities, community, tmp) ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
{ "community: %s\n", community->community);
num_edges += HASH_COUNT(community->edges); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
} ressize = 0;
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, num = 0;
"edges %u\n", HASH_ITER(hh, community->edges, peer, tmpPeer) {
num_edges); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"\t%-4u %-18s %-17s %-21s %lu\n",
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ++num, ip_subnet_to_str(ip_bit_str, &peer->dev_addr),
"errors %u\n", macaddr_str(mac_buf, peer->mac_addr),
(unsigned int)sss->stats.errors); sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
"reg_sup %u\n", ressize = 0;
(unsigned int)sss->stats.reg_super); }
}
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_nak %u\n", "-------------------------------------------------------------------------------------\n");
(unsigned int)sss->stats.reg_super_nak);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "uptime %lu | ", (now - sss->start_time));
"fwd %u\n",
(unsigned int)sss->stats.fwd); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"edges %u | ",
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, num_edges);
"broadcast %u\n",
(unsigned int)sss->stats.broadcast); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_sup %u | ",
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, (unsigned int) sss->stats.reg_super);
"last fwd %lu sec ago\n",
(long unsigned int)(now - sss->stats.last_fwd)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_nak %u | ",
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, (unsigned int) sss->stats.reg_super_nak);
"last reg %lu sec ago\n",
(long unsigned int)(now - sss->stats.last_reg_super)); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"errors %u \n",
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, (unsigned int) sss->stats.errors);
"cur_cmnts %u\n", HASH_COUNT(sss->communities));
HASH_ITER(hh, sss->communities, community, tmp) { ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, "fwd %u | ",
"community: %s\n", community->community); (unsigned int) sss->stats.fwd);
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize);
ressize = 0; ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"broadcast %u | ",
num = 0; (unsigned int) sss->stats.broadcast);
HASH_ITER(hh, community->edges, peer, tmpPeer) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"\t[id: %u][MAC: %s][edge: %s][last seen: %lu sec ago]\n", "cur_cmnts %u\n", HASH_COUNT(sss->communities));
++num, macaddr_str(mac_buf, peer->mac_addr),
sock_to_cstr(sockbuf, &(peer->sock)), now-peer->last_seen); ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"last fwd %lu sec ago\n",
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize); (long unsigned int) (now - sss->stats.last_fwd));
ressize = 0;
} ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
} "last reg %lu sec ago\n\n",
(long unsigned int) (now - sss->stats.last_reg_super));
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"\n"); sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize);
return 0;
return 0;
} }
static int sendto_mgmt(n2n_sn_t *sss, static int sendto_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock, const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf, const uint8_t *mgmt_buf,
@ -528,6 +570,7 @@ static int process_udp(n2n_sn_t * sss,
char buf[32]; char buf[32];
struct sn_community *comm, *tmp; struct sn_community *comm, *tmp;
uint64_t stamp; uint64_t stamp;
const n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0}; /* 00:00:00:00:00:00 */
traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]", traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]",
udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)),
@ -791,6 +834,9 @@ static int process_udp(n2n_sn_t * sss,
n2n_common_t cmn2; n2n_common_t cmn2;
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE];
size_t encx=0; size_t encx=0;
n2n_ip_subnet_t ipaddr;
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
/* Edge requesting registration with us. */ /* Edge requesting registration with us. */
sss->stats.last_reg_super=now; sss->stats.last_reg_super=now;
@ -836,6 +882,12 @@ static int process_udp(n2n_sn_t * sss,
memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t));
memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t)); memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t));
if ((reg.dev_addr.net_addr == 0) || (reg.dev_addr.net_addr == 0xFFFFFFFF) || (reg.dev_addr.net_bitlen == 0) ||
((reg.dev_addr.net_addr & 0xFFFF0000) == 0xA9FE0000 /* 169.254.0.0 */)) {
assign_one_ip_addr(sss, comm, &ipaddr);
ack.dev_addr.net_addr = ipaddr.net_addr;
ack.dev_addr.net_bitlen = ipaddr.net_bitlen;
}
ack.lifetime = reg_lifetime(sss); ack.lifetime = reg_lifetime(sss);
ack.sock.family = AF_INET; ack.sock.family = AF_INET;
@ -843,13 +895,14 @@ static int process_udp(n2n_sn_t * sss,
memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE);
ack.num_sn=0; /* No backup */ ack.num_sn=0; /* No backup */
memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t));
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]",
macaddr_str(mac_buf, reg.edgeMac), macaddr_str(mac_buf, reg.edgeMac),
sock_to_cstr(sockbuf, &(ack.sock))); sock_to_cstr(sockbuf, &(ack.sock)));
update_edge(sss, reg.edgeMac, comm, &(ack.sock), now); if(memcmp(reg.edgeMac, &null_mac, N2N_MAC_SIZE) != 0){
update_edge(sss, &reg, comm, &(ack.sock), now);
}
encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack);

260
src/wire.c

@ -289,130 +289,135 @@ int decode_REGISTER( n2n_REGISTER_t * reg,
return retval; return retval;
} }
int encode_REGISTER_SUPER( uint8_t * base,
size_t * idx,
const n2n_common_t * common,
const n2n_REGISTER_SUPER_t * reg )
{
int retval=0;
retval += encode_common( base, idx, common );
retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE );
retval += encode_mac( base, idx, reg->edgeMac );
retval += encode_uint16( base, idx, 0 ); /* NULL auth scheme */
retval += encode_uint16( base, idx, 0 ); /* No auth data */
return retval; int encode_REGISTER_SUPER(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_REGISTER_SUPER_t *reg) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_mac(base, idx, reg->edgeMac);
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen);
retval += encode_uint16(base, idx, 0); /* NULL auth scheme */
retval += encode_uint16(base, idx, 0); /* No auth data */
return retval;
} }
int decode_REGISTER_SUPER( n2n_REGISTER_SUPER_t * reg,
const n2n_common_t * cmn, /* info on how to interpret it */
const uint8_t * base,
size_t * rem,
size_t * idx )
{
size_t retval=0;
memset( reg, 0, sizeof(n2n_REGISTER_SUPER_t) );
retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx );
retval += decode_mac( reg->edgeMac, base, rem, idx );
retval += decode_uint16( &(reg->auth.scheme), base, rem, idx );
retval += decode_uint16( &(reg->auth.toksize), base, rem, idx );
retval += decode_buf( reg->auth.token, reg->auth.toksize, base, rem, idx );
return retval;
}
int encode_REGISTER_ACK( uint8_t * base, int decode_REGISTER_SUPER(n2n_REGISTER_SUPER_t *reg,
size_t * idx, const n2n_common_t *cmn, /* info on how to interpret it */
const n2n_common_t * common, const uint8_t *base,
const n2n_REGISTER_ACK_t * reg ) size_t *rem,
{ size_t *idx) {
int retval=0; size_t retval = 0;
retval += encode_common( base, idx, common ); memset(reg, 0, sizeof(n2n_REGISTER_SUPER_t));
retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE ); retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += encode_mac( base, idx, reg->dstMac ); retval += decode_mac(reg->edgeMac, base, rem, idx);
retval += encode_mac( base, idx, reg->srcMac ); retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx);
retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx);
retval += decode_uint16(&(reg->auth.scheme), base, rem, idx);
retval += decode_uint16(&(reg->auth.toksize), base, rem, idx);
retval += decode_buf(reg->auth.token, reg->auth.toksize, base, rem, idx);
return retval;
}
/* The socket in REGISTER_ACK is the socket from which the REGISTER
* arrived. This is sent back to the sender so it knows what its public
* socket is. */
if ( 0 != reg->sock.family )
{
retval += encode_sock( base, idx, &(reg->sock) );
}
return retval; int encode_REGISTER_ACK(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_REGISTER_ACK_t *reg) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_mac(base, idx, reg->dstMac);
retval += encode_mac(base, idx, reg->srcMac);
/* The socket in REGISTER_ACK is the socket from which the REGISTER
* arrived. This is sent back to the sender so it knows what its public
* socket is. */
if (0 != reg->sock.family) {
retval += encode_sock(base, idx, &(reg->sock));
}
return retval;
} }
int decode_REGISTER_ACK( n2n_REGISTER_ACK_t * reg,
const n2n_common_t * cmn, /* info on how to interpret it */
const uint8_t * base,
size_t * rem,
size_t * idx )
{
size_t retval=0;
memset( reg, 0, sizeof(n2n_REGISTER_ACK_t) );
retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx );
retval += decode_mac( reg->dstMac, base, rem, idx );
retval += decode_mac( reg->srcMac, base, rem, idx );
/* The socket in REGISTER_ACK is the socket from which the REGISTER
* arrived. This is sent back to the sender so it knows what its public
* socket is. */
if ( cmn->flags & N2N_FLAGS_SOCKET )
{
retval += decode_sock( &(reg->sock), base, rem, idx );
}
return retval; int decode_REGISTER_ACK(n2n_REGISTER_ACK_t *reg,
const n2n_common_t *cmn, /* info on how to interpret it */
const uint8_t *base,
size_t *rem,
size_t *idx) {
size_t retval = 0;
memset(reg, 0, sizeof(n2n_REGISTER_ACK_t));
retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_mac(reg->dstMac, base, rem, idx);
retval += decode_mac(reg->srcMac, base, rem, idx);
/* The socket in REGISTER_ACK is the socket from which the REGISTER
* arrived. This is sent back to the sender so it knows what its public
* socket is. */
if (cmn->flags & N2N_FLAGS_SOCKET) {
retval += decode_sock(&(reg->sock), base, rem, idx);
}
return retval;
} }
int encode_REGISTER_SUPER_ACK( uint8_t * base,
size_t * idx,
const n2n_common_t * common,
const n2n_REGISTER_SUPER_ACK_t * reg )
{
int retval=0;
retval += encode_common( base, idx, common );
retval += encode_buf( base, idx, reg->cookie, N2N_COOKIE_SIZE );
retval += encode_mac( base, idx, reg->edgeMac );
retval += encode_uint16( base, idx, reg->lifetime );
retval += encode_sock( base, idx, &(reg->sock) );
retval += encode_uint8( base, idx, reg->num_sn );
if ( reg->num_sn > 0 )
{
/* We only support 0 or 1 at this stage */
retval += encode_sock( base, idx, &(reg->sn_bak) );
}
return retval; int encode_REGISTER_SUPER_ACK(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_REGISTER_SUPER_ACK_t *reg) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_buf(base, idx, reg->cookie, N2N_COOKIE_SIZE);
retval += encode_mac(base, idx, reg->edgeMac);
retval += encode_uint32(base, idx, reg->dev_addr.net_addr);
retval += encode_uint8(base, idx, reg->dev_addr.net_bitlen);
retval += encode_uint16(base, idx, reg->lifetime);
retval += encode_sock(base, idx, &(reg->sock));
retval += encode_uint8(base, idx, reg->num_sn);
if (reg->num_sn > 0) {
/* We only support 0 or 1 at this stage */
retval += encode_sock(base, idx, &(reg->sn_bak));
}
return retval;
} }
int decode_REGISTER_SUPER_ACK( n2n_REGISTER_SUPER_ACK_t * reg,
const n2n_common_t * cmn, /* info on how to interpret it */
const uint8_t * base,
size_t * rem,
size_t * idx )
{
size_t retval=0;
memset( reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t) ); int decode_REGISTER_SUPER_ACK(n2n_REGISTER_SUPER_ACK_t *reg,
retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx ); const n2n_common_t *cmn, /* info on how to interpret it */
retval += decode_mac( reg->edgeMac, base, rem, idx ); const uint8_t *base,
retval += decode_uint16( &(reg->lifetime), base, rem, idx ); size_t *rem,
size_t *idx) {
size_t retval = 0;
/* Socket is mandatory in this message type */ memset(reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
retval += decode_sock( &(reg->sock), base, rem, idx ); retval += decode_buf(reg->cookie, N2N_COOKIE_SIZE, base, rem, idx);
retval += decode_mac(reg->edgeMac, base, rem, idx);
retval += decode_uint32(&(reg->dev_addr.net_addr), base, rem, idx);
retval += decode_uint8(&(reg->dev_addr.net_bitlen), base, rem, idx);
retval += decode_uint16(&(reg->lifetime), base, rem, idx);
/* Following the edge socket are an array of backup supernodes. */ /* Socket is mandatory in this message type */
retval += decode_uint8( &(reg->num_sn), base, rem, idx ); retval += decode_sock(&(reg->sock), base, rem, idx);
if ( reg->num_sn > 0 )
{
/* We only support 0 or 1 at this stage */
retval += decode_sock( &(reg->sn_bak), base, rem, idx );
}
return retval; /* Following the edge socket are an array of backup supernodes. */
retval += decode_uint8(&(reg->num_sn), base, rem, idx);
if (reg->num_sn > 0) {
/* We only support 0 or 1 at this stage */
retval += decode_sock(&(reg->sn_bak), base, rem, idx);
}
return retval;
} }
int fill_sockaddr( struct sockaddr * addr, int fill_sockaddr( struct sockaddr * addr,
size_t addrlen, size_t addrlen,
const n2n_sock_t * sock ) const n2n_sock_t * sock )
@ -475,35 +480,36 @@ int decode_PACKET( n2n_PACKET_t * pkt,
return retval; return retval;
} }
int encode_PEER_INFO( uint8_t * base,
size_t * idx,
const n2n_common_t * common,
const n2n_PEER_INFO_t * pkt )
{
int retval=0;
retval += encode_common( base, idx, common );
retval += encode_uint16( base, idx, pkt->aflags );
retval += encode_mac( base, idx, pkt->mac );
retval += encode_sock( base, idx, &pkt->sock );
return retval; int encode_PEER_INFO(uint8_t *base,
size_t *idx,
const n2n_common_t *common,
const n2n_PEER_INFO_t *pkt) {
int retval = 0;
retval += encode_common(base, idx, common);
retval += encode_uint16(base, idx, pkt->aflags);
retval += encode_mac(base, idx, pkt->mac);
retval += encode_sock(base, idx, &pkt->sock);
return retval;
} }
int decode_PEER_INFO( n2n_PEER_INFO_t * pkt,
const n2n_common_t * cmn, /* info on how to interpret it */
const uint8_t * base,
size_t * rem,
size_t * idx )
{
size_t retval=0;
memset( pkt, 0, sizeof(n2n_PEER_INFO_t) );
retval += decode_uint16( &(pkt->aflags), base, rem, idx );
retval += decode_mac( pkt->mac, base, rem, idx );
retval += decode_sock( &pkt->sock, base, rem, idx );
return retval; int decode_PEER_INFO(n2n_PEER_INFO_t *pkt,
const n2n_common_t *cmn, /* info on how to interpret it */
const uint8_t *base,
size_t *rem,
size_t *idx) {
size_t retval = 0;
memset(pkt, 0, sizeof(n2n_PEER_INFO_t));
retval += decode_uint16(&(pkt->aflags), base, rem, idx);
retval += decode_mac(pkt->mac, base, rem, idx);
retval += decode_sock(&pkt->sock, base, rem, idx);
return retval;
} }
int encode_QUERY_PEER( uint8_t * base, int encode_QUERY_PEER( uint8_t * base,
size_t * idx, size_t * idx,
const n2n_common_t * common, const n2n_common_t * common,

15
win32/n2n_win32.h

@ -98,13 +98,14 @@ struct ip {
/* ************************************* */ /* ************************************* */
typedef struct tuntap_dev { typedef struct tuntap_dev {
HANDLE device_handle; HANDLE device_handle;
char *device_name; char *device_name;
char *ifName; char *ifName;
OVERLAPPED overlap_read, overlap_write; OVERLAPPED overlap_read, overlap_write;
uint8_t mac_addr[6]; n2n_mac_t mac_addr;
uint32_t ip_addr, device_mask; uint32_t ip_addr;
unsigned int mtu; uint32_t device_mask;
unsigned int mtu;
} tuntap_dev; } tuntap_dev;
#define index(a, b) strchr(a, b) #define index(a, b) strchr(a, b)

7
win32/winconfig.h

@ -1,8 +1,15 @@
/* winconfig.h. Win32 replacement for file generated from config.h.in by configure. */ /* winconfig.h. Win32 replacement for file generated from config.h.in by configure. */
/* OS name */ /* OS name */
#ifndef PACKAGE_OSNAME
#define PACKAGE_OSNAME N2N_OSNAME #define PACKAGE_OSNAME N2N_OSNAME
#endif
/* Define to the version of this package. */ /* Define to the version of this package. */
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION N2N_VERSION #define PACKAGE_VERSION N2N_VERSION
#endif
#ifndef GIT_RELEASE
#define GIT_RELEASE N2N_VERSION #define GIT_RELEASE N2N_VERSION
#endif

Loading…
Cancel
Save