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