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