3c20f3b2762a8f06efedeafbee2a85cdf519eb3d
[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.19 2000/06/30 21:03:51 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   conn_list_t *old;
395 cp
396   if(debug_lvl > 1)
397     syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->real_hostname);
398
399   if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
400     {
401        syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
402               cl->real_hostname);
403        return -1;
404     }
405     
406   cl->vpn_hostname = hostlookup(htonl(cl->vpn_ip));
407
408   if(cl->protocol_version != PROT_CURRENT)
409     {
410       syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
411              cl->protocol_version);
412       return -1;
413     }
414
415   if(cl->status.outgoing)
416     {
417       /* First check if the host we connected to is already in our
418          connection list. If so, we are probably making a loop, which
419          is not desirable.
420        */
421        
422       if(old=lookup_conn(cl->vpn_ip))
423         {
424           if(debug_lvl>0)
425             syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"),
426               cl->vpn_hostname, cl->real_hostname);
427           cl->status.outgoing = 0;
428           old->status.outgoing = 1;
429           terminate_connection(cl);
430           return 0;
431         }
432
433       if(setup_vpn_connection(cl) < 0)
434         return -1;
435       send_basic_info(cl);
436     }
437   else
438     {
439         
440       if(setup_vpn_connection(cl) < 0)
441         return -1;
442       send_passphrase(cl);
443     }
444 cp
445   return 0;
446 }
447
448 int passphrase_h(conn_list_t *cl)
449 {
450 cp
451   cl->pp = xmalloc(sizeof(*(cl->pp)));
452
453   if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
454     {
455       syslog(LOG_ERR, _("Got bad PASSPHRASE from %s (%s)"),
456               cl->vpn_hostname, cl->real_hostname);
457       return -1;
458     }
459   cl->pp->len = strlen(cl->pp->phrase);
460     
461   if(debug_lvl > 1)
462     syslog(LOG_DEBUG, _("Got PASSPHRASE from %s (%s)"),
463               cl->vpn_hostname, cl->real_hostname);
464
465   if(cl->status.outgoing)
466     send_passphrase(cl);
467   else
468     send_public_key(cl);
469 cp
470   return 0;
471 }
472
473 int public_key_h(conn_list_t *cl)
474 {
475   char *g_n;
476   conn_list_t *old;
477 cp
478   if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
479     {
480        syslog(LOG_ERR, _("Got bad PUBLIC_KEY from %s (%s)"),
481               cl->vpn_hostname, cl->real_hostname);
482        return -1;
483     }  
484
485   if(debug_lvl > 1)
486     syslog(LOG_DEBUG, _("Got PUBLIC_KEY from %s (%s)"),
487               cl->vpn_hostname, cl->real_hostname);
488
489   if(verify_passphrase(cl, g_n))
490     {
491       /* intruder! */
492       syslog(LOG_ERR, _("Intruder from %s: passphrase for %s does not match!"),
493               cl->real_hostname, cl->vpn_hostname);
494       return -1;
495     }
496
497   if(cl->status.outgoing)
498     send_public_key(cl);
499   else
500     {
501       send_ack(cl);
502
503       /* Okay, before we active the connection, we check if there is another entry
504          in the connection list with the same vpn_ip. If so, it presumably is an
505          old connection that has timed out but we don't know it yet.
506        */
507
508       while(old = lookup_conn(cl->vpn_ip)) 
509         {
510           if(debug_lvl > 1)
511             syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
512             cl->vpn_hostname, old->real_hostname, cl->real_hostname);
513           old->status.active = 0;
514           terminate_connection(old);
515         }
516         
517       cl->status.active = 1;
518
519       if(debug_lvl > 0)
520         syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
521                            cl->vpn_hostname, cl->real_hostname);
522
523       notify_others(cl, NULL, send_add_host);
524       notify_one(cl);
525     }
526 cp
527   return 0;
528 }
529
530 int ack_h(conn_list_t *cl)
531 {
532 cp
533   if(debug_lvl > 1)
534     syslog(LOG_DEBUG, _("Got ACK from %s (%s)"),
535               cl->vpn_hostname, cl->real_hostname);
536   
537   cl->status.active = 1;
538
539   if(debug_lvl > 0)
540     syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
541               cl->vpn_hostname, cl->real_hostname);
542
543   notify_others(cl, NULL, send_add_host);
544   notify_one(cl);
545
546   upstreamindex = 0;
547 cp
548   return 0;
549 }
550
551 int termreq_h(conn_list_t *cl)
552 {
553 cp
554   if(!cl->status.active)
555     {
556       syslog(LOG_ERR, _("Got unauthorized TERMREQ from %s (%s)"),
557               cl->vpn_hostname, cl->real_hostname);
558       return -1;
559     }
560     
561   if(debug_lvl > 1)
562    syslog(LOG_DEBUG, _("Got TERMREQ from %s (%s)"),
563              cl->vpn_hostname, cl->real_hostname);
564   
565   cl->status.termreq = 1;
566
567   terminate_connection(cl);
568 cp
569   return 0;
570 }
571
572 int timeout_h(conn_list_t *cl)
573 {
574 cp
575   if(!cl->status.active)
576     {
577       syslog(LOG_ERR, _("Got unauthorized TIMEOUT from %s (%s)"),
578               cl->vpn_hostname, cl->real_hostname);
579       return -1;
580     }
581
582   if(debug_lvl > 1)
583     syslog(LOG_DEBUG, _("Got TIMEOUT from %s (%s)"),
584               cl->vpn_hostname, cl->real_hostname);
585
586   cl->status.termreq = 1;
587   terminate_connection(cl);
588 cp
589   return 0;
590 }
591
592 int del_host_h(conn_list_t *cl)
593 {
594   ip_t vpn_ip;
595   conn_list_t *fw;
596 cp
597   if(!cl->status.active)
598     {
599       syslog(LOG_ERR, _("Got unauthorized DEL_HOST from %s (%s)"),
600               cl->vpn_hostname, cl->real_hostname);
601       return -1;
602     }
603
604   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
605     {
606        syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
607               cl->vpn_hostname, cl->real_hostname);
608        return -1;
609     }  
610
611   if(!(fw = lookup_conn(vpn_ip)))
612     {
613       syslog(LOG_ERR, _("Got DEL_HOST for %d.%d.%d.%d from %s (%s) which does not exist?"),
614              IP_ADDR_V(vpn_ip), cl->vpn_hostname, cl->real_hostname);
615       return 0;
616     }
617
618   /* Connections lists are really messed up if this happens */
619   if(vpn_ip == myself->vpn_ip)
620     {
621       syslog(LOG_ERR, _("Warning: got DEL_HOST from %s (%s) for ourself, restarting"),
622                cl->vpn_hostname, cl->real_hostname);
623       sighup = 1;
624       return 0;
625     }
626
627   if(debug_lvl > 1)
628     syslog(LOG_DEBUG, _("Got DEL_HOST for %s (%s) from %s (%s)"),
629            fw->vpn_hostname, fw->real_hostname, cl->vpn_hostname, cl->real_hostname);
630
631   notify_others(fw, cl, send_del_host);
632
633   fw->status.termreq = 1;
634   fw->status.active = 0;
635
636   terminate_connection(fw);
637 cp
638   return 0;
639 }
640
641 int ping_h(conn_list_t *cl)
642 {
643 cp
644   if(!cl->status.active)
645     {
646       syslog(LOG_ERR, _("Got unauthorized PING from %s (%s)"),
647               cl->vpn_hostname, cl->real_hostname);
648       return -1;
649     }
650
651   if(debug_lvl > 1)
652     syslog(LOG_DEBUG, _("Got PING from %s (%s)"),
653               cl->vpn_hostname, cl->real_hostname);
654
655   cl->status.pinged = 0;
656   cl->status.got_pong = 1;
657
658   send_pong(cl);
659 cp
660   return 0;
661 }
662
663 int pong_h(conn_list_t *cl)
664 {
665 cp
666   if(!cl->status.active)
667     {
668       syslog(LOG_ERR, _("Got unauthorized PONG from %s (%s)"),
669               cl->vpn_hostname, cl->real_hostname);
670       return -1;
671     }
672
673   if(debug_lvl > 1)
674     syslog(LOG_DEBUG, _("Got PONG from %s (%s)"),
675               cl->vpn_hostname, cl->real_hostname);
676
677   cl->status.got_pong = 1;
678 cp
679   return 0;
680 }
681
682 int add_host_h(conn_list_t *cl)
683 {
684   ip_t real_ip;
685   ip_t vpn_ip;
686   ip_t vpn_mask;
687   unsigned short port;
688   int flags;
689   conn_list_t *ncn, *old;
690 cp
691   if(!cl->status.active)
692     {
693       syslog(LOG_ERR, _("Got unauthorized ADD_HOST from %s (%s)"),
694               cl->vpn_hostname, cl->real_hostname);
695       return -1;
696     }
697     
698   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
699     {
700        syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"),
701               cl->vpn_hostname, cl->real_hostname);
702        return -1;
703     }  
704
705   if(old = lookup_conn(vpn_ip))
706     {
707       if((real_ip==old->real_ip) && (vpn_mask==old->vpn_mask) && (port==old->port))
708         {
709           if(debug_lvl>1)
710             syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
711                    old->vpn_hostname, old->real_hostname, cl->vpn_hostname, cl->real_hostname);
712           goto skip_add_host;  /* One goto a day keeps the deeply nested if constructions away. */
713         }
714       else
715         {
716           if(debug_lvl>1)
717             syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
718                    old->vpn_hostname, old->real_hostname);
719           old->status.active = 0;
720           terminate_connection(old);
721         }
722     }
723   
724   /* Connections lists are really messed up if this happens */
725   if(vpn_ip == myself->vpn_ip)
726     {
727       syslog(LOG_ERR, _("Warning: got ADD_HOST from %s (%s) for ourself, restarting"),
728                cl->vpn_hostname, cl->real_hostname);
729       sighup = 1;
730       return 0;
731     }
732     
733   ncn = new_conn_list();
734   ncn->real_ip = real_ip;
735   ncn->real_hostname = hostlookup(htonl(real_ip));
736   ncn->vpn_ip = vpn_ip;
737   ncn->vpn_mask = vpn_mask;
738   ncn->vpn_hostname = hostlookup(htonl(vpn_ip));
739   ncn->port = port;
740   ncn->flags = flags;
741   ncn->nexthop = cl;
742   ncn->next = conn_list;
743   conn_list = ncn;
744   ncn->status.active = 1;
745
746   if(debug_lvl > 1)
747     syslog(LOG_DEBUG, _("Got ADD_HOST for %s (%s) from %s (%s)"),
748            ncn->vpn_hostname, ncn->real_hostname, cl->vpn_hostname, cl->real_hostname);
749
750 skip_add_host:
751
752   notify_others(ncn, cl, send_add_host);
753 cp
754   return 0;
755 }
756
757 int req_key_h(conn_list_t *cl)
758 {
759   ip_t to;
760   ip_t from;
761   conn_list_t *fw;
762 cp
763   if(!cl->status.active)
764     {
765       syslog(LOG_ERR, _("Got unauthorized REQ_KEY from %s (%s)"),
766               cl->vpn_hostname, cl->real_hostname);
767       return -1;
768     }
769
770   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
771     {
772        syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
773               cl->vpn_hostname, cl->real_hostname);
774        return -1;
775     }  
776
777   if(debug_lvl > 1)
778     syslog(LOG_DEBUG, _("Got REQ_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
779            IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
780
781   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
782     {  /* hey! they want something from ME! :) */
783       send_key_answer(cl, from);
784       return 0;
785     }
786
787   fw = lookup_conn(to);
788   
789   if(!fw)
790     {
791       syslog(LOG_ERR, _("Attempting to forward REQ_KEY to %d.%d.%d.%d, which does not exist?"),
792              IP_ADDR_V(to));
793       return -1;
794     }
795
796   if(debug_lvl > 1)
797     syslog(LOG_DEBUG, _("Forwarding REQ_KEY to %s (%s)"),
798            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
799   
800   cl->buffer[cl->reqlen-1] = '\n';
801   
802   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
803     {
804       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
805       return -1;
806     }
807 cp
808   return 0;
809 }
810
811 void set_keys(conn_list_t *cl, int expiry, char *key)
812 {
813   char *ek;
814 cp
815   if(!cl->public_key)
816     {
817       cl->public_key = xmalloc(sizeof(*cl->key));
818       cl->public_key->key = NULL;
819     }
820     
821   if(cl->public_key->key)
822     free(cl->public_key->key);
823   cl->public_key->length = strlen(key);
824   cl->public_key->expiry = expiry;
825   cl->public_key->key = xmalloc(cl->public_key->length + 1);
826   strcpy(cl->public_key->key, key);
827
828   ek = make_shared_key(key);
829   
830   if(!cl->key)
831     {
832       cl->key = xmalloc(sizeof(*cl->key));
833       cl->key->key = NULL;
834     }
835
836   if(cl->key->key)
837     free(cl->key->key);
838
839   cl->key->length = strlen(ek);
840   cl->key->expiry = expiry;
841   cl->key->key = xmalloc(cl->key->length + 1);
842   strcpy(cl->key->key, ek);
843 cp
844 }
845
846 int ans_key_h(conn_list_t *cl)
847 {
848   ip_t to;
849   ip_t from;
850   int expiry;
851   char *key;
852   conn_list_t *fw, *gk;
853 cp
854   if(!cl->status.active)
855     {
856       syslog(LOG_ERR, _("Got unauthorized ANS_KEY from %s (%s)"),
857               cl->vpn_hostname, cl->real_hostname);
858       return -1;
859     }
860
861   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
862     {
863        syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
864               cl->vpn_hostname, cl->real_hostname);
865        return -1;
866     }  
867
868   if(debug_lvl > 1)
869     syslog(LOG_DEBUG, _("Got ANS_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
870             IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
871
872   if(to == myself->vpn_ip)
873     {  /* hey! that key's for ME! :) */
874       gk = lookup_conn(from);
875
876       if(!gk)
877         {
878           syslog(LOG_ERR, _("Receiving ANS_KEY origin %d.%d.%d.%d from %s (%s), which does not exist?"),
879                  IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
880           return -1;
881         }
882
883       set_keys(gk, expiry, key);
884       gk->status.validkey = 1;
885       gk->status.waitingforkey = 0;
886       flush_queues(gk);
887       return 0;
888     }
889
890   fw = lookup_conn(to);
891   
892   if(!fw)
893     {
894       syslog(LOG_ERR, _("Attempting to forward ANS_KEY to %d.%d.%d.%d, which does not exist?"),
895              IP_ADDR_V(to));
896       return -1;
897     }
898
899   if(debug_lvl > 1)
900     syslog(LOG_DEBUG, _("Forwarding ANS_KEY to %s (%s)"),
901            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
902
903   cl->buffer[cl->reqlen-1] = '\n';
904
905   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
906     {
907       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
908       return -1;
909     }
910 cp
911   return 0;
912 }
913
914 int key_changed_h(conn_list_t *cl)
915 {
916   ip_t from;
917   conn_list_t *ik;
918 cp
919   if(!cl->status.active)
920     {
921       syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from %s (%s)"),
922               cl->vpn_hostname, cl->real_hostname);
923       return -1;
924     }
925
926   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
927     {
928        syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
929               cl->vpn_hostname, cl->real_hostname);
930        return -1;
931     }  
932
933   ik = lookup_conn(from);
934
935   if(!ik)
936     {
937       syslog(LOG_ERR, _("Got KEY_CHANGED origin %d.%d.%d.%d from %s (%s), which does not exist?"),
938              IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
939       return -1;
940     }
941
942   if(debug_lvl > 1)
943     syslog(LOG_DEBUG, _("Got KEY_CHANGED origin %s from %s (%s)"),
944             ik->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
945
946   ik->status.validkey = 0;
947   ik->status.waitingforkey = 0;
948
949   notify_others(ik, cl, send_key_changed);
950 cp
951   return 0;
952 }
953
954 int (*request_handlers[256])(conn_list_t*) = {
955   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
956   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
957   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
958   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
959   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
960   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
961   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
962   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
963   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
964   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
965   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
966   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
967   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
968   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
969   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
970   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
971   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
972   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
973   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
974   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
975 };