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