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