Propagate CFLAGS from configure to gcc.
[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 + 1, 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     Naughty zarq! Now you see what cheating will get you... [GS]
601   */
602   if(len > sizeof(add_host_t)) /* Another ADD_HOST follows */
603     {
604       if(request_handlers[d[sizeof(add_host_t)]] == NULL)
605         syslog(LOG_ERR, "Unknown request %d.", d[sizeof(add_host_t)]);
606       if(request_handlers[d[sizeof(add_host_t)]](cl, d + sizeof(add_host_t), len - sizeof(add_host_t)) < 0)
607         return -1;
608     }
609
610   return 0;
611 }
612
613 int req_key_h(conn_list_t *cl, unsigned char *d, int len)
614 {
615   key_req_t *tmp = (key_req_t*)d;
616   conn_list_t *fw;
617
618   if(debug_lvl > 2)
619     syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
620            IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
621
622   if((tmp->to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
623     {  /* hey! they want something from ME! :) */
624       send_key_answer(cl, tmp->from);
625       return 0;
626     }
627
628   fw = lookup_conn(tmp->to);
629   
630   if(!fw)
631   {
632     syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
633            IP_ADDR_V(tmp->to));
634     return -1;
635   }
636
637   if(debug_lvl > 3)
638     syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
639            IP_ADDR_V(fw->nexthop->vpn_ip));
640   if(send(fw->nexthop->meta_socket, tmp, sizeof(key_req_t), 0) < 0)
641     {
642       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
643       return -1;
644     }
645
646   return 0;
647 }
648
649 void set_keys(conn_list_t *cl, key_req_t *k)
650 {
651   char *ek;
652
653   if(!cl->public_key)
654     {
655       cl->public_key = xmalloc(sizeof(enc_key_t));
656       cl->public_key->key = NULL;
657     }
658   if(cl->public_key->key)
659     free(cl->public_key->key);
660   cl->public_key->length = k->len;
661   cl->public_key->expiry = k->expiry;
662   cl->public_key->key = xmalloc(k->len + 1);
663   strcpy(cl->public_key->key, &(k->key));
664
665   ek = make_shared_key(&(k->key));
666   if(!cl->key)
667     {
668       cl->key = xmalloc(sizeof(enc_key_t));
669       cl->key->key = NULL;
670     }
671   if(cl->key->key)
672     free(cl->key->key);
673   cl->key->length = strlen(ek);
674   cl->key->expiry = k->expiry;
675   cl->key->key = xmalloc(strlen(ek) + 1);
676   strcpy(cl->key->key, ek);
677 }
678
679 int ans_key_h(conn_list_t *cl, unsigned char *d, int len)
680 {
681   key_req_t *tmp = (key_req_t*)d;
682   conn_list_t *fw, *gk;
683
684   if(debug_lvl > 3)
685     syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
686            IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
687
688   if(tmp->to == myself->vpn_ip)
689     {  /* hey! that key's for ME! :) */
690       if(debug_lvl > 2)
691         syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
692       gk = lookup_conn(tmp->from);
693
694       if(!gk)
695         {
696           syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
697                  IP_ADDR_V(tmp->from));
698           return -1;
699         }
700
701       set_keys(gk, tmp);
702       gk->status.validkey = 1;
703       gk->status.waitingforkey = 0;
704       flush_queues(gk);
705       return 0;
706     }
707
708   fw = lookup_conn(tmp->to);
709   
710   if(!fw)
711   {
712     syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
713            IP_ADDR_V(tmp->to));
714     return -1;
715   }
716
717   if(debug_lvl > 2)
718     syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
719            IP_ADDR_V(fw->nexthop->vpn_ip));
720   if(send(fw->nexthop->meta_socket, tmp, sizeof(key_req_t)+tmp->len, 0) < 0)
721     {
722       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
723       return -1;
724     }
725
726   return 0;
727 }
728
729 int key_changed_h(conn_list_t *cl, unsigned char *d, int len)
730 {
731   key_changed_t *tmp = (key_changed_t*)d;
732   conn_list_t *ik;
733
734   if(debug_lvl > 2)
735     syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
736            IP_ADDR_V(tmp->from));
737
738   ik = lookup_conn(tmp->from);
739
740   if(!ik)
741     {
742       syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
743              IP_ADDR_V(tmp->from));
744       return -1;
745     }
746
747   ik->status.validkey = 0;
748   ik->status.waitingforkey = 0;
749
750   if(debug_lvl > 3)
751     syslog(LOG_DEBUG, "Forwarding key invalidation request");
752
753   notify_others(cl, ik, send_key_changed);
754
755   return 0;
756 }
757
758 int (*request_handlers[256])(conn_list_t*, unsigned char*, int) = {
759   0, ack_h, 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   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
763   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
764   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
765   add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
771   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
772   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
774   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, 0, 0, 0, 0,
778   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
779 };
780