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