Cleanups:
[tinc] / src / protocol.c
1 /*
2     protocol.c -- handle the meta-protocol
3     Copyright (C) 1999 Ivo Timmermans <zarq@iname.com>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <sys/socket.h>
26 #include <unistd.h>
27
28 #include <utils.h>
29 #include <xalloc.h>
30
31 #include "conf.h"
32 #include "encr.h"
33 #include "net.h"
34 #include "netutl.h"
35 #include "protocol.h"
36
37 int send_ack(conn_list_t *cl)
38 {
39   unsigned char tmp = ACK;
40 cp
41   if(debug_lvl > 2)
42     syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
43
44   syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
45   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
46     {
47       syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
48       return -1;
49     }
50 cp
51   return 0;
52 }
53
54 int send_termreq(conn_list_t *cl)
55 {
56   termreq_t tmp;
57 cp
58   tmp.type = TERMREQ;
59   tmp.vpn_ip = myself->vpn_ip;
60
61   if(debug_lvl > 2)
62     syslog(LOG_DEBUG, "Send TERMREQ(" IP_ADDR_S ") to " IP_ADDR_S, IP_ADDR_V(tmp.vpn_ip),
63            IP_ADDR_V(cl->vpn_ip));
64
65   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
66     {
67       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
68       return -1;
69     }
70 cp
71   return 0;
72 }
73
74 int send_timeout(conn_list_t *cl)
75 {
76   termreq_t tmp;
77 cp
78   tmp.type = PINGTIMEOUT;
79   tmp.vpn_ip = myself->vpn_ip;
80
81   if(debug_lvl > 2)
82     syslog(LOG_DEBUG, "Send TIMEOUT(" IP_ADDR_S ") to " IP_ADDR_S, IP_ADDR_V(tmp.vpn_ip),
83            IP_ADDR_V(cl->vpn_ip));
84
85   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
86     {
87       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
88       return -1;
89     }
90 cp
91   return 0;
92 }
93
94 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
95 {
96   del_host_t tmp;
97 cp
98   tmp.type = DEL_HOST;
99   tmp.vpn_ip = new_host->vpn_ip;
100
101   if(debug_lvl > 2)
102     syslog(LOG_DEBUG, "Sending delete host %lx to " IP_ADDR_S,
103            tmp.vpn_ip, IP_ADDR_V(cl->vpn_ip));
104
105   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
106     {
107       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
108       return -1;
109     }
110 cp
111   return 0;
112 }
113
114 int send_ping(conn_list_t *cl)
115 {
116   unsigned char tmp = PING;
117 cp
118   if(debug_lvl > 3)
119     syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
120
121   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
122     {
123       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
124       return -1;
125     }
126 cp
127   return 0;
128 }
129
130 int send_pong(conn_list_t *cl)
131 {
132   unsigned char tmp = PONG;
133 cp
134   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
135     {
136       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
137       return -1;
138     }
139 cp
140   return 0;
141 }
142
143 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
144 {
145   add_host_t tmp;
146 cp
147   tmp.type = ADD_HOST;
148   tmp.real_ip = new_host->real_ip;
149   tmp.vpn_ip = new_host->vpn_ip;
150   tmp.vpn_mask = new_host->vpn_mask;
151   tmp.portnr = new_host->port;
152
153   if(debug_lvl > 2)
154     syslog(LOG_DEBUG, "Sending add host (%lx/%lx %lx:%hd) to " IP_ADDR_S,
155            tmp.vpn_ip, tmp.vpn_mask, tmp.real_ip, tmp.portnr,
156            IP_ADDR_V(cl->vpn_ip));
157
158   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
159     {
160       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
161       return -1;
162     }
163 cp
164   return 0;
165 }
166
167 int send_key_changed(conn_list_t *cl, conn_list_t *src)
168 {
169   key_changed_t tmp;
170 cp
171   tmp.type = KEY_CHANGED;
172   tmp.from = src->vpn_ip;
173
174   if(debug_lvl > 2)
175     syslog(LOG_DEBUG, "Sending KEY_CHANGED (%lx) to " IP_ADDR_S,
176            tmp.from, IP_ADDR_V(cl->vpn_ip));
177
178   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
179     {
180       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
181       return -1;
182     }
183 cp
184   return 0;
185 }
186
187 void send_key_changed2(void)
188 {
189   conn_list_t *p;
190 cp
191   for(p = conn_list; p != NULL; p = p->next)
192     if(p->status.meta && p->protocol_version > PROT_3)
193       send_key_changed(p, myself);
194 cp
195 }
196
197 int send_basic_info(conn_list_t *cl)
198 {
199   basic_info_t tmp;
200 cp
201   tmp.type = BASIC_INFO;
202   tmp.protocol = PROT_CURRENT;
203
204   tmp.portnr = myself->port;
205   tmp.vpn_ip = myself->vpn_ip;
206   tmp.vpn_mask = myself->vpn_mask;
207
208   if(debug_lvl > 2)
209     syslog(LOG_DEBUG, "Send BASIC_INFO(%d,%hd," IP_ADDR_S "," IP_ADDR_S ") to " IP_ADDR_S,
210            tmp.protocol, tmp.portnr, IP_ADDR_V(tmp.vpn_ip), IP_ADDR_V(tmp.vpn_mask),
211            IP_ADDR_V(cl->real_ip));
212
213   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
214     {
215       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
216       return -1;
217     }
218 cp
219   return 0;
220 }
221
222 int send_passphrase(conn_list_t *cl)
223 {
224   passphrase_t tmp;
225 cp
226   tmp.type = PASSPHRASE;
227   encrypt_passphrase(&tmp);
228
229   if(debug_lvl > 2)
230     syslog(LOG_DEBUG, "Send PASSPHRASE(%hd,...) to " IP_ADDR_S, tmp.len,
231            IP_ADDR_V(cl->vpn_ip));
232
233   if((write(cl->meta_socket, &tmp, tmp.len+3)) < 0)
234     {
235       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
236       return -1;
237     }
238 cp
239   return 0;
240 }
241
242 int send_public_key(conn_list_t *cl)
243 {
244   public_key_t *tmp;
245 cp
246   tmp = (public_key_t*)xmalloc(strlen(my_public_key_base36)+sizeof(*tmp));
247   tmp->type = PUBLIC_KEY;
248   tmp->len = strlen(my_public_key_base36);
249   strcpy(&tmp->key, my_public_key_base36);
250
251   if(debug_lvl > 2)
252     syslog(LOG_DEBUG, "Send PUBLIC_KEY(%hd,%s) to " IP_ADDR_S, tmp->len, &tmp->key,
253            IP_ADDR_V(cl->vpn_ip));
254
255   if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
256     {
257       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
258       return -1;
259     }
260 cp
261   return 0;
262 }
263
264 int send_calculate(conn_list_t *cl, char *k)
265 {
266   calculate_t *tmp;
267 cp
268   tmp = xmalloc(strlen(k)+sizeof(*tmp));
269   tmp->type = CALCULATE;
270   tmp->len = strlen(k);
271   strcpy(&tmp->key, k);
272
273   if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
274     {
275       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
276       return -1;
277     }
278 cp
279   return 0;
280 }
281
282 int send_key_request(ip_t to)
283 {
284   key_req_t *tmp;
285   conn_list_t *fw;
286 cp
287   tmp = xmalloc(sizeof(*tmp));
288   tmp->type = REQ_KEY;
289   tmp->to = to;
290   tmp->from = myself->vpn_ip;
291   tmp->len = 0;
292
293   fw = lookup_conn(to);
294   if(!fw)
295     {
296       syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
297              IP_ADDR_V(to));
298       return -1;
299     }
300
301   if(debug_lvl > 2)
302     syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
303            IP_ADDR_V(fw->nexthop->vpn_ip));
304   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)) < 0)
305     {
306       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
307       return -1;
308     }
309   fw->status.waitingforkey = 1;
310 cp
311   return 0;
312 }
313
314 int send_key_answer(conn_list_t *cl, ip_t to)
315 {
316   key_req_t *tmp;
317   conn_list_t *fw;
318 cp
319   tmp = xmalloc(sizeof(*tmp)+strlen(my_public_key_base36));
320   tmp->type = ANS_KEY;
321   tmp->to = to;
322   tmp->from = myself->vpn_ip;
323   tmp->expiry = my_key_expiry;
324   tmp->len = strlen(my_public_key_base36);
325   strcpy(&tmp->key, my_public_key_base36);
326
327   fw = lookup_conn(to);
328   
329   if(!fw)
330   {
331     syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
332            IP_ADDR_V(to));
333     return -1;
334   }
335   
336   if(debug_lvl > 2)
337     syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
338            IP_ADDR_V(fw->nexthop->vpn_ip));
339   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
340     {
341       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
342       return -1;
343     }
344 cp
345   return 0;
346 }
347
348 /*
349   notify all my direct connections of a new host
350   that was added to the vpn, with the exception
351   of the source of the announcement.
352 */
353 int notify_others(conn_list_t *new, conn_list_t *source,
354                   int (*function)(conn_list_t*, conn_list_t*))
355 {
356   conn_list_t *p;
357 cp
358   for(p = conn_list; p != NULL; p = p->next)
359     if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
360       function(p, new);
361 cp
362   return 0;
363 }
364
365 /*
366   notify one connection of everything
367   i have connected
368 */
369 int notify_one(conn_list_t *new)
370 {
371   conn_list_t *p;
372 cp
373   for(p = conn_list; p != NULL; p = p->next)
374     if(p != new && p->protocol_version > PROT_3)
375       send_add_host(new, p);
376 cp
377   return 0;
378 }
379
380 /*
381   The incoming request handlers
382 */
383
384 int basic_info_h(conn_list_t *cl, unsigned char *d, int len)
385 {
386   basic_info_t *tmp = (basic_info_t*)d;
387 cp
388   cl->protocol_version = tmp->protocol;
389   cl->port = tmp->portnr;
390   cl->vpn_ip = tmp->vpn_ip;
391   cl->vpn_mask = tmp->vpn_mask;
392
393   if(cl->protocol_version < PROT_CURRENT)
394     {
395       syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
396              cl->protocol_version);
397       return -1;
398     }
399
400   if(debug_lvl > 2)
401     syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
402            IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
403   if(debug_lvl > 1)
404     syslog(LOG_DEBUG, "Peer uses protocol version %d",
405            cl->protocol_version);
406
407   if(cl->status.outgoing)
408     {
409       if(setup_vpn_connection(cl) < 0)
410         return -1;
411       send_basic_info(cl);
412     }
413   else
414     {
415       if(setup_vpn_connection(cl) < 0)
416         return -1;
417       send_passphrase(cl);
418     }
419
420   cl->status.active = 0;
421 cp
422   return 0;
423 }
424
425 int passphrase_h(conn_list_t *cl, unsigned char *d, int len)
426 {
427   passphrase_t *tmp = (passphrase_t*)d;
428 cp
429   cl->pp = xmalloc(tmp->len+3);
430   memcpy(cl->pp, tmp, tmp->len+3);
431
432   if(debug_lvl > 2)
433     syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", cl->pp->len);
434
435   if(cl->status.outgoing)
436     send_passphrase(cl);
437   else
438     send_public_key(cl);
439 cp
440   return 0;
441 }
442
443 int public_key_h(conn_list_t *cl, unsigned char *d, int len)
444 {
445   char *g_n;
446   public_key_t *tmp = (public_key_t*)d;
447 cp
448   if(debug_lvl > 2)
449     syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", tmp->len, &tmp->key);
450
451   g_n = xmalloc(tmp->len+1);
452   strcpy(g_n, &tmp->key);
453
454   if(verify_passphrase(cl, g_n))
455     {
456       /* intruder! */
457       syslog(LOG_ERR, "Intruder: passphrase does not match.");
458       return -1;
459     }
460
461   if(debug_lvl > 2)
462     syslog(LOG_INFO, "Passphrase OK");
463
464   if(cl->status.outgoing)
465     send_public_key(cl);
466   else
467     send_ack(cl);
468
469   cl->status.active = 1;
470   notify_others(cl, NULL, send_add_host);
471   notify_one(cl);
472 cp
473   return 0;
474 }
475
476 int ack_h(conn_list_t *cl, unsigned char *d, int len)
477 {
478 cp
479   if(debug_lvl > 2)
480     syslog(LOG_DEBUG, "got ACK");
481   
482   cl->status.active = 1;
483   syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
484
485   /*
486                         === FIXME ===
487     Now I'm going to cheat. The meta protocol is actually
488     a stream of requests, that may come in in the same TCP
489     packet. This is the only place that it will happen,
490     though.
491     I may change it in the future, if it appears that this
492     is not retainable.
493   */
494   if(len > 1) /* An ADD_HOST follows */
495     {
496       if(request_handlers[d[1]] == NULL)
497         syslog(LOG_ERR, "Unknown request %d.", d[1]);
498       if(request_handlers[d[1]](cl, d + 1, len - 1) < 0)
499         return -1;
500     }
501 cp
502   return 0;
503 }
504
505 int termreq_h(conn_list_t *cl, unsigned char *d, int len)
506 {
507 cp
508   syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
509   cl->status.termreq = 1;
510   terminate_connection(cl);
511
512   notify_others(cl, NULL, send_del_host);
513 cp
514   return 0;
515 }
516
517 int timeout_h(conn_list_t *cl, unsigned char *d, int len)
518 {
519 cp
520   syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
521   cl->status.termreq = 1;
522   terminate_connection(cl);
523 cp
524   return 0;
525 }
526
527 int del_host_h(conn_list_t *cl, unsigned char *d, int len)
528 {
529   del_host_t *tmp = (del_host_t*)d;
530   conn_list_t *fw;
531 cp
532   if(debug_lvl > 2)
533     syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
534            IP_ADDR_V(tmp->vpn_ip));
535
536   if(!(fw = lookup_conn(tmp->vpn_ip)))
537     {
538       syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
539              IP_ADDR_V(tmp->vpn_ip));
540       return 0;
541     }
542
543   notify_others(cl, fw, send_del_host);
544
545   fw->status.termreq = 1;
546   terminate_connection(fw);
547 cp
548   return 0;
549 }
550
551 int ping_h(conn_list_t *cl, unsigned char *d, int len)
552 {
553 cp
554   if(debug_lvl > 3)
555     syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
556   cl->status.pinged = 0;
557   cl->status.got_pong = 1;
558
559   send_pong(cl);
560 cp
561   return 0;
562 }
563
564 int pong_h(conn_list_t *cl, unsigned char *d, int len)
565 {
566 cp
567   if(debug_lvl > 3)
568     syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
569   cl->status.got_pong = 1;
570 cp
571   return 0;
572 }
573
574 int add_host_h(conn_list_t *cl, unsigned char *d, int len)
575 {
576   add_host_t *tmp = (add_host_t*)d;
577   conn_list_t *ncn, *fw;
578 cp
579   if(debug_lvl > 2)
580     syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
581   if(debug_lvl > 3)
582     syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
583            IP_ADDR_V(tmp->vpn_ip), IP_ADDR_V(tmp->vpn_mask), tmp->portnr);
584
585   /*
586     Suggestion of Hans Bayle
587   */
588   if((fw = lookup_conn(tmp->vpn_ip)))
589     {
590       notify_others(fw, cl, send_add_host);
591       return 0;
592     }
593
594   ncn = new_conn_list();
595   ncn->real_ip = tmp->real_ip;
596   ncn->vpn_ip = tmp->vpn_ip;
597   ncn->vpn_mask = tmp->vpn_mask;
598   ncn->port = tmp->portnr;
599   ncn->hostname = hostlookup(tmp->real_ip);
600   ncn->nexthop = cl;
601   ncn->next = conn_list;
602   conn_list = ncn;
603   ncn->status.active = 1;
604   notify_others(ncn, cl, send_add_host);
605
606   /*
607     again, i'm cheating here. see the comment in ack_h.
608     Naughty zarq! Now you see what cheating will get you... [GS]
609   */
610   if(len > sizeof(*tmp)) /* Another ADD_HOST follows */
611     {
612       if(request_handlers[d[sizeof(*tmp)]] == NULL)
613         syslog(LOG_ERR, "Unknown request %d.", d[sizeof(*tmp)]);
614       if(request_handlers[d[sizeof(*tmp)]](cl, d + sizeof(*tmp), len - sizeof(*tmp)) < 0)
615         return -1;
616     }
617 cp
618   return 0;
619 }
620
621 int req_key_h(conn_list_t *cl, unsigned char *d, int len)
622 {
623   key_req_t *tmp = (key_req_t*)d;
624   conn_list_t *fw;
625 cp
626   if(debug_lvl > 2)
627     syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
628            IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
629
630   if((tmp->to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
631     {  /* hey! they want something from ME! :) */
632       send_key_answer(cl, tmp->from);
633       return 0;
634     }
635
636   fw = lookup_conn(tmp->to);
637   
638   if(!fw)
639   {
640     syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
641            IP_ADDR_V(tmp->to));
642     return -1;
643   }
644
645   if(debug_lvl > 3)
646     syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
647            IP_ADDR_V(fw->nexthop->vpn_ip));
648   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)) < 0)
649     {
650       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
651       return -1;
652     }
653 cp
654   return 0;
655 }
656
657 void set_keys(conn_list_t *cl, key_req_t *k)
658 {
659   char *ek;
660 cp
661   if(!cl->public_key)
662     {
663       cl->public_key = xmalloc(sizeof(*cl->key));
664       cl->public_key->key = NULL;
665     }
666   if(cl->public_key->key)
667     free(cl->public_key->key);
668   cl->public_key->length = k->len;
669   cl->public_key->expiry = k->expiry;
670   cl->public_key->key = xmalloc(k->len + 1);
671   strcpy(cl->public_key->key, &(k->key));
672
673   ek = make_shared_key(&(k->key));
674   if(!cl->key)
675     {
676       cl->key = xmalloc(sizeof(*cl->key));
677       cl->key->key = NULL;
678     }
679   if(cl->key->key)
680     free(cl->key->key);
681   cl->key->length = strlen(ek);
682   cl->key->expiry = k->expiry;
683   cl->key->key = xmalloc(strlen(ek) + 1);
684   strcpy(cl->key->key, ek);
685 cp
686 }
687
688 int ans_key_h(conn_list_t *cl, unsigned char *d, int len)
689 {
690   key_req_t *tmp = (key_req_t*)d;
691   conn_list_t *fw, *gk;
692 cp
693   if(debug_lvl > 3)
694     syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
695            IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
696
697   if(tmp->to == myself->vpn_ip)
698     {  /* hey! that key's for ME! :) */
699       if(debug_lvl > 2)
700         syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
701       gk = lookup_conn(tmp->from);
702
703       if(!gk)
704         {
705           syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
706                  IP_ADDR_V(tmp->from));
707           return -1;
708         }
709
710       set_keys(gk, tmp);
711       gk->status.validkey = 1;
712       gk->status.waitingforkey = 0;
713       flush_queues(gk);
714       return 0;
715     }
716
717   fw = lookup_conn(tmp->to);
718   
719   if(!fw)
720   {
721     syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
722            IP_ADDR_V(tmp->to));
723     return -1;
724   }
725
726   if(debug_lvl > 2)
727     syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
728            IP_ADDR_V(fw->nexthop->vpn_ip));
729   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
730     {
731       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
732       return -1;
733     }
734 cp
735   return 0;
736 }
737
738 int key_changed_h(conn_list_t *cl, unsigned char *d, int len)
739 {
740   key_changed_t *tmp = (key_changed_t*)d;
741   conn_list_t *ik;
742 cp
743   if(debug_lvl > 2)
744     syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
745            IP_ADDR_V(tmp->from));
746
747   ik = lookup_conn(tmp->from);
748
749   if(!ik)
750     {
751       syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
752              IP_ADDR_V(tmp->from));
753       return -1;
754     }
755
756   ik->status.validkey = 0;
757   ik->status.waitingforkey = 0;
758
759   if(debug_lvl > 3)
760     syslog(LOG_DEBUG, "Forwarding key invalidation request");
761
762   notify_others(cl, ik, send_key_changed);
763 cp
764   return 0;
765 }
766
767 int (*request_handlers[256])(conn_list_t*, unsigned char*, int) = {
768   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
769   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
772   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
773   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
774   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
775   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
776   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
777   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
778   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
780   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
781   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
782   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
783   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
785   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
786   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
788 };