- New semantics for BASIC_INFO, ADD_HOST and DEL_HOST requests. This will
[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.16 2000/06/29 17:09:06 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 "conf.h"
38 #include "encr.h"
39 #include "net.h"
40 #include "netutl.h"
41 #include "protocol.h"
42
43 #include "system.h"
44
45 char buffer[MAXBUFSIZE+1];
46 int buflen;
47
48 /* Outgoing request routines */
49
50 int send_ack(conn_list_t *cl)
51 {
52 cp
53   if(debug_lvl > 1)
54     syslog(LOG_DEBUG, _("Sending ACK to %s (%s)"),
55            cl->vpn_hostname, cl->real_hostname);
56
57   buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
58
59   if((write(cl->meta_socket, buffer, buflen)) < 0)
60     {
61       syslog(LOG_ERR, _("Send failed: %d:%d: %m"), __FILE__, __LINE__);
62       return -1;
63     }
64 cp
65   return 0;
66 }
67
68 int send_termreq(conn_list_t *cl)
69 {
70 cp
71   if(debug_lvl > 1)
72     syslog(LOG_DEBUG, _("Sending TERMREQ to %s (%s)"),
73            cl->vpn_hostname, cl->real_hostname);
74
75   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
76
77   if(write(cl->meta_socket, buffer, buflen) < 0)
78     {
79       if(debug_lvl > 1)
80         syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
81       return -1;
82     }
83 cp
84   return 0;
85 }
86
87 int send_timeout(conn_list_t *cl)
88 {
89 cp
90   if(debug_lvl > 1)
91     syslog(LOG_DEBUG, _("Sending TIMEOUT to %s (%s)"),
92            cl->vpn_hostname, cl->real_hostname);
93
94   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
95
96   if((write(cl->meta_socket, buffer, buflen)) < 0)
97     {
98       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
99       return -1;
100     }
101 cp
102   return 0;
103 }
104
105 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
106 {
107 cp
108   if(debug_lvl > 1)
109     syslog(LOG_DEBUG, _("Sending DEL_HOST for %s (%s) to %s (%s)"),
110            new_host->vpn_hostname, new_host->real_hostname, cl->vpn_hostname, cl->real_hostname);
111
112   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
113
114   if((write(cl->meta_socket, buffer, buflen)) < 0)
115     {
116       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
117       return -1;
118     }
119 cp
120   return 0;
121 }
122
123 int send_ping(conn_list_t *cl)
124 {
125 cp
126   if(debug_lvl > 1)
127     syslog(LOG_DEBUG, _("Sending PING to %s (%s)"),
128            cl->vpn_hostname, cl->real_hostname);
129
130   buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
131
132   if((write(cl->meta_socket, buffer, buflen)) < 0)
133     {
134       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
135       return -1;
136     }
137 cp
138   return 0;
139 }
140
141 int send_pong(conn_list_t *cl)
142 {
143 cp
144   if(debug_lvl > 1)
145     syslog(LOG_DEBUG, _("Sending PONG to %s (%s)"),
146            cl->vpn_hostname, cl->real_hostname);
147
148   buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
149
150   if((write(cl->meta_socket, buffer, buflen)) < 0)
151     {
152       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
153       return -1;
154     }
155 cp
156   return 0;
157 }
158
159 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
160 {
161   ip_t real_ip;
162   int flags;
163   char *hostname;
164 cp
165   real_ip = new_host->real_ip;
166   hostname = new_host->real_hostname;
167   flags = new_host->flags;
168   
169   /* If we need to propagate information about a new host that wants us to export
170    * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
171    * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
172    * work correctly.
173    */
174      
175   if(flags & EXPORTINDIRECTDATA)
176     {
177       flags &= ~EXPORTINDIRECTDATA;
178       flags |= INDIRECTDATA;
179       real_ip = myself->vpn_ip;
180       hostname = myself->real_hostname;
181     }
182
183   if(debug_lvl > 1)
184     syslog(LOG_DEBUG, _("Sending ADD_HOST for %s (%s) to %s (%s)"),
185            new_host->vpn_hostname, hostname, cl->vpn_hostname, cl->real_hostname);
186
187   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x %d\n", ADD_HOST, real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port, flags);
188
189   if((write(cl->meta_socket, buffer, buflen)) < 0)
190     {
191       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
192       return -1;
193     }
194 cp
195   return 0;
196 }
197
198 int send_key_changed(conn_list_t *cl, conn_list_t *src)
199 {
200 cp
201   if(debug_lvl > 1)
202     syslog(LOG_DEBUG, _("Sending KEY_CHANGED origin %s to %s (%s)"),
203            src->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
204
205   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
206
207   if((write(cl->meta_socket, buffer, buflen)) < 0)
208     {
209       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
210       return -1;
211     }
212 cp
213   return 0;
214 }
215
216 void send_key_changed_all(void)
217 {
218   conn_list_t *p;
219 cp
220   for(p = conn_list; p != NULL; p = p->next)
221     if(p->status.meta && p->status.active)
222       send_key_changed(p, myself);
223 cp
224 }
225
226 int send_basic_info(conn_list_t *cl)
227 {
228 cp
229   if(debug_lvl > 1)
230     syslog(LOG_DEBUG, _("Sending BASIC_INFO to %s"),
231            cl->real_hostname);
232
233   buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x %d\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port, myself->flags);
234
235   if((write(cl->meta_socket, buffer, buflen)) < 0)
236     {
237       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
238       return -1;
239     }
240 cp
241   return 0;
242 }
243
244 int send_passphrase(conn_list_t *cl)
245 {
246   passphrase_t tmp;
247 cp
248   encrypt_passphrase(&tmp);
249
250   if(debug_lvl > 1)
251     syslog(LOG_DEBUG, _("Sending PASSPHRASE to %s (%s)"),
252            cl->vpn_hostname, cl->real_hostname);
253
254   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
255
256   if((write(cl->meta_socket, buffer, buflen)) < 0)
257     {
258       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
259       return -1;
260     }
261 cp
262   return 0;
263 }
264
265 int send_public_key(conn_list_t *cl)
266 {
267 cp
268   if(debug_lvl > 1)
269     syslog(LOG_DEBUG, _("Sending PUBLIC_KEY to %s (%s)"),
270            cl->vpn_hostname, cl->real_hostname);
271
272   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
273
274   if((write(cl->meta_socket, buffer, buflen)) < 0)
275     {
276       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
277       return -1;
278     }
279 cp
280   return 0;
281 }
282
283 /* WDN doet deze functie? (GS)
284 int send_calculate(conn_list_t *cl, char *k)
285 {
286 cp
287   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
288
289   if((write(cl->meta_socket, buffer, buflen)) < 0)
290     {
291       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
292       return -1;
293     }
294 cp
295   return 0;
296 }
297 */
298
299 int send_key_request(ip_t to)
300 {
301   conn_list_t *fw;
302 cp
303   fw = lookup_conn(to);
304   if(!fw)
305     {
306       syslog(LOG_ERR, _("Attempting to send REQ_KEY to %d.%d.%d.%d, which does not exist?"),
307              IP_ADDR_V(to));
308       return -1;
309     }
310
311   if(debug_lvl > 1)
312     syslog(LOG_DEBUG, _("Sending REQ_KEY to %s (%s)"),
313            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
314
315   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
316
317   if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
318     {
319       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
320       return -1;
321     }
322   fw->status.waitingforkey = 1;
323 cp
324   return 0;
325 }
326
327 int send_key_answer(conn_list_t *cl, ip_t to)
328 {
329   conn_list_t *fw;
330 cp
331
332   fw = lookup_conn(to);
333   
334   if(!fw)
335     {
336       syslog(LOG_ERR, _("Attempting to send ANS_KEY to %d.%d.%d.%d, which does not exist?"),
337              IP_ADDR_V(to));
338       return -1;
339     }
340
341  if(debug_lvl > 1)
342     syslog(LOG_DEBUG, _("Sending ANS_KEY to %s (%s)"),
343            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
344
345   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
346
347   if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
348     {
349       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
350       return -1;
351     }
352 cp
353   return 0;
354 }
355
356 /*
357   notify all my direct connections of a new host
358   that was added to the vpn, with the exception
359   of the source of the announcement.
360 */
361 int notify_others(conn_list_t *new, conn_list_t *source,
362                   int (*function)(conn_list_t*, conn_list_t*))
363 {
364   conn_list_t *p;
365 cp
366   for(p = conn_list; p != NULL; p = p->next)
367     if(p != new && p != source && p->status.meta && p->status.active)
368       function(p, new);
369 cp
370   return 0;
371 }
372
373 /*
374   notify one connection of everything
375   i have connected
376 */
377 int notify_one(conn_list_t *new)
378 {
379   conn_list_t *p;
380 cp
381   for(p = conn_list; p != NULL; p = p->next)
382     if(p != new && p->status.active)
383       send_add_host(new, p);
384 cp
385   return 0;
386 }
387
388 /*
389   The incoming request handlers
390 */
391
392 int basic_info_h(conn_list_t *cl)
393 {
394 cp
395   if(debug_lvl > 1)
396     syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->real_hostname);
397
398   if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
399     {
400        syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
401               cl->real_hostname);
402        return -1;
403     }
404     
405   cl->vpn_hostname = hostlookup(htonl(cl->vpn_ip));
406
407   if(cl->protocol_version != PROT_CURRENT)
408     {
409       syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
410              cl->protocol_version);
411       return -1;
412     }
413
414   if(cl->status.outgoing)
415     {
416       if(setup_vpn_connection(cl) < 0)
417         return -1;
418       send_basic_info(cl);
419     }
420   else
421     {
422       /* First check if the host we connected to is already in our
423          connection list. If so, we are probably making a loop, which
424          is not desirable. It should not happen though.
425        */
426        
427       if(lookup_conn(cl->vpn_ip))
428         {
429           if(debug_lvl>0)
430             syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list, aborting connect"),
431               cl->vpn_hostname, cl->real_hostname);
432           return -1;
433         }
434         
435       if(setup_vpn_connection(cl) < 0)
436         return -1;
437       send_passphrase(cl);
438     }
439 cp
440   return 0;
441 }
442
443 int passphrase_h(conn_list_t *cl)
444 {
445 cp
446   cl->pp = xmalloc(sizeof(*(cl->pp)));
447
448   if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
449     {
450       syslog(LOG_ERR, _("Got bad PASSPHRASE from %s (%s)"),
451               cl->vpn_hostname, cl->real_hostname);
452       return -1;
453     }
454   cl->pp->len = strlen(cl->pp->phrase);
455     
456   if(debug_lvl > 1)
457     syslog(LOG_DEBUG, _("Got PASSPHRASE from %s (%s)"),
458               cl->vpn_hostname, cl->real_hostname);
459
460   if(cl->status.outgoing)
461     send_passphrase(cl);
462   else
463     send_public_key(cl);
464 cp
465   return 0;
466 }
467
468 int public_key_h(conn_list_t *cl)
469 {
470   char *g_n;
471   conn_list_t *old;
472 cp
473   if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
474     {
475        syslog(LOG_ERR, _("Got bad PUBLIC_KEY from %s (%s)"),
476               cl->vpn_hostname, cl->real_hostname);
477        return -1;
478     }  
479
480   if(debug_lvl > 1)
481     syslog(LOG_DEBUG, _("Got PUBLIC_KEY from %s (%s)"),
482               cl->vpn_hostname, cl->real_hostname);
483
484   if(verify_passphrase(cl, g_n))
485     {
486       /* intruder! */
487       syslog(LOG_ERR, _("Intruder from %s: passphrase for %s does not match!"),
488               cl->real_hostname, cl->vpn_hostname);
489       return -1;
490     }
491
492   if(cl->status.outgoing)
493     send_public_key(cl);
494   else
495     {
496       send_ack(cl);
497
498       /* Okay, before we active the connection, we check if there is another entry
499          in the connection list with the same vpn_ip. If so, it presumably is an
500          old connection that has timed out but we don't know it yet.
501        */
502
503       while(old = lookup_conn(cl->vpn_ip)) 
504         {
505           syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
506             cl->vpn_hostname, old->real_hostname, cl->real_hostname);
507           old->status.active = 0;
508           terminate_connection(old);
509         }
510         
511       cl->status.active = 1;
512
513       if(debug_lvl > 0)
514         syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
515                            cl->vpn_hostname, cl->real_hostname);
516
517       notify_others(cl, NULL, send_add_host);
518       notify_one(cl);
519     }
520 cp
521   return 0;
522 }
523
524 int ack_h(conn_list_t *cl)
525 {
526 cp
527   if(debug_lvl > 1)
528     syslog(LOG_DEBUG, _("Got ACK from %s (%s)"),
529               cl->vpn_hostname, cl->real_hostname);
530   
531   cl->status.active = 1;
532
533   syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
534               cl->vpn_hostname, cl->real_hostname);
535
536   notify_others(cl, NULL, send_add_host);
537   notify_one(cl);
538
539   upstreamindex = 0;
540 cp
541   return 0;
542 }
543
544 int termreq_h(conn_list_t *cl)
545 {
546 cp
547   if(!cl->status.active)
548     {
549       syslog(LOG_ERR, _("Got unauthorized TERMREQ from %s (%s)"),
550               cl->vpn_hostname, cl->real_hostname);
551       return -1;
552     }
553     
554   if(debug_lvl > 1)
555    syslog(LOG_DEBUG, _("Got TERMREQ from %s (%s)"),
556              cl->vpn_hostname, cl->real_hostname);
557   
558   cl->status.termreq = 1;
559
560   terminate_connection(cl);
561 cp
562   return 0;
563 }
564
565 int timeout_h(conn_list_t *cl)
566 {
567 cp
568   if(!cl->status.active)
569     {
570       syslog(LOG_ERR, _("Got unauthorized TIMEOUT from %s (%s)"),
571               cl->vpn_hostname, cl->real_hostname);
572       return -1;
573     }
574
575   if(debug_lvl > 1)
576     syslog(LOG_DEBUG, _("Got TIMEOUT from %s (%s)"),
577               cl->vpn_hostname, cl->real_hostname);
578
579   cl->status.termreq = 1;
580   terminate_connection(cl);
581 cp
582   return 0;
583 }
584
585 int del_host_h(conn_list_t *cl)
586 {
587   ip_t vpn_ip;
588   conn_list_t *fw;
589 cp
590   if(!cl->status.active)
591     {
592       syslog(LOG_ERR, _("Got unauthorized DEL_HOST from %s (%s)"),
593               cl->vpn_hostname, cl->real_hostname);
594       return -1;
595     }
596
597   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
598     {
599        syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
600               cl->vpn_hostname, cl->real_hostname);
601        return -1;
602     }  
603
604   if(!(fw = lookup_conn(vpn_ip)))
605     {
606       syslog(LOG_ERR, _("Got DEL_HOST for %d.%d.%d.%d from %s (%s) which does not exist?"),
607              IP_ADDR_V(vpn_ip), cl->vpn_hostname, cl->real_hostname);
608       return 0;
609     }
610
611   if(debug_lvl > 1)
612     syslog(LOG_DEBUG, _("Got DEL_HOST for %s (%s) from %s (%s)"),
613            fw->vpn_hostname, fw->real_hostname, cl->vpn_hostname, cl->real_hostname);
614
615   notify_others(fw, cl, send_del_host);
616
617   fw->status.termreq = 1;
618   fw->status.active = 0;
619
620   terminate_connection(fw);
621 cp
622   return 0;
623 }
624
625 int ping_h(conn_list_t *cl)
626 {
627 cp
628   if(!cl->status.active)
629     {
630       syslog(LOG_ERR, _("Got unauthorized PING from %s (%s)"),
631               cl->vpn_hostname, cl->real_hostname);
632       return -1;
633     }
634
635   if(debug_lvl > 1)
636     syslog(LOG_DEBUG, _("Got PING from %s (%s)"),
637               cl->vpn_hostname, cl->real_hostname);
638
639   cl->status.pinged = 0;
640   cl->status.got_pong = 1;
641
642   send_pong(cl);
643 cp
644   return 0;
645 }
646
647 int pong_h(conn_list_t *cl)
648 {
649 cp
650   if(!cl->status.active)
651     {
652       syslog(LOG_ERR, _("Got unauthorized PONG from %s (%s)"),
653               cl->vpn_hostname, cl->real_hostname);
654       return -1;
655     }
656
657   if(debug_lvl > 1)
658     syslog(LOG_DEBUG, _("Got PONG from %s (%s)"),
659               cl->vpn_hostname, cl->real_hostname);
660
661   cl->status.got_pong = 1;
662 cp
663   return 0;
664 }
665
666 int add_host_h(conn_list_t *cl)
667 {
668   ip_t real_ip;
669   ip_t vpn_ip;
670   ip_t vpn_mask;
671   unsigned short port;
672   int flags;
673   conn_list_t *ncn, *old;
674 cp
675   if(!cl->status.active)
676     {
677       syslog(LOG_ERR, _("Got unauthorized ADD_HOST from %s (%s)"),
678               cl->vpn_hostname, cl->real_hostname);
679       return -1;
680     }
681     
682   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
683     {
684        syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"),
685               cl->vpn_hostname, cl->real_hostname);
686        return -1;
687     }  
688
689   if(old = lookup_conn(vpn_ip))
690     {
691       if((real_ip==old->real_ip) && (vpn_mask==old->vpn_mask) && (port==old->port))
692         {
693           if(debug_lvl>1)
694             syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
695                    old->vpn_hostname, old->real_hostname, cl->vpn_hostname, cl->real_hostname);
696           goto skip_add_host;  /* One goto a day keeps the deeply nested if constructions away. */
697         }
698       else
699         {
700           if(debug_lvl>1)
701             syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
702                    old->vpn_hostname, old->real_hostname);
703           old->status.active = 0;
704           terminate_connection(old);
705         }
706     }
707     
708   ncn = new_conn_list();
709   ncn->real_ip = real_ip;
710   ncn->real_hostname = hostlookup(htonl(real_ip));
711   ncn->vpn_ip = vpn_ip;
712   ncn->vpn_mask = vpn_mask;
713   ncn->vpn_hostname = hostlookup(htonl(vpn_ip));
714   ncn->port = port;
715   ncn->flags = flags;
716   ncn->nexthop = cl;
717   ncn->next = conn_list;
718   conn_list = ncn;
719   ncn->status.active = 1;
720
721   if(debug_lvl > 1)
722     syslog(LOG_DEBUG, _("Got ADD_HOST for %s (%s) from %s (%s)"),
723            ncn->vpn_hostname, ncn->real_hostname, cl->vpn_hostname, cl->real_hostname);
724
725 skip_add_host:
726
727   notify_others(ncn, cl, send_add_host);
728 cp
729   return 0;
730 }
731
732 int req_key_h(conn_list_t *cl)
733 {
734   ip_t to;
735   ip_t from;
736   conn_list_t *fw;
737 cp
738   if(!cl->status.active)
739     {
740       syslog(LOG_ERR, _("Got unauthorized REQ_KEY from %s (%s)"),
741               cl->vpn_hostname, cl->real_hostname);
742       return -1;
743     }
744
745   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
746     {
747        syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
748               cl->vpn_hostname, cl->real_hostname);
749        return -1;
750     }  
751
752   if(debug_lvl > 1)
753     syslog(LOG_DEBUG, _("Got REQ_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
754            IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
755
756   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
757     {  /* hey! they want something from ME! :) */
758       send_key_answer(cl, from);
759       return 0;
760     }
761
762   fw = lookup_conn(to);
763   
764   if(!fw)
765     {
766       syslog(LOG_ERR, _("Attempting to forward REQ_KEY to %d.%d.%d.%d, which does not exist?"),
767              IP_ADDR_V(to));
768       return -1;
769     }
770
771   if(debug_lvl > 1)
772     syslog(LOG_DEBUG, _("Forwarding REQ_KEY to %s (%s)"),
773            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
774   
775   cl->buffer[cl->reqlen-1] = '\n';
776   
777   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
778     {
779       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
780       return -1;
781     }
782 cp
783   return 0;
784 }
785
786 void set_keys(conn_list_t *cl, int expiry, char *key)
787 {
788   char *ek;
789 cp
790   if(!cl->public_key)
791     {
792       cl->public_key = xmalloc(sizeof(*cl->key));
793       cl->public_key->key = NULL;
794     }
795     
796   if(cl->public_key->key)
797     free(cl->public_key->key);
798   cl->public_key->length = strlen(key);
799   cl->public_key->expiry = expiry;
800   cl->public_key->key = xmalloc(cl->public_key->length + 1);
801   strcpy(cl->public_key->key, key);
802
803   ek = make_shared_key(key);
804   
805   if(!cl->key)
806     {
807       cl->key = xmalloc(sizeof(*cl->key));
808       cl->key->key = NULL;
809     }
810
811   if(cl->key->key)
812     free(cl->key->key);
813
814   cl->key->length = strlen(ek);
815   cl->key->expiry = expiry;
816   cl->key->key = xmalloc(cl->key->length + 1);
817   strcpy(cl->key->key, ek);
818 cp
819 }
820
821 int ans_key_h(conn_list_t *cl)
822 {
823   ip_t to;
824   ip_t from;
825   int expiry;
826   char *key;
827   conn_list_t *fw, *gk;
828 cp
829   if(!cl->status.active)
830     {
831       syslog(LOG_ERR, _("Got unauthorized ANS_KEY from %s (%s)"),
832               cl->vpn_hostname, cl->real_hostname);
833       return -1;
834     }
835
836   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
837     {
838        syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
839               cl->vpn_hostname, cl->real_hostname);
840        return -1;
841     }  
842
843   if(debug_lvl > 1)
844     syslog(LOG_DEBUG, _("Got ANS_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
845             IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
846
847   if(to == myself->vpn_ip)
848     {  /* hey! that key's for ME! :) */
849       gk = lookup_conn(from);
850
851       if(!gk)
852         {
853           syslog(LOG_ERR, _("Receiving ANS_KEY origin %d.%d.%d.%d from %s (%s), which does not exist?"),
854                  IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
855           return -1;
856         }
857
858       set_keys(gk, expiry, key);
859       gk->status.validkey = 1;
860       gk->status.waitingforkey = 0;
861       flush_queues(gk);
862       return 0;
863     }
864
865   fw = lookup_conn(to);
866   
867   if(!fw)
868     {
869       syslog(LOG_ERR, _("Attempting to forward ANS_KEY to %d.%d.%d.%d, which does not exist?"),
870              IP_ADDR_V(to));
871       return -1;
872     }
873
874   if(debug_lvl > 1)
875     syslog(LOG_DEBUG, _("Forwarding ANS_KEY to %s (%s)"),
876            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
877
878   cl->buffer[cl->reqlen-1] = '\n';
879
880   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
881     {
882       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
883       return -1;
884     }
885 cp
886   return 0;
887 }
888
889 int key_changed_h(conn_list_t *cl)
890 {
891   ip_t from;
892   conn_list_t *ik;
893 cp
894   if(!cl->status.active)
895     {
896       syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from %s (%s)"),
897               cl->vpn_hostname, cl->real_hostname);
898       return -1;
899     }
900
901   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
902     {
903        syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
904               cl->vpn_hostname, cl->real_hostname);
905        return -1;
906     }  
907
908   ik = lookup_conn(from);
909
910   if(!ik)
911     {
912       syslog(LOG_ERR, _("Got KEY_CHANGED origin %d.%d.%d.%d from %s (%s), which does not exist?"),
913              IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
914       return -1;
915     }
916
917   if(debug_lvl > 1)
918     syslog(LOG_DEBUG, _("Got KEY_CHANGED origin %s from %s (%s)"),
919             ik->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
920
921   ik->status.validkey = 0;
922   ik->status.waitingforkey = 0;
923
924   notify_others(ik, cl, send_key_changed);
925 cp
926   return 0;
927 }
928
929 int (*request_handlers[256])(conn_list_t*) = {
930   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
931   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
932   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
933   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
934   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
935   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
936   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
937   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
938   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
939   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
940   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
941   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
942   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
943   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
944   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
945   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
947   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
950 };