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