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