return meshlink_clear_canonical_address(handle, node);
}
- /// Add an Address for the local node.
- /** This function adds an Address for the local node, which will be used for invitation URLs.
- * @deprecated This function is deprecated, use set_canonical_address() and/or add_invitation_address().
- *
- * @param address A string containing the address, which can be either in numeric format or a hostname.
- *
- * @return This function returns true if the address was added, false otherwise.
- */
- bool add_address(const char *address) __attribute__((__deprecated__("use set_canonical_address() and/or add_invitation_address() instead"))) {
- return meshlink_set_canonical_address(handle, get_self(), address, NULL);
- }
-
- /** This function performs tries to discover the local node's external address
- * by contacting the meshlink.io server. If a reverse lookup of the address works,
- * the FQDN associated with the address will be returned.
- *
- * Please note that this is function only returns a single address,
- * even if the local node might have more than one external address.
- * In that case, there is no control over which address will be selected.
- * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT,
- * there is no guarantee that the external address will be valid for an extended period of time.
- *
- * This function is blocking. It can take several seconds before it returns.
- * There is no guarantee it will be able to resolve the external address.
- * Failures might be because by temporary network outages.
- *
- * @param family The address family to check, for example AF_INET or AF_INET6. If AF_UNSPEC is given,
- * this might return the external address for any working address family.
- *
- * @return This function returns a pointer to a C string containing the discovered external address,
- * or NULL if there was an error looking up the address.
- * After get_external_address() returns, the application is free to overwrite or free this string.
- */
- bool get_external_address(int family = AF_UNSPEC) {
- return meshlink_get_external_address_for_family(handle, family);
- }
-
- /** This function performs tries to discover the address of the local interface used for outgoing connection.
- *
- * Please note that this is function only returns a single address,
- * even if the local node might have more than one external address.
- * In that case, there is no control over which address will be selected.
- * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT,
- * there is no guarantee that the external address will be valid for an extended period of time.
- *
- * This function will fail if it couldn't find a local address for the given address family.
- * If hostname resolving is requested, this function may block for a few seconds.
- *
- * @param family The address family to check, for example AF_INET or AF_INET6. If AF_UNSPEC is given,
- * this might return the external address for any working address family.
- *
- * @return This function returns a pointer to a C string containing the discovered external address,
- * or NULL if there was an error looking up the address.
- * After get_external_address() returns, the application is free to overwrite or free this string.
- */
- bool get_local_address(int family = AF_UNSPEC) {
- return meshlink_get_local_address_for_family(handle, family);
- }
-
- /// Try to discover the external address for the local node, and add it to its list of addresses.
- /** This function is equivalent to:
- *
- * mesh->add_address(mesh->get_external_address());
- *
- * Read the description of get_external_address() for the limitations of this function.
- *
- * @return This function returns true if the address was added, false otherwise.
- */
- bool add_external_address() {
- return meshlink_add_external_address(handle);
- }
-
/// Set the scheduling granularity of the application
/** This should be set to the effective scheduling granularity for the application.
* This depends on the scheduling granularity of the operating system, the application's
*/
bool meshlink_clear_canonical_address(struct meshlink_handle *mesh, struct meshlink_node *node) __attribute__((__warn_unused_result__));
-/// Add an Address for the local node.
-/** This function adds an Address for the local node, which will be used for invitation URLs.
- * @deprecated This function is deprecated, use meshlink_set_canonical_address() and/or meshlink_add_invitation_address().
- *
- * \memberof meshlink_handle
- * @param mesh A handle which represents an instance of MeshLink.
- * @param address A nul-terminated C string containing the address, which can be either in numeric format or a hostname.
- *
- * @return This function returns true if the address was added, false otherwise.
- */
-bool meshlink_add_address(struct meshlink_handle *mesh, const char *address) __attribute__((__warn_unused_result__, __deprecated__("use meshlink_set_canonical_address() and/or meshlink_add_invitation_address() instead")));
-
-/// Try to discover the external address for the local node.
-/** This function performs tries to discover the local node's external address
- * by contacting the meshlink.io server. If a reverse lookup of the address works,
- * the FQDN associated with the address will be returned.
- *
- * Please note that this is function only returns a single address,
- * even if the local node might have more than one external address.
- * In that case, there is no control over which address will be selected.
- * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT,
- * there is no guarantee that the external address will be valid for an extended period of time.
- *
- * This function is blocking. It can take several seconds before it returns.
- * There is no guarantee it will be able to resolve the external address.
- * Failures might be because by temporary network outages.
- *
- * \memberof meshlink_handle
- * @param mesh A handle which represents an instance of MeshLink.
- *
- * @return This function returns a pointer to a C string containing the discovered external address,
- * or NULL if there was an error looking up the address.
- * After meshlink_get_external_address() returns, the application is free to overwrite or free this string.
- */
-char *meshlink_get_external_address(struct meshlink_handle *mesh) __attribute__((__warn_unused_result__));
-
-/// Try to discover the external address for the local node.
-/** This function performs tries to discover the local node's external address
- * by contacting the meshlink.io server. If a reverse lookup of the address works,
- * the FQDN associated with the address will be returned.
- *
- * Please note that this is function only returns a single address,
- * even if the local node might have more than one external address.
- * In that case, there is no control over which address will be selected.
- * Also note that if you have a dynamic IP address, or are behind carrier-grade NAT,
- * there is no guarantee that the external address will be valid for an extended period of time.
- *
- * This function is blocking. It can take several seconds before it returns.
- * There is no guarantee it will be able to resolve the external address.
- * Failures might be because by temporary network outages.
- *
- * \memberof meshlink_handle
- * @param mesh A handle which represents an instance of MeshLink.
- * @param address_family The address family to check, for example AF_INET or AF_INET6. If AF_UNSPEC is given,
- * this might return the external address for any working address family.
- *
- * @return This function returns a pointer to a C string containing the discovered external address,
- * or NULL if there was an error looking up the address.
- * After meshlink_get_external_address_for_family() returns, the application is free to overwrite or free this string.
- */
-char *meshlink_get_external_address_for_family(struct meshlink_handle *mesh, int address_family) __attribute__((__warn_unused_result__));
-
-/// Try to discover the local address for the local node.
-/** This function performs tries to discover the address of the local interface used for outgoing connection.
- *
- * Please note that this is function only returns a single address,
- * even if the interface might have more than one address.
- * In that case, there is no control over which address will be selected.
- * Also note that if you have a dynamic IP address,
- * there is no guarantee that the local address will be valid for an extended period of time.
- *
- * This function will fail if it couldn't find a local address for the given address family.
- * If hostname resolving is requested, this function may block for a few seconds.
- *
- * \memberof meshlink_handle
- * @param mesh A handle which represents an instance of MeshLink.
- * @param address_family The address family to check, for example AF_INET or AF_INET6. If AF_UNSPEC is given,
- * this might return the local address for any working address family.
- *
- * @return This function returns a pointer to a C string containing the discovered local address,
- * or NULL if there was an error looking up the address.
- * After meshlink_get_local_address_for_family() returns, the application is free to overwrite or free this string.
- */
-char *meshlink_get_local_address_for_family(struct meshlink_handle *mesh, int address_family) __attribute__((__warn_unused_result__));
-
-/// Try to discover the external address for the local node, and add it to its list of addresses.
-/** This function is equivalent to:
- *
- * meshlink_set_canonical_address(mesh, meshlink_get_self(mesh), meshlink_get_external_address(mesh), NULL);
- *
- * Read the description of meshlink_get_external_address() for the limitations of this function.
- *
- * \memberof meshlink_handle
- * @param mesh A handle which represents an instance of MeshLink.
- *
- * @return This function returns true if the address was added, false otherwise.
- */
-bool meshlink_add_external_address(struct meshlink_handle *mesh) __attribute__((__warn_unused_result__));
-
/** This function allows the local node to join an existing mesh using an invitation URL generated by another node.
* An invitation can only be used if the local node has never connected to other nodes before.
* After a successfully accepted invitation, the name of the local node may have changed.
}
-// Find out what local address a socket would use if we connect to the given address.
-// We do this using connect() on a UDP socket, so the kernel has to resolve the address
-// of both endpoints, but this will actually not send any UDP packet.
-static bool getlocaladdr(const char *destaddr, sockaddr_t *sa, socklen_t *salen, int netns) {
- struct addrinfo *rai = NULL;
- const struct addrinfo hint = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_DGRAM,
- .ai_protocol = IPPROTO_UDP,
- .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV,
- };
-
- if(getaddrinfo(destaddr, "80", &hint, &rai) || !rai) {
- return false;
- }
-
- int sock = socket_in_netns(rai->ai_family, rai->ai_socktype, rai->ai_protocol, netns);
-
- if(sock == -1) {
- freeaddrinfo(rai);
- return false;
- }
-
- if(connect(sock, rai->ai_addr, rai->ai_addrlen) && !sockwouldblock(errno)) {
- closesocket(sock);
- freeaddrinfo(rai);
- return false;
- }
-
- freeaddrinfo(rai);
-
- if(getsockname(sock, &sa->sa, salen)) {
- closesocket(sock);
- return false;
- }
-
- closesocket(sock);
- return true;
-}
-
-static bool getlocaladdrname(const char *destaddr, char *host, socklen_t hostlen, int netns) {
- sockaddr_t sa;
- socklen_t salen = sizeof(sa);
-
- if(!getlocaladdr(destaddr, &sa, &salen, netns)) {
- return false;
- }
-
- if(getnameinfo(&sa.sa, salen, host, hostlen, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) {
- return false;
- }
-
- return true;
-}
-
-char *meshlink_get_external_address(meshlink_handle_t *mesh) {
- return meshlink_get_external_address_for_family(mesh, AF_UNSPEC);
-}
-
-char *meshlink_get_external_address_for_family(meshlink_handle_t *mesh, int family) {
- logger(mesh, MESHLINK_DEBUG, "meshlink_get_external_address_for_family(%d)", family);
- const char *url = mesh->external_address_url;
-
- if(!url) {
- url = "http://meshlink.io/host.cgi";
- }
-
- /* Find the hostname part between the slashes */
- if(strncmp(url, "http://", 7)) {
- abort();
- meshlink_errno = MESHLINK_EINTERNAL;
- return NULL;
- }
-
- const char *begin = url + 7;
-
- const char *end = strchr(begin, '/');
-
- if(!end) {
- end = begin + strlen(begin);
- }
-
- /* Make a copy */
- char host[end - begin + 1];
- strncpy(host, begin, end - begin);
- host[end - begin] = 0;
-
- char *port = strchr(host, ':');
-
- if(port) {
- *port++ = 0;
- }
-
- logger(mesh, MESHLINK_DEBUG, "Trying to discover externally visible hostname...\n");
- struct addrinfo *ai = str2addrinfo(host, port ? port : "80", SOCK_STREAM);
- char line[256];
- char *hostname = NULL;
-
- for(struct addrinfo *aip = ai; aip; aip = aip->ai_next) {
- if(family != AF_UNSPEC && aip->ai_family != family) {
- continue;
- }
-
- int s = socket_in_netns(aip->ai_family, aip->ai_socktype, aip->ai_protocol, mesh->netns);
-
-#ifdef SO_NOSIGPIPE
- int nosigpipe = 1;
- setsockopt(s, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
-#endif
-
- if(s >= 0) {
- set_timeout(s, 5000);
-
- if(connect(s, aip->ai_addr, aip->ai_addrlen)) {
- closesocket(s);
- s = -1;
- }
- }
-
- if(s >= 0) {
- send(s, "GET ", 4, 0);
- send(s, url, strlen(url), 0);
- send(s, " HTTP/1.0\r\n\r\n", 13, 0);
- int len = recv(s, line, sizeof(line) - 1, MSG_WAITALL);
-
- if(len > 0) {
- line[len] = 0;
-
- if(line[len - 1] == '\n') {
- line[--len] = 0;
- }
-
- char *p = strrchr(line, '\n');
-
- if(p && p[1]) {
- hostname = xstrdup(p + 1);
- }
- }
-
- closesocket(s);
-
- if(hostname) {
- break;
- }
- }
- }
-
- if(ai) {
- freeaddrinfo(ai);
- }
-
- // Check that the hostname is reasonable
- if(hostname && !is_valid_hostname(hostname)) {
- free(hostname);
- hostname = NULL;
- }
-
- if(!hostname) {
- meshlink_errno = MESHLINK_ERESOLV;
- }
-
- return hostname;
-}
-
-static bool is_localaddr(sockaddr_t *sa) {
- switch(sa->sa.sa_family) {
- case AF_INET:
- return *(uint8_t *)(&sa->in.sin_addr.s_addr) == 127;
-
- case AF_INET6: {
- uint16_t first = sa->in6.sin6_addr.s6_addr[0] << 8 | sa->in6.sin6_addr.s6_addr[1];
- return first == 0 || (first & 0xffc0) == 0xfe80;
- }
-
- default:
- return false;
- }
-}
-
-#ifdef HAVE_GETIFADDRS
-struct getifaddrs_in_netns_params {
- struct ifaddrs **ifa;
- int netns;
-};
-
-#ifdef HAVE_SETNS
-static void *getifaddrs_in_netns_thread(void *arg) {
- struct getifaddrs_in_netns_params *params = arg;
-
- if(setns(params->netns, CLONE_NEWNET) == -1) {
- meshlink_errno = MESHLINK_EINVAL;
- return NULL;
- }
-
- if(getifaddrs(params->ifa) != 0) {
- *params->ifa = NULL;
- }
-
- return NULL;
-}
-#endif // HAVE_SETNS
-
-static int getifaddrs_in_netns(struct ifaddrs **ifa, int netns) {
- if(netns == -1) {
- return getifaddrs(ifa);
- }
-
-#ifdef HAVE_SETNS
- struct getifaddrs_in_netns_params params = {ifa, netns};
- pthread_t thr;
-
- if(pthread_create(&thr, NULL, getifaddrs_in_netns_thread, ¶ms) == 0) {
- if(pthread_join(thr, NULL) != 0) {
- abort();
- }
- }
-
- return *params.ifa ? 0 : -1;
-#else
- return -1;
-#endif // HAVE_SETNS
-
-}
-#endif
-
-char *meshlink_get_local_address_for_family(meshlink_handle_t *mesh, int family) {
- logger(mesh, MESHLINK_DEBUG, "meshlink_get_local_address_for_family(%d)", family);
-
- if(!mesh) {
- meshlink_errno = MESHLINK_EINVAL;
- return NULL;
- }
-
- // Determine address of the local interface used for outgoing connections.
- char localaddr[NI_MAXHOST];
- bool success = false;
-
- if(family == AF_INET) {
- success = getlocaladdrname("93.184.216.34", localaddr, sizeof(localaddr), mesh->netns);
- } else if(family == AF_INET6) {
- success = getlocaladdrname("2606:2800:220:1:248:1893:25c8:1946", localaddr, sizeof(localaddr), mesh->netns);
- }
-
-#ifdef HAVE_GETIFADDRS
-
- if(!success) {
- struct ifaddrs *ifa = NULL;
- getifaddrs_in_netns(&ifa, mesh->netns);
-
- for(struct ifaddrs *ifap = ifa; ifap; ifap = ifap->ifa_next) {
- sockaddr_t *sa = (sockaddr_t *)ifap->ifa_addr;
-
- if(!sa || sa->sa.sa_family != family) {
- continue;
- }
-
- if(is_localaddr(sa)) {
- continue;
- }
-
- if(!getnameinfo(&sa->sa, SALEN(sa->sa), localaddr, sizeof(localaddr), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV)) {
- success = true;
- break;
- }
- }
-
- freeifaddrs(ifa);
- }
-
-#endif
-
- if(!success) {
- meshlink_errno = MESHLINK_ENETWORK;
- return NULL;
- }
-
- return xstrdup(localaddr);
-}
-
static bool write_main_config_files(meshlink_handle_t *mesh) {
if(!mesh->confbase) {
return true;
return tmin;
}
-// Get our local address(es) by simulating connecting to an Internet host.
-static void add_local_addresses(meshlink_handle_t *mesh) {
- sockaddr_t sa;
- sa.storage.ss_family = AF_UNKNOWN;
- socklen_t salen = sizeof(sa);
-
- // IPv4 example.org
-
- if(getlocaladdr("93.184.216.34", &sa, &salen, mesh->netns)) {
- sa.in.sin_port = ntohs(atoi(mesh->myport));
- node_add_recent_address(mesh, mesh->self, &sa);
- }
-
- // IPv6 example.org
-
- salen = sizeof(sa);
-
- if(getlocaladdr("2606:2800:220:1:248:1893:25c8:1946", &sa, &salen, mesh->netns)) {
- sa.in6.sin6_port = ntohs(atoi(mesh->myport));
- node_add_recent_address(mesh, mesh->self, &sa);
- }
-}
-
static bool meshlink_setup(meshlink_handle_t *mesh) {
if(!config_destroy(mesh->confbase, "new")) {
logger(mesh, MESHLINK_ERROR, "Could not delete configuration in %s/new: %s\n", mesh->confbase, strerror(errno));
return NULL;
}
- add_local_addresses(mesh);
-
if(!node_write_config(mesh, mesh->self, new_configuration)) {
logger(NULL, MESHLINK_ERROR, "Cannot update configuration\n");
return NULL;
return config_sync(mesh, "current");
}
-bool meshlink_add_address(meshlink_handle_t *mesh, const char *address) {
- logger(mesh, MESHLINK_DEBUG, "meshlink_add_address(%s)", address ? address : "(null)");
-
- return meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL);
-}
-
-bool meshlink_add_external_address(meshlink_handle_t *mesh) {
- logger(mesh, MESHLINK_DEBUG, "meshlink_add_external_address()");
-
- if(!mesh) {
- meshlink_errno = MESHLINK_EINVAL;
- return false;
- }
-
- char *address = meshlink_get_external_address(mesh);
-
- if(!address) {
- return false;
- }
-
- bool rval = meshlink_set_canonical_address(mesh, (meshlink_node_t *)mesh->self, address, NULL);
- free(address);
-
- return rval;
-}
-
bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
logger(mesh, MESHLINK_DEBUG, "meshlink_join(%s)", invitation ? invitation : "(null)");
devtool_set_meta_status_cb
devtool_set_inviter_commits_first
devtool_trybind_probe
-meshlink_add_address
-meshlink_add_external_address
meshlink_channel_abort
meshlink_channel_aio_fd_receive
meshlink_channel_aio_fd_send
meshlink_get_all_nodes_by_dev_class
meshlink_get_all_nodes_by_last_reachable
meshlink_get_all_nodes_by_submesh
-meshlink_get_external_address
-meshlink_get_external_address_for_family
meshlink_get_fingerprint
-meshlink_get_local_address_for_family
meshlink_get_node
meshlink_get_node_dev_class
meshlink_get_node_reachability