return true;
}
-static int check_port(meshlink_handle_t *mesh) {
+int check_port(meshlink_handle_t *mesh) {
for(int i = 0; i < 1000; i++) {
int port = 0x1000 + (rand() & 0x7fff);
FILE *f = fopen(filename, "a");
if(!f) {
- logger(mesh, MESHLINK_DEBUG, "Please change MeshLink's Port manually.\n");
+ meshlink_errno = MESHLINK_ESTORAGE;
+ logger(mesh, MESHLINK_DEBUG, "Could not store Port.\n");
return 0;
}
}
}
- logger(mesh, MESHLINK_DEBUG, "Please change MeshLink's Port manually.\n");
+ meshlink_errno = MESHLINK_ENETWORK;
+ logger(mesh, MESHLINK_DEBUG, "Could not find any available network port.\n");
return 0;
}
static bool invitation_send(void *handle, uint8_t type, const void *data, size_t len) {
(void)type;
meshlink_handle_t *mesh = handle;
+ const char *ptr = data;
while(len) {
- int result = send(mesh->sock, data, len, 0);
+ int result = send(mesh->sock, ptr, len, 0);
if(result == -1 && errno == EINTR) {
continue;
return false;
}
- data += result;
+ ptr += result;
len -= result;
}
logger(mesh, MESHLINK_DEBUG, "Done.\n");
}
- snprintf(privname, sizeof(privname), "%s" SLASH "ecdsa_key.priv", mesh->confbase);
+ if (snprintf(privname, sizeof(privname), "%s" SLASH "ecdsa_key.priv", mesh->confbase) >= PATH_MAX) {
+ logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "ecdsa_key.priv\n", mesh->confbase);
+ meshlink_errno = MESHLINK_ESTORAGE;
+ return false;
+ }
+
f = fopen(privname, "wb");
if(!f) {
if(!ecdsa_keygen(mesh)) {
meshlink_errno = MESHLINK_EINTERNAL;
+ unlink(filename);
return false;
}
- check_port(mesh);
+ if (check_port(mesh) == 0) {
+ meshlink_errno = MESHLINK_ENETWORK;
+ unlink(filename);
+ return false;
+ }
return true;
}
event_loop_init(&mesh->loop);
mesh->loop.data = mesh;
+ meshlink_queue_init(&mesh->outpacketqueue);
+
// Check whether meshlink.conf already exists
char filename[PATH_MAX];
char invname[PATH_MAX];
struct stat st;
- snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name);
+ if (snprintf(invname, sizeof(invname), "%s" SLASH "%s", filename, ent->d_name) >= PATH_MAX) {
+ logger(mesh, MESHLINK_DEBUG, "Filename too long: %s" SLASH "%s", filename, ent->d_name);
+ continue;
+ }
if(!stat(invname, &st)) {
if(mesh->invitation_key && deadline < st.st_mtime) {
pthread_mutex_lock(&(mesh->mesh_mutex));
+ //Before doing meshlink_join make sure we are not connected to another mesh
+ if(mesh->threadstarted) {
+ logger(mesh, MESHLINK_DEBUG, "Already connected to a mesh\n");
+ meshlink_errno = MESHLINK_EINVAL;
+ pthread_mutex_unlock(&(mesh->mesh_mutex));
+ return false;
+ }
+
//TODO: think of a better name for this variable, or of a different way to tokenize the invitation URL.
char copy[strlen(invitation) + 1];
strcpy(copy, invitation);
}
char *address = copy;
- char *port = NULL;
-
- if(*address == '[') {
- address++;
- char *bracket = strchr(address, ']');
-
- if(!bracket) {
- goto invalid;
- }
-
- *bracket = 0;
-
- if(bracket[1] == ':') {
- port = bracket + 2;
- }
- } else {
- port = strchr(address, ':');
-
- if(port) {
- *port++ = 0;
- }
- }
+ char *port = strrchr(address, ':');
- if(!port) {
+ if (!port) {
goto invalid;
}
+ *port++ = 0;
+
if(!b64decode(slash, mesh->hash, 18) || !b64decode(slash + 24, mesh->cookie, 18)) {
goto invalid;
}
}
char *b64key = ecdsa_get_base64_public_key(key);
+ char *comma;
+ mesh->sock = -1;
+
+ while (address && *address) {
+ // We allow commas in the address part to support multiple addresses in one invitation URL.
+ comma = strchr(address, ',');
+ if (comma)
+ *comma++ = 0;
+
+ // IPv6 address are enclosed in brackets, per RFC 3986
+ if (*address == '[') {
+ address++;
+ char *bracket = strchr(address, ']');
+ if (!bracket)
+ goto invalid;
+ *bracket++ = 0;
+ if (comma && bracket != comma)
+ goto invalid;
+ }
- //Before doing meshlink_join make sure we are not connected to another mesh
- if(mesh->threadstarted) {
- goto invalid;
- }
+ // Connect to the meshlink daemon mentioned in the URL.
+ struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
+ if (ai) {
+ for (struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
+ mesh->sock = socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
- // Connect to the meshlink daemon mentioned in the URL.
- struct addrinfo *ai = str2addrinfo(address, port, SOCK_STREAM);
+ if(mesh->sock == -1) {
+ logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
+ meshlink_errno = MESHLINK_ENETWORK;
+ continue;
+ }
- if(!ai) {
- meshlink_errno = MESHLINK_ERESOLV;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
+ set_timeout(mesh->sock, 5000);
- mesh->sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if(connect(mesh->sock, aip->ai_addr, aip->ai_addrlen)) {
+ logger(mesh, MESHLINK_DEBUG, "Could not connect to %s port %s: %s\n", address, port, strerror(errno));
+ meshlink_errno = MESHLINK_ENETWORK;
+ closesocket(mesh->sock);
+ mesh->sock = -1;
+ continue;
+ }
+ }
- if(mesh->sock <= 0) {
- logger(mesh, MESHLINK_DEBUG, "Could not open socket: %s\n", strerror(errno));
- freeaddrinfo(ai);
- meshlink_errno = MESHLINK_ENETWORK;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
- }
+ freeaddrinfo(ai);
+ } else {
+ meshlink_errno = MESHLINK_ERESOLV;
+ }
- set_timeout(mesh->sock, 5000);
+ if (mesh->sock != -1 || !comma)
+ break;
- if(connect(mesh->sock, ai->ai_addr, ai->ai_addrlen)) {
- logger(mesh, MESHLINK_DEBUG, "Could not connect to %s port %s: %s\n", address, port, strerror(errno));
- closesocket(mesh->sock);
- freeaddrinfo(ai);
- meshlink_errno = MESHLINK_ENETWORK;
- pthread_mutex_unlock(&(mesh->mesh_mutex));
- return false;
+ address = comma;
}
- freeaddrinfo(ai);
+ if (mesh->sock == -1) {
+ pthread_mutex_unlock(&mesh->mesh_mutex);
+ return false;
+ }
logger(mesh, MESHLINK_DEBUG, "Connected to %s port %s...\n", address, port);
return true;
invalid:
- logger(mesh, MESHLINK_DEBUG, "Invalid invitation URL or you are already connected to a Mesh ?\n");
+ logger(mesh, MESHLINK_DEBUG, "Invalid invitation URL\n");
meshlink_errno = MESHLINK_EINVAL;
pthread_mutex_unlock(&(mesh->mesh_mutex));
return false;