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