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