Include ../intl in the include path, and add @INTLLIBS@ to the list of libraries.
[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 2000/05/30 21:36:16 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     {
455       send_ack(cl);
456
457       /* Okay, before we active the connection, we check if there is another entry
458          in the connection list with the same vpn_ip. If so, it presumably is an
459          old connection that has timed out but we don't know it yet. Because our
460          conn_list entry is not active, lookup_conn will skip ourself. */
461
462       while(old=lookup_conn(cl->vpn_ip)) 
463         terminate_connection(old);
464
465       cl->status.active = 1;
466       notify_others(cl, NULL, send_add_host);
467       notify_one(cl);
468     }
469 cp
470   return 0;
471 }
472
473 int ack_h(conn_list_t *cl)
474 {
475 cp
476   if(debug_lvl > 2)
477     syslog(LOG_DEBUG, _("got ACK"));
478   
479   cl->status.active = 1;
480   syslog(LOG_NOTICE, _("Connection with %s activated."), cl->hostname);
481 cp
482   return 0;
483 }
484
485 int termreq_h(conn_list_t *cl)
486 {
487 cp
488   syslog(LOG_NOTICE, _(IP_ADDR_S " wants to quit"), IP_ADDR_V(cl->vpn_ip));
489   cl->status.termreq = 1;
490   terminate_connection(cl);
491
492   notify_others(cl, NULL, send_del_host);
493 cp
494   return 0;
495 }
496
497 int timeout_h(conn_list_t *cl)
498 {
499 cp
500   if(!cl->status.active) return -1;
501   syslog(LOG_NOTICE, _(IP_ADDR_S " says it's gotten a timeout from us"), IP_ADDR_V(cl->vpn_ip));
502   cl->status.termreq = 1;
503   terminate_connection(cl);
504 cp
505   return 0;
506 }
507
508 int del_host_h(conn_list_t *cl)
509 {
510   ip_t vpn_ip;
511   conn_list_t *fw;
512 cp
513   if(!cl->status.active) return -1;
514
515   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
516     {
517        syslog(LOG_ERR, _("got bad DEL_HOST request: %s"), cl->buffer);
518        return -1;
519     }  
520
521   if(debug_lvl > 2)
522     syslog(LOG_DEBUG, _("got DEL_HOST for " IP_ADDR_S),
523            IP_ADDR_V(vpn_ip));
524
525   if(!(fw = lookup_conn(vpn_ip)))
526     {
527       syslog(LOG_ERR, _("Somebody wanted to delete " IP_ADDR_S " which does not exist?"),
528              IP_ADDR_V(vpn_ip));
529       return 0;
530     }
531
532   notify_others(cl, fw, send_del_host);
533
534   fw->status.termreq = 1;
535   terminate_connection(fw);
536 cp
537   return 0;
538 }
539
540 int ping_h(conn_list_t *cl)
541 {
542 cp
543   if(!cl->status.active) return -1;
544   if(debug_lvl > 3)
545     syslog(LOG_DEBUG, _("responding to ping from " IP_ADDR_S), IP_ADDR_V(cl->vpn_ip));
546   cl->status.pinged = 0;
547   cl->status.got_pong = 1;
548
549   send_pong(cl);
550 cp
551   return 0;
552 }
553
554 int pong_h(conn_list_t *cl)
555 {
556 cp
557   if(!cl->status.active) return -1;
558   if(debug_lvl > 3)
559     syslog(LOG_DEBUG, _("ok, got pong from " IP_ADDR_S), IP_ADDR_V(cl->vpn_ip));
560   cl->status.got_pong = 1;
561 cp
562   return 0;
563 }
564
565 int add_host_h(conn_list_t *cl)
566 {
567   ip_t real_ip;
568   ip_t vpn_ip;
569   ip_t vpn_mask;
570   unsigned short port;
571   conn_list_t *ncn, *fw;
572 cp
573   if(!cl->status.active)
574     return -1;
575   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
576     {
577        syslog(LOG_ERR, _("got bad ADD_HOST request: %s"), cl->buffer);
578        return -1;
579     }  
580
581   if(debug_lvl > 2)
582     syslog(LOG_DEBUG, _("Add host request from " IP_ADDR_S), IP_ADDR_V(cl->vpn_ip));
583   if(debug_lvl > 3)
584     syslog(LOG_DEBUG, _("got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)"),
585            IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
586
587   /*
588     Suggestion of Hans Bayle
589   */
590   if((fw = lookup_conn(vpn_ip)))
591     {
592       if(fw->nexthop == cl)
593         notify_others(fw, cl, send_add_host);
594       else
595         if(debug_lvl > 1)
596           syslog(LOG_DEBUG, _("Invalid add_host request from " IP_ADDR_S),
597                               IP_ADDR_V(cl->vpn_ip));
598       return 0;
599     }
600
601   ncn = new_conn_list();
602   ncn->real_ip = real_ip;
603   ncn->vpn_ip = vpn_ip;
604   ncn->vpn_mask = vpn_mask;
605   ncn->port = port;
606   ncn->hostname = hostlookup(real_ip);
607   ncn->nexthop = cl;
608   ncn->next = conn_list;
609   conn_list = ncn;
610   ncn->status.active = 1;
611   notify_others(ncn, cl, send_add_host);
612 cp
613   return 0;
614 }
615
616 int req_key_h(conn_list_t *cl)
617 {
618   ip_t to;
619   ip_t from;
620   conn_list_t *fw;
621 cp
622   if(!cl->status.active) return -1;
623   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
624     {
625        syslog(LOG_ERR, _("got bad request: %s"), cl->buffer);
626        return -1;
627     }  
628
629   if(debug_lvl > 2)
630     syslog(LOG_DEBUG, _("got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S),
631            IP_ADDR_V(from), IP_ADDR_V(to));
632
633   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
634     {  /* hey! they want something from ME! :) */
635       send_key_answer(cl, from);
636       return 0;
637     }
638
639   fw = lookup_conn(to);
640   
641   if(!fw)
642     {
643       syslog(LOG_ERR, _("Attempting to forward key request to " IP_ADDR_S ", which does not exist?"),
644              IP_ADDR_V(to));
645       return -1;
646     }
647
648   if(debug_lvl > 3)
649     syslog(LOG_DEBUG, _("Forwarding request for public key to " IP_ADDR_S),
650            IP_ADDR_V(fw->nexthop->vpn_ip));
651   
652   cl->buffer[cl->reqlen-1] = '\n';
653   
654   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
655     {
656       syslog(LOG_ERR, _("send failed: %s:%d: %m"), __FILE__, __LINE__);
657       return -1;
658     }
659 cp
660   return 0;
661 }
662
663 void set_keys(conn_list_t *cl, int expiry, char *key)
664 {
665   char *ek;
666 cp
667   if(!cl->public_key)
668     {
669       cl->public_key = xmalloc(sizeof(*cl->key));
670       cl->public_key->key = NULL;
671     }
672     
673   if(cl->public_key->key)
674     free(cl->public_key->key);
675   cl->public_key->length = strlen(key);
676   cl->public_key->expiry = expiry;
677   cl->public_key->key = xmalloc(cl->public_key->length + 1);
678   strcpy(cl->public_key->key, key);
679
680   ek = make_shared_key(key);
681   
682   if(!cl->key)
683     {
684       cl->key = xmalloc(sizeof(*cl->key));
685       cl->key->key = NULL;
686     }
687
688   if(cl->key->key)
689     free(cl->key->key);
690
691   cl->key->length = strlen(ek);
692   cl->key->expiry = expiry;
693   cl->key->key = xmalloc(cl->key->length + 1);
694   strcpy(cl->key->key, ek);
695 cp
696 }
697
698 int ans_key_h(conn_list_t *cl)
699 {
700   ip_t to;
701   ip_t from;
702   int expiry;
703   char *key;
704   conn_list_t *fw, *gk;
705 cp
706   if(!cl->status.active) return -1;
707   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
708     {
709        syslog(LOG_ERR, _("got bad ANS_KEY request: %s"), cl->buffer);
710        return -1;
711     }  
712
713   if(debug_lvl > 3)
714     syslog(LOG_DEBUG, _("got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S),
715            IP_ADDR_V(from), IP_ADDR_V(to));
716
717   if(to == myself->vpn_ip)
718     {  /* hey! that key's for ME! :) */
719       if(debug_lvl > 2)
720         syslog(LOG_DEBUG, _("Yeah! key arrived. Now do something with it."));
721       gk = lookup_conn(from);
722
723       if(!gk)
724         {
725           syslog(LOG_ERR, _("Receiving key from " IP_ADDR_S ", which does not exist?"),
726                  IP_ADDR_V(from));
727           return -1;
728         }
729
730       set_keys(gk, expiry, key);
731       gk->status.validkey = 1;
732       gk->status.waitingforkey = 0;
733       flush_queues(gk);
734       return 0;
735     }
736
737   fw = lookup_conn(to);
738   
739   if(!fw)
740     {
741       syslog(LOG_ERR, _("Attempting to forward key to " IP_ADDR_S ", which does not exist?"),
742              IP_ADDR_V(to));
743       return -1;
744     }
745
746   if(debug_lvl > 2)
747     syslog(LOG_DEBUG, _("Forwarding public key to " IP_ADDR_S),
748            IP_ADDR_V(fw->nexthop->vpn_ip));
749
750   cl->buffer[cl->reqlen-1] = '\n';
751
752   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
753     {
754       syslog(LOG_ERR, _("send failed: %s:%d: %m"), __FILE__, __LINE__);
755       return -1;
756     }
757 cp
758   return 0;
759 }
760
761 int key_changed_h(conn_list_t *cl)
762 {
763   ip_t from;
764   conn_list_t *ik;
765 cp
766   if(!cl->status.active) return -1;
767   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
768     {
769        syslog(LOG_ERR, _("got bad ANS_KEY request: %s"), cl->buffer);
770        return -1;
771     }  
772
773   if(debug_lvl > 2)
774     syslog(LOG_DEBUG, _("got KEY_CHANGED from " IP_ADDR_S),
775            IP_ADDR_V(from));
776
777   ik = lookup_conn(from);
778
779   if(!ik)
780     {
781       syslog(LOG_ERR, _("Got changed key from " IP_ADDR_S ", which does not exist?"),
782              IP_ADDR_V(from));
783       return -1;
784     }
785
786   ik->status.validkey = 0;
787   ik->status.waitingforkey = 0;
788
789   if(debug_lvl > 3)
790     syslog(LOG_DEBUG, _("Forwarding key invalidation request"));
791
792   notify_others(cl, ik, send_key_changed);
793 cp
794   return 0;
795 }
796
797 int (*request_handlers[256])(conn_list_t*) = {
798   0, ack_h, 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   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
802   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
803   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
804   add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
807   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
808   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
809   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
810   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
811   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
812   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
813   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
814   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
815   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
816   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
817   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
818 };