ecdsa_t *ecdsa; /* his public ECDSA key */
int protocol_major; /* used protocol */
int protocol_minor; /* used protocol */
-
- // Unused/deprecated
- uint32_t options; /* options for this connection */
- int incompression;
- int outcompression;
} connection_t;
extern void init_connections(struct meshlink_handle *mesh);
p->from = (meshlink_node_t *)e->from;
p->to = (meshlink_node_t *)e->to;
p->address = e->address.storage;
- p->options = e->options;
p->weight = e->weight;
n++;
goto fail;
}
- if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->options), stream) || !fstrwrite(",\n", stream)) {
- goto fail;
- }
-
if(!fstrwrite("\t\t\t\"devclass\": ", stream) || !fstrwrite(__itoa(((node_t *)nodes[i])->devclass), stream) || !fstrwrite("\n", stream)) {
goto fail;
}
free(address);
- if(!fstrwrite("\t\t\t\"options\": ", stream) || !fstrwrite(__itoa(edges[i].options), stream) || !fstrwrite(",\n", stream)) {
- goto fail;
- }
-
if(!fstrwrite("\t\t\t\"weight\": ", stream) || !fstrwrite(__itoa(edges[i].weight), stream) || !fstrwrite("\n", stream)) {
goto fail;
}
pthread_mutex_lock(&mesh->mesh_mutex);
- status->options = internal->options;
memcpy(&status->status, &internal->status, sizeof status->status);
memcpy(&status->address, &internal->address, sizeof status->address);
status->mtu = internal->mtu;
// changed by meshlink.
struct sockaddr_storage address;///< The address information associated
// with this edge.
- uint32_t options; ///< Edge options. @TODO what are edge options?
int weight; ///< Weight assigned to this edge.
};
/// The status of a node.
struct devtool_node_status {
- uint32_t options;
uint32_t status;
struct sockaddr_storage address;
uint16_t mtu;
struct edge_t *reverse; /* edge in the opposite direction, if available */
int weight; /* weight of this edge */
-
- // Deprecated
- uint32_t options; /* options turned on for this edge */
} edge_t;
extern void init_edges(struct meshlink_handle *mesh);
For the SSSP algorithm Dijkstra's seems to be a nice choice. Currently a
simple breadth-first search is presented here.
- The SSSP algorithm will also be used to determine whether nodes are directly,
- indirectly or not reachable from the source. It will also set the correct
- destination address and port of a node if possible.
+ The SSSP algorithm will also be used to determine whether nodes are
+ reachable from the source. It will also set the correct destination address
+ and port of a node if possible.
*/
#include "system.h"
for splay_each(node_t, n, mesh->nodes) {
n->status.visited = false;
- n->status.indirect = true;
n->distance = -1;
}
/* Begin with mesh->self */
mesh->self->status.visited = true;
- mesh->self->status.indirect = false;
mesh->self->nexthop = mesh->self;
mesh->self->prevedge = NULL;
- mesh->self->via = mesh->self;
mesh->self->distance = 0;
list_insert_head(todo_list, mesh->self);
of nodes behind it.
*/
- bool indirect = n->status.indirect || e->options & OPTION_INDIRECT;
-
if(e->to->status.visited
- && (!e->to->status.indirect || indirect)
&& (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight)) {
continue;
}
e->to->status.visited = true;
- e->to->status.indirect = indirect;
e->to->nexthop = (n->nexthop == mesh->self) ? e->to : n->nexthop;
e->to->prevedge = e;
- e->to->via = indirect ? n->via : e->to;
- e->to->options = e->options;
e->to->distance = n->distance + 1;
if(!e->to->status.reachable || (e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)) {
if(!n->status.reachable) {
update_node_udp(mesh, n, NULL);
n->status.broadcast = false;
- n->options = 0;
} else if(n->connection) {
if(n->connection->outgoing) {
send_req_key(mesh, n);
char line[4096];
char buffer[4096];
- // Unused variables
+ // Proxy configuration, currently not exposed.
char *proxyhost;
char *proxyport;
char *proxyuser;
char *proxypass;
proxytype_t proxytype;
- sockaddr_t localdiscovery_address;
- bool localdiscovery;
};
/// A handle for a MeshLink node.
timeout = mesh->pingtimeout;
}
- for(int i = 0; i < 4 + mesh->localdiscovery; i++) {
+ for(int i = 0; i < 5; i++) {
int len;
if(i == 0) {
return;
}
- if(n->outcompression) {
- logger(mesh, MESHLINK_ERROR, "Error while compressing packet to %s", n->name);
- return;
- }
-
sptps_send_record(&n->sptps, type, origpkt->data, origpkt->len);
return;
}
*sock = rand() % mesh->listen_sockets;
if(mesh->listen_socket[*sock].sa.sa.sa_family == AF_INET6) {
- if(mesh->localdiscovery_address.sa.sa_family == AF_INET6) {
- mesh->localdiscovery_address.in6.sin6_port = n->prevedge->address.in.sin_port;
- *sa = &mesh->localdiscovery_address;
- } else {
- broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
- broadcast_ipv6.in6.sin6_scope_id = mesh->listen_socket[*sock].sa.in6.sin6_scope_id;
- *sa = &broadcast_ipv6;
- }
+ broadcast_ipv6.in6.sin6_port = n->prevedge->address.in.sin_port;
+ broadcast_ipv6.in6.sin6_scope_id = mesh->listen_socket[*sock].sa.in6.sin6_scope_id;
+ *sa = &broadcast_ipv6;
} else {
- if(mesh->localdiscovery_address.sa.sa_family == AF_INET) {
- mesh->localdiscovery_address.in.sin_port = n->prevedge->address.in.sin_port;
- *sa = &mesh->localdiscovery_address;
- } else {
- broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
- *sa = &broadcast_ipv4;
- }
+ broadcast_ipv4.in.sin_port = n->prevedge->address.in.sin_port;
+ *sa = &broadcast_ipv4;
}
}
/* Send it via TCP if it is a handshake packet, TCPOnly is in use, or this packet is larger than the MTU. */
- if(type >= SPTPS_HANDSHAKE || ((mesh->self->options | to->options) & OPTION_TCPONLY) || (type != PKT_PROBE && len > to->minmtu)) {
+ if(type >= SPTPS_HANDSHAKE || (type != PKT_PROBE && len > to->minmtu)) {
char buf[len * 4 / 3 + 5];
b64encode(data, buf, len);
/* If no valid key is known yet, send the packets using ANS_KEY requests,
to ensure we get to learn the reflexive UDP address. */
if(!to->status.validkey) {
- to->incompression = mesh->self->incompression;
- return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, to->incompression);
+ return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %s -1 -1 -1 %d", ANS_KEY, mesh->self->name, to->name, buf, 0);
} else {
return send_request(mesh, to->nexthop->connection, NULL, "%d %s %s %d %s", REQ_KEY, mesh->self->name, to->name, REQ_SPTPS, buf);
}
bool setup_myself(meshlink_handle_t *mesh) {
/* Set some defaults */
- mesh->localdiscovery = true;
keylifetime = 3600; // TODO: check if this can be removed as well
mesh->maxtimeout = 900;
- mesh->self->options |= OPTION_PMTU_DISCOVERY;
/* Done */
mesh->self->nexthop = mesh->self;
- mesh->self->via = mesh->self;
mesh->self->status.reachable = true;
mesh->self->last_state_change = mesh->loop.now.tv_sec;
#endif
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO)
-
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = IP_PMTUDISC_DO;
- setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
- }
-
+ option = IP_PMTUDISC_DO;
+ setsockopt(nfd, IPPROTO_IP, IP_MTU_DISCOVER, (void *)&option, sizeof(option));
#elif defined(IP_DONTFRAGMENT)
-
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = 1;
- setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
- }
-
-#else
-#warning No way to disable IPv4 fragmentation
+ option = 1;
+ setsockopt(nfd, IPPROTO_IP, IP_DONTFRAGMENT, (void *)&option, sizeof(option));
#endif
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO)
-
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = IPV6_PMTUDISC_DO;
- setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
- }
-
+ option = IPV6_PMTUDISC_DO;
+ setsockopt(nfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (void *)&option, sizeof(option));
#elif defined(IPV6_DONTFRAG)
-
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- option = 1;
- setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
- }
-
-#else
-#warning No way to disable IPv6 fragmentation
+ option = 1;
+ setsockopt(nfd, IPPROTO_IPV6, IPV6_DONTFRAG, (void *)&option, sizeof(option));
#endif
if(bind(nfd, &sa->sa, SALEN(sa->sa))) {
uint16_t waitingforkey: 1; /* 1 if we already sent out a request */
uint16_t visited: 1; /* 1 if this node has been visited by one of the graph algorithms */
uint16_t reachable: 1; /* 1 if this node is reachable in the graph */
- uint16_t indirect: 1; /* 1 if this node is not directly reachable by us */
uint16_t udp_confirmed: 1; /* 1 if the address is one that we received UDP traffic on */
uint16_t broadcast: 1; /* 1 if the next UDP packet should be broadcast to the local network */
uint16_t blacklisted: 1; /* 1 if the node is blacklist so we never want to speak with him anymore */
int distance;
struct node_t *nexthop; /* nearest node from us to him */
struct edge_t *prevedge; /* nearest node from him to us */
- struct node_t *via; /* next hop for UDP packets */
struct splay_tree_t *edge_tree; /* Edges with this node as one of the endpoints */
-
- // Unused
- uint32_t options; /* options turned on for this node */
- int incompression; /* Compressionlevel, 0 = no compression */
- int outcompression; /* Compressionlevel, 0 = no compression */
} node_t;
extern void init_nodes(struct meshlink_handle *mesh);
}
bool send_ack(meshlink_handle_t *mesh, connection_t *c) {
-
- /* Check some options */
-
- if(mesh->self->options & OPTION_PMTU_DISCOVERY) {
- c->options |= OPTION_PMTU_DISCOVERY;
- }
-
- return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, (c->options & 0xffffff) | (PROT_MINOR << 24));
+ return send_request(mesh, c, NULL, "%d %s %d %x", ACK, mesh->myport, mesh->devclass, OPTION_PMTU_DISCOVERY | (PROT_MINOR << 24));
}
static void send_everything(meshlink_handle_t *mesh, connection_t *c) {
n->connection = c;
c->node = n;
- if(!(c->options & options & OPTION_PMTU_DISCOVERY)) {
- c->options &= ~OPTION_PMTU_DISCOVERY;
- options &= ~OPTION_PMTU_DISCOVERY;
- }
-
- c->options |= options;
-
/* Activate this connection */
c->allow_request = ALL;
sockaddrcpy_setport(&c->edge->address, &c->address, atoi(hisport));
c->edge->weight = dev_class_traits[devclass].edge_weight;
c->edge->connection = c;
- c->edge->options = c->options;
edge_add(mesh, c->edge);
x = send_request(mesh, c, s, "%d %x %s %d %s %s %s %s %d %s %x %d %d", ADD_EDGE, rand(),
e->from->name, e->from->devclass, from_submesh, e->to->name, address, port,
- e->to->devclass, to_submesh, e->options, e->weight, contradictions);
+ e->to->devclass, to_submesh, OPTION_PMTU_DISCOVERY, e->weight, contradictions);
free(address);
free(port);
int to_devclass;
char to_submesh_name[MAX_STRING_SIZE] = "";
sockaddr_t address;
- uint32_t options;
int weight;
int contradictions = 0;
submesh_t *s = NULL;
- if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %d "MAX_STRING" %x %d %d",
+ if(sscanf(request, "%*d %*x "MAX_STRING" %d "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %d "MAX_STRING" %*x %d %d",
from_name, &from_devclass, from_submesh_name, to_name, to_address, to_port, &to_devclass, to_submesh_name,
- &options, &weight, &contradictions) < 10) {
+ &weight, &contradictions) < 9) {
logger(mesh, MESHLINK_ERROR, "Got bad %s from %s", "ADD_EDGE", c->name);
return false;
}
e = lookup_edge(from, to);
if(e) {
- if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) {
+ if(e->weight != weight || sockaddrcmp(&e->address, &address)) {
if(from == mesh->self) {
logger(mesh, MESHLINK_WARNING, "Got %s from %s for ourself which does not match existing entry",
"ADD_EDGE", c->name);
e->from = from;
e->to = to;
e->address = address;
- e->options = options;
e->weight = weight;
edge_add(mesh, e);
to->status.validkey = false;
to->status.waitingforkey = true;
to->last_req_key = mesh->loop.now.tv_sec;
- to->incompression = mesh->self->incompression;
return sptps_start(&to->sptps, to, true, true, mesh->private_key, to->ecdsa, label, sizeof(label) - 1, send_initial_sptps_data, receive_sptps_record);
}
return true;
}
- from->outcompression = compression;
-
/* SPTPS or old-style key exchange? */
char buf[strlen(key)];
update_node_udp(mesh, from, &sa);
}
- if(from->options & OPTION_PMTU_DISCOVERY && !(from->options & OPTION_TCPONLY)) {
- send_mtu_probe(mesh, from);
- }
+ send_mtu_probe(mesh, from);
}
return true;
void route(meshlink_handle_t *mesh, node_t *source, vpn_packet_t *packet) {
// TODO: route on name or key
- node_t *owner = NULL;
- node_t *via = NULL;
meshlink_packethdr_t *hdr = (meshlink_packethdr_t *) packet->data;
- owner = lookup_node(mesh, (char *)hdr->destination);
+ node_t *dest = lookup_node(mesh, (char *)hdr->destination);
logger(mesh, MESHLINK_DEBUG, "Routing packet from \"%s\" to \"%s\"\n", hdr->source, hdr->destination);
//Check Length
return;
}
- if(owner == NULL) {
+ if(dest == NULL) {
//Lookup failed
- logger(mesh, MESHLINK_WARNING, "Can't lookup the owner of a packet in the route() function. This should never happen!\n");
+ logger(mesh, MESHLINK_WARNING, "Can't lookup the destination of a packet in the route() function. This should never happen!\n");
logger(mesh, MESHLINK_WARNING, "Destination was: %s\n", hdr->destination);
return;
}
- if(owner == mesh->self) {
+ if(dest == mesh->self) {
const void *payload = packet->data + sizeof(*hdr);
size_t len = packet->len - sizeof(*hdr);
return;
}
- if(!owner->status.reachable) {
+ if(!dest->status.reachable) {
//TODO: check what to do here, not just print a warning
- logger(mesh, MESHLINK_WARNING, "The owner of a packet in the route() function is unreachable. Dropping packet.\n");
+ logger(mesh, MESHLINK_WARNING, "The destination of a packet in the route() function is unreachable. Dropping packet.\n");
return;
}
- via = (owner->via == mesh->self) ? owner->nexthop : owner->via;
-
- if(via == source) {
+ if(dest == source) {
logger(mesh, MESHLINK_ERROR, "Routing loop for packet from %s!", source->name);
return;
}
- send_packet(mesh, owner, packet);
+ send_packet(mesh, dest, packet);
return;
}