From 78aa01ad3048c2d3052bcc8c17c57a719dffadcf Mon Sep 17 00:00:00 2001 From: Jeremy Lakeman Date: Fri, 7 Dec 2012 16:04:40 +1030 Subject: [PATCH] Add stun lookup messages --- constants.h | 2 + overlay_address.c | 3 +- overlay_interface.c | 15 ++++- overlay_mdp.c | 4 +- overlay_mdp_services.c | 128 ++++++++++++++++++++++++++++++++++++++++- overlay_olsr.c | 2 +- serval.h | 4 +- 7 files changed, 150 insertions(+), 8 deletions(-) diff --git a/constants.h b/constants.h index 4f1cbddc..a55c5290 100644 --- a/constants.h +++ b/constants.h @@ -125,6 +125,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define MAX_SIGNATURES 16 #define MDP_PORT_KEYMAPREQUEST 1 +#define MDP_PORT_STUNREQ 4 +#define MDP_PORT_STUN 5 #define MDP_PORT_PROBE 6 #define MDP_PORT_ECHO 7 #define MDP_PORT_DNALOOKUP 10 diff --git a/overlay_address.c b/overlay_address.c index bb126a2c..2caafad8 100644 --- a/overlay_address.c +++ b/overlay_address.c @@ -413,7 +413,8 @@ static int find_subscr_buffer(struct decode_context *context, struct overlay_buf ob_append_bytes(context->please_explain->payload, id, len); }else{ - context->previous=*subscriber; + if (context) + context->previous=*subscriber; } return 0; } diff --git a/overlay_interface.c b/overlay_interface.c index 32b4ef24..123ddeab 100644 --- a/overlay_interface.c +++ b/overlay_interface.c @@ -131,7 +131,16 @@ error: return -1; } -overlay_interface * overlay_interface_find(struct in_addr addr){ +overlay_interface * overlay_interface_get_default(){ + int i; + for (i=0;isin_addr; /* Try to identify the real interface that the packet arrived on */ - interface = overlay_interface_find(src); + interface = overlay_interface_find(src, 0); /* Drop the packet if we don't find a match */ if (!interface){ diff --git a/overlay_mdp.c b/overlay_mdp.c index ee928727..bfe7eef8 100644 --- a/overlay_mdp.c +++ b/overlay_mdp.c @@ -527,6 +527,8 @@ int overlay_mdp_check_binding(struct subscriber *subscriber, int port, int userG case MDP_PORT_RHIZOME_RESPONSE: case MDP_PORT_RHIZOME_REQUEST: case MDP_PORT_PROBE: + case MDP_PORT_STUNREQ: + case MDP_PORT_STUN: return 0; } } @@ -1017,7 +1019,7 @@ void overlay_mdp_poll(struct sched_ent *alarm) schedule(&scans[i].alarm); } }else{ - struct overlay_interface *interface = overlay_interface_find(scan->addr); + struct overlay_interface *interface = overlay_interface_find(scan->addr, 1); if (!interface){ overlay_mdp_reply_error(alarm->poll.fd,recvaddr_un,recvaddrlen, 1, "Unable to find matching interface"); return; diff --git a/overlay_mdp_services.c b/overlay_mdp_services.c index e85353bb..bef64636 100644 --- a/overlay_mdp_services.c +++ b/overlay_mdp_services.c @@ -314,7 +314,7 @@ overlay_mdp_service_probe(overlay_mdp_frame *mdp) int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface){ if (interface==NULL) - interface = overlay_interface_find(addr.sin_addr); + interface = overlay_interface_find(addr.sin_addr, 1); if (!interface) return WHY("I don't know which interface to use"); @@ -338,6 +338,8 @@ int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay frame->payload = ob_new(); frame->send_copies=3; + // TODO call mdp payload encryption / signing without calling overlay_mdp_dispatch... + if ((!peer) || !(peer->reachable&REACHABLE)) my_subscriber->send_full=1; @@ -367,6 +369,128 @@ int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay return 0; } +// append the address of a unicast link into a packet buffer +static int overlay_append_unicast_address(struct subscriber *subscriber, struct overlay_buffer *buff) +{ + if (!(subscriber->reachable & REACHABLE_UNICAST)) + return 0; + if (subscriber->reachable & REACHABLE_ASSUMED) + return 0; + if (overlay_address_append(NULL, buff, subscriber)) + return -1; + if (ob_append_ui32(buff, subscriber->address.sin_addr.s_addr)) + return -1; + if (ob_append_ui16(buff, subscriber->address.sin_port)) + return -1; + ob_checkpoint(buff); + DEBUGF("Added STUN info for %s", alloca_tohex_sid(subscriber->sid)); + return 0; +} + +static int overlay_mdp_service_stun_req(overlay_mdp_frame *mdp) +{ + DEBUGF("Processing STUN request from %s", alloca_tohex_sid(mdp->out.src.sid)); + + struct overlay_buffer *payload = ob_static(mdp->out.payload, mdp->out.payload_length); + ob_limitsize(payload, mdp->out.payload_length); + + overlay_mdp_frame reply; + bzero(&reply, sizeof(reply)); + reply.packetTypeAndFlags=MDP_TX; + + bcopy(mdp->out.src.sid, reply.out.dst.sid, SID_SIZE); + bcopy(mdp->out.dst.sid, reply.out.src.sid, SID_SIZE); + reply.out.src.port=MDP_PORT_STUNREQ; + reply.out.dst.port=MDP_PORT_STUN; + + struct overlay_buffer *replypayload = ob_static(reply.out.payload, sizeof(reply.out.payload)); + + ob_checkpoint(replypayload); + while(ob_remaining(payload)>0){ + struct subscriber *subscriber=NULL; + + if (overlay_address_parse(NULL, payload, &subscriber)) + break; + + if (!subscriber) + continue; + + if (overlay_append_unicast_address(subscriber, replypayload)) + break; + } + + ob_rewind(replypayload); + reply.out.payload_length=ob_position(replypayload); + + if (reply.out.payload_length) + overlay_mdp_dispatch(&reply,0 /* system generated */, + NULL,0); + + ob_free(replypayload); + ob_free(payload); + return 0; +} + +static int overlay_mdp_service_stun(overlay_mdp_frame *mdp) +{ + struct overlay_buffer *buff = ob_static(mdp->out.payload, mdp->out.payload_length); + ob_limitsize(buff, mdp->out.payload_length); + + DEBUGF("Processing STUN info from %s", alloca_tohex_sid(mdp->out.src.sid)); + + while(ob_remaining(buff)>0){ + struct subscriber *subscriber=NULL; + struct sockaddr_in addr; + + // TODO explain addresses, link expiry time, resolve differences between addresses... + + if (overlay_address_parse(NULL, buff, &subscriber)){ + break; + } + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ob_get_ui32(buff); + addr.sin_port = ob_get_ui16(buff); + + if (!subscriber || (subscriber->reachable!=REACHABLE_NONE)) + continue; + + overlay_send_probe(subscriber, addr, NULL); + } + + ob_free(buff); + return 0; +} + +int overlay_send_stun_request(struct subscriber *server, struct subscriber *request){ + if ((!server) || (!request)) + return -1; + if (!(subscriber_is_reachable(server)&REACHABLE)) + return -1; + // don't bother with a stun request if the peer is already reachable directly + // TODO link timeouts + if (subscriber_is_reachable(request)&REACHABLE_DIRECT) + return -1; + + overlay_mdp_frame mdp; + bzero(&mdp, sizeof(mdp)); + mdp.packetTypeAndFlags=MDP_TX; + + bcopy(my_subscriber->sid, mdp.out.src.sid, SID_SIZE); + bcopy(server->sid, mdp.out.dst.sid, SID_SIZE); + mdp.out.src.port=MDP_PORT_STUN; + mdp.out.dst.port=MDP_PORT_STUNREQ; + + struct overlay_buffer *payload = ob_static(mdp.out.payload, sizeof(mdp.out.payload)); + overlay_address_append(NULL, payload, request); + mdp.out.payload_length=ob_position(payload); + DEBUGF("Sending STUN request to %s", alloca_tohex_sid(server->sid)); + overlay_mdp_dispatch(&mdp,0 /* system generated */, + NULL,0); + ob_free(payload); + return 0; +} + int overlay_mdp_try_interal_services(overlay_mdp_frame *mdp) { IN(); @@ -376,6 +500,8 @@ int overlay_mdp_try_interal_services(overlay_mdp_frame *mdp) case MDP_PORT_DNALOOKUP: RETURN(overlay_mdp_service_dnalookup(mdp)); case MDP_PORT_ECHO: RETURN(overlay_mdp_service_echo(mdp)); case MDP_PORT_PROBE: RETURN(overlay_mdp_service_probe(mdp)); + case MDP_PORT_STUNREQ: RETURN(overlay_mdp_service_stun_req(mdp)); + case MDP_PORT_STUN: RETURN(overlay_mdp_service_stun(mdp)); case MDP_PORT_RHIZOME_REQUEST: if (is_rhizome_mdp_server_running()) { RETURN(overlay_mdp_service_rhizomerequest(mdp)); diff --git a/overlay_olsr.c b/overlay_olsr.c index 44325ff8..36f2b4bf 100644 --- a/overlay_olsr.c +++ b/overlay_olsr.c @@ -144,7 +144,7 @@ static void parse_frame(struct overlay_buffer *buff){ goto end; // locate the interface we should send outgoing unicast packets to - overlay_interface *interface = overlay_interface_find(*addr); + overlay_interface *interface = overlay_interface_find(*addr, 1); if (interface){ // always update the IP address we heard them from, even if we don't need to use it right now context.sender->address.sin_family = AF_INET; diff --git a/serval.h b/serval.h index cc681319..c8670241 100644 --- a/serval.h +++ b/serval.h @@ -615,7 +615,8 @@ int overlay_route_node_info(overlay_mdp_nodeinfo *node_info); int overlay_interface_register(char *name, struct in_addr addr, struct in_addr mask); -overlay_interface * overlay_interface_find(struct in_addr addr); +overlay_interface * overlay_interface_get_default(); +overlay_interface * overlay_interface_find(struct in_addr addr, int return_default); overlay_interface * overlay_interface_find_name(const char *name); int overlay_broadcast_ensemble(int interface_number, struct sockaddr_in *recipientaddr, @@ -712,6 +713,7 @@ void server_shutdown_check(struct sched_ent *alarm); void overlay_mdp_poll(struct sched_ent *alarm); int overlay_mdp_try_interal_services(overlay_mdp_frame *mdp); int overlay_send_probe(struct subscriber *peer, struct sockaddr_in addr, overlay_interface *interface); +int overlay_send_stun_request(struct subscriber *server, struct subscriber *request); void fd_periodicstats(struct sched_ent *alarm); void rhizome_check_connections(struct sched_ent *alarm);