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