2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000 Guus Sliepen <guus@sliepen.warande.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: protocol.c,v 1.28.4.48 2000/10/29 00:24:31 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
37 #include <netinet/in.h>
39 #include <openssl/sha.h>
40 #include <openssl/rand.h>
52 int check_id(char *id)
56 for (i = 0; i < strlen(id); i++)
57 if(!isalnum(id[i]) && id[i] != '_')
63 /* Generic request routines - takes care of logging and error detection as well */
65 int send_request(conn_list_t *cl, const char *format, ...)
68 char buffer[MAXBUFSIZE];
72 /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic,
73 and there is a limit on the input buffer anyway */
75 va_start(args, format);
76 len = vsnprintf(buffer, MAXBUFSIZE, format, args);
77 request = va_arg(args, int);
80 if(len < 0 || len > MAXBUFSIZE-1)
82 syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
88 if(debug_lvl >= DEBUG_PROTOCOL)
89 syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
92 return send_meta(cl, buffer, len);
95 int receive_request(conn_list_t *cl)
99 if(sscanf(cl->buffer, "%d", &request) == 1)
101 if((request < 0) || (request > 255) || (request_handlers[request] == NULL))
103 syslog(LOG_ERR, _("Unknown request from %s (%s)"),
104 cl->name, cl->hostname);
109 if(debug_lvl >= DEBUG_PROTOCOL)
110 syslog(LOG_DEBUG, _("Got %s from %s (%s)"),
111 request_name[request], cl->name, cl->hostname);
114 if(request_handlers[request](cl))
115 /* Something went wrong. Probably scriptkiddies. Terminate. */
117 syslog(LOG_ERR, _("Error while processing %s from %s (%s)"),
118 request_name[request], cl->name, cl->hostname);
124 syslog(LOG_ERR, _("Bogus data received from %s (%s)"),
125 cl->name, cl->hostname);
132 /* Connection protocol:
141 ---------------------------------------
142 Any negotations about the meta protocol
143 encryption go here(u).
144 ---------------------------------------
147 ---------------------------------------
153 (E) Encrypted with symmetric cipher.
155 Part of the challenge is directly used to set the symmetric cipher key and the initial vector.
156 Since a man-in-the-middle cannot decrypt the RSA challenges, this means that he cannot get or
157 forge the key for the symmetric cipher.
160 int send_id(conn_list_t *cl)
163 cl->allow_request = CHALLENGE;
165 return send_request(cl, "%d %s %d %lx %hd", ID, myself->name, myself->protocol_version, myself->options, myself->port);
168 int id_h(conn_list_t *cl)
173 if(sscanf(cl->buffer, "%*d %as %d %lx %hd", &cl->name, &cl->protocol_version, &cl->options, &cl->port) != 4)
175 syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
179 /* Check if version matches */
181 if(cl->protocol_version != myself->protocol_version)
183 syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
184 cl->name, cl->hostname, cl->protocol_version);
188 /* Check if identity is a valid name */
190 if(check_id(cl->name))
192 syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
196 /* Load information about peer */
198 if(read_host_config(cl))
200 syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
204 /* First check if the host we connected to is already in our
205 connection list. If so, we are probably making a loop, which
209 if(cl->status.outgoing)
211 if((old = lookup_id(cl->name)))
213 if(debug_lvl >= DEBUG_CONNECTIONS)
214 syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
215 cl->status.outgoing = 0;
216 old->status.outgoing = 1;
217 terminate_connection(cl);
222 if((cfg = get_config_val(cl->config, publickey)))
224 cl->rsa_key = RSA_new();
225 BN_hex2bn(&cl->rsa_key->n, cfg->data.ptr);
226 BN_hex2bn(&cl->rsa_key->e, "FFFF");
230 syslog(LOG_ERR, _("No public key known for %s (%s)"), cl->name, cl->hostname);
234 return send_challenge(cl);
237 int send_challenge(conn_list_t *cl)
242 len = RSA_size(cl->rsa_key);
244 /* Allocate buffers for the challenge */
246 buffer = xmalloc(len*2+1);
249 free(cl->hischallenge);
251 cl->hischallenge = xmalloc(len);
253 /* Seed the PRNG with urandom (can't afford to block) */
255 RAND_load_file("/dev/urandom", 1024);
257 /* Copy random data to the buffer */
259 RAND_bytes(cl->hischallenge, len);
261 cl->hischallenge[0] &= 0x7F; /* Somehow if the first byte is more than 0xD0 or something like that, decryption fails... */
263 if(debug_lvl >= DEBUG_SCARY_THINGS)
265 bin2hex(cl->hischallenge, buffer, len);
266 buffer[len*2] = '\0';
267 syslog(LOG_DEBUG, _("Generated random challenge (unencrypted): %s"), buffer);
270 /* Encrypt the random data */
272 if(RSA_public_encrypt(len, cl->hischallenge, buffer, cl->rsa_key, RSA_NO_PADDING) != len) /* NO_PADDING because the message size equals the RSA key size and it is totally random */
274 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
279 /* Convert the encrypted random data to a hexadecimal formatted string */
281 bin2hex(buffer, buffer, len);
282 buffer[len*2] = '\0';
284 /* Send the challenge */
286 cl->allow_request = CHAL_REPLY;
287 x = send_request(cl, "%d %s", CHALLENGE, buffer);
293 int challenge_h(conn_list_t *cl)
298 if(sscanf(cl->buffer, "%*d %as", &buffer) != 1)
300 syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
304 len = RSA_size(myself->rsa_key);
306 /* Check if the length of the challenge is all right */
308 if(strlen(buffer) != len*2)
310 syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
315 /* Allocate buffers for the challenge */
318 cl->mychallenge = xmalloc(len);
320 /* Convert the challenge from hexadecimal back to binary */
322 hex2bin(buffer,buffer,len);
324 /* Decrypt the challenge */
326 if(RSA_private_decrypt(len, buffer, cl->mychallenge, myself->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */
328 syslog(LOG_ERR, _("Error during encryption of challenge for %s (%s)"), cl->name, cl->hostname);
333 if(debug_lvl >= DEBUG_SCARY_THINGS)
335 bin2hex(cl->mychallenge, buffer, len);
336 buffer[len*2] = '\0';
337 syslog(LOG_DEBUG, _("Received random challenge (unencrypted): %s"), buffer);
342 /* Rest is done by send_chal_reply() */
344 return send_chal_reply(cl);
347 int send_chal_reply(conn_list_t *cl)
349 char hash[SHA_DIGEST_LENGTH*2+1];
353 syslog(LOG_ERR, _("Trying to send CHAL_REPLY to %s (%s) without a valid CHALLENGE"), cl->name, cl->hostname);
357 /* Calculate the hash from the challenge we received */
359 SHA1(cl->mychallenge, RSA_size(myself->rsa_key), hash);
361 /* Convert the hash to a hexadecimal formatted string */
363 bin2hex(hash,hash,SHA_DIGEST_LENGTH);
364 hash[SHA_DIGEST_LENGTH*2] = '\0';
368 if(cl->status.outgoing)
369 cl->allow_request = ID;
371 cl->allow_request = ACK;
374 return send_request(cl, "%d %s", CHAL_REPLY, hash);
377 int chal_reply_h(conn_list_t *cl)
380 char myhash[SHA_DIGEST_LENGTH];
382 if(sscanf(cl->buffer, "%*d %as", &hishash) != 1)
384 syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
389 /* Check if the length of the hash is all right */
391 if(strlen(hishash) != SHA_DIGEST_LENGTH*2)
393 syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
398 /* Convert the hash to binary format */
400 hex2bin(hishash, hishash, SHA_DIGEST_LENGTH);
402 /* Calculate the hash from the challenge we sent */
404 SHA1(cl->hischallenge, RSA_size(cl->rsa_key), myhash);
406 /* Verify the incoming hash with the calculated hash */
408 if(memcmp(hishash, myhash, SHA_DIGEST_LENGTH))
410 syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
411 if(debug_lvl >= DEBUG_SCARY_THINGS)
413 bin2hex(myhash, hishash, SHA_DIGEST_LENGTH);
414 hishash[SHA_DIGEST_LENGTH*2] = '\0';
415 syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash);
424 /* Identity has now been positively verified.
425 If we are accepting this new connection, then send our identity,
426 if we are making this connecting, acknowledge.
429 if(cl->status.outgoing)
435 int send_ack(conn_list_t *cl)
438 cl->allow_request = ACK;
440 return send_request(cl, "%d", ACK);
443 int ack_h(conn_list_t *cl)
445 conn_list_t *old, *p;
448 /* Okay, before we active the connection, we check if there is another entry
449 in the connection list with the same name. If so, it presumably is an
450 old connection that has timed out but we don't know it yet.
453 while((old = lookup_id(cl->name)))
455 if(debug_lvl >= DEBUG_CONNECTIONS)
456 syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
457 cl->name, old->hostname, cl->hostname);
459 terminate_connection(old);
462 /* Activate this connection */
464 cl->allow_request = ALL;
465 cl->status.active = 1;
468 if(debug_lvl >= DEBUG_CONNECTIONS)
469 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
472 if(!cl->status.outgoing)
475 /* Send him our subnets */
477 for(s = myself->subnets; s; s = s->next)
478 send_add_subnet(cl, s);
480 /* And send him all the hosts and their subnets we know... */
482 for(p = conn_list; p; p = p->next)
483 if(p != cl && p->status.active)
485 /* Notify others of this connection */
488 send_add_host(p, cl);
490 /* Notify new connection of everything we know */
492 send_add_host(cl, p);
494 for(s = p->subnets; s; s = s->next)
495 send_add_subnet(cl, s);
501 /* Address and subnet information exchange */
503 int send_add_subnet(conn_list_t *cl, subnet_t *subnet)
508 x = send_request(cl, "%d %s %s", ADD_SUBNET,
509 subnet->owner->name, netstr = net2str(subnet));
515 int add_subnet_h(conn_list_t *cl)
519 conn_list_t *owner, *p;
522 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 2)
524 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
525 free(name); free(subnetstr);
529 /* Check if owner name is a valid */
533 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
534 free(name); free(subnetstr);
538 /* Check if subnet string is valid */
540 if(!(subnet = str2net(subnetstr)))
542 syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
543 free(name); free(subnetstr);
549 /* Check if somebody tries to add a subnet of ourself */
551 if(!strcmp(name, myself->name))
553 syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
554 cl->name, cl->hostname);
560 /* Check if the owner of the new subnet is in the connection list */
562 if(!(owner = lookup_id(name)))
564 syslog(LOG_ERR, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
565 name, cl->name, cl->hostname);
570 /* If everything is correct, add the subnet to the list of the owner */
572 subnet_add(owner, subnet);
576 for(p = conn_list; p; p = p->next)
577 if(p->status.meta && p->status.active && p!= cl)
578 send_add_subnet(p, subnet);
583 int send_del_subnet(conn_list_t *cl, subnet_t *subnet)
588 netstr = net2str(subnet);
589 x = send_request(cl, "%d %s %s", DEL_SUBNET, subnet->owner->name, netstr);
595 int del_subnet_h(conn_list_t *cl)
599 conn_list_t *owner, *p;
602 if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
604 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
605 free(name); free(subnetstr);
609 /* Check if owner name is a valid */
613 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
614 free(name); free(subnetstr);
618 /* Check if subnet string is valid */
620 if(!(subnet = str2net(subnetstr)))
622 syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
623 free(name); free(subnetstr);
629 /* Check if somebody tries to add a subnet of ourself */
631 if(!strcmp(name, myself->name))
633 syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
634 cl->name, cl->hostname);
640 /* Check if the owner of the new subnet is in the connection list */
642 if(!(owner = lookup_id(name)))
644 syslog(LOG_ERR, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
645 name, cl->name, cl->hostname);
650 /* If everything is correct, delete the subnet from the list of the owner */
656 for(p = conn_list; p; p = p->next)
657 if(p->status.meta && p->status.active && p!= cl)
658 send_del_subnet(p, subnet);
663 /* New and closed connections notification */
665 int send_add_host(conn_list_t *cl, conn_list_t *other)
668 return send_request(cl, "%d %s %lx:%d %lx", ADD_HOST,
669 other->name, other->address, other->port, other->options);
672 int add_host_h(conn_list_t *cl)
674 conn_list_t *old, *new;
677 new = new_conn_list();
679 if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &new->name, &new->address, &new->port, &new->options) != 4)
681 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
685 /* Check if identity is a valid name */
687 if(check_id(new->name))
689 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
694 /* Check if somebody tries to add ourself */
696 if(!strcmp(new->name, myself->name))
698 syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
704 /* Fill in more of the new conn_list structure */
706 new->hostname = hostlookup(htonl(new->address));
708 /* Check if the new host already exists in the connnection list */
710 if((old = lookup_id(new->name)))
712 if((new->address == old->address) && (new->port == old->port))
714 if(debug_lvl >= DEBUG_CONNECTIONS)
715 syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
716 old->name, old->hostname, new->name, new->hostname);
722 if(debug_lvl >= DEBUG_CONNECTIONS)
723 syslog(LOG_NOTICE, _("Removing old entry for %s (%s) in favour of new connection"),
724 old->name, old->hostname);
726 terminate_connection(old);
730 /* Hook it up into the conn_list */
734 /* Tell the rest about the new host */
736 for(p = conn_list; p; p = p->next)
737 if(p->status.meta && p->status.active && p!=cl)
738 send_add_host(p, new);
740 /* Fill in rest of conn_list structure */
743 new->status.active = 1;
749 int send_del_host(conn_list_t *cl, conn_list_t *other)
752 return send_request(cl, "%d %s %lx:%d %lx", DEL_HOST,
753 other->name, other->address, other->port, other->options);
756 int del_host_h(conn_list_t *cl)
762 conn_list_t *old, *p;
764 if(sscanf(cl->buffer, "%*d %as %lx:%d %lx", &name, &address, &port, &options) != 4)
766 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
767 cl->name, cl->hostname);
771 /* Check if identity is a valid name */
775 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
780 /* Check if somebody tries to delete ourself */
782 if(!strcmp(name, myself->name))
784 syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
785 cl->name, cl->hostname);
791 /* Check if the new host already exists in the connnection list */
793 if(!(old = lookup_id(name)))
795 syslog(LOG_ERR, _("Got DEL_HOST from %s (%s) for %s which is not in our connection list"),
796 name, cl->name, cl->hostname);
801 /* Check if the rest matches */
803 if(address!=old->address || port!=old->port || options!=old->options || cl!=old->nexthop)
805 syslog(LOG_WARNING, _("Got DEL_HOST from %s (%s) for %s which doesn't match"), cl->name, cl->hostname, old->name);
809 /* Ok, since EVERYTHING seems to check out all right, delete it */
811 old->status.active = 0;
812 terminate_connection(old);
814 /* Tell the rest about the new host */
816 for(p = conn_list; p; p = p->next)
817 if(p->status.meta && p->status.active && p!=cl)
818 send_del_host(p, old);
823 /* Status and error notification routines */
825 int send_status(conn_list_t *cl, int statusno, char *statusstring)
829 statusstring = status_text[statusno];
831 return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
834 int status_h(conn_list_t *cl)
839 if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
841 syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
842 cl->name, cl->hostname);
846 if(debug_lvl >= DEBUG_STATUS)
848 syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
849 cl->name, cl->hostname, status_text[statusno], statusstring);
857 int send_error(conn_list_t *cl, int errno, char *errstring)
861 errstring = strerror(errno);
862 return send_request(cl, "%d %d %s", ERROR, errno, errstring);
865 int error_h(conn_list_t *cl)
870 if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
872 syslog(LOG_ERR, _("Got bad ERROR from %s (%s)"),
873 cl->name, cl->hostname);
877 if(debug_lvl >= DEBUG_ERROR)
879 syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
880 cl->name, cl->hostname, strerror(errno), errorstring);
884 terminate_connection(cl);
889 int send_termreq(conn_list_t *cl)
892 return send_request(cl, "%d", TERMREQ);
895 int termreq_h(conn_list_t *cl)
898 terminate_connection(cl);
903 /* Keepalive routines - FIXME: needs a closer look */
905 int send_ping(conn_list_t *cl)
907 cl->status.pinged = 1;
909 return send_request(cl, "%d", PING);
912 int ping_h(conn_list_t *cl)
915 return send_pong(cl);
918 int send_pong(conn_list_t *cl)
921 return send_request(cl, "%d", PONG);
924 int pong_h(conn_list_t *cl)
927 cl->status.got_pong = 1;
934 int send_key_changed(conn_list_t *from, conn_list_t *cl)
938 for(p = conn_list; p != NULL; p = p->next)
940 if(p!=cl && p->status.meta && p->status.active)
941 send_request(p, "%d %s", KEY_CHANGED,
948 int key_changed_h(conn_list_t *cl)
953 if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
955 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
956 cl->name, cl->hostname);
960 if(!(from = lookup_id(from_id)))
962 syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
963 cl->name, cl->hostname, from_id);
970 from->status.validkey = 0;
971 from->status.waitingforkey = 0;
973 send_key_changed(from, cl);
978 int send_req_key(conn_list_t *from, conn_list_t *to)
981 return send_request(to->nexthop, "%d %s %s", REQ_KEY,
982 from->name, to->name);
985 int req_key_h(conn_list_t *cl)
987 char *from_id, *to_id;
988 conn_list_t *from, *to;
990 if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
992 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
993 cl->name, cl->hostname);
997 if(!(from = lookup_id(from_id)))
999 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
1000 cl->name, cl->hostname, from_id);
1001 free(from_id); free(to_id);
1005 /* Check if this key request is for us */
1007 if(!strcmp(to_id, myself->name))
1009 send_ans_key(myself, from, myself->cipher_pktkey);
1013 if(!(to = lookup_id(to_id)))
1015 syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
1016 cl->name, cl->hostname, to_id);
1017 free(from_id); free(to_id);
1020 send_req_key(from, to);
1023 free(from_id); free(to_id);
1028 int send_ans_key(conn_list_t *from, conn_list_t *to, char *pktkey)
1031 return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
1032 from->name, to->name, pktkey);
1035 int ans_key_h(conn_list_t *cl)
1037 char *from_id, *to_id, *pktkey;
1039 conn_list_t *from, *to;
1041 if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &pktkey) != 3)
1043 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
1044 cl->name, cl->hostname);
1048 if(!(from = lookup_id(from_id)))
1050 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
1051 cl->name, cl->hostname, from_id);
1052 free(from_id); free(to_id); free(pktkey);
1056 /* Check if this key request is for us */
1058 if(!strcmp(to_id, myself->name))
1060 /* It is for us, convert it to binary and set the key with it. */
1062 keylength = strlen(pktkey);
1064 /* Don't do this... yet
1065 if((keylength%2) || (keylength <= 0))
1067 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key"),
1068 cl->name, cl->hostname, from->name);
1069 free(from_id); free(to_id); free(pktkey);
1073 hex2bin(pktkey, pktkey, keylength);
1074 BF_set_key(cl->cipher_pktkey, keylength, pktkey);
1077 from->status.validkey = 1;
1078 from->status.waitingforkey = 0;
1082 if(!(to = lookup_id(to_id)))
1084 syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
1085 cl->name, cl->hostname, to_id);
1086 free(from_id); free(to_id); free(pktkey);
1089 send_ans_key(from, to, pktkey);
1092 free(from_id); free(to_id); free(pktkey);
1097 /* Jumptable for the request handlers */
1099 int (*request_handlers[])(conn_list_t*) = {
1100 id_h, challenge_h, chal_reply_h, ack_h,
1101 status_h, error_h, termreq_h,
1103 add_host_h, del_host_h,
1104 add_subnet_h, del_subnet_h,
1105 key_changed_h, req_key_h, ans_key_h,
1110 char (*request_name[]) = {
1111 "ID", "CHALLENGE", "CHAL_REPLY", "ACK",
1112 "STATUS", "ERROR", "TERMREQ",
1114 "ADD_HOST", "DEL_HOST",
1115 "ADD_SUBNET", "DEL_SUBNET",
1116 "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1119 /* Status strings */
1121 char (*status_text[]) = {
1127 char (*error_text[]) = {