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