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