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