+
+ /* Forward it if necessary */
+
+ if(to != myself) {
+ if(tunnelserver)
+ return true;
+
+ if(!to->status.reachable) {
+ logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
+ "ANS_KEY", c->name, c->hostname, to_name);
+ return true;
+ }
+
+ if(!*address && from->address.sa.sa_family != AF_UNSPEC) {
+ char *address, *port;
+ ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
+ sockaddr2str(&from->address, &address, &port);
+ send_request(to->nexthop->connection, "%s %s %s", request, address, port);
+ free(address);
+ free(port);
+ return true;
+ }
+
+ return send_request(to->nexthop->connection, "%s", request);
+ }
+
+ /* Check and lookup cipher and digest algorithms */
+
+ if(!cipher_open_by_nid(&from->outcipher, cipher)) {
+ logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
+ return false;
+ }
+
+ keylen = strlen(key) / 2;
+
+ if(keylen != cipher_keylength(&from->outcipher)) {
+ logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
+ return false;
+ }
+
+ if(!digest_open_by_nid(&from->outdigest, digest, maclength)) {
+ logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
+ return false;
+ }
+
+ if(maclength != digest_length(&from->outdigest)) {
+ logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
+ return false;
+ }
+
+ if(compression < 0 || compression > 11) {
+ logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
+ return true;
+ }
+
+ from->outcompression = compression;
+
+ /* Update our copy of the origin's packet key */
+
+ hex2bin(key, key, keylen);
+ cipher_set_key(&from->outcipher, key, false);
+ digest_set_key(&from->outdigest, key, keylen);
+
+ from->status.validkey = true;
+ from->sent_seqno = 0;
+
+ if(*address && *port) {
+ ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
+ sockaddr_t sa = str2sockaddr(address, port);
+ update_node_udp(from, &sa);
+ }
+
+ if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent)
+ send_mtu_probe(from);
+
+ return true;