- Added log message when SIGCHLD is received ("thanks" to Ivo van Dong)
[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.28.4.14 2000/06/28 13:41:02 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 > 1)
54     syslog(LOG_DEBUG, _("Sending ACK to " IP_ADDR_S " (%s)"),
55            IP_ADDR_V(cl->vpn_ip), cl->hostname);
56
57   buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
58
59   if((write(cl->meta_socket, buffer, buflen)) < 0)
60     {
61       syslog(LOG_ERR, _("Send failed: %d:%d: %m"), __FILE__, __LINE__);
62       return -1;
63     }
64 cp
65   return 0;
66 }
67
68 int send_termreq(conn_list_t *cl)
69 {
70 cp
71   if(debug_lvl > 1)
72     syslog(LOG_DEBUG, _("Sending TERMREQ to " IP_ADDR_S " (%s)"),
73            IP_ADDR_V(cl->vpn_ip), cl->hostname);
74
75   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
76
77   if(write(cl->meta_socket, buffer, buflen) < 0)
78     {
79       if(debug_lvl > 1)
80         syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
81       return -1;
82     }
83 cp
84   return 0;
85 }
86
87 int send_timeout(conn_list_t *cl)
88 {
89 cp
90   if(debug_lvl > 1)
91     syslog(LOG_DEBUG, _("Sending TIMEOUT to " IP_ADDR_S " (%s)"),
92            IP_ADDR_V(cl->vpn_ip), cl->hostname);
93
94   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
95
96   if((write(cl->meta_socket, buffer, buflen)) < 0)
97     {
98       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
99       return -1;
100     }
101 cp
102   return 0;
103 }
104
105 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
106 {
107 cp
108   if(debug_lvl > 1)
109     syslog(LOG_DEBUG, _("Sending DEL_HOST for " IP_ADDR_S " (%s) to " IP_ADDR_S " (%s)"),
110            IP_ADDR_V(new_host->vpn_ip), new_host->hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
111
112   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
113
114   if((write(cl->meta_socket, buffer, buflen)) < 0)
115     {
116       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
117       return -1;
118     }
119 cp
120   return 0;
121 }
122
123 int send_ping(conn_list_t *cl)
124 {
125 cp
126   if(debug_lvl > 1)
127     syslog(LOG_DEBUG, _("Sending PING to " IP_ADDR_S " (%s)"),
128            IP_ADDR_V(cl->vpn_ip), cl->hostname);
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   if(debug_lvl > 1)
145     syslog(LOG_DEBUG, _("Sending PONG to " IP_ADDR_S " (%s)"),
146            IP_ADDR_V(cl->vpn_ip), cl->hostname);
147
148   buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
149
150   if((write(cl->meta_socket, buffer, buflen)) < 0)
151     {
152       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
153       return -1;
154     }
155 cp
156   return 0;
157 }
158
159 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
160 {
161   ip_t real_ip;
162   int flags;
163   char *hostname;
164 cp
165   real_ip = new_host->real_ip;
166   hostname = new_host->hostname;
167   flags = new_host->flags;
168   
169   /* If we need to propagate information about a new host that wants us to export
170    * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
171    * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
172    * work correctly.
173    */
174      
175   if(flags & EXPORTINDIRECTDATA)
176     {
177       flags &= ~EXPORTINDIRECTDATA;
178       flags |= INDIRECTDATA;
179       real_ip = myself->vpn_ip;
180       hostname = myself->hostname;
181     }
182
183   if(debug_lvl > 1)
184     syslog(LOG_DEBUG, _("Sending ADD_HOST for " IP_ADDR_S " (%s) to " IP_ADDR_S " (%s)"),
185            IP_ADDR_V(new_host->vpn_ip), hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
186
187   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x %d\n", ADD_HOST, real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port, flags);
188
189   if((write(cl->meta_socket, buffer, buflen)) < 0)
190     {
191       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
192       return -1;
193     }
194 cp
195   return 0;
196 }
197
198 int send_key_changed(conn_list_t *cl, conn_list_t *src)
199 {
200 cp
201   if(debug_lvl > 1)
202     syslog(LOG_DEBUG, _("Sending KEY_CHANGED origin " IP_ADDR_S " to " IP_ADDR_S " (%s)"),
203            IP_ADDR_V(src->vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
204
205   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
206
207   if((write(cl->meta_socket, buffer, buflen)) < 0)
208     {
209       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
210       return -1;
211     }
212 cp
213   return 0;
214 }
215
216 void send_key_changed_all(void)
217 {
218   conn_list_t *p;
219 cp
220   for(p = conn_list; p != NULL; p = p->next)
221     if(p->status.meta && p->status.active)
222       send_key_changed(p, myself);
223 cp
224 }
225
226 int send_basic_info(conn_list_t *cl)
227 {
228 cp
229   if(debug_lvl > 1)
230     syslog(LOG_DEBUG, _("Sending BASIC_INFO to %s"),
231            cl->hostname);
232
233   buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x %d\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port, myself->flags);
234
235   if((write(cl->meta_socket, buffer, buflen)) < 0)
236     {
237       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
238       return -1;
239     }
240 cp
241   return 0;
242 }
243
244 int send_passphrase(conn_list_t *cl)
245 {
246   passphrase_t tmp;
247 cp
248   encrypt_passphrase(&tmp);
249
250   if(debug_lvl > 1)
251     syslog(LOG_DEBUG, _("Sending PASSPHRASE to " IP_ADDR_S " (%s)"),
252            IP_ADDR_V(cl->vpn_ip), cl->hostname);
253
254   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
255
256   if((write(cl->meta_socket, buffer, buflen)) < 0)
257     {
258       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
259       return -1;
260     }
261 cp
262   return 0;
263 }
264
265 int send_public_key(conn_list_t *cl)
266 {
267 cp
268   if(debug_lvl > 1)
269     syslog(LOG_DEBUG, _("Sending PUBLIC_KEY to " IP_ADDR_S " (%s)"),
270            IP_ADDR_V(cl->vpn_ip), cl->hostname);
271
272   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
273
274   if((write(cl->meta_socket, buffer, buflen)) < 0)
275     {
276       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
277       return -1;
278     }
279 cp
280   return 0;
281 }
282
283 /* WDN doet deze functie? (GS)
284 int send_calculate(conn_list_t *cl, char *k)
285 {
286 cp
287   buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
288
289   if((write(cl->meta_socket, buffer, buflen)) < 0)
290     {
291       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
292       return -1;
293     }
294 cp
295   return 0;
296 }
297 */
298
299 int send_key_request(ip_t to)
300 {
301   conn_list_t *fw;
302 cp
303   fw = lookup_conn(to);
304   if(!fw)
305     {
306       syslog(LOG_ERR, _("Attempting to send REQ_KEY to " IP_ADDR_S ", which does not exist?"),
307              IP_ADDR_V(to));
308       return -1;
309     }
310
311   if(debug_lvl > 1)
312     syslog(LOG_DEBUG, _("Sending REQ_KEY to " IP_ADDR_S " (%s)"),
313            IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
314
315   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
316
317   if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
318     {
319       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
320       return -1;
321     }
322   fw->status.waitingforkey = 1;
323 cp
324   return 0;
325 }
326
327 int send_key_answer(conn_list_t *cl, ip_t to)
328 {
329   conn_list_t *fw;
330 cp
331
332   fw = lookup_conn(to);
333   
334   if(!fw)
335     {
336       syslog(LOG_ERR, _("Attempting to send ANS_KEY to " IP_ADDR_S ", which does not exist?"),
337              IP_ADDR_V(to));
338       return -1;
339     }
340
341  if(debug_lvl > 1)
342     syslog(LOG_DEBUG, _("Sending ANS_KEY to " IP_ADDR_S " (%s)"),
343            IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
344
345   buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
346
347   if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
348     {
349       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
350       return -1;
351     }
352 cp
353   return 0;
354 }
355
356 /*
357   notify all my direct connections of a new host
358   that was added to the vpn, with the exception
359   of the source of the announcement.
360 */
361 int notify_others(conn_list_t *new, conn_list_t *source,
362                   int (*function)(conn_list_t*, conn_list_t*))
363 {
364   conn_list_t *p;
365 cp
366   for(p = conn_list; p != NULL; p = p->next)
367     if(p != new && p != source && p->status.meta && p->status.active)
368       function(p, new);
369 cp
370   return 0;
371 }
372
373 /*
374   notify one connection of everything
375   i have connected
376 */
377 int notify_one(conn_list_t *new)
378 {
379   conn_list_t *p;
380 cp
381   for(p = conn_list; p != NULL; p = p->next)
382     if(p != new && p->status.active)
383       send_add_host(new, p);
384 cp
385   return 0;
386 }
387
388 /*
389   The incoming request handlers
390 */
391
392 int basic_info_h(conn_list_t *cl)
393 {
394 cp
395   if(debug_lvl > 1)
396     syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->hostname);
397
398   if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
399     {
400        syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
401               cl->hostname);
402        return -1;
403     }  
404
405   if(cl->protocol_version != PROT_CURRENT)
406     {
407       syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
408              cl->protocol_version);
409       return -1;
410     }
411
412   if(cl->status.outgoing)
413     {
414       if(setup_vpn_connection(cl) < 0)
415         return -1;
416       send_basic_info(cl);
417     }
418   else
419     {
420       if(setup_vpn_connection(cl) < 0)
421         return -1;
422       send_passphrase(cl);
423     }
424 cp
425   return 0;
426 }
427
428 int passphrase_h(conn_list_t *cl)
429 {
430 cp
431   cl->pp = xmalloc(sizeof(*(cl->pp)));
432
433   if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
434     {
435       syslog(LOG_ERR, _("Got bad PASSPHRASE from " IP_ADDR_S " (%s)"),
436               IP_ADDR_V(cl->vpn_ip), cl->hostname);
437       return -1;
438     }
439   cl->pp->len = strlen(cl->pp->phrase);
440     
441   if(debug_lvl > 1)
442     syslog(LOG_DEBUG, _("Got PASSPHRASE from " IP_ADDR_S " (%s)"),
443               IP_ADDR_V(cl->vpn_ip), cl->hostname);
444
445   if(cl->status.outgoing)
446     send_passphrase(cl);
447   else
448     send_public_key(cl);
449 cp
450   return 0;
451 }
452
453 int public_key_h(conn_list_t *cl)
454 {
455   char *g_n;
456   conn_list_t *old;
457 cp
458   if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
459     {
460        syslog(LOG_ERR, _("Got bad PUBLIC_KEY from " IP_ADDR_S " (%s)"),
461               IP_ADDR_V(cl->vpn_ip), cl->hostname);
462        return -1;
463     }  
464
465   if(debug_lvl > 1)
466     syslog(LOG_DEBUG, _("Got PUBLIC_KEY from " IP_ADDR_S " (%s)"),
467               IP_ADDR_V(cl->vpn_ip), cl->hostname);
468
469   if(verify_passphrase(cl, g_n))
470     {
471       /* intruder! */
472       syslog(LOG_ERR, _("Intruder: passphrase does not match!"));
473       return -1;
474     }
475
476   if(cl->status.outgoing)
477     send_public_key(cl);
478   else
479     {
480       send_ack(cl);
481
482       /* Okay, before we active the connection, we check if there is another entry
483          in the connection list with the same vpn_ip. If so, it presumably is an
484          old connection that has timed out but we don't know it yet. Because our
485          conn_list entry is not active, lookup_conn will skip ourself. */
486
487       while(old = lookup_conn(cl->vpn_ip)) 
488         terminate_connection(old);
489
490       cl->status.active = 1;
491
492       if(debug_lvl > 0)
493         syslog(LOG_NOTICE, _("Connection with " IP_ADDR_S " (%s) activated"),
494                            IP_ADDR_V(cl->vpn_ip), cl->hostname);
495
496       notify_others(cl, NULL, send_add_host);
497       notify_one(cl);
498     }
499 cp
500   return 0;
501 }
502
503 int ack_h(conn_list_t *cl)
504 {
505 cp
506   if(debug_lvl > 1)
507     syslog(LOG_DEBUG, _("Got ACK from " IP_ADDR_S " (%s)"),
508               IP_ADDR_V(cl->vpn_ip), cl->hostname);
509   
510   cl->status.active = 1;
511
512   syslog(LOG_NOTICE, _("Connection with " IP_ADDR_S " (%s) activated"),
513               IP_ADDR_V(cl->vpn_ip), cl->hostname);
514
515   notify_others(cl, NULL, send_add_host);
516   notify_one(cl);
517
518   upstreamindex = 0;
519 cp
520   return 0;
521 }
522
523 int termreq_h(conn_list_t *cl)
524 {
525 cp
526   if(!cl->status.active)
527     {
528       syslog(LOG_ERR, _("Got unauthorized TERMREQ from " IP_ADDR_S " (%s)"),
529               IP_ADDR_V(cl->vpn_ip), cl->hostname);
530       return -1;
531     }
532     
533   if(debug_lvl > 1)
534    syslog(LOG_DEBUG, _("Got TERMREQ from " IP_ADDR_S " (%s)"),
535              IP_ADDR_V(cl->vpn_ip), cl->hostname);
536   
537   cl->status.termreq = 1;
538
539   if(cl->status.active)
540     notify_others(cl, NULL, send_del_host);
541
542   cl->status.active = 0;
543
544   terminate_connection(cl);
545 cp
546   return 0;
547 }
548
549 int timeout_h(conn_list_t *cl)
550 {
551 cp
552   if(!cl->status.active)
553     {
554       syslog(LOG_ERR, _("Got unauthorized TIMEOUT from " IP_ADDR_S " (%s)"),
555               IP_ADDR_V(cl->vpn_ip), cl->hostname);
556       return -1;
557     }
558
559   if(debug_lvl > 1)
560     syslog(LOG_DEBUG, _("Got TIMEOUT from " IP_ADDR_S " (%s)"),
561               IP_ADDR_V(cl->vpn_ip), cl->hostname);
562
563   cl->status.termreq = 1;
564   terminate_connection(cl);
565 cp
566   return 0;
567 }
568
569 int del_host_h(conn_list_t *cl)
570 {
571   ip_t vpn_ip;
572   conn_list_t *fw;
573 cp
574   if(!cl->status.active)
575     {
576       syslog(LOG_ERR, _("Got unauthorized DEL_HOST from " IP_ADDR_S " (%s)"),
577               IP_ADDR_V(cl->vpn_ip), cl->hostname);
578       return -1;
579     }
580
581   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
582     {
583        syslog(LOG_ERR, _("Got bad DEL_HOST from " IP_ADDR_S " (%s)"),
584               IP_ADDR_V(cl->vpn_ip), cl->hostname);
585        return -1;
586     }  
587
588   if(!(fw = lookup_conn(vpn_ip)))
589     {
590       syslog(LOG_ERR, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (%s) which does not exist?"),
591              IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), cl->hostname);
592       return 0;
593     }
594
595   if(debug_lvl > 1)
596     syslog(LOG_DEBUG, _("Got DEL_HOST for " IP_ADDR_S " (%s) from " IP_ADDR_S " (%s)"),
597            IP_ADDR_V(fw->vpn_ip), fw->hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
598
599   notify_others(fw, cl, send_del_host);
600
601   fw->status.termreq = 1;
602   fw->status.active = 0;
603
604   terminate_connection(fw);
605 cp
606   return 0;
607 }
608
609 int ping_h(conn_list_t *cl)
610 {
611 cp
612   if(!cl->status.active)
613     {
614       syslog(LOG_ERR, _("Got unauthorized PING from " IP_ADDR_S " (%s)"),
615               IP_ADDR_V(cl->vpn_ip), cl->hostname);
616       return -1;
617     }
618
619   if(debug_lvl > 1)
620     syslog(LOG_DEBUG, _("Got PING from " IP_ADDR_S " (%s)"),
621               IP_ADDR_V(cl->vpn_ip), cl->hostname);
622
623   cl->status.pinged = 0;
624   cl->status.got_pong = 1;
625
626   send_pong(cl);
627 cp
628   return 0;
629 }
630
631 int pong_h(conn_list_t *cl)
632 {
633 cp
634   if(!cl->status.active)
635     {
636       syslog(LOG_ERR, _("Got unauthorized PONG from " IP_ADDR_S " (%s)"),
637               IP_ADDR_V(cl->vpn_ip), cl->hostname);
638       return -1;
639     }
640
641   if(debug_lvl > 1)
642     syslog(LOG_DEBUG, _("Got PONG from " IP_ADDR_S " (%s)"),
643               IP_ADDR_V(cl->vpn_ip), cl->hostname);
644
645   cl->status.got_pong = 1;
646 cp
647   return 0;
648 }
649
650 int add_host_h(conn_list_t *cl)
651 {
652   ip_t real_ip;
653   ip_t vpn_ip;
654   ip_t vpn_mask;
655   unsigned short port;
656   int flags;
657   conn_list_t *ncn, *old;
658 cp
659   if(!cl->status.active)
660     {
661       syslog(LOG_ERR, _("Got unauthorized ADD_HOST from " IP_ADDR_S " (%s)"),
662               IP_ADDR_V(cl->vpn_ip), cl->hostname);
663       return -1;
664     }
665     
666   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
667     {
668        syslog(LOG_ERR, _("Got bad ADD_HOST from " IP_ADDR_S " (%s)"),
669               IP_ADDR_V(cl->vpn_ip), cl->hostname);
670        return -1;
671     }  
672
673   while(old = lookup_conn(vpn_ip))
674       terminate_connection(old);
675     
676   ncn = new_conn_list();
677   ncn->real_ip = real_ip;
678   ncn->hostname = hostlookup(htonl(real_ip));
679   ncn->vpn_ip = vpn_ip;
680   ncn->vpn_mask = vpn_mask;
681   ncn->port = port;
682   ncn->flags = flags;
683   ncn->nexthop = cl;
684   ncn->next = conn_list;
685   conn_list = ncn;
686   ncn->status.active = 1;
687
688   if(debug_lvl > 1)
689     syslog(LOG_DEBUG, _("Got ADD_HOST for " IP_ADDR_S " (%s) from " IP_ADDR_S " (%s)"),
690            IP_ADDR_V(ncn->vpn_ip), ncn->hostname, IP_ADDR_V(cl->vpn_ip), cl->hostname);
691
692   notify_others(ncn, cl, send_add_host);
693 cp
694   return 0;
695 }
696
697 int req_key_h(conn_list_t *cl)
698 {
699   ip_t to;
700   ip_t from;
701   conn_list_t *fw;
702 cp
703   if(!cl->status.active)
704     {
705       syslog(LOG_ERR, _("Got unauthorized REQ_KEY from " IP_ADDR_S " (%s)"),
706               IP_ADDR_V(cl->vpn_ip), cl->hostname);
707       return -1;
708     }
709
710   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
711     {
712        syslog(LOG_ERR, _("Got bad REQ_KEY from " IP_ADDR_S " (%s)"),
713               IP_ADDR_V(cl->vpn_ip), cl->hostname);
714        return -1;
715     }  
716
717   if(debug_lvl > 1)
718     syslog(LOG_DEBUG, _("Got REQ_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
719            IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
720
721   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
722     {  /* hey! they want something from ME! :) */
723       send_key_answer(cl, from);
724       return 0;
725     }
726
727   fw = lookup_conn(to);
728   
729   if(!fw)
730     {
731       syslog(LOG_ERR, _("Attempting to forward REQ_KEY to " IP_ADDR_S ", which does not exist?"),
732              IP_ADDR_V(to));
733       return -1;
734     }
735
736   if(debug_lvl > 1)
737     syslog(LOG_DEBUG, _("Forwarding REQ_KEY to " IP_ADDR_S " (%s)"),
738            IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
739   
740   cl->buffer[cl->reqlen-1] = '\n';
741   
742   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
743     {
744       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
745       return -1;
746     }
747 cp
748   return 0;
749 }
750
751 void set_keys(conn_list_t *cl, int expiry, char *key)
752 {
753   char *ek;
754 cp
755   if(!cl->public_key)
756     {
757       cl->public_key = xmalloc(sizeof(*cl->key));
758       cl->public_key->key = NULL;
759     }
760     
761   if(cl->public_key->key)
762     free(cl->public_key->key);
763   cl->public_key->length = strlen(key);
764   cl->public_key->expiry = expiry;
765   cl->public_key->key = xmalloc(cl->public_key->length + 1);
766   strcpy(cl->public_key->key, key);
767
768   ek = make_shared_key(key);
769   
770   if(!cl->key)
771     {
772       cl->key = xmalloc(sizeof(*cl->key));
773       cl->key->key = NULL;
774     }
775
776   if(cl->key->key)
777     free(cl->key->key);
778
779   cl->key->length = strlen(ek);
780   cl->key->expiry = expiry;
781   cl->key->key = xmalloc(cl->key->length + 1);
782   strcpy(cl->key->key, ek);
783 cp
784 }
785
786 int ans_key_h(conn_list_t *cl)
787 {
788   ip_t to;
789   ip_t from;
790   int expiry;
791   char *key;
792   conn_list_t *fw, *gk;
793 cp
794   if(!cl->status.active)
795     {
796       syslog(LOG_ERR, _("Got unauthorized ANS_KEY from " IP_ADDR_S " (%s)"),
797               IP_ADDR_V(cl->vpn_ip), cl->hostname);
798       return -1;
799     }
800
801   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
802     {
803        syslog(LOG_ERR, _("Got bad ANS_KEY from " IP_ADDR_S " (%s)"),
804               IP_ADDR_V(cl->vpn_ip), cl->hostname);
805        return -1;
806     }  
807
808   if(debug_lvl > 1)
809     syslog(LOG_DEBUG, _("Got ANS_KEY origin " IP_ADDR_S " destination " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
810             IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), cl->hostname);
811
812   if(to == myself->vpn_ip)
813     {  /* hey! that key's for ME! :) */
814       gk = lookup_conn(from);
815
816       if(!gk)
817         {
818           syslog(LOG_ERR, _("Receiving ANS_KEY from " IP_ADDR_S ", which does not exist?"),
819                  IP_ADDR_V(from));
820           return -1;
821         }
822
823       set_keys(gk, expiry, key);
824       gk->status.validkey = 1;
825       gk->status.waitingforkey = 0;
826       flush_queues(gk);
827       return 0;
828     }
829
830   fw = lookup_conn(to);
831   
832   if(!fw)
833     {
834       syslog(LOG_ERR, _("Attempting to forward ANS_KEY to " IP_ADDR_S ", which does not exist?"),
835              IP_ADDR_V(to));
836       return -1;
837     }
838
839   if(debug_lvl > 1)
840     syslog(LOG_DEBUG, _("Forwarding ANS_KEY to " IP_ADDR_S " (%s)"),
841            IP_ADDR_V(fw->nexthop->vpn_ip), fw->nexthop->hostname);
842
843   cl->buffer[cl->reqlen-1] = '\n';
844
845   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
846     {
847       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
848       return -1;
849     }
850 cp
851   return 0;
852 }
853
854 int key_changed_h(conn_list_t *cl)
855 {
856   ip_t from;
857   conn_list_t *ik;
858 cp
859   if(!cl->status.active)
860     {
861       syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from " IP_ADDR_S " (%s)"),
862               IP_ADDR_V(cl->vpn_ip), cl->hostname);
863       return -1;
864     }
865
866   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
867     {
868        syslog(LOG_ERR, _("Got bad KEY_CHANGED from " IP_ADDR_S " (%s)"),
869               IP_ADDR_V(cl->vpn_ip), cl->hostname);
870        return -1;
871     }  
872
873   if(debug_lvl > 1)
874     syslog(LOG_DEBUG, _("Got KEY_CHANGED origin " IP_ADDR_S " from " IP_ADDR_S " (%s)"),
875             IP_ADDR_V(from), IP_ADDR_V(cl->vpn_ip), cl->hostname);
876
877   ik = lookup_conn(from);
878
879   if(!ik)
880     {
881       syslog(LOG_ERR, _("Got KEY_CHANGED from " IP_ADDR_S ", which does not exist?"),
882              IP_ADDR_V(from));
883       return -1;
884     }
885
886   ik->status.validkey = 0;
887   ik->status.waitingforkey = 0;
888
889   notify_others(ik, cl, send_key_changed);
890 cp
891   return 0;
892 }
893
894 int (*request_handlers[256])(conn_list_t*) = {
895   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
896   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
897   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
898   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
899   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
900   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
901   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
902   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
903   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
904   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
905   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
906   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
908   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
909   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
910   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
911   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
913   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
914   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
915 };