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