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