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