diff --git a/include/n2n.h b/include/n2n.h index ccabd0a..8b2836f 100644 --- a/include/n2n.h +++ b/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; + 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 */ + 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 */ + 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; + + 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); diff --git a/include/n2n_define.h b/include/n2n_define.h index 4d3c48b..86d1af4 100644 --- a/include/n2n_define.h +++ b/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" diff --git a/include/n2n_wire.h b/include/n2n_wire.h index 7cd0e41..e5c1ebd 100644 --- a/include/n2n_wire.h +++ b/include/n2n_wire.h @@ -20,19 +20,10 @@ #define N2N_WIRE_H_ #include - -#if defined(WIN32) -#include "win32/n2n_win32.h" - -#if defined(__MINGW32__) +#ifndef _MSC_VER +/* Not included in Visual Studio 2008 */ #include -#endif /* #ifdef __MINGW32__ */ - -#else /* #if defined(WIN32) */ -#include -#include -#include /* 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 +#include /* 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 +/* 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 */ + 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; diff --git a/src/edge.c b/src/edge.c index 5681df8..d874c43 100644 --- a/src/edge.c +++ b/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); } diff --git a/src/edge_utils.c b/src/edge_utils.c index 90ea8cb..377afce 100644 --- a/src/edge_utils.c +++ b/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; isn_num; ++i) - traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i])); + for(i=0; iconf.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(®, 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(®, 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, ®); + 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, ®); - 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, ®); } 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)); + 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->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; - } + 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); diff --git a/src/example_edge_embed.c b/src/example_edge_embed.c index ac809d5..b26b3d4 100644 --- a/src/example_edge_embed.c +++ b/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); diff --git a/src/n2n.c b/src/n2n.c index 7c8109e..4c877e6 100644 --- a/src/n2n.c +++ b/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; +void hexdump(const uint8_t *buf, size_t len) { + size_t i; - if(0 == len) { return; } + if (0 == len) { return; } - for(i=0; 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() { @@ -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; diff --git a/src/sn.c b/src/sn.c index 4087152..8724d5d 100644 --- a/src/sn.c +++ b/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(); + print_n2n_version(); - printf("supernode (see supernode.conf)\n" - "or\n" - ); - printf("supernode "); - printf("-l "); - printf("-c "); + printf("supernode (see supernode.conf)\n" + "or\n" + ); + printf("supernode "); + printf("-l "); + printf("-c "); #if defined(N2N_HAVE_DAEMON) - printf("[-f] "); + printf("[-f] "); #endif #ifndef WIN32 - printf("[-u -g ] "); + printf("[-u -g ] "); #endif /* ifndef WIN32 */ - printf("[-t ] "); - printf("[-v] "); - printf("\n\n"); + printf("[-t ] "); + printf("[-d ] "); + printf("[-v] "); + printf("\n\n"); - printf("-l \tSet UDP main listen port to \n"); - printf("-c \tFile containing the allowed communities.\n"); + printf("-l | Set UDP main listen port to \n"); + printf("-c | 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 \tUser ID (numeric) to use when privileges are dropped.\n"); - printf("-g \tGroup ID (numeric) to use when privileges are dropped.\n"); + printf("-u | User ID (numeric) to use when privileges are dropped.\n"); + printf("-g | Group ID (numeric) to use when privileges are dropped.\n"); #endif /* ifndef WIN32 */ - printf("-t \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 | Management UDP Port (for multiple supernodes on a machine).\n"); + printf("-d | 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 : ""); + //traceEvent(TRACE_NORMAL, "Option %c = %s", optkey, _optarg ? _optarg : ""); - switch(optkey) { - case 'l': /* local-port */ - sss->lport = atoi(_optarg); - break; + switch (optkey) { + case 'l': /* local-port */ + sss->lport = atoi(_optarg); + break; - case 't': /* mgmt-port */ - sss->mport = 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); diff --git a/src/sn_utils.c b/src/sn_utils.c index e607839..d14fa54 100644 --- a/src/sn_utils.c +++ b/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; + 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)); + 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, edgeMac, scan); + HASH_FIND_PEER(comm->edges, reg->edgeMac, scan); - if (NULL == scan) - { - /* Not known */ + if (NULL == scan) { + /* 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), edgeMac, sizeof(n2n_mac_t)); - memcpy(&(scan->sock), sender_sock, sizeof(n2n_sock_t)); - scan->last_valid_time_stamp = initial_time_stamp (); + 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); + 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)); + 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, 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)); - } - } + 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; + scan->last_seen = now; + return 0; } + +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); +} + + +/** 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; + 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"); + traceEvent(TRACE_DEBUG, "process_mgmt"); - ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "----------------\n"); + 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; - ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "uptime %lu\n", (now - sss->start_time)); + 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); - HASH_ITER(hh, sss->communities, community, tmp) - { - 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, + "-------------------------------------------------------------------------------------\n"); - ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, - "edges %u\n", - num_edges); + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "uptime %lu | ", (now - sss->start_time)); - 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, + "edges %u | ", + num_edges); - 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_sup %u | ", + (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, + "reg_nak %u | ", + (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, + "errors %u \n", + (unsigned int) sss->stats.errors); - 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, + "fwd %u | ", + (unsigned int) sss->stats.fwd); - 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, + "broadcast %u | ", + (unsigned int) sss->stats.broadcast); - 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)); - 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; + ressize += snprintf(resbuf + ressize, N2N_SN_PKTBUF_SIZE - ressize, + "last fwd %lu sec ago\n", + (long unsigned int) (now - sss->stats.last_fwd)); - 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); + 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); - ressize = 0; - } - } + sendto_mgmt(sss, sender_sock, (const uint8_t *) resbuf, ressize); - ressize += snprintf(resbuf+ressize, N2N_SN_PKTBUF_SIZE-ressize, - "\n"); - sendto_mgmt(sss, sender_sock, (const uint8_t *)resbuf, ressize); - - return 0; + 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, ®, comm, &(ack.sock), now); + } encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); diff --git a/src/wire.c b/src/wire.c index 7febcc4..a23d47b 100644 --- a/src/wire.c +++ b/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 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; } -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) ); - } +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); - 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 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 ); - } +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); - 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 (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, diff --git a/win32/n2n_win32.h b/win32/n2n_win32.h index bd21791..60b330f 100644 --- a/win32/n2n_win32.h +++ b/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) diff --git a/win32/winconfig.h b/win32/winconfig.h index 3a8cea0..c206f13 100644 --- a/win32/winconfig.h +++ b/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 +