-int id_h(connection_t *c)
-{
- char name[MAX_STRING_SIZE];
- int bla;
-cp
- if(sscanf(c->buffer, "%*d "MAX_STRING" %d", name, &c->protocol_version) != 2)
- {
- syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name, c->hostname);
- return -1;
- }
-
- /* Check if identity is a valid name */
-
- if(check_id(name))
- {
- syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ID", c->name, c->hostname, "invalid name");
- return -1;
- }
-
- /* If we set c->name in advance, make sure we are connected to the right host */
-
- if(c->name)
- {
- if(strcmp(c->name, name))
- {
- syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, c->name);
- return -1;
- }
- }
- else
- c->name = xstrdup(name);
-
- /* Check if version matches */
-
- if(c->protocol_version != myself->connection->protocol_version)
- {
- syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
- c->name, c->hostname, c->protocol_version);
- return -1;
- }
-
- if(bypass_security)
- {
- if(!c->config_tree)
- init_configuration(&c->config_tree);
- c->allow_request = ACK;
- return send_ack(c);
- }
-
- if(!c->config_tree)
- {
- init_configuration(&c->config_tree);
-
- if((bla = read_connection_config(c)))
- {
- syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, c->name);
- return -1;
- }
- }
-
- if(read_rsa_public_key(c))
- {
- return -1;
- }
-
- /* Check some options */
-
- if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &bla) && bla) || myself->options & OPTION_INDIRECT)
- c->options |= OPTION_INDIRECT;
-
- if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &bla) && bla) || myself->options & OPTION_TCPONLY)
- c->options |= OPTION_TCPONLY | OPTION_INDIRECT;
-
- c->allow_request = METAKEY;
-cp
- return send_metakey(c);
+bool id_h(connection_t *c, const char *request) {
+ char name[MAX_STRING_SIZE];
+
+ if(sscanf(request, "%*d " MAX_STRING " %d.%d", name, &c->protocol_major, &c->protocol_minor) < 2) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s)", "ID", c->name,
+ c->hostname);
+ return false;
+ }
+
+ /* Check if this is a control connection */
+
+ if(name[0] == '^' && !strcmp(name + 1, controlcookie)) {
+ c->status.control = true;
+ c->allow_request = CONTROL;
+ c->last_ping_time = time(NULL) + 3600;
+
+ free(c->name);
+ c->name = xstrdup("<control>");
+
+ return send_request(c, "%d %d %d", ACK, TINC_CTL_VERSION_CURRENT, getpid());
+ }
+
+ /* Check if identity is a valid name */
+
+ if(!check_id(name)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ID", c->name,
+ c->hostname, "invalid name");
+ return false;
+ }
+
+ /* If this is an outgoing connection, make sure we are connected to the right host */
+
+ if(c->outgoing) {
+ if(strcmp(c->name, name)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s is %s instead of %s", c->hostname, name,
+ c->name);
+ return false;
+ }
+ } else {
+ if(c->name)
+ free(c->name);
+ c->name = xstrdup(name);
+ }
+
+ /* Check if version matches */
+
+ if(c->protocol_major != myself->connection->protocol_major) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s (%s) uses incompatible version %d.%d",
+ c->name, c->hostname, c->protocol_major, c->protocol_minor);
+ return false;
+ }
+
+ if(bypass_security) {
+ if(!c->config_tree)
+ init_configuration(&c->config_tree);
+ c->allow_request = ACK;
+ return send_ack(c);
+ }
+
+ if(!experimental)
+ c->protocol_minor = 0;
+
+ if(!c->config_tree) {
+ init_configuration(&c->config_tree);
+
+ if(!read_connection_config(c)) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Peer %s had unknown identity (%s)", c->hostname,
+ c->name);
+ return false;
+ }
+
+ if(experimental && c->protocol_minor >= 2) {
+ if(!read_ecdsa_public_key(c))
+ return false;
+ }
+ } else {
+ if(c->protocol_minor && !ecdsa_active(&c->ecdsa))
+ c->protocol_minor = 1;
+ }
+
+ c->allow_request = METAKEY;
+
+ if(c->protocol_minor >= 2) {
+ c->allow_request = ACK;
+ char label[25 + strlen(myself->name) + strlen(c->name)];
+
+ if(c->outgoing)
+ snprintf(label, sizeof label, "tinc TCP key expansion %s %s", myself->name, c->name);
+ else
+ snprintf(label, sizeof label, "tinc TCP key expansion %s %s", c->name, myself->name);
+
+ return sptps_start(&c->sptps, c, c->outgoing, false, myself->connection->ecdsa, c->ecdsa, label, sizeof label, send_meta_sptps, receive_meta_sptps);
+ } else {
+ return send_metakey(c);
+ }