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