Browse Source

Added DHCP function embedded in sn.

1. Automatically assign IP addresses to the edge through the DHCP function that comes with sn, the default IP address pool is 172.17.12.0/24.
2. The -d parameter is added to sn, and the IP address pool of the embedded DHCP can be customized.
3. Now edge does not need to add -a and -s parameters to automatically obtain the IP address.
4. The IP automatically obtained by the cross-community edge can be the same, because the communities are isolated from each other and do not interfere with each other.
5. On the management side of sn (127.0.0.1:5645), you can now view the IP address of the tutap adapter of each edge.
6. Fix many bugs that have a certain chance of causing memory leaks.
7. Note: This version is not fully compatible with the previous version.
pull/355/head
fengdaolong 4 years ago
parent
commit
92dfa67e22
  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 */
#ifdef WIN32
#include "win32/n2n_win32.h"
#ifdef _MSC_VER
#include "config.h" /* Visual C++ */
#else
@ -171,12 +169,13 @@ typedef struct ether_hdr ether_hdr_t;
#ifndef WIN32
typedef struct tuntap_dev {
int fd;
int if_idx;
uint8_t mac_addr[6];
uint32_t ip_addr, device_mask;
uint16_t mtu;
char dev_name[N2N_IFNAMSIZ];
int fd;
int if_idx;
n2n_mac_t mac_addr;
uint32_t ip_addr;
uint32_t device_mask;
uint16_t mtu;
char dev_name[N2N_IFNAMSIZ];
} tuntap_dev;
#define SOCKET int
@ -192,26 +191,31 @@ typedef char ipstr_t[32];
/** Common type used to hold stringified MAC addresses. */
#define N2N_MACSTR_SIZE 32
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 char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE];
typedef struct n2n_route {
in_addr_t net_addr;
int net_bitlen;
in_addr_t gateway;
in_addr_t net_addr;
uint8_t net_bitlen;
in_addr_t gateway;
} n2n_route_t;
typedef struct n2n_edge n2n_edge_t;
@ -253,8 +257,8 @@ typedef struct n2n_edge_callbacks {
typedef struct n2n_tuntap_priv_config {
char tuntap_dev_name[N2N_IFNAMSIZ];
char ip_mode[N2N_IF_MODE_SIZE];
char ip_addr[N2N_NETMASK_STR_SIZE];
char netmask[N2N_NETMASK_STR_SIZE];
dec_ip_str_t ip_addr;
dec_ip_str_t netmask;
char device_mac[N2N_MACNAMSIZ];
int mtu;
uint8_t got_s;
@ -267,30 +271,32 @@ typedef struct n2n_tuntap_priv_config {
/* *************************************************** */
typedef struct n2n_edge_conf {
n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES];
n2n_route_t *routes; /**< Networks to route through n2n */
n2n_community_t community_name; /**< The community. 16 full octets. */
uint8_t header_encryption; /**< Header encryption indicator. */
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 */
n2n_transform_t transop_id; /**< The transop to use. */
uint16_t compression; /**< Compress outgoing data packets before encryption */
uint16_t num_routes; /**< Number of routes in routes */
uint8_t dyn_ip_mode; /**< Interface IP address is dynamically allocated, eg. DHCP. */
uint8_t allow_routing; /**< Accept packet no to interface address. */
uint8_t drop_multicast; /**< Multicast ethernet addresses. */
uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */
uint8_t allow_p2p; /**< Allow P2P connection */
uint8_t sn_num; /**< Number of supernode addresses defined. */
uint8_t tos; /** TOS for sent packets */
char *encrypt_key;
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 local_port;
int mgmt_port;
n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES];
n2n_route_t *routes; /**< Networks to route through n2n */
n2n_community_t community_name; /**< The community. 16 full octets. */
uint8_t header_encryption; /**< Header encryption indicator. */
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 */
n2n_transform_t transop_id; /**< The transop to use. */
uint16_t compression; /**< Compress outgoing data packets before encryption */
uint16_t num_routes; /**< Number of routes in routes */
uint8_t tuntap_ip_mode; /**< Interface IP address allocated mode, eg. DHCP. */
uint8_t allow_routing; /**< Accept packet no to interface address. */
uint8_t drop_multicast; /**< Multicast ethernet addresses. */
uint8_t disable_pmtu_discovery; /**< Disable the Path MTU discovery. */
uint8_t allow_p2p; /**< Allow P2P connection */
uint8_t sn_num; /**< Number of supernode addresses defined. */
uint8_t tos; /** TOS for sent packets */
char *encrypt_key;
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 local_port;
int mgmt_port;
} n2n_edge_conf_t;
struct n2n_edge_stats {
uint32_t tx_p2p;
uint32_t rx_p2p;
@ -304,44 +310,45 @@ struct n2n_edge {
n2n_edge_conf_t conf;
/* Status */
uint8_t sn_idx; /**< Currently active supernode. */
uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */
size_t sup_attempts; /**< Number of remaining attempts to this supernode. */
tuntap_dev device; /**< All about the TUNTAP device */
n2n_trans_op_t transop; /**< The transop to use when encoding */
n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */
n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */
n2n_edge_callbacks_t cb; /**< API callbacks */
void *user_data; /**< Can hold user data */
uint64_t sn_last_valid_time_stamp;/*< last valid time stamp from supernode */
uint8_t sn_idx; /**< Currently active supernode. */
uint8_t sn_wait; /**< Whether we are waiting for a supernode response. */
size_t sup_attempts; /**< Number of remaining attempts to this supernode. */
tuntap_dev device; /**< All about the TUNTAP device */
n2n_trans_op_t transop; /**< The transop to use when encoding */
n2n_cookie_t last_cookie; /**< Cookie sent in last REGISTER_SUPER. */
n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */
n2n_edge_callbacks_t cb; /**< API callbacks */
void *user_data; /**< Can hold user data */
uint64_t sn_last_valid_time_stamp;/**< last valid time stamp from supernode */
/* Sockets */
n2n_sock_t supernode;
int udp_sock;
int udp_mgmt_sock; /**< socket for status info. */
int udp_mgmt_sock; /**< socket for status info. */
#ifndef SKIP_MULTICAST_PEERS_DISCOVERY
n2n_sock_t multicast_peer; /**< Multicast peer group (for local edges) */
int udp_multicast_sock; /**< socket for local multicast registrations. */
int multicast_joined; /**< 1 if the group has been joined.*/
n2n_sock_t multicast_peer; /**< Multicast peer group (for local edges) */
int udp_multicast_sock; /**< socket for local multicast registrations. */
int multicast_joined; /**< 1 if the group has been joined.*/
#endif
/* Peers */
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 * known_peers; /**< Edges we are connected to. */
struct peer_info * pending_peers; /**< Edges we have tried to register with. */
/* Timers */
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_sup; /**< Last time a packet arrived from supernode. */
time_t start_time; /**< For calculating uptime */
/* Statistics */
struct n2n_edge_stats stats;
/* Tuntap config */
n2n_tuntap_priv_config_t tuntap_priv_conf;
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_sup; /**< Last time a packet arrived from supernode. */
time_t start_time; /**< For calculating uptime */
struct n2n_edge_stats stats; /**< Statistics */
n2n_tuntap_priv_config_t tuntap_priv_conf; /**< Tuntap config */
};
typedef struct sn_stats
{
size_t errors; /* Number of errors encountered. */
@ -365,21 +372,21 @@ struct sn_community
UT_hash_handle hh; /* makes this structure hashable */
};
typedef struct n2n_sn
{
time_t start_time; /* Used to measure uptime. */
sn_stats_t stats;
int daemon; /* If non-zero then daemonise. */
uint16_t lport; /* Local UDP port to bind to. */
uint16_t mport; /* Management UDP port to bind to. */
int sock; /* Main socket for UDP traffic with edges. */
int mgmt_sock; /* management socket. */
typedef struct n2n_sn {
time_t start_time; /* Used to measure uptime. */
sn_stats_t stats;
int daemon; /* If non-zero then daemonise. */
uint16_t lport; /* Local UDP port to bind to. */
uint16_t mport; /* Management UDP port to bind to. */
int sock; /* Main socket for UDP traffic with edges. */
int mgmt_sock; /* management socket. */
n2n_ip_subnet_t dhcp_addr; /* Address range of dhcp service. */
#ifndef WIN32
uid_t userid;
gid_t groupid;
#endif
int lock_communities; /* If true, only loaded communities can be used. */
struct sn_community *communities;
int lock_communities; /* If true, only loaded communities can be used. */
struct sn_community *communities;
} n2n_sn_t;
/* ************************************** */
@ -426,6 +433,8 @@ void tuntap_get_address(struct tuntap_dev *tuntap);
/* Utils */
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);
int str2mac( uint8_t * outmac /* 6 bytes */, const char * s );
uint8_t is_multi_broadcast(const uint8_t * dest_mac);
@ -438,6 +447,7 @@ void print_edge_stats(const n2n_edge_t *eee);
/* Sockets */
char* sock_to_cstr( n2n_sock_str_t out,
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);
int sock_equal( const n2n_sock_t * a,
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);
/* 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_set_callbacks(n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks);
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
/* 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"

93
include/n2n_wire.h

@ -20,19 +20,10 @@
#define N2N_WIRE_H_
#include <stdlib.h>
#if defined(WIN32)
#include "win32/n2n_win32.h"
#if defined(__MINGW32__)
#include <stdint.h>
#endif /* #ifdef __MINGW32__ */
#else /* #if defined(WIN32) */
#ifndef _MSC_VER
/* Not included in Visual Studio 2008 */
#include <stdint.h>
#include <netinet/in.h>
#include <sys/socket.h> /* AF_INET and AF_INET6 */
#endif /* #if defined(WIN32) */
#endif
#define N2N_PKT_VERSION 2
#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 */
#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
{
n2n_ping=0, /* Not used */
@ -86,6 +84,12 @@ typedef enum n2n_pc
#define N2N_EINVAL -3
#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
{
uint8_t family; /* AF_INET or AF_INET6; or 0 if invalid */
@ -117,18 +121,18 @@ typedef struct n2n_common
typedef struct n2n_REGISTER
{
n2n_cookie_t cookie; /* Link REGISTER and REGISTER_ACK */
n2n_mac_t srcMac; /* MAC of registering party */
n2n_mac_t dstMac; /* MAC of target edge */
n2n_sock_t sock; /* REVISIT: unused? */
n2n_cookie_t cookie; /**< Link REGISTER and REGISTER_ACK */
n2n_mac_t srcMac; /**< MAC of registering party */
n2n_mac_t dstMac; /**< MAC of target edge */
n2n_sock_t sock; /**< REVISIT: unused? */
} n2n_REGISTER_t;
typedef struct n2n_REGISTER_ACK
{
n2n_cookie_t cookie; /* Return cookie from REGISTER */
n2n_mac_t srcMac; /* MAC of acknowledging party (supernode or edge) */
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_cookie_t cookie; /**< Return cookie from REGISTER */
n2n_mac_t srcMac; /**< MAC of acknowledging party (supernode or edge) */
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_REGISTER_ACK_t;
typedef struct n2n_PACKET
@ -141,30 +145,30 @@ typedef struct n2n_PACKET
} n2n_PACKET_t;
/* Linked with n2n_register_super in n2n_pc_t. Only from edge to supernode. */
typedef struct n2n_REGISTER_SUPER
{
n2n_cookie_t cookie; /* Link REGISTER_SUPER and REGISTER_SUPER_ACK */
n2n_mac_t edgeMac; /* MAC to register with edge sending socket */
n2n_auth_t auth; /* Authentication scheme and tokens */
typedef struct n2n_REGISTER_SUPER {
n2n_cookie_t cookie; /**< Link REGISTER_SUPER and REGISTER_SUPER_ACK */
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_REGISTER_SUPER_t;
/* Linked with n2n_register_super_ack in n2n_pc_t. Only from supernode to edge. */
typedef struct n2n_REGISTER_SUPER_ACK
{
n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */
n2n_mac_t edgeMac; /* MAC registered to edge sending socket */
uint16_t lifetime; /* How long the registration will live */
n2n_sock_t sock; /* Sending sockets associated with edgeMac */
/* The packet format provides additional supernode definitions here.
* uint8_t count, then for each count there is one
* n2n_sock_t.
*/
uint8_t num_sn; /* Number of supernodes that were send
typedef struct n2n_REGISTER_SUPER_ACK {
n2n_cookie_t cookie; /**< Return cookie from REGISTER_SUPER */
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 */
n2n_sock_t sock; /**< Sending sockets associated with edgeMac */
/** The packet format provides additional supernode definitions here.
* uint8_t count, then for each count there is one
* n2n_sock_t.
*/
uint8_t num_sn; /**< Number of supernodes that were send
* even if we cannot store them all. If
* 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;
@ -174,13 +178,14 @@ typedef struct n2n_REGISTER_SUPER_NAK
n2n_cookie_t cookie; /* Return cookie from REGISTER_SUPER */
} n2n_REGISTER_SUPER_NAK_t;
typedef struct n2n_PEER_INFO
{
uint16_t aflags;
n2n_mac_t mac;
n2n_sock_t sock;
typedef struct n2n_PEER_INFO {
uint16_t aflags;
n2n_mac_t mac;
n2n_sock_t sock;
} n2n_PEER_INFO_t;
typedef struct n2n_QUERY_PEER
{
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];
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);
break;
}
@ -818,7 +818,6 @@ int main(int argc, char* argv[]) {
#else
snprintf(ec.tuntap_dev_name, sizeof(ec.tuntap_dev_name), "edge0");
#endif
snprintf(ec.ip_mode, sizeof(ec.ip_mode), "static");
snprintf(ec.netmask, sizeof(ec.netmask), "255.255.255.0");
if((argc >= 2) && (argv[1][0] != '-')) {
@ -861,21 +860,6 @@ int main(int argc, char* argv[]) {
/* Random 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
/* If running suid root then we need to setuid before using the force. */
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))
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)
exit(1);
if((eee = edge_init(&tuntap, &conf, &rc)) == NULL) {
if((eee = edge_init(&conf, &rc)) == NULL) {
traceEvent(TRACE_ERROR, "Failed in edge_init");
exit(1);
}
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
if(ec.daemon) {
if(eee->tuntap_priv_conf.daemon) {
setUseSyslog(1); /* traceEvent output now goes to syslog. */
daemonize();
}
@ -919,13 +937,13 @@ int main(int argc, char* argv[]) {
#endif
#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",
(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. */
if((setgid(ec.groupid) != 0)
|| (setuid(ec.userid) != 0)) {
if((setgid(eee->tuntap_priv_conf.groupid) != 0)
|| (setuid(eee->tuntap_priv_conf.userid) != 0)) {
traceEvent(TRACE_ERROR, "Unable to drop privileges [%u/%s]", errno, strerror(errno));
exit(1);
}
@ -961,10 +979,8 @@ int main(int argc, char* argv[]) {
/* Cleanup */
edge_term(eee);
edge_term_conf(&conf);
tuntap_close(&tuntap);
if(conf.encrypt_key) free(conf.encrypt_key);
edge_term_conf(&eee->conf);
tuntap_close(&eee->device);
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.
*/
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_edge_t *eee = calloc(1, sizeof(n2n_edge_t));
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
memcpy(&eee->conf, conf, sizeof(*conf));
memcpy(&eee->device, dev, sizeof(*dev));
eee->start_time = time(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
#endif
for(i=0; i<conf->sn_num; ++i)
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i]));
for(i=0; i<eee->conf.sn_num; ++i)
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (eee->conf.sn_ip_array[i]));
/* 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 */
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 */
if(conf->header_encryption == HEADER_ENCRYPTION_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)
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");
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");
goto edge_init_error;
}
@ -389,7 +388,7 @@ static const int definitely_from_supernode = 1;
* and verify it (and also update, if applicable).
*/
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 * 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 n2n_mac_t null_mac = {0, 0, 0, 0, 0, 0};
static const n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
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.
*/
@ -736,41 +735,44 @@ static void check_join_multicast_group(n2n_edge_t *eee) {
/** 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) {
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
size_t idx;
/* ssize_t sent; */
n2n_common_t cmn;
n2n_REGISTER_SUPER_t reg;
n2n_sock_str_t sockbuf;
uint8_t pktbuf[N2N_PKT_BUF_SIZE] = {0};
size_t idx;
/* ssize_t sent; */
n2n_common_t cmn;
n2n_REGISTER_SUPER_t reg;
n2n_sock_str_t sockbuf;
memset(&cmn, 0, sizeof(cmn));
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);
memset(&cmn, 0, sizeof(cmn));
memset(&reg, 0, sizeof(reg));
for (idx = 0; (sn_idx==0) && (idx < N2N_COOKIE_SIZE); ++idx)
eee->last_cookie[idx] = n2n_rand() % 0xff;
cmn.ttl = N2N_DEFAULT_TTL;
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);
reg.auth.scheme=0; /* No auth yet */
for (idx = 0; (sn_idx==0) && (idx < N2N_COOKIE_SIZE); ++idx)
eee->last_cookie[idx] = n2n_rand() % 0xff;
idx=0;
encode_mac(reg.edgeMac, &idx, eee->device.mac_addr);
memcpy(reg.cookie, eee->last_cookie, N2N_COOKIE_SIZE);
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;
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, &reg);
idx = 0;
encode_mac(reg.edgeMac, &idx, eee->device.mac_addr);
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
sock_to_cstr(sockbuf, supernode));
idx = 0;
encode_REGISTER_SUPER(pktbuf, &idx, &cmn, &reg);
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));
traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s",
sock_to_cstr(sockbuf, supernode));
/* 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.
*/
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;
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. */
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_sock_str_t sockbuf1;
@ -1750,14 +1752,14 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
* to double check this.
*/
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);
/* NOTE: only ACK to peers */
send_register_ack(eee, orig_sender, &reg);
}
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),
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:
{
// 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;
if (bTrace)
{
@ -1801,7 +1809,6 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
bTrace = 0;
}
n2n_REGISTER_SUPER_ACK_t ra;
if(eee->sn_wait)
{
@ -1839,6 +1846,20 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
eee->last_sup = now;
eee->sn_wait=0;
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)
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.");
}
break;
} case MSG_TYPE_PEER_INFO: {
}
case MSG_TYPE_PEER_INFO: {
n2n_PEER_INFO_t pi;
struct peer_info * scan;
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));
}
if(eee->conf.dyn_ip_mode &&
if((eee->conf.tuntap_ip_mode == TUNTAP_IP_MODE_DHCP) &&
((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) {
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) {
memset(conf, 0, sizeof(*conf));
conf->local_port = 0 /* any port */;
conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */
conf->transop_id = N2N_TRANSFORM_ID_NULL;
conf->header_encryption = HEADER_ENCRYPTION_NONE;
conf->compression = N2N_COMPRESSION_ID_NONE;
conf->drop_multicast = 1;
conf->allow_p2p = 1;
conf->disable_pmtu_discovery = 1;
conf->register_interval = REGISTER_SUPER_INTERVAL_DFL;
if(getenv("N2N_KEY")) {
conf->encrypt_key = strdup(getenv("N2N_KEY"));
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
}
memset(conf, 0, sizeof(*conf));
conf->local_port = 0 /* any port */;
conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */
conf->transop_id = N2N_TRANSFORM_ID_NULL;
conf->header_encryption = HEADER_ENCRYPTION_NONE;
conf->compression = N2N_COMPRESSION_ID_NONE;
conf->drop_multicast = 1;
conf->allow_p2p = 1;
conf->disable_pmtu_discovery = 1;
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"));
conf->transop_id = N2N_TRANSFORM_ID_TWOFISH;
}
}
/* ************************************** */
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);
/* Init edge */
if((eee = edge_init(&tuntap, &conf, &rv)) == NULL)
if((eee = edge_init(&conf, &rv)) == NULL)
goto quick_edge_init_end;
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
conf.disable_pmtu_discovery = 1; // Whether to disable the path MTU discovery
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.local_port = 0; // What port to use (0 = any port)
conf.mgmt_port = N2N_EDGE_MGMT_PORT; // Edge management port (5644 by default)
@ -59,7 +59,7 @@ int main()
return -1;
}
eee = edge_init(&tuntap, &conf, &rc);
eee = edge_init(&conf, &rc);
if (eee == NULL)
{
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);
}
/** 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,
@ -231,21 +254,21 @@ char* msg_type2str(uint16_t msg_type) {
/* *********************************************** */
void hexdump(const uint8_t * buf, size_t len)
{
size_t i;
if(0 == len) { return; }
void hexdump(const uint8_t *buf, size_t len) {
size_t i;
for(i=0; i<len; i++)
{
if((i > 0) &&((i % 16) == 0)) { printf("\n"); }
printf("%02X ", buf[i] & 0xFF);
}
if (0 == len) { return; }
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() {
@ -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. */
int sock_equal(const n2n_sock_t * a,
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) {
time_t clock;
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. */
static void help() {
print_n2n_version();
printf("supernode <config file> (see supernode.conf)\n"
"or\n"
);
printf("supernode ");
printf("-l <local port> ");
printf("-c <path> ");
print_n2n_version();
printf("supernode <config file> (see supernode.conf)\n"
"or\n"
);
printf("supernode ");
printf("-l <local port> ");
printf("-c <path> ");
#if defined(N2N_HAVE_DAEMON)
printf("[-f] ");
printf("[-f] ");
#endif
#ifndef WIN32
printf("[-u <uid> -g <gid>] ");
printf("[-u <uid> -g <gid>] ");
#endif /* ifndef WIN32 */
printf("[-t <mgmt port>] ");
printf("[-v] ");
printf("\n\n");
printf("[-t <mgmt port>] ");
printf("[-d <net/bit>] ");
printf("[-v] ");
printf("\n\n");
printf("-l <port>\tSet UDP main listen port to <port>\n");
printf("-c <path>\tFile containing the allowed communities.\n");
printf("-l <port> | Set UDP main listen port to <port>\n");
printf("-c <path> | File containing the allowed communities.\n");
#if defined(N2N_HAVE_DAEMON)
printf("-f \tRun in foreground.\n");
printf("-f | Run in foreground.\n");
#endif /* #if defined(N2N_HAVE_DAEMON) */
#ifndef WIN32
printf("-u <UID>\tUser ID (numeric) to use when privileges are dropped.\n");
printf("-g <GID>\tGroup 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> | Group ID (numeric) to use when privileges are dropped.\n");
#endif /* ifndef WIN32 */
printf("-t <port>\tManagement UDP Port (for multiple supernodes on a machine).\n");
printf("-v \tIncrease verbosity. Can be used multiple times.\n");
printf("-h \tThis help message.\n");
printf("\n");
printf("-t <port> | Management UDP Port (for multiple supernodes on a machine).\n");
printf("-d <net/bit> | Subnet that provides dhcp service for edge. eg. -d 172.17.12.0/24\n");
printf("-v | Increase verbosity. Can be used multiple times.\n");
printf("-h | This help message.\n");
printf("\n");
exit(1);
exit(1);
}
/* *************************************************** */
static int setOption(int optkey, char *_optarg, n2n_sn_t *sss) {
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
switch(optkey) {
case 'l': /* local-port */
sss->lport = atoi(_optarg);
break;
case 't': /* mgmt-port */
sss->mport = atoi(_optarg);
break;
//traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : "");
switch (optkey) {
case 'l': /* local-port */
sss->lport = atoi(_optarg);
break;
case 't': /* mgmt-port */
sss->mport = atoi(_optarg);
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
case 'u': /* unprivileged uid */
sss->userid = atoi(_optarg);
break;
case 'u': /* unprivileged uid */
sss->userid = atoi(_optarg);
break;
case 'g': /* unprivileged uid */
sss->groupid = atoi(_optarg);
break;
case 'g': /* unprivileged uid */
sss->groupid = atoi(_optarg);
break;
#endif
case 'c': /* community file */
load_allowed_sn_community(sss, _optarg);
break;
case 'c': /* community file */
load_allowed_sn_community(sss, _optarg);
break;
case 'f': /* foreground */
sss->daemon = 0;
break;
case 'f': /* foreground */
sss->daemon = 0;
break;
case 'h': /* help */
help();
break;
case 'h': /* help */
help();
break;
case 'v': /* verbose */
setTraceLevel(getTraceLevel() + 1);
break;
case 'v': /* verbose */
setTraceLevel(getTraceLevel() + 1);
break;
default:
traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char)optkey);
return(-1);
}
default:
traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored.", (char) optkey);
return (-1);
}
return(0);
return (0);
}
/* *********************************************** */
static const struct option long_options[] = {
{ "communities", required_argument, NULL, 'c' },
{ "foreground", no_argument, NULL, 'f' },
{ "local-port", required_argument, NULL, 'l' },
{ "mgmt-port", required_argument, NULL, 't' },
{ "help" , no_argument, NULL, 'h' },
{ "verbose", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
{"communities", required_argument, NULL, 'c'},
{"foreground", no_argument, NULL, 'f'},
{"local-port", required_argument, NULL, 'l'},
{"mgmt-port", required_argument, NULL, 't'},
{"dhcp", required_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"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) {
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)) != '?') {
if(c == 255) break;
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 int update_edge(n2n_sn_t *sss,
const n2n_mac_t edgeMac,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
time_t now);
@ -204,23 +204,25 @@ static int try_broadcast(n2n_sn_t * sss,
/** Initialise the supernode structure */
int sn_init(n2n_sn_t *sss)
{
int sn_init(n2n_sn_t *sss) {
#ifdef WIN32
initWin32();
initWin32();
#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->lport = N2N_SN_LPORT_DEFAULT;
sss->mport = N2N_SN_MGMT_PORT;
sss->sock = -1;
sss->mgmt_sock = -1;
sss->daemon = 1; /* By defult run as a daemon. */
sss->lport = N2N_SN_LPORT_DEFAULT;
sss->mport = N2N_SN_MGMT_PORT;
sss->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
@ -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
* supernode. */
static int update_edge(n2n_sn_t *sss,
const n2n_mac_t edgeMac,
const n2n_REGISTER_SUPER_t* reg,
struct sn_community *comm,
const n2n_sock_t *sender_sock,
time_t now)
{
macstr_t mac_buf;
n2n_sock_str_t sockbuf;
struct peer_info *scan;
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]",
macaddr_str(mac_buf, edgeMac),
sock_to_cstr(sockbuf, sender_sock));
HASH_FIND_PEER(comm->edges, edgeMac, scan);
if (NULL == scan)
{
/* Not known */
scan = (struct peer_info *)calloc(1,
sizeof(struct peer_info)); /* deallocated in purge_expired_registrations */
memcpy(&(scan->mac_addr), edgeMac, sizeof(n2n_mac_t));
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
scan->last_valid_time_stamp = initial_time_stamp ();
time_t now) {
macstr_t mac_buf;
n2n_sock_str_t sockbuf;
struct peer_info *scan;
traceEvent(TRACE_DEBUG, "update_edge for %s [%s]",
macaddr_str(mac_buf, reg->edgeMac),
sock_to_cstr(sockbuf, sender_sock));
HASH_FIND_PEER(comm->edges, reg->edgeMac, scan);
if (NULL == scan) {
/* Not known */
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;
scan->dev_addr.net_bitlen = reg->dev_addr.net_bitlen;
memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t));
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",
macaddr_str(mac_buf, 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));
static signed int peer_tap_ip_sort(struct peer_info *a, struct peer_info *b) {
uint32_t a_host_id = a->dev_addr.net_addr & (~bitlen2mask(a->dev_addr.net_bitlen));
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);
}
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;
return 0;
/** The IP address assigned to the edge by the DHCP function of sn. */
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
@ -409,89 +451,89 @@ static int process_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf,
size_t mgmt_size,
time_t now)
{
char resbuf[N2N_SN_PKTBUF_SIZE];
size_t ressize = 0;
uint32_t num_edges = 0;
uint32_t num = 0;
struct sn_community *community, *tmp;
struct peer_info * peer, *tmpPeer;
macstr_t mac_buf;
n2n_sock_str_t sockbuf;
traceEvent(TRACE_DEBUG, "process_mgmt");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"----------------\n");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"uptime %lu\n", (now - sss->start_time));
HASH_ITER(hh, sss->communities, community, tmp)
{
num_edges += HASH_COUNT(community->edges);
}
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"edges %u\n",
num_edges);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"errors %u\n",
(unsigned int)sss->stats.errors);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_sup %u\n",
(unsigned int)sss->stats.reg_super);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_nak %u\n",
(unsigned int)sss->stats.reg_super_nak);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"fwd %u\n",
(unsigned int)sss->stats.fwd);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"broadcast %u\n",
(unsigned int)sss->stats.broadcast);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"last fwd %lu sec ago\n",
(long unsigned int)(now - sss->stats.last_fwd));
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"last reg %lu sec ago\n",
(long unsigned int)(now - sss->stats.last_reg_super));
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"cur_cmnts %u\n", HASH_COUNT(sss->communities));
HASH_ITER(hh, sss->communities, community, tmp) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"community: %s\n", community->community);
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize);
ressize = 0;
num = 0;
HASH_ITER(hh, community->edges, peer, tmpPeer) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"\t[id: %u][MAC: %s][edge: %s][last seen: %lu sec ago]\n",
++num, macaddr_str(mac_buf, peer->mac_addr),
sock_to_cstr(sockbuf, &(peer->sock)), now-peer->last_seen);
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize);
ressize = 0;
}
}
ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize,
"\n");
sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize);
return 0;
time_t now) {
char resbuf[N2N_SN_PKTBUF_SIZE];
size_t ressize = 0;
uint32_t num_edges = 0;
uint32_t num = 0;
struct sn_community *community, *tmp;
struct peer_info *peer, *tmpPeer;
macstr_t mac_buf;
n2n_sock_str_t sockbuf;
dec_ip_bit_str_t ip_bit_str = {'\0'};
traceEvent(TRACE_DEBUG, "process_mgmt");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"\tid tun_tap MAC edge last_seen\n");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"-------------------------------------------------------------------------------------\n");
HASH_ITER(hh, sss->communities, community, tmp) {
num_edges += HASH_COUNT(community->edges);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"community: %s\n", community->community);
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
ressize = 0;
num = 0;
HASH_ITER(hh, community->edges, peer, tmpPeer) {
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"\t%-4u %-18s %-17s %-21s %lu\n",
++num, ip_subnet_to_str(ip_bit_str, &peer->dev_addr),
macaddr_str(mac_buf, peer->mac_addr),
sock_to_cstr(sockbuf, &(peer->sock)), now - peer->last_seen);
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
ressize = 0;
}
}
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"-------------------------------------------------------------------------------------\n");
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"uptime %lu | ", (now - sss->start_time));
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"edges %u | ",
num_edges);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_sup %u | ",
(unsigned int) sss->stats.reg_super);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"reg_nak %u | ",
(unsigned int) sss->stats.reg_super_nak);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"errors %u \n",
(unsigned int) sss->stats.errors);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"fwd %u | ",
(unsigned int) sss->stats.fwd);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"broadcast %u | ",
(unsigned int) sss->stats.broadcast);
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"cur_cmnts %u\n", HASH_COUNT(sss->communities));
ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize,
"last fwd %lu sec ago\n",
(long unsigned int) (now - sss->stats.last_fwd));
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));
sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize);
return 0;
}
static int sendto_mgmt(n2n_sn_t *sss,
const struct sockaddr_in *sender_sock,
const uint8_t *mgmt_buf,
@ -528,6 +570,7 @@ static int process_udp(n2n_sn_t * sss,
char buf[32];
struct sn_community *comm, *tmp;
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]",
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;
uint8_t ackbuf[N2N_SN_PKTBUF_SIZE];
size_t encx=0;
n2n_ip_subnet_t ipaddr;
memset(&ack, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
/* Edge requesting registration with us. */
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.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.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);
ack.num_sn=0; /* No backup */
memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t));
traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]",
macaddr_str(mac_buf, reg.edgeMac),
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);

260
src/wire.c

@ -289,130 +289,135 @@ int decode_REGISTER( n2n_REGISTER_t * reg,
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,
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 );
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_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) );
retval += decode_buf( reg->cookie, N2N_COOKIE_SIZE, base, rem, idx );
retval += decode_mac( reg->edgeMac, base, rem, idx );
retval += decode_uint16( &(reg->lifetime), base, rem, idx );
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;
/* Socket is mandatory in this message type */
retval += decode_sock( &(reg->sock), base, rem, idx );
memset(reg, 0, sizeof(n2n_REGISTER_SUPER_ACK_t));
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. */
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 );
}
/* Socket is mandatory in this message type */
retval += decode_sock(&(reg->sock), 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,
size_t addrlen,
const n2n_sock_t * sock )
@ -475,35 +480,36 @@ int decode_PACKET( n2n_PACKET_t * pkt,
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,
size_t * idx,
const n2n_common_t * common,

15
win32/n2n_win32.h

@ -98,13 +98,14 @@ struct ip {
/* ************************************* */
typedef struct tuntap_dev {
HANDLE device_handle;
char *device_name;
char *ifName;
OVERLAPPED overlap_read, overlap_write;
uint8_t mac_addr[6];
uint32_t ip_addr, device_mask;
unsigned int mtu;
HANDLE device_handle;
char *device_name;
char *ifName;
OVERLAPPED overlap_read, overlap_write;
n2n_mac_t mac_addr;
uint32_t ip_addr;
uint32_t device_mask;
unsigned int mtu;
} tuntap_dev;
#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. */
/* OS name */
#ifndef PACKAGE_OSNAME
#define PACKAGE_OSNAME N2N_OSNAME
#endif
/* Define to the version of this package. */
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION N2N_VERSION
#endif
#ifndef GIT_RELEASE
#define GIT_RELEASE N2N_VERSION
#endif

Loading…
Cancel
Save