Skip to content

Commit

Permalink
Add the callbacks API
Browse files Browse the repository at this point in the history
Callbacks allow n2n API users to extend n2n without modifying the upstream code. This also allows us
to move the hin2n code, which is specific of android, out of the n2n repository.
  • Loading branch information
emanuele-f committed Jun 30, 2020
1 parent c6b7b67 commit 346631f
Showing 2 changed files with 84 additions and 67 deletions.
37 changes: 35 additions & 2 deletions include/n2n.h
Original file line number Diff line number Diff line change
@@ -215,6 +215,36 @@ typedef struct n2n_route {
in_addr_t gateway;
} n2n_route_t;

typedef struct n2n_edge n2n_edge_t; /* Opaque, see edge_utils.c */

/* *************************************************** */

typedef enum {
N2N_ACCEPT = 0,
N2N_DROP = 1
} n2n_verdict;

/* *************************************************** */

/* Callbacks allow external programs to attach functions in response to
* N2N events. */
typedef struct n2n_edge_callbacks {
/* The supernode registration has been updated */
void (*sn_registration_updated)(n2n_edge_t *eee, time_t now, const n2n_sock_t *sn);

/* A packet has been received from a peer. N2N_DROP can be returned to
* drop the packet. The packet payload can be modified. */
n2n_verdict (*packet_from_peer)(n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size);

/* A packet has been received from the TAP interface. N2N_DROP can be
* returned to drop the packet. The packet payload can be modified. */
n2n_verdict (*packet_from_tap)(n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size);

void (*ip_address_changed)(n2n_edge_t *eee, uint32_t old_ip, uint32_t new_ip);
} n2n_edge_callbacks_t;

/* *************************************************** */

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 */
@@ -238,8 +268,6 @@ typedef struct n2n_edge_conf {
int mgmt_port;
} n2n_edge_conf_t;

typedef struct n2n_edge n2n_edge_t; /* Opaque, see edge_utils.c */

typedef struct sn_stats
{
size_t errors; /* Number of errors encountered. */
@@ -351,6 +379,11 @@ 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);
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);
void* edge_get_userdata(n2n_edge_t *eee);
void edge_send_packet2net(n2n_edge_t *eee, uint8_t *tap_pkt, size_t len);
void edge_read_from_tap(n2n_edge_t *eee);
int run_edge_loop(n2n_edge_t *eee, int *keep_running);
int quick_edge_init(char *device_name, char *community_name,
char *encrypt_key, char *device_mac,
114 changes: 49 additions & 65 deletions src/edge_utils.c
Original file line number Diff line number Diff line change
@@ -43,12 +43,6 @@ static void check_known_peer_sock_change(n2n_edge_t * eee,

/* ************************************** */

#ifdef __ANDROID_NDK__
#include "../android/edge_android.c"
#endif

/* ************************************** */

int edge_verify_conf(const n2n_edge_conf_t *conf) {
if(conf->community_name[0] == 0)
return(-1);
@@ -89,7 +83,9 @@ struct n2n_edge {
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_route_t *sn_route_to_clean; /**< Supernode route to clean */
n2n_edge_callbacks_t cb; /**< API callbacks */
void *user_data; /**< Can hold user data */

/* Sockets */
n2n_sock_t supernode;
@@ -102,11 +98,6 @@ struct n2n_edge {
int multicast_joined; /**< 1 if the group has been joined.*/
#endif

#ifdef __ANDROID_NDK__
uint32_t gateway_ip; /**< The IP address of the gateway */
n2n_mac_t gateway_mac; /**< The MAC address of the gateway */
#endif

/* Peers */
struct peer_info * known_peers; /**< Edges we are connected to. */
struct peer_info * pending_peers; /**< Edges we have tried to register with. */
@@ -123,6 +114,24 @@ struct n2n_edge {

/* ************************************** */

void edge_set_callbacks(n2n_edge_t *eee, const n2n_edge_callbacks_t *callbacks) {
memcpy(&eee->cb, callbacks, sizeof(n2n_edge_callbacks_t));
}

/* ************************************** */

void edge_set_userdata(n2n_edge_t *eee, void *user_data) {
eee->user_data = user_data;
}

/* ************************************** */

void* edge_get_userdata(n2n_edge_t *eee) {
return(eee->user_data);
}

/* ************************************** */

const char* transop_str(enum n2n_transform tr) {
switch(tr) {
case N2N_TRANSFORM_ID_NULL: return("null");
@@ -254,11 +263,9 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
rc = n2n_transop_cc20_init(&eee->conf, &eee->transop);
break;
#endif
#ifndef __ANDROID_NDK__
case N2N_TRANSFORM_ID_SPECK:
rc = n2n_transop_speck_init(&eee->conf, &eee->transop);
break;
#endif
default:
rc = n2n_transop_null_init(&eee->conf, &eee->transop);
}
@@ -909,17 +916,6 @@ static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) {

traceEvent(TRACE_WARNING, "Supernode not responding, now trying %s", supernode_ip(eee));

#ifdef __ANDROID_NDK__
int change = 0;
pthread_mutex_lock(&g_status->mutex);
change = g_status->running_status == EDGE_STAT_SUPERNODE_DISCONNECT ? 0 : 1;
g_status->running_status = EDGE_STAT_SUPERNODE_DISCONNECT;
pthread_mutex_unlock(&g_status->mutex);
if (change) {
g_status->report_edge_status();
}
#endif /* #ifdef __ANDROID_NDK__ */

eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS;
}
else
@@ -1098,18 +1094,13 @@ static int handle_PACKET(n2n_edge_t * eee,
}
}

#ifdef __ANDROID_NDK__
if((psize >= 36) &&
(ntohs(*((uint16_t*)&eth_payload[12])) == 0x0806) && /* ARP */
(ntohs(*((uint16_t*)&eth_payload[20])) == 0x0002) && /* REPLY */
(!memcmp(&eth_payload[28], &eee->gateway_ip, 4))) { /* From gateway */
memcpy(eee->gateway_mac, &eth_payload[22], 6);

traceEvent(TRACE_INFO, "Gateway MAC: %02X:%02X:%02X:%02X:%02X:%02X",
eee->gateway_mac[0], eee->gateway_mac[1], eee->gateway_mac[2],
eee->gateway_mac[3], eee->gateway_mac[4], eee->gateway_mac[5]);
}
#endif
if(eee->cb.packet_from_peer) {
if(eee->cb.packet_from_peer(eee, orig_sender, eth_payload, eth_size) == N2N_DROP) {
traceEvent(TRACE_DEBUG, "DROP packet %u", (unsigned int)eth_size);

return(0);
}
}

/* Write ethernet packet to tap device. */
traceEvent(TRACE_DEBUG, "sending to TAP %u", (unsigned int)eth_size);
@@ -1386,7 +1377,7 @@ static int send_packet(n2n_edge_t * eee,
/* ************************************** */

/** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */
static void send_packet2net(n2n_edge_t * eee,
void edge_send_packet2net(n2n_edge_t * eee,
uint8_t *tap_pkt, size_t len) {
ipstr_t ip_buf;
n2n_mac_t destMac;
@@ -1400,13 +1391,6 @@ static void send_packet2net(n2n_edge_t * eee,

ether_hdr_t eh;

#ifdef __ANDROID_NDK__
if(!memcmp(tap_pkt, null_mac, 6)) {
traceEvent(TRACE_DEBUG, "Detected packet for the gateway");
memcpy(tap_pkt, eee->gateway_mac, 6);
}
#endif

/* tap_pkt is not aligned so we have to copy to aligned memory */
memcpy(&eh, tap_pkt, sizeof(ether_hdr_t));

@@ -1533,7 +1517,7 @@ static void send_packet2net(n2n_edge_t * eee,
/** Read a single packet from the TAP interface, process it and write out the
* corresponding packet to the cooked socket.
*/
static void readFromTAPSocket(n2n_edge_t * eee) {
void edge_read_from_tap(n2n_edge_t * eee) {
/* tun -> remote */
uint8_t eth_pkt[N2N_PKT_BUF_SIZE];
macstr_t mac_buf;
@@ -1572,7 +1556,15 @@ static void readFromTAPSocket(n2n_edge_t * eee) {
}
else
{
send_packet2net(eee, eth_pkt, len);
if(eee->cb.packet_from_tap) {
if(eee->cb.packet_from_tap(eee, eth_pkt, len) == N2N_DROP) {
traceEvent(TRACE_DEBUG, "DROP packet %u", (unsigned int)len);

return;
}
}

edge_send_packet2net(eee, eth_pkt, len);
}
}
}
@@ -1690,7 +1682,6 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
{
/* Another edge is registering with us */
n2n_REGISTER_t reg;
n2n_mac_t null_mac = { '\0' };
int via_multicast;

decode_REGISTER(&reg, &cmn, udp_buf, &rem, &idx);
@@ -1780,20 +1771,8 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) {
eee->sn_wait=0;
eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */

#ifdef __ANDROID_NDK__
int change = 0;

pthread_mutex_lock(&g_status->mutex);
change = g_status->running_status == EDGE_STAT_CONNECTED ? 0 : 1;
g_status->running_status = EDGE_STAT_CONNECTED;
pthread_mutex_unlock(&g_status->mutex);

if (change) {
g_status->report_edge_status();
}

update_gateway_mac(eee);
#endif /* #ifdef __ANDROID_NDK__ */
if(eee->cb.sn_registration_updated)
eee->cb.sn_registration_updated(eee, now, &sender);

/* NOTE: the register_interval should be chosen by the edge node
* based on its NAT configuration. */
@@ -1886,7 +1865,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
*
* select() is used to wait for input on either the TAP fd or the UDP/TCP
* socket. When input is present the data is read and processed by either
* readFromIPSocket() or readFromTAPSocket()
* readFromIPSocket() or edge_read_from_tap()
*/

while(*keep_running) {
@@ -1943,7 +1922,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {

#ifdef __ANDROID_NDK__
if(uip_arp_len != 0) {
readFromTAPSocket(eee);
edge_read_from_tap(eee);
uip_arp_len = 0;
}
#endif /* #ifdef __ANDROID_NDK__ */
@@ -1958,7 +1937,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {
if(FD_ISSET(eee->device.fd, &socket_mask)) {
/* Read an ethernet frame from the TAP socket. Write on the IP
* socket. */
readFromTAPSocket(eee);
edge_read_from_tap(eee);
}
#endif
}
@@ -1978,9 +1957,14 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) {

if(eee->conf.dyn_ip_mode &&
((nowTime - lastIfaceCheck) > IFACE_UPDATE_INTERVAL)) {
uint32_t old_ip = eee->device.ip_addr;

traceEvent(TRACE_NORMAL, "Re-checking dynamic IP address.");
tuntap_get_address(&(eee->device));
lastIfaceCheck = nowTime;

if((old_ip != eee->device.ip_addr) && eee->cb.ip_address_changed)
eee->cb.ip_address_changed(eee, old_ip, eee->device.ip_addr);
}

#ifdef __ANDROID_NDK__

0 comments on commit 346631f

Please sign in to comment.