a6f302906cb90118addb95433d9506eb024a320b
[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.17 2000/06/29 19:47:03 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 %s (%s)"),
55            cl->vpn_hostname, cl->real_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 %s (%s)"),
73            cl->vpn_hostname, cl->real_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 %s (%s)"),
92            cl->vpn_hostname, cl->real_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 %s (%s) to %s (%s)"),
110            new_host->vpn_hostname, new_host->real_hostname, cl->vpn_hostname, cl->real_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 %s (%s)"),
128            cl->vpn_hostname, cl->real_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 %s (%s)"),
146            cl->vpn_hostname, cl->real_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->real_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->real_hostname;
181     }
182
183   if(debug_lvl > 1)
184     syslog(LOG_DEBUG, _("Sending ADD_HOST for %s (%s) to %s (%s)"),
185            new_host->vpn_hostname, hostname, cl->vpn_hostname, cl->real_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 %s to %s (%s)"),
203            src->vpn_hostname, cl->vpn_hostname, cl->real_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->real_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 %s (%s)"),
252            cl->vpn_hostname, cl->real_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 %s (%s)"),
270            cl->vpn_hostname, cl->real_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 %d.%d.%d.%d, 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 %s (%s)"),
313            fw->nexthop->vpn_hostname, fw->nexthop->real_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 %d.%d.%d.%d, 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 %s (%s)"),
343            fw->nexthop->vpn_hostname, fw->nexthop->real_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   conn_list_t *old;
395 cp
396   if(debug_lvl > 1)
397     syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->real_hostname);
398
399   if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
400     {
401        syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
402               cl->real_hostname);
403        return -1;
404     }
405     
406   cl->vpn_hostname = hostlookup(htonl(cl->vpn_ip));
407
408   if(cl->protocol_version != PROT_CURRENT)
409     {
410       syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
411              cl->protocol_version);
412       return -1;
413     }
414
415   if(cl->status.outgoing)
416     {
417       /* First check if the host we connected to is already in our
418          connection list. If so, we are probably making a loop, which
419          is not desirable.
420        */
421        
422       if(old=lookup_conn(cl->vpn_ip))
423         {
424           if(debug_lvl>0)
425             syslog(LOG_NOTICE, _("Uplink %s (%s) is already in our connection list"),
426               cl->vpn_hostname, cl->real_hostname);
427           cl->status.outgoing = 0;
428           old->status.outgoing = 1;
429           terminate_connection(cl);
430           return 0;
431         }
432
433       if(setup_vpn_connection(cl) < 0)
434         return -1;
435       send_basic_info(cl);
436     }
437   else
438     {
439         
440       if(setup_vpn_connection(cl) < 0)
441         return -1;
442       send_passphrase(cl);
443     }
444 cp
445   return 0;
446 }
447
448 int passphrase_h(conn_list_t *cl)
449 {
450 cp
451   cl->pp = xmalloc(sizeof(*(cl->pp)));
452
453   if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
454     {
455       syslog(LOG_ERR, _("Got bad PASSPHRASE from %s (%s)"),
456               cl->vpn_hostname, cl->real_hostname);
457       return -1;
458     }
459   cl->pp->len = strlen(cl->pp->phrase);
460     
461   if(debug_lvl > 1)
462     syslog(LOG_DEBUG, _("Got PASSPHRASE from %s (%s)"),
463               cl->vpn_hostname, cl->real_hostname);
464
465   if(cl->status.outgoing)
466     send_passphrase(cl);
467   else
468     send_public_key(cl);
469 cp
470   return 0;
471 }
472
473 int public_key_h(conn_list_t *cl)
474 {
475   char *g_n;
476   conn_list_t *old;
477 cp
478   if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
479     {
480        syslog(LOG_ERR, _("Got bad PUBLIC_KEY from %s (%s)"),
481               cl->vpn_hostname, cl->real_hostname);
482        return -1;
483     }  
484
485   if(debug_lvl > 1)
486     syslog(LOG_DEBUG, _("Got PUBLIC_KEY from %s (%s)"),
487               cl->vpn_hostname, cl->real_hostname);
488
489   if(verify_passphrase(cl, g_n))
490     {
491       /* intruder! */
492       syslog(LOG_ERR, _("Intruder from %s: passphrase for %s does not match!"),
493               cl->real_hostname, cl->vpn_hostname);
494       return -1;
495     }
496
497   if(cl->status.outgoing)
498     send_public_key(cl);
499   else
500     {
501       send_ack(cl);
502
503       /* Okay, before we active the connection, we check if there is another entry
504          in the connection list with the same vpn_ip. If so, it presumably is an
505          old connection that has timed out but we don't know it yet.
506        */
507
508       while(old = lookup_conn(cl->vpn_ip)) 
509         {
510           syslog(LOG_NOTICE, _("Removing old entry for %s at %s in favour of new connection from %s"),
511             cl->vpn_hostname, old->real_hostname, cl->real_hostname);
512           old->status.active = 0;
513           terminate_connection(old);
514         }
515         
516       cl->status.active = 1;
517
518       if(debug_lvl > 0)
519         syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
520                            cl->vpn_hostname, cl->real_hostname);
521
522       notify_others(cl, NULL, send_add_host);
523       notify_one(cl);
524     }
525 cp
526   return 0;
527 }
528
529 int ack_h(conn_list_t *cl)
530 {
531 cp
532   if(debug_lvl > 1)
533     syslog(LOG_DEBUG, _("Got ACK from %s (%s)"),
534               cl->vpn_hostname, cl->real_hostname);
535   
536   cl->status.active = 1;
537
538   syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
539               cl->vpn_hostname, cl->real_hostname);
540
541   notify_others(cl, NULL, send_add_host);
542   notify_one(cl);
543
544   upstreamindex = 0;
545 cp
546   return 0;
547 }
548
549 int termreq_h(conn_list_t *cl)
550 {
551 cp
552   if(!cl->status.active)
553     {
554       syslog(LOG_ERR, _("Got unauthorized TERMREQ from %s (%s)"),
555               cl->vpn_hostname, cl->real_hostname);
556       return -1;
557     }
558     
559   if(debug_lvl > 1)
560    syslog(LOG_DEBUG, _("Got TERMREQ from %s (%s)"),
561              cl->vpn_hostname, cl->real_hostname);
562   
563   cl->status.termreq = 1;
564
565   terminate_connection(cl);
566 cp
567   return 0;
568 }
569
570 int timeout_h(conn_list_t *cl)
571 {
572 cp
573   if(!cl->status.active)
574     {
575       syslog(LOG_ERR, _("Got unauthorized TIMEOUT from %s (%s)"),
576               cl->vpn_hostname, cl->real_hostname);
577       return -1;
578     }
579
580   if(debug_lvl > 1)
581     syslog(LOG_DEBUG, _("Got TIMEOUT from %s (%s)"),
582               cl->vpn_hostname, cl->real_hostname);
583
584   cl->status.termreq = 1;
585   terminate_connection(cl);
586 cp
587   return 0;
588 }
589
590 int del_host_h(conn_list_t *cl)
591 {
592   ip_t vpn_ip;
593   conn_list_t *fw;
594 cp
595   if(!cl->status.active)
596     {
597       syslog(LOG_ERR, _("Got unauthorized DEL_HOST from %s (%s)"),
598               cl->vpn_hostname, cl->real_hostname);
599       return -1;
600     }
601
602   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
603     {
604        syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
605               cl->vpn_hostname, cl->real_hostname);
606        return -1;
607     }  
608
609   if(!(fw = lookup_conn(vpn_ip)))
610     {
611       syslog(LOG_ERR, _("Got DEL_HOST for %d.%d.%d.%d from %s (%s) which does not exist?"),
612              IP_ADDR_V(vpn_ip), cl->vpn_hostname, cl->real_hostname);
613       return 0;
614     }
615
616   if(debug_lvl > 1)
617     syslog(LOG_DEBUG, _("Got DEL_HOST for %s (%s) from %s (%s)"),
618            fw->vpn_hostname, fw->real_hostname, cl->vpn_hostname, cl->real_hostname);
619
620   notify_others(fw, cl, send_del_host);
621
622   fw->status.termreq = 1;
623   fw->status.active = 0;
624
625   terminate_connection(fw);
626 cp
627   return 0;
628 }
629
630 int ping_h(conn_list_t *cl)
631 {
632 cp
633   if(!cl->status.active)
634     {
635       syslog(LOG_ERR, _("Got unauthorized PING from %s (%s)"),
636               cl->vpn_hostname, cl->real_hostname);
637       return -1;
638     }
639
640   if(debug_lvl > 1)
641     syslog(LOG_DEBUG, _("Got PING from %s (%s)"),
642               cl->vpn_hostname, cl->real_hostname);
643
644   cl->status.pinged = 0;
645   cl->status.got_pong = 1;
646
647   send_pong(cl);
648 cp
649   return 0;
650 }
651
652 int pong_h(conn_list_t *cl)
653 {
654 cp
655   if(!cl->status.active)
656     {
657       syslog(LOG_ERR, _("Got unauthorized PONG from %s (%s)"),
658               cl->vpn_hostname, cl->real_hostname);
659       return -1;
660     }
661
662   if(debug_lvl > 1)
663     syslog(LOG_DEBUG, _("Got PONG from %s (%s)"),
664               cl->vpn_hostname, cl->real_hostname);
665
666   cl->status.got_pong = 1;
667 cp
668   return 0;
669 }
670
671 int add_host_h(conn_list_t *cl)
672 {
673   ip_t real_ip;
674   ip_t vpn_ip;
675   ip_t vpn_mask;
676   unsigned short port;
677   int flags;
678   conn_list_t *ncn, *old;
679 cp
680   if(!cl->status.active)
681     {
682       syslog(LOG_ERR, _("Got unauthorized ADD_HOST from %s (%s)"),
683               cl->vpn_hostname, cl->real_hostname);
684       return -1;
685     }
686     
687   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
688     {
689        syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"),
690               cl->vpn_hostname, cl->real_hostname);
691        return -1;
692     }  
693
694   if(old = lookup_conn(vpn_ip))
695     {
696       if((real_ip==old->real_ip) && (vpn_mask==old->vpn_mask) && (port==old->port))
697         {
698           if(debug_lvl>1)
699             syslog(LOG_NOTICE, _("Got duplicate ADD_HOST for %s (%s) from %s (%s)"),
700                    old->vpn_hostname, old->real_hostname, cl->vpn_hostname, cl->real_hostname);
701           goto skip_add_host;  /* One goto a day keeps the deeply nested if constructions away. */
702         }
703       else
704         {
705           if(debug_lvl>1)
706             syslog(LOG_NOTICE, _("Removing old entry for %s (%s)"),
707                    old->vpn_hostname, old->real_hostname);
708           old->status.active = 0;
709           terminate_connection(old);
710         }
711     }
712     
713   ncn = new_conn_list();
714   ncn->real_ip = real_ip;
715   ncn->real_hostname = hostlookup(htonl(real_ip));
716   ncn->vpn_ip = vpn_ip;
717   ncn->vpn_mask = vpn_mask;
718   ncn->vpn_hostname = hostlookup(htonl(vpn_ip));
719   ncn->port = port;
720   ncn->flags = flags;
721   ncn->nexthop = cl;
722   ncn->next = conn_list;
723   conn_list = ncn;
724   ncn->status.active = 1;
725
726   if(debug_lvl > 1)
727     syslog(LOG_DEBUG, _("Got ADD_HOST for %s (%s) from %s (%s)"),
728            ncn->vpn_hostname, ncn->real_hostname, cl->vpn_hostname, cl->real_hostname);
729
730 skip_add_host:
731
732   notify_others(ncn, cl, send_add_host);
733 cp
734   return 0;
735 }
736
737 int req_key_h(conn_list_t *cl)
738 {
739   ip_t to;
740   ip_t from;
741   conn_list_t *fw;
742 cp
743   if(!cl->status.active)
744     {
745       syslog(LOG_ERR, _("Got unauthorized REQ_KEY from %s (%s)"),
746               cl->vpn_hostname, cl->real_hostname);
747       return -1;
748     }
749
750   if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
751     {
752        syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
753               cl->vpn_hostname, cl->real_hostname);
754        return -1;
755     }  
756
757   if(debug_lvl > 1)
758     syslog(LOG_DEBUG, _("Got REQ_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
759            IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
760
761   if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
762     {  /* hey! they want something from ME! :) */
763       send_key_answer(cl, from);
764       return 0;
765     }
766
767   fw = lookup_conn(to);
768   
769   if(!fw)
770     {
771       syslog(LOG_ERR, _("Attempting to forward REQ_KEY to %d.%d.%d.%d, which does not exist?"),
772              IP_ADDR_V(to));
773       return -1;
774     }
775
776   if(debug_lvl > 1)
777     syslog(LOG_DEBUG, _("Forwarding REQ_KEY to %s (%s)"),
778            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
779   
780   cl->buffer[cl->reqlen-1] = '\n';
781   
782   if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
783     {
784       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
785       return -1;
786     }
787 cp
788   return 0;
789 }
790
791 void set_keys(conn_list_t *cl, int expiry, char *key)
792 {
793   char *ek;
794 cp
795   if(!cl->public_key)
796     {
797       cl->public_key = xmalloc(sizeof(*cl->key));
798       cl->public_key->key = NULL;
799     }
800     
801   if(cl->public_key->key)
802     free(cl->public_key->key);
803   cl->public_key->length = strlen(key);
804   cl->public_key->expiry = expiry;
805   cl->public_key->key = xmalloc(cl->public_key->length + 1);
806   strcpy(cl->public_key->key, key);
807
808   ek = make_shared_key(key);
809   
810   if(!cl->key)
811     {
812       cl->key = xmalloc(sizeof(*cl->key));
813       cl->key->key = NULL;
814     }
815
816   if(cl->key->key)
817     free(cl->key->key);
818
819   cl->key->length = strlen(ek);
820   cl->key->expiry = expiry;
821   cl->key->key = xmalloc(cl->key->length + 1);
822   strcpy(cl->key->key, ek);
823 cp
824 }
825
826 int ans_key_h(conn_list_t *cl)
827 {
828   ip_t to;
829   ip_t from;
830   int expiry;
831   char *key;
832   conn_list_t *fw, *gk;
833 cp
834   if(!cl->status.active)
835     {
836       syslog(LOG_ERR, _("Got unauthorized ANS_KEY from %s (%s)"),
837               cl->vpn_hostname, cl->real_hostname);
838       return -1;
839     }
840
841   if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
842     {
843        syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
844               cl->vpn_hostname, cl->real_hostname);
845        return -1;
846     }  
847
848   if(debug_lvl > 1)
849     syslog(LOG_DEBUG, _("Got ANS_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
850             IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
851
852   if(to == myself->vpn_ip)
853     {  /* hey! that key's for ME! :) */
854       gk = lookup_conn(from);
855
856       if(!gk)
857         {
858           syslog(LOG_ERR, _("Receiving ANS_KEY origin %d.%d.%d.%d from %s (%s), which does not exist?"),
859                  IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
860           return -1;
861         }
862
863       set_keys(gk, expiry, key);
864       gk->status.validkey = 1;
865       gk->status.waitingforkey = 0;
866       flush_queues(gk);
867       return 0;
868     }
869
870   fw = lookup_conn(to);
871   
872   if(!fw)
873     {
874       syslog(LOG_ERR, _("Attempting to forward ANS_KEY to %d.%d.%d.%d, which does not exist?"),
875              IP_ADDR_V(to));
876       return -1;
877     }
878
879   if(debug_lvl > 1)
880     syslog(LOG_DEBUG, _("Forwarding ANS_KEY to %s (%s)"),
881            fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
882
883   cl->buffer[cl->reqlen-1] = '\n';
884
885   if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
886     {
887       syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
888       return -1;
889     }
890 cp
891   return 0;
892 }
893
894 int key_changed_h(conn_list_t *cl)
895 {
896   ip_t from;
897   conn_list_t *ik;
898 cp
899   if(!cl->status.active)
900     {
901       syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from %s (%s)"),
902               cl->vpn_hostname, cl->real_hostname);
903       return -1;
904     }
905
906   if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
907     {
908        syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
909               cl->vpn_hostname, cl->real_hostname);
910        return -1;
911     }  
912
913   ik = lookup_conn(from);
914
915   if(!ik)
916     {
917       syslog(LOG_ERR, _("Got KEY_CHANGED origin %d.%d.%d.%d from %s (%s), which does not exist?"),
918              IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
919       return -1;
920     }
921
922   if(debug_lvl > 1)
923     syslog(LOG_DEBUG, _("Got KEY_CHANGED origin %s from %s (%s)"),
924             ik->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
925
926   ik->status.validkey = 0;
927   ik->status.waitingforkey = 0;
928
929   notify_others(ik, cl, send_key_changed);
930 cp
931   return 0;
932 }
933
934 int (*request_handlers[256])(conn_list_t*) = {
935   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
936   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
937   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
938   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
939   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
940   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
941   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
942   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
943   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
944   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
945   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
946   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
947   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
948   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
949   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
950   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
951   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
952   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
953   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
954   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
955 };