35b07882275865d3effaf9f54ac538f34ed3cfa0
[tinc] / src / protocol.c
1 /*
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>
5
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.
10
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.
15
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.
19
20     $Id: protocol.c,v 1.28.4.33 2000/09/17 21:42:05 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <sys/types.h>
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <syslog.h>
30 #include <sys/socket.h>
31 #include <unistd.h>
32 #include <stdio.h>
33
34 #include <utils.h>
35 #include <xalloc.h>
36
37 #include <netinet/in.h>
38
39 #include <openssl/sha.h>
40
41 #include "conf.h"
42 #include "encr.h"
43 #include "net.h"
44 #include "netutl.h"
45 #include "protocol.h"
46
47 #include "system.h"
48
49 int check_id(char *id)
50 {
51   int i;
52
53   for (i = 0; i < strlen(id); i++)
54     {
55       if(!isalpha(id[i]) && id[i] != '_')
56         {
57           return 0;
58         }
59     }
60
61   return 1;
62 }
63
64 /* Generic outgoing request routine - takes care of logging and error detection as well */
65
66 int send_request(conn_list_t *cl, const char *format, int request, /*args*/ ...)
67 {
68   va_list args;
69   char buffer[MAXBUFSIZE+1];
70   int len;
71
72 cp
73   /* Use vsnprintf instead of vasprintf: faster, no memory fragmentation, cleanup is automatic,
74      and there is a limit on the input buffer anyway */
75
76   va_start(args, request);
77   len = vsnprintf(buffer, MAXBUFSIZE+1, format, args);
78   va_end(args);
79
80   if(len < 0 || len > MAXBUFSIZE)
81     {
82       syslog(LOG_ERR, _("Output buffer overflow while sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
83       return -1;
84     }
85
86   if(debug_lvl >= DEBUG_META)
87     syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request],
88            cl->name, cl->hostname, buffer);
89   else if(debug_lvl >= DEBUG_PROTOCOL)
90     syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], cl->name, cl->hostname);
91
92
93   if(cl->status.encryptin)
94     {
95       /* FIXME: Do encryption */
96     }
97
98   if((write(cl->meta_socket, buffer, len)) < 0)
99     {
100       syslog(LOG_ERR, _("Sending meta data failed:  %m"));
101       return -1;
102     }
103 cp
104 }
105
106 /* Connection protocol:
107
108    Client               Server
109    send_id(u)
110                         send_challenge(R)
111    send_chal_reply(H)
112                         send_id(u)
113    send_challenge(R)
114                         send_chal_reply(H)
115    ---------------------------------------
116    Any negotations about the meta protocol
117    encryption go here(u).
118    ---------------------------------------
119    send_ack(u)
120                         send_ack(u)
121    ---------------------------------------
122    Other requests(E)...
123
124    (u) Unencrypted,
125    (R) RSA,
126    (H) SHA1,
127    (E) Encrypted with symmetric cipher.
128
129    Part of the challenge is directly used to set the symmetric cipher key and the initial vector.
130    Since a man-in-the-middle cannot decrypt the RSA challenges, this means that he cannot get or
131    forge the key for the symmetric cipher.
132 */
133
134 int send_id(conn_list_t *cl)
135 {
136 cp
137   return send_request(cl, "%d %s %d %s", ID,
138                       myself->name, myself->protocol_version, opt2str(myself->options));
139 }
140
141 int id_h(conn_list_t *cl)
142 {
143   conn_list_t *old;
144   char *options;
145 cp
146   if(sscanf(cl->buffer, "%*d %as %d %as", &cl->name, &cl->protocol_version, &options) != 3)
147     {
148        syslog(LOG_ERR, _("Got bad ID from %s"), cl->hostname);
149        return -1;
150     }
151
152   /* Check if version matches */
153
154   if(cl->protocol_version != myself->protocol_version)
155     {
156       syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"),
157              cl->name, cl->hostname, cl->protocol_version);
158       return -1;
159     }
160
161   /* Check if option string is valid */
162
163   if((cl->options = str2opt(options)) == -1)
164     {
165       syslog(LOG_ERR, _("Peer %s uses invalid option string"), cl->hostname);
166       return -1;
167     }
168
169   /* Check if identity is a valid name */
170
171   if(!check_id(cl->name))
172     {
173       syslog(LOG_ERR, _("Peer %s uses invalid identity name"), cl->hostname);
174       return -1;
175     }
176
177   /* Load information about peer */
178
179   if(!read_id(cl))
180     {
181       syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), cl->hostname, cl->name);
182       return -1;
183     }
184
185
186   /* First check if the host we connected to is already in our
187      connection list. If so, we are probably making a loop, which
188      is not desirable.
189    */
190
191   if(cl->status.outgoing)
192     {
193       if((old = lookup_id(cl->name)))
194         {
195           if(debug_lvl > DEBUG_CONNECTIONS)
196             syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"), cl->name, cl->hostname);
197           cl->status.outgoing = 0;
198           old->status.outgoing = 1;
199           terminate_connection(cl);
200           return 0;
201         }
202     }
203
204   /* Send a challenge to verify the identity */
205
206   cl->allow_request = CHAL_REPLY;
207 cp
208   return send_challenge(cl);
209 }
210
211 int send_challenge(conn_list_t *cl)
212 {
213   char *buffer;
214   int keylength;
215   int x;
216 cp
217   if(cl->chal_answer)
218     free(cl->chal_answer);
219
220   /* Allocate buffers for the challenge and the hash */
221
222   cl->chal_answer = xmalloc(SHA_DIGEST_LENGTH);
223   keylength = BN_num_bytes(cl->rsakey->length);
224   buffer = xmalloc(keylength*2);
225
226   /* Copy random data and the public key to the buffer */
227
228   RAND_bytes(buffer, keylength);
229   BN_bn2bin(cl->rsakey->length, buffer+keylength);
230
231   /* If we don't have a blowfish key set yet, use the random data from the challenge to do so. */
232
233   if(!cl->status.encryptin)
234     {
235       set_metakey(cl, buffer, keylength);
236     }
237
238   /* Calculate the hash from that */
239
240   SHA1(buffer, keylength*2, cl->chal_answer);
241
242   /* Convert the random data to a hexadecimal formatted string */
243
244   bin2hex(buffer,buffer,keylength);
245   buffer[keylength*2] = '\0';
246
247   /* Send the challenge */
248
249   cl->allow_request = CHAL_REPLY;
250   x = send_request(cl, "%d %s", CHALLENGE, buffer);
251   free(buffer);
252   cl->status.encryptout = 1;
253 cp
254   return x;
255 }
256
257 int challenge_h(conn_list_t *cl)
258 {
259   char *challenge;
260   int x;
261
262 cp
263   if(sscanf(cl->buffer, "%*d %as", &cl->name, &challenge) != 1)
264     {
265        syslog(LOG_ERR, _("Got bad CHALLENGE from %s (%s)"), cl->name, cl->hostname);
266        return -1;
267     }
268
269   /* Rest is done by send_chal_reply() */
270
271   x = send_chal_reply(cl, challenge);
272   free(challenge);
273 cp
274   return x;
275 }
276
277 int send_chal_reply(conn_list_t *cl, char *challenge)
278 {
279   char *buffer;
280   int keylength;
281   char *hash;
282   int x;
283
284 cp
285   keylength = BN_num_bytes(myself->rsakey->length);
286
287   /* Check if the length of the challenge is all right */
288
289   if(strlen(challenge) != keylength*2)
290     {
291       syslog(LOG_ERR, _("Intruder: wrong challenge length from %s (%s)"), cl->name, cl->hostname);
292       return -1;
293     }
294
295   /* Allocate buffers for the challenge and the hash */
296
297   buffer = xmalloc(keylength*2);
298   hash = xmalloc(SHA_DIGEST_LENGTH*2+1);
299
300   /* Copy the incoming random data and our public key to the buffer */
301
302   hex2bin(challenge, buffer, keylength);
303   BN_bn2bin(myself->rsakey->length, buffer+keylength);
304
305   /* Calculate the hash from that */
306
307   SHA1(buffer, keylength*2, hash);
308
309   /* If we don't have a blowfish key set yet, use the random data from the challenge to do so. */
310
311   if(!cl->status.encrypted)
312     {
313       set_metakey(cl, buffer, keylength);
314       cl->status.encrypted = 1;
315     }
316
317   free(buffer);
318
319   /* Convert the hash to a hexadecimal formatted string */
320
321   bin2hex(hash,hash,SHA_DIGEST_LENGTH);
322   hash[SHA_DIGEST_LENGTH*2] = '\0';
323
324   /* Send the reply */
325
326   if(cl->status.outgoing)
327     cl->allow_request = ID;
328   else
329     cl->allow_request = ACK;
330
331   x = send_request(cl, "%d %s", CHAL_REPLY, hash);
332   free(hash);
333 cp
334   return x;
335 }
336
337 int chal_reply_h(conn_list_t *cl)
338 {
339   char *hash;
340 cp
341   if(sscanf(cl->buffer, "%*d %as", &cl->name, &hash) != 2)
342     {
343        syslog(LOG_ERR, _("Got bad CHAL_REPLY from %s (%s)"), cl->name, cl->hostname);
344        return -1;
345     }
346
347   /* Check if the length of the hash is all right */
348
349   if(strlen(hash) != SHA_DIGEST_LENGTH*2)
350     {
351       syslog(LOG_ERR, _("Intruder: wrong challenge reply length from %s (%s)"), cl->name, cl->hostname);
352       return -1;
353     }
354
355   /* Convert the hash to binary format */
356
357   hex2bin(hash, hash, SHA_DIGEST_LENGTH);
358
359   /* Verify the incoming hash with the calculated hash */
360
361   if(!memcmp(hash, cl->chal_answer, SHA_DIGEST_LENGTH))
362     {
363       syslog(LOG_ERR, _("Intruder: wrong challenge reply from %s (%s)"), cl->name, cl->hostname);
364       return -1;
365     }
366
367   /* Identity has now been positively verified.
368      If we are accepting this new connection, then send our identity,
369      if we are making this connecting, acknowledge.
370    */
371
372   free(hash);
373   free(cl->chal_answer);
374
375 cp
376   if(cl->status.outgoing)
377     {
378       cl->allow_request = ACK;
379       return send_ack(cl);
380     }
381   else
382     {
383       cl->allow_request = CHALLENGE;
384       return send_id(cl);
385     }
386 }
387
388 int send_ack(conn_list_t *cl)
389 {
390 cp
391   return send_request(cl, "%d", ACK);
392 }
393
394 int ack_h(conn_list_t *cl)
395 {
396   conn_list_t *old;
397
398 cp
399   /* Okay, before we active the connection, we check if there is another entry
400      in the connection list with the same vpn_ip. If so, it presumably is an
401      old connection that has timed out but we don't know it yet.
402    */
403
404   while((old = lookup_id(cl->name)))
405     {
406       if(debug_lvl > DEBUG_CONNECTIONS)
407         syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
408         cl->name, old->hostname, cl->hostname);
409       old->status.active = 0;
410       terminate_connection(old);
411     }
412
413   /* Activate this connection */
414
415   cl->allow_request = ALL;
416   cl->status.active = 1;
417
418   if(debug_lvl > DEBUG_CONNECTIONS)
419     syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), cl->name, cl->hostname);
420
421   /* Exchange information about other tinc daemons */
422
423   notify_others(cl, NULL, send_add_host);
424   notify_one(cl);
425
426   upstreamindex = 0;
427
428 cp
429   if(cl->status.outgoing)
430     return 0;
431   else
432     return send_ack(cl);
433 }
434
435 /* Address and subnet information exchange */
436
437 int send_add_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
438 {
439 cp
440   return send_request(cl, "%d %s %s", ADD_SUBNET,
441                       other->name, net2str(subnet));
442 }
443
444 int add_subnet_h(conn_list_t *cl)
445 {
446   char *subnetstr;
447   char *name;
448   conn_list_t *owner;
449   subnet_t *subnet, *old;
450 cp
451   if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
452     {
453        syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s)"), cl->name, cl->hostname);
454        return -1;
455     }
456
457   /* Check if owner name is a valid */
458
459   if(!check_id(name))
460     {
461       syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
462       return -1;
463     }
464
465   /* Check if subnet string is valid */
466
467   if((subnet = str2net(subnetstr)) == -1)
468     {
469       syslog(LOG_ERR, _("Got bad ADD_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
470       return -1;
471     }
472   
473   /* Check if somebody tries to add a subnet of ourself */
474
475   if(!strcmp(name, myself->name))
476     {
477       syslog(LOG_ERR, _("Warning: got ADD_SUBNET from %s (%s) for ourself, restarting"),
478              cl->name, cl->hostname);
479       sighup = 1;
480       return 0;
481     }
482
483   /* Check if the owner of the new subnet is in the connection list */
484
485   if(!(owner = lookup_id(name))
486     {
487       syslog(LOG_NOTICE, _("Got ADD_SUBNET for %s from %s (%s) which is not in our connection list"),
488              name, cl->name, cl->hostname);
489     }
490
491
492 }
493
494 int send_del_subnet(conn_list_t *cl, conn_list_t *other, subnet_t *subnet)
495 {
496 cp
497   return send_request(cl, "%d %s %s", DEL_SUBNET, other->name, net2str(subnet));
498 }
499
500 int del_subnet_h(conn_list_t *cl)
501 {
502   char *subnetstr;
503   char *name;
504   conn_list_t *owner;
505   subnet_t *subnet, *old;
506 cp
507   if(sscanf(cl->buffer, "%*d %as %as", &name, &subnetstr) != 3)
508     {
509        syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s)"), cl->name, cl->hostname);
510        return -1;
511     }
512
513   /* Check if owner name is a valid */
514
515   if(!check_id(name))
516     {
517       syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid identity name"), cl->name, cl->hostname);
518       return -1;
519     }
520
521   /* Check if subnet string is valid */
522
523   if((subnet = str2net(subnetstr)) == -1)
524     {
525       syslog(LOG_ERR, _("Got bad DEL_SUBNET from %s (%s): invalid subnet string"), cl->name, cl->hostname);
526       return -1;
527     }
528
529   /* Check if somebody tries to delete a subnet of ourself */
530
531   if(!strcmp(name, myself->name))
532     {
533       syslog(LOG_ERR, _("Warning: got DEL_SUBNET from %s (%s) for ourself, restarting"),
534              cl->name, cl->hostname);
535       sighup = 1;
536       return 0;
537     }
538
539   /* Check if the owner of the new subnet is in the connection list */
540
541   if(!(owner = lookup_id(name))
542     {
543       syslog(LOG_NOTICE, _("Got DEL_SUBNET for %s from %s (%s) which is not in our connection list"),
544              name, cl->name, cl->hostname);
545     }
546 }
547
548 /* New and closed connections notification */
549
550 int send_add_host(conn_list_t *cl, conn_list_t *other)
551 {
552 cp
553   return send_request(cl, "%d %s %lx:%d %s", ADD_HOST, other->name, other->real_ip, other->port, opt2str(other->options));
554 }
555
556 int add_host_h(conn_list_t *cl)
557 {
558   char *options;
559   conn_list_t *old, *new;
560 cp
561   new = new_conn_list();
562
563   if(sscanf(cl->buffer, "%*d %as %lx:%d %as", &new->name, &new->real_ip, &new->port, &options) != 4)
564     {
565        syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"), cl->name, cl->hostname);
566        return -1;
567     }
568
569   /* Check if option string is valid */
570
571   if((new->options = str2opt(options)) == -1)
572     {
573       syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid option string"), cl->name, cl->hostname);
574       return -1;
575     }
576
577   /* Check if identity is a valid name */
578
579   if(!check_id(new->name))
580     {
581       syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s): invalid identity name"), cl->name, cl->hostname);
582       return -1;
583     }
584
585   /* Check if somebody tries to add ourself */
586
587   if(!strcmp(new->name, myself->name))
588     {
589       syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"), cl->name, cl->hostname);
590       sighup = 1;
591       return 0;
592     }
593
594   /* Fill in more of the new conn_list structure */
595
596   new->hostname = hostlookup(htonl(new->real_ip));
597
598   /* Check if the new host already exists in the connnection list */
599
600   if((old = lookup_id(new->name)))
601     {
602       if((new->real_ip == old->real_ip) && (new->port == old->port))
603         {
604           if(debug_lvl > DEBUG_CONNECTIONS)
605             syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
606                    old->name, old->hostname, new->name, new->hostname);
607           return 0;
608         }
609       else
610         {
611           if(debug_lvl > DEBUG_CONNECTIONS)
612             syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
613                    old->name, old->hostname);
614           old->status.active = 0;
615           terminate_connection(old);
616         }
617     }
618
619   /* Fill in rest of conn_list structure */
620
621   new->nexthop = cl;
622   new->status.active = 1;
623
624   /* Hook it up into the conn_list */
625
626   conn_list_add(conn_list, new);
627
628   /* Tell the rest about the new host */
629
630   notify_others(new, cl, send_add_host);
631
632 cp
633   return 0;
634 }
635
636 int send_del_host(conn_list_t *cl, conn_list_t *other)
637 {
638 cp
639   return send_request(cl, "%d %s %lx:%d", DEL_HOST,
640                       other->name, other->real_ip, other->port);
641 }
642
643 int del_host_h(conn_list_t *cl)
644 {
645   char *id;
646   ip_t address;
647   port_t port;
648   conn_list_t *old;
649
650 cp
651   if(sscanf(cl->buffer, "%*d %as %lx:%d", &id, &address, &port) != 3)
652     {
653       syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
654              cl->name, cl->hostname);
655       return -1;
656     }
657
658   /* Check if somebody tries to delete ourself */
659
660   if(!strcmp(id, myself->name))
661     {
662       syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
663              cl->name, cl->hostname);
664       sighup = 1;
665       return 0;
666     }
667
668   /* Check if the new host already exists in the connnection list */
669
670   if((old = lookup_id(id)))
671     {
672       if((address == old->real_ip) && (port == old->port))
673         {
674           notify_others(old, cl, send_del_host);
675
676           old->status.termreq = 1;
677           old->status.active = 0;
678
679           terminate_connection(old);
680 cp
681           return 0;
682         }
683     }
684
685   if(debug_lvl > DEBUG_CONNECTIONS)
686     {
687       syslog(LOG_NOTICE, _("Got DEL_HOST for %s from %s (%s) which is not in our connection list"),
688              id, cl->name, cl->hostname);
689     }
690 cp
691   return 0;
692 }
693
694 /* Status and error notification routines */
695
696 int send_status(conn_list_t *cl, int statusno, char *statusstring)
697 {
698 cp
699   if(!statusstring)
700     statusstring = status_text[statusno];
701 cp
702   return send_request(cl, "%d %d %s", STATUS, statusno, statusstring);
703 }
704
705 int status_h(conn_list_t *cl)
706 {
707   int statusno;
708   char *statusstring;
709 cp
710   if(sscanf(cl->buffer, "%*d %d %as", &statusno, &statusstring) != 2)
711     {
712        syslog(LOG_ERR, _("Got bad STATUS from %s (%s)"),
713               cl->name, cl->hostname);
714        return -1;
715     }
716
717   if(debug_lvl > DEBUG_STATUS)
718     {
719       syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
720              cl->name, cl->hostname, status_text[statusno], statusstring);
721     }
722
723 cp
724   free(statusstring);
725   return 0;
726 }
727
728 int send_error(conn_list_t *cl, int errno, char *errstring)
729 {
730 cp
731   if(!errstring)
732     errstring = strerror(errno);
733   return send_request(cl, "%d %d %s", ERROR, errno, errstring);
734 }
735
736 int error_h(conn_list_t *cl)
737 {
738   int errno;
739   char *errorstring;
740 cp
741   if(sscanf(cl->buffer, "%*d %d %as", &errno, &errorstring) != 2)
742     {
743        syslog(LOG_ERR, _("Got bad error from %s (%s)"),
744               cl->name, cl->hostname);
745        return -1;
746     }
747
748   if(debug_lvl > DEBUG_error)
749     {
750       syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
751              cl->name, cl->hostname, strerror(errno), errorstring);
752     }
753
754   free(errorstring);
755   cl->status.termreq = 1;
756   terminate_connection(cl);
757 cp
758   return 0;
759 }
760
761 int send_termreq(conn_list_t *cl)
762 {
763 cp
764   return send_request(cl, "%d", TERMREQ);
765 }
766
767 int termreq_h(conn_list_t *cl)
768 {
769 cp
770   cl->status.termreq = 1;
771   terminate_connection(cl);
772 cp
773   return 0;
774 }
775
776 /* Keepalive routines - FIXME: needs a closer look */
777
778 int send_ping(conn_list_t *cl)
779 {
780   cl->status.pinged = 1;
781 cp
782   return send_request(cl, "%d", PING);
783 }
784
785 int ping_h(conn_list_t *cl)
786 {
787 cp
788   return send_pong(cl);
789 }
790
791 int send_pong(conn_list_t *cl)
792 {
793 cp
794   return send_request(cl, "%d", PONG);
795 }
796
797 int pong_h(conn_list_t *cl)
798 {
799 cp
800   cl->status.got_pong = 1;
801 cp
802   return 0;
803 }
804
805 /* Key exchange */
806
807 int send_key_changed(conn_list_t *from, conn_list_t *cl)
808 {
809   conn_list_t *p;
810 cp
811   for(p = conn_list; p != NULL; p = p->next)
812     {
813       if(p!=cl && p->status.meta && p->status.active)
814         send_request(p, "%d %s", KEY_CHANGED,
815                      from->name);
816     }
817 cp
818   return 0;
819 }
820
821 int key_changed_h(conn_list_t *cl)
822 {
823   char *from_id;
824   conn_list_t *from;
825 cp
826   if(sscanf(cl->buffer, "%*d %as", &from_id) != 1)
827     {
828       syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
829              cl->name, cl->hostname);
830       return -1;
831     }
832
833   if(!(from = lookup_id(from_id)))
834     {
835       syslog(LOG_ERR, _("Got KEY_CHANGED from %s (%s) origin %s which does not exist in our connection list"),
836              cl->name, cl->hostname, from_id);
837       free(from_id);
838       return -1;
839     }
840
841   free(from_id);
842
843   from->status.validkey = 0;
844   from->status.waitingforkey = 0;
845
846   send_key_changed(from, cl);
847 cp
848   return 0;
849 }
850
851 int send_req_key(conn_list_t *from, conn_list_t *to)
852 {
853 cp
854   return send_request(to->nexthop, "%d %s %s", REQ_KEY,
855                       from->name, to->name);
856 }
857
858 int req_key_h(conn_list_t *cl)
859 {
860   char *from_id, *to_id;
861   conn_list_t *from, *to;
862 cp
863   if(sscanf(cl->buffer, "%*d %as %as", &from_id, &to_id) != 2)
864     {
865        syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
866               cl->name, cl->hostname);
867        return -1;
868     }
869
870   if(!(from = lookup_id(from_id)))
871     {
872       syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) origin %s which does not exist in our connection list"),
873              cl->name, cl->hostname, from_id);
874       free(from_id); free(to_id);
875       return -1;
876     }
877
878   /* Check if this key request is for us */
879
880   if(!strcmp(to_id, myself->name))
881     {
882       send_ans_key(myself, from, myself->datakey->key);
883     }
884   else
885     {
886       if(!(to = lookup_id(to_id)))
887         {
888           syslog(LOG_ERR, _("Got REQ_KEY from %s (%s) destination %s which does not exist in our connection list"),
889                  cl->name, cl->hostname, to_id);
890           free(from_id); free(to_id);
891           return -1;
892         }
893       send_req_key(from, to);
894     }
895
896   free(from_id); free(to_id);
897 cp
898   return 0;
899 }
900
901 int send_ans_key(conn_list_t *from, conn_list_t *to, char *datakey)
902 {
903 cp
904   return send_request(to->nexthop, "%d %s %s %s", ANS_KEY,
905                       from->name, to->name, datakey);
906 }
907
908 int ans_key_h(conn_list_t *cl)
909 {
910   char *from_id, *to_id, *datakey;
911   int keylength;
912   conn_list_t *from, *to;
913 cp
914   if(sscanf(cl->buffer, "%*d %as %as %as", &from_id, &to_id, &datakey) != 3)
915     {
916        syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
917               cl->name, cl->hostname);
918        return -1;
919     }
920
921   if(!(from = lookup_id(from_id)))
922     {
923       syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) origin %s which does not exist in our connection list"),
924              cl->name, cl->hostname, from_id);
925       free(from_id); free(to_id); free(datakey);
926       return -1;
927     }
928
929   /* Check if this key request is for us */
930
931   if(!strcmp(to_id, myself->name))
932     {
933       /* It is for us, convert it to binary and set the key with it. */
934
935       keylength = strlen(datakey);
936
937       if((keylength%2) || (keylength <= 0))
938         {
939           syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s) origin %s: invalid key"),
940                  cl->name, cl->hostname, from->name);
941           free(from_id); free(to_id); free(datakey);
942           return -1;
943         }
944       keylength /= 2;
945       hex2bin(datakey, datakey, keylength);
946       BF_set_key(cl->datakey, keylength, datakey);
947     }
948   else
949     {
950       if(!(to = lookup_id(to_id)))
951         {
952           syslog(LOG_ERR, _("Got ANS_KEY from %s (%s) destination %s which does not exist in our connection list"),
953                  cl->name, cl->hostname, to_id);
954           free(from_id); free(to_id); free(datakey);
955           return -1;
956         }
957       send_ans_key(from, to, datakey);
958     }
959
960   free(from_id); free(to_id); free(datakey);
961 cp
962   return 0;
963 }
964
965 /* Old routines */
966
967 /*
968   Notify all my direct connections of a new host
969   that was added to the vpn, with the exception
970   of the source of the announcement.
971 */
972
973 int notify_others(conn_list_t *new, conn_list_t *source,
974                   int (*function)(conn_list_t*, conn_list_t*))
975 {
976   conn_list_t *p;
977 cp
978   for(p = conn_list; p != NULL; p = p->next)
979     if(p != new && p != source && p->status.meta && p->status.active)
980       function(p, new);
981 cp
982   return 0;
983 }
984
985 /*
986   Notify one connection of everything
987   I have connected
988 */
989
990 int notify_one(conn_list_t *new)
991 {
992   conn_list_t *p;
993 cp
994   for(p = conn_list; p != NULL; p = p->next)
995     if(p != new && p->status.active)
996       send_add_host(new, p);
997 cp
998   return 0;
999 }
1000
1001 /* "Complete overhaul". */
1002
1003 int (*request_handlers[])(conn_list_t*) = {
1004   id_h, challenge_h, chal_reply_h, ack_h,
1005   status_h, error_h, termreq_h,
1006   ping_h, pong_h,
1007   add_host_h, del_host_h,
1008   add_subnet_h, del_subnet_h,
1009   key_changed_h, req_key_h, ans_key_h,
1010 };
1011
1012 char (*request_name[]) = {
1013   "ID", "CHALLENGE", "CHAL_REPLY", "ACK",
1014   "STATUS", "ERROR", "TERMREQ",
1015   "PING", "PONG",
1016   "ADD_HOST", "DEL_HOST",
1017   "ADD_SUBNET", "DEL_SUBNET",
1018   "KEY_CHANGED", "REQ_KEY", "ANS_KEY",
1019 };