]> git.meshlink.io Git - meshlink/blob - src/protocol.c
b76dbd4262f95c28986f6fce7696fe36a6988377
[meshlink] / 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.3 2000/06/25 15:45:09 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(!cl->status.active)
516     {
517       syslog(LOG_ERR, _("Got unauthorized TERMREQ from " IP_ADDR_S " (" IP_ADDR_S ")"),
518               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
519       return -1;
520     }
521     
522   if(debug_lvl > 1)
523    syslog(LOG_DEBUG, _("Got TERMREQ from " IP_ADDR_S " (" IP_ADDR_S ")"),
524              IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
525   
526   cl->status.termreq = 1;
527   cl->status.active = 0;
528
529   if(cl->status.active)
530     notify_others(cl, NULL, send_del_host);
531
532   terminate_connection(cl);
533 cp
534   return 0;
535 }
536
537 int timeout_h(conn_list_t *cl)
538 {
539 cp
540   if(!cl->status.active)
541     {
542       syslog(LOG_ERR, _("Got unauthorized TIMEOUT from " IP_ADDR_S " (" IP_ADDR_S ")"),
543               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
544       return -1;
545     }
546
547   if(debug_lvl > 1)
548     syslog(LOG_DEBUG, _("Got TIMEOUT from " IP_ADDR_S " (" IP_ADDR_S ")"),
549               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
550
551   cl->status.termreq = 1;
552   terminate_connection(cl);
553 cp
554   return 0;
555 }
556
557 int del_host_h(conn_list_t *cl)
558 {
559   ip_t vpn_ip;
560   conn_list_t *fw;
561 cp
562   if(!cl->status.active)
563     {
564       syslog(LOG_ERR, _("Got unauthorized DEL_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
565               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
566       return -1;
567     }
568
569   if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
570     {
571        syslog(LOG_ERR, _("Got bad DEL_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
572               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
573        return -1;
574     }  
575
576   if(debug_lvl > 1)
577     syslog(LOG_DEBUG, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ")"),
578            IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
579
580   if(!(fw = lookup_conn(vpn_ip)))
581     {
582       syslog(LOG_ERR, _("Got DEL_HOST for " IP_ADDR_S " from " IP_ADDR_S " (" IP_ADDR_S ") which does not exist?"),
583              IP_ADDR_V(vpn_ip), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
584       return 0;
585     }
586
587   notify_others(cl, fw, send_del_host);
588
589   fw->status.termreq = 1;
590   terminate_connection(fw);
591 cp
592   return 0;
593 }
594
595 int ping_h(conn_list_t *cl)
596 {
597 cp
598   if(!cl->status.active)
599     {
600       syslog(LOG_ERR, _("Got unauthorized PING from " IP_ADDR_S " (" IP_ADDR_S ")"),
601               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
602       return -1;
603     }
604
605   if(debug_lvl > 1)
606     syslog(LOG_DEBUG, _("Got PING from " IP_ADDR_S " (" IP_ADDR_S ")"),
607               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
608
609   cl->status.pinged = 0;
610   cl->status.got_pong = 1;
611
612   send_pong(cl);
613 cp
614   return 0;
615 }
616
617 int pong_h(conn_list_t *cl)
618 {
619 cp
620   if(!cl->status.active)
621     {
622       syslog(LOG_ERR, _("Got unauthorized PONG from " IP_ADDR_S " (" IP_ADDR_S ")"),
623               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
624       return -1;
625     }
626
627   if(debug_lvl > 1)
628     syslog(LOG_DEBUG, _("Got PONG from " IP_ADDR_S " (" IP_ADDR_S ")"),
629               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
630
631   cl->status.got_pong = 1;
632 cp
633   return 0;
634 }
635
636 int add_host_h(conn_list_t *cl)
637 {
638   ip_t real_ip;
639   ip_t vpn_ip;
640   ip_t vpn_mask;
641   unsigned short port;
642   int flags;
643   conn_list_t *ncn, *fw;
644 cp
645   if(!cl->status.active)
646     {
647       syslog(LOG_ERR, _("Got unauthorized ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
648               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
649       return -1;
650     }
651     
652   if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
653     {
654        syslog(LOG_ERR, _("Got bad ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
655               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
656        return -1;
657     }  
658
659   if(debug_lvl > 1)
660     syslog(LOG_DEBUG, _("Got ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
661               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
662
663   /*
664     Suggestion of Hans Bayle
665   */
666   if((fw = lookup_conn(vpn_ip)))
667     {
668       if(fw->nexthop == cl)
669         notify_others(fw, cl, send_add_host);
670       else
671         syslog(LOG_DEBUG, _("Invalid ADD_HOST from " IP_ADDR_S " (" IP_ADDR_S ")"),
672             IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
673       return 0;
674     }
675
676   ncn = new_conn_list();
677   ncn->real_ip = real_ip;
678   ncn->vpn_ip = vpn_ip;
679   ncn->vpn_mask = vpn_mask;
680   ncn->port = port;
681   ncn->flags = flags;
682   ncn->nexthop = cl;
683   ncn->next = conn_list;
684   conn_list = ncn;
685   ncn->status.active = 1;
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 " (" IP_ADDR_S ")"),
700               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
707               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
713            IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
732            IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
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 " (" IP_ADDR_S ")"),
791               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
798               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
804             IP_ADDR_V(from), IP_ADDR_V(to), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
835            IP_ADDR_V(fw->nexthop->vpn_ip), IP_ADDR_V(fw->nexthop->real_ip));
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 " (" IP_ADDR_S ")"),
856               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
863               IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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 " (" IP_ADDR_S ")"),
869             IP_ADDR_V(from), IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->real_ip));
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(cl, ik, 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 };