Fix for a DoS attack:
[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->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->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->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   if(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   syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
494   cl->status.termreq = 1;
495   terminate_connection(cl);
496 cp
497   return 0;
498 }
499
500 int del_host_h(conn_list_t *cl)
501 {
502   ip_t vpn_ip;
503   conn_list_t *fw;
504 cp
505   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
506     {
507        syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
508        return -1;
509     }  
510
511   if(debug_lvl > 2)
512     syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
513            IP_ADDR_V(vpn_ip));
514
515   if(!(fw = lookup_conn(vpn_ip)))
516     {
517       syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
518              IP_ADDR_V(vpn_ip));
519       return 0;
520     }
521
522   notify_others(cl, fw, send_del_host);
523
524   fw->status.termreq = 1;
525   terminate_connection(fw);
526 cp
527   return 0;
528 }
529
530 int ping_h(conn_list_t *cl)
531 {
532 cp
533   if(debug_lvl > 3)
534     syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
535   cl->status.pinged = 0;
536   cl->status.got_pong = 1;
537
538   send_pong(cl);
539 cp
540   return 0;
541 }
542
543 int pong_h(conn_list_t *cl)
544 {
545 cp
546   if(debug_lvl > 3)
547     syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
548   cl->status.got_pong = 1;
549 cp
550   return 0;
551 }
552
553 int add_host_h(conn_list_t *cl)
554 {
555   ip_t real_ip;
556   ip_t vpn_ip;
557   ip_t vpn_mask;
558   unsigned short port;
559   conn_list_t *ncn, *fw;
560 cp
561   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
562     {
563        syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
564        return -1;
565     }  
566
567   if(debug_lvl > 2)
568     syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
569   if(debug_lvl > 3)
570     syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
571            IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
572
573   /*
574     Suggestion of Hans Bayle
575   */
576   if((fw = lookup_conn(vpn_ip)))
577     {
578       notify_others(fw, cl, send_add_host);
579       return 0;
580     }
581
582   ncn = new_conn_list();
583   ncn->real_ip = real_ip;
584   ncn->vpn_ip = vpn_ip;
585   ncn->vpn_mask = vpn_mask;
586   ncn->port = port;
587   ncn->hostname = hostlookup(real_ip);
588   ncn->nexthop = cl;
589   ncn->next = conn_list;
590   conn_list = ncn;
591   ncn->status.active = 1;
592   notify_others(ncn, cl, send_add_host);
593 cp
594   return 0;
595 }
596
597 int req_key_h(conn_list_t *cl)
598 {
599   ip_t to;
600   ip_t from;
601   conn_list_t *fw;
602 cp
603   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
604     {
605        syslog(LOG_ERR, "got bad request: %s", cl->buffer);
606        return -1;
607     }  
608
609   if(debug_lvl > 2)
610     syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
611            IP_ADDR_V(from), IP_ADDR_V(to));
612
613   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
614     {  /* hey! they want something from ME! :) */
615       send_key_answer(cl, from);
616       return 0;
617     }
618
619   fw = lookup_conn(to);
620   
621   if(!fw)
622     {
623       syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
624              IP_ADDR_V(to));
625       return -1;
626     }
627
628   if(debug_lvl > 3)
629     syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
630            IP_ADDR_V(fw->nexthop->vpn_ip));
631   
632   cl->buffer[cl->reqlen-1] = '\n';
633   
634   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
635     {
636       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
637       return -1;
638     }
639 cp
640   return 0;
641 }
642
643 void set_keys(conn_list_t *cl, int expiry, char *key)
644 {
645   char *ek;
646 cp
647   if(!cl->public_key)
648     {
649       cl->public_key = xmalloc(sizeof(*cl->key));
650       cl->public_key->key = NULL;
651     }
652     
653   if(cl->public_key->key)
654     free(cl->public_key->key);
655   cl->public_key->length = strlen(key);
656   cl->public_key->expiry = expiry;
657   cl->public_key->key = xmalloc(cl->public_key->length + 1);
658   strcpy(cl->public_key->key, key);
659
660   ek = make_shared_key(key);
661   
662   if(!cl->key)
663     {
664       cl->key = xmalloc(sizeof(*cl->key));
665       cl->key->key = NULL;
666     }
667
668   if(cl->key->key)
669     free(cl->key->key);
670
671   cl->key->length = strlen(ek);
672   cl->key->expiry = expiry;
673   cl->key->key = xmalloc(cl->key->length + 1);
674   strcpy(cl->key->key, ek);
675 cp
676 }
677
678 int ans_key_h(conn_list_t *cl)
679 {
680   ip_t to;
681   ip_t from;
682   int expiry;
683   char *key;
684   conn_list_t *fw, *gk;
685 cp
686   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
687     {
688        syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
689        return -1;
690     }  
691
692   if(debug_lvl > 3)
693     syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
694            IP_ADDR_V(from), IP_ADDR_V(to));
695
696   if(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(from);
701
702       if(!gk)
703         {
704           syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
705                  IP_ADDR_V(from));
706           return -1;
707         }
708
709       set_keys(gk, expiry, key);
710       gk->status.validkey = 1;
711       gk->status.waitingforkey = 0;
712       flush_queues(gk);
713       return 0;
714     }
715
716   fw = lookup_conn(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(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
729   cl->buffer[cl->reqlen-1] = '\n';
730
731   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
732     {
733       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
734       return -1;
735     }
736 cp
737   return 0;
738 }
739
740 int key_changed_h(conn_list_t *cl)
741 {
742   ip_t from;
743   conn_list_t *ik;
744 cp
745   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
746     {
747        syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
748        return -1;
749     }  
750
751   if(debug_lvl > 2)
752     syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
753            IP_ADDR_V(from));
754
755   ik = lookup_conn(from);
756
757   if(!ik)
758     {
759       syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
760              IP_ADDR_V(from));
761       return -1;
762     }
763
764   ik->status.validkey = 0;
765   ik->status.waitingforkey = 0;
766
767   if(debug_lvl > 3)
768     syslog(LOG_DEBUG, "Forwarding key invalidation request");
769
770   notify_others(cl, ik, send_key_changed);
771 cp
772   return 0;
773 }
774
775 int (*request_handlers[256])(conn_list_t*) = {
776   0, ack_h, 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   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
780   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
781   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
782   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
783   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
785   0, 0, 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   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
789   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
790   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
791   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
792   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
793   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
794   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
795   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
796 };