New way of handling the meta protocol.
[oweals/tinc.git] / src / protocol.c
1 /*
2     protocol.c -- handle the meta-protocol
3     Copyright (C) 1999 Ivo Timmermans <zarq@iname.com>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <syslog.h>
25 #include <sys/socket.h>
26 #include <unistd.h>
27
28 #include <utils.h>
29 #include <xalloc.h>
30
31 #include "conf.h"
32 #include "encr.h"
33 #include "net.h"
34 #include "netutl.h"
35 #include "protocol.h"
36
37 int send_ack(conn_list_t *cl)
38 {
39   unsigned char tmp = ACK;
40 cp
41   if(debug_lvl > 2)
42     syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
43
44   syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
45   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
46     {
47       syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
48       return -1;
49     }
50 cp
51   return 0;
52 }
53
54 int send_termreq(conn_list_t *cl)
55 {
56   termreq_t tmp;
57 cp
58   memset(&tmp, 0, sizeof(tmp));
59   tmp.type = TERMREQ;
60   tmp.vpn_ip = myself->vpn_ip;
61
62   if(debug_lvl > 2)
63     syslog(LOG_DEBUG, "Send TERMREQ(" IP_ADDR_S ") to " IP_ADDR_S, IP_ADDR_V(tmp.vpn_ip),
64            IP_ADDR_V(cl->vpn_ip));
65
66   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
67     {
68       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
69       return -1;
70     }
71 cp
72   return 0;
73 }
74
75 int send_timeout(conn_list_t *cl)
76 {
77   termreq_t tmp;
78 cp
79   memset(&tmp, 0, sizeof(tmp));
80   tmp.type = PINGTIMEOUT;
81   tmp.vpn_ip = myself->vpn_ip;
82
83   if(debug_lvl > 2)
84     syslog(LOG_DEBUG, "Send TIMEOUT(" IP_ADDR_S ") to " IP_ADDR_S, IP_ADDR_V(tmp.vpn_ip),
85            IP_ADDR_V(cl->vpn_ip));
86
87   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
88     {
89       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
90       return -1;
91     }
92 cp
93   return 0;
94 }
95
96 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
97 {
98   del_host_t tmp;
99 cp
100   memset(&tmp, 0, sizeof(tmp));
101   tmp.type = DEL_HOST;
102   tmp.vpn_ip = new_host->vpn_ip;
103
104   if(debug_lvl > 2)
105     syslog(LOG_DEBUG, "Sending delete host %lx to " IP_ADDR_S,
106            tmp.vpn_ip, IP_ADDR_V(cl->vpn_ip));
107
108   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
109     {
110       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
111       return -1;
112     }
113 cp
114   return 0;
115 }
116
117 int send_ping(conn_list_t *cl)
118 {
119   unsigned char tmp = PING;
120 cp
121   if(debug_lvl > 3)
122     syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
123
124   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
125     {
126       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
127       return -1;
128     }
129 cp
130   return 0;
131 }
132
133 int send_pong(conn_list_t *cl)
134 {
135   unsigned char tmp = PONG;
136 cp
137   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
138     {
139       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
140       return -1;
141     }
142 cp
143   return 0;
144 }
145
146 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
147 {
148   add_host_t tmp;
149 cp
150   memset(&tmp, 0, sizeof(tmp));
151   tmp.type = ADD_HOST;
152   tmp.real_ip = new_host->real_ip;
153   tmp.vpn_ip = new_host->vpn_ip;
154   tmp.vpn_mask = new_host->vpn_mask;
155   tmp.portnr = new_host->port;
156
157   if(debug_lvl > 2)
158     syslog(LOG_DEBUG, "Sending add host (%lx/%lx %lx:%hd) to " IP_ADDR_S,
159            tmp.vpn_ip, tmp.vpn_mask, tmp.real_ip, tmp.portnr,
160            IP_ADDR_V(cl->vpn_ip));
161
162   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
163     {
164       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
165       return -1;
166     }
167 cp
168   return 0;
169 }
170
171 int send_key_changed(conn_list_t *cl, conn_list_t *src)
172 {
173   key_changed_t tmp;
174 cp
175   memset(&tmp, 0, sizeof(tmp));
176   tmp.type = KEY_CHANGED;
177   tmp.from = src->vpn_ip;
178
179   if(debug_lvl > 2)
180     syslog(LOG_DEBUG, "Sending KEY_CHANGED (%lx) to " IP_ADDR_S,
181            tmp.from, IP_ADDR_V(cl->vpn_ip));
182
183   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
184     {
185       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
186       return -1;
187     }
188 cp
189   return 0;
190 }
191
192 void send_key_changed2(void)
193 {
194   conn_list_t *p;
195 cp
196   for(p = conn_list; p != NULL; p = p->next)
197     if(p->status.meta && p->protocol_version > PROT_3)
198       send_key_changed(p, myself);
199 cp
200 }
201
202 int send_basic_info(conn_list_t *cl)
203 {
204   basic_info_t tmp;
205 cp
206   memset(&tmp, 0, sizeof(tmp));
207   tmp.type = BASIC_INFO;
208   tmp.protocol = PROT_CURRENT;
209
210   tmp.portnr = myself->port;
211   tmp.vpn_ip = myself->vpn_ip;
212   tmp.vpn_mask = myself->vpn_mask;
213
214   if(debug_lvl > 2)
215     syslog(LOG_DEBUG, "Send BASIC_INFO(%d,%hd," IP_ADDR_S "," IP_ADDR_S ") to " IP_ADDR_S,
216            tmp.protocol, tmp.portnr, IP_ADDR_V(tmp.vpn_ip), IP_ADDR_V(tmp.vpn_mask),
217            IP_ADDR_V(cl->real_ip));
218
219   if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
220     {
221       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
222       return -1;
223     }
224 cp
225   return 0;
226 }
227
228 int send_passphrase(conn_list_t *cl)
229 {
230   passphrase_t tmp;
231 cp
232   memset(&tmp, 0, sizeof(tmp));
233   tmp.type = PASSPHRASE;
234   encrypt_passphrase(&tmp);
235
236   if(debug_lvl > 2)
237     syslog(LOG_DEBUG, "Send PASSPHRASE(%hd,...) to " IP_ADDR_S, tmp.len,
238            IP_ADDR_V(cl->vpn_ip));
239
240   if((write(cl->meta_socket, &tmp, tmp.len+3)) < 0)
241     {
242       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
243       return -1;
244     }
245 cp
246   return 0;
247 }
248
249 int send_public_key(conn_list_t *cl)
250 {
251   public_key_t *tmp;
252 cp
253   tmp = (public_key_t*)xmalloc(strlen(my_public_key_base36)+sizeof(*tmp));
254   memset(tmp, 0, sizeof(*tmp));
255   tmp->type = PUBLIC_KEY;
256   tmp->len = strlen(my_public_key_base36);
257   strcpy(&tmp->key, my_public_key_base36);
258
259   if(debug_lvl > 2)
260     syslog(LOG_DEBUG, "Send PUBLIC_KEY(%hd,%s) to " IP_ADDR_S, tmp->len, &tmp->key,
261            IP_ADDR_V(cl->vpn_ip));
262
263   if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
264     {
265       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
266       return -1;
267     }
268 cp
269   return 0;
270 }
271
272 int send_calculate(conn_list_t *cl, char *k)
273 {
274   calculate_t *tmp;
275 cp
276   tmp = xmalloc(strlen(k)+sizeof(*tmp));
277   memset(tmp, 0, sizeof(*tmp));
278   tmp->type = CALCULATE;
279   tmp->len = strlen(k);
280   strcpy(&tmp->key, k);
281
282   if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
283     {
284       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
285       return -1;
286     }
287 cp
288   return 0;
289 }
290
291 int send_key_request(ip_t to)
292 {
293   key_req_t *tmp;
294   conn_list_t *fw;
295 cp
296   tmp = xmalloc(sizeof(*tmp));
297   memset(tmp, 0, sizeof(*tmp));
298   tmp->type = REQ_KEY;
299   tmp->to = to;
300   tmp->from = myself->vpn_ip;
301   tmp->len = 0;
302
303   fw = lookup_conn(to);
304   if(!fw)
305     {
306       syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
307              IP_ADDR_V(to));
308       return -1;
309     }
310
311   if(debug_lvl > 2)
312     syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
313            IP_ADDR_V(fw->nexthop->vpn_ip));
314   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)) < 0)
315     {
316       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
317       return -1;
318     }
319   fw->status.waitingforkey = 1;
320 cp
321   return 0;
322 }
323
324 int send_key_answer(conn_list_t *cl, ip_t to)
325 {
326   key_req_t *tmp;
327   conn_list_t *fw;
328 cp
329   tmp = xmalloc(sizeof(*tmp)+strlen(my_public_key_base36));
330   memset(tmp, 0, sizeof(*tmp));
331   tmp->type = ANS_KEY;
332   tmp->to = to;
333   tmp->from = myself->vpn_ip;
334   tmp->expiry = my_key_expiry;
335   tmp->len = strlen(my_public_key_base36);
336   strcpy(&tmp->key, my_public_key_base36);
337
338 cp
339   fw = lookup_conn(to);
340   
341 cp
342   if(!fw)
343     {
344       syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
345              IP_ADDR_V(to));
346       return -1;
347     }
348 cp
349
350   syslog(LOG_DEBUG, "key sent = %s", tmp->key);
351   if(debug_lvl > 2)
352     syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
353            IP_ADDR_V(fw->nexthop->vpn_ip));
354 cp
355   if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
356     {
357       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
358       return -1;
359     }
360 cp
361   return 0;
362 }
363
364 /*
365   notify all my direct connections of a new host
366   that was added to the vpn, with the exception
367   of the source of the announcement.
368 */
369 int notify_others(conn_list_t *new, conn_list_t *source,
370                   int (*function)(conn_list_t*, conn_list_t*))
371 {
372   conn_list_t *p;
373 cp
374   for(p = conn_list; p != NULL; p = p->next)
375     if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
376       function(p, new);
377 cp
378   return 0;
379 }
380
381 /*
382   notify one connection of everything
383   i have connected
384 */
385 int notify_one(conn_list_t *new)
386 {
387   conn_list_t *p;
388 cp
389   for(p = conn_list; p != NULL; p = p->next)
390     if(p != new && p->protocol_version > PROT_3)
391       send_add_host(new, p);
392 cp
393   return 0;
394 }
395
396 /*
397   The incoming request handlers
398 */
399
400 int basic_info_h(conn_list_t *cl)
401 {
402   basic_info_t tmp;
403 cp
404   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
405     {
406       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
407       return -1;
408     }
409
410   cl->protocol_version = tmp.protocol;
411   cl->port = tmp.portnr;
412   cl->vpn_ip = tmp.vpn_ip;
413   cl->vpn_mask = tmp.vpn_mask;
414
415   if(cl->protocol_version < PROT_CURRENT)
416     {
417       syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
418              cl->protocol_version);
419       return -1;
420     }
421
422   if(debug_lvl > 2)
423     syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
424            IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
425   if(debug_lvl > 1)
426     syslog(LOG_DEBUG, "Peer uses protocol version %d",
427            cl->protocol_version);
428
429   if(cl->status.outgoing)
430     {
431       if(setup_vpn_connection(cl) < 0)
432         return -1;
433       send_basic_info(cl);
434     }
435   else
436     {
437       if(setup_vpn_connection(cl) < 0)
438         return -1;
439       send_passphrase(cl);
440     }
441
442   cl->status.active = 0;
443 cp
444   return 0;
445 }
446
447 int passphrase_h(conn_list_t *cl)
448 {
449   char unused;
450   unsigned short int len;
451 cp
452   if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
453     {
454       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
455       return -1;
456     }
457
458   if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
459     {
460       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
461       return -1;
462     }
463   
464   cl->pp = xmalloc(len+4);
465
466   cl->pp->len = len;
467   if(read(cl->meta_socket, &(cl->pp->phrase), len) <= 0)
468     {
469       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
470       return -1;
471     }
472   
473   if(debug_lvl > 2)
474     syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", len);
475
476   if(cl->status.outgoing)
477     send_passphrase(cl);
478   else
479     send_public_key(cl);
480 cp
481   return 0;
482 }
483
484 int public_key_h(conn_list_t *cl)
485 {
486   char *g_n;
487   unsigned short int len;
488   char unused;
489 cp
490   if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
491     {
492       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
493       return -1;
494     }
495   if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
496     {
497       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
498       return -1;
499     }
500
501   g_n = xmalloc(len+2);
502
503   if(read(cl->meta_socket, g_n, len+2) <= 0)
504     {
505       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
506       return -1;
507     }
508
509   if(debug_lvl > 2)
510     syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", len, g_n);
511
512   if(verify_passphrase(cl, g_n))
513     {
514       /* intruder! */
515       syslog(LOG_ERR, "Intruder: passphrase does not match.");
516       return -1;
517     }
518
519   if(debug_lvl > 2)
520     syslog(LOG_INFO, "Passphrase OK");
521
522   if(cl->status.outgoing)
523     send_public_key(cl);
524   else
525     send_ack(cl);
526
527   cl->status.active = 1;
528   notify_others(cl, NULL, send_add_host);
529   notify_one(cl);
530 cp
531   return 0;
532 }
533
534 int ack_h(conn_list_t *cl)
535 {
536 cp
537   if(debug_lvl > 2)
538     syslog(LOG_DEBUG, "got ACK");
539   
540   cl->status.active = 1;
541   syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
542 cp
543   return 0;
544 }
545
546 int termreq_h(conn_list_t *cl)
547 {
548 cp
549   syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
550   cl->status.termreq = 1;
551   terminate_connection(cl);
552
553   notify_others(cl, NULL, send_del_host);
554 cp
555   return 0;
556 }
557
558 int timeout_h(conn_list_t *cl)
559 {
560 cp
561   syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
562   cl->status.termreq = 1;
563   terminate_connection(cl);
564 cp
565   return 0;
566 }
567
568 int del_host_h(conn_list_t *cl)
569 {
570   del_host_t tmp;
571   conn_list_t *fw;
572 cp
573   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
574     {
575       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
576       return -1;
577     }
578
579   if(debug_lvl > 2)
580     syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
581            IP_ADDR_V(tmp.vpn_ip));
582
583   if(!(fw = lookup_conn(tmp.vpn_ip)))
584     {
585       syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
586              IP_ADDR_V(tmp.vpn_ip));
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(debug_lvl > 3)
602     syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
603   cl->status.pinged = 0;
604   cl->status.got_pong = 1;
605
606   send_pong(cl);
607 cp
608   return 0;
609 }
610
611 int pong_h(conn_list_t *cl)
612 {
613 cp
614   if(debug_lvl > 3)
615     syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
616   cl->status.got_pong = 1;
617 cp
618   return 0;
619 }
620
621 int add_host_h(conn_list_t *cl)
622 {
623   add_host_t tmp;
624   conn_list_t *ncn, *fw;
625 cp
626   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
627     {
628       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
629       return -1;
630     }
631
632   if(debug_lvl > 2)
633     syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
634   if(debug_lvl > 3)
635     syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
636            IP_ADDR_V(tmp.vpn_ip), IP_ADDR_V(tmp.vpn_mask), tmp.portnr);
637
638   /*
639     Suggestion of Hans Bayle
640   */
641   if((fw = lookup_conn(tmp.vpn_ip)))
642     {
643       notify_others(fw, cl, send_add_host);
644       return 0;
645     }
646
647   ncn = new_conn_list();
648   ncn->real_ip = tmp.real_ip;
649   ncn->vpn_ip = tmp.vpn_ip;
650   ncn->vpn_mask = tmp.vpn_mask;
651   ncn->port = tmp.portnr;
652   ncn->hostname = hostlookup(tmp.real_ip);
653   ncn->nexthop = cl;
654   ncn->next = conn_list;
655   conn_list = ncn;
656   ncn->status.active = 1;
657   notify_others(ncn, cl, send_add_host);
658 cp
659   return 0;
660 }
661
662 int req_key_h(conn_list_t *cl)
663 {
664   key_req_t tmp;
665   conn_list_t *fw;
666 cp
667   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
668     {
669       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
670       return -1;
671     }
672
673   if(debug_lvl > 2)
674     syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
675            IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
676
677   if((tmp.to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
678     {  /* hey! they want something from ME! :) */
679       send_key_answer(cl, tmp.from);
680       return 0;
681     }
682
683   fw = lookup_conn(tmp.to);
684   
685   if(!fw)
686     {
687       syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
688              IP_ADDR_V(tmp.to));
689       return -1;
690     }
691
692   if(debug_lvl > 3)
693     syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
694            IP_ADDR_V(fw->nexthop->vpn_ip));
695   
696   tmp.type = REQ_KEY;
697   tmp.key = 0;
698   if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp)) < 0)
699     {
700       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
701       return -1;
702     }
703 cp
704   return 0;
705 }
706
707 void set_keys(conn_list_t *cl, key_req_t *k, char *key)
708 {
709   char *ek;
710 cp
711   if(!cl->public_key)
712     {
713       cl->public_key = xmalloc(sizeof(*cl->key));
714       cl->public_key->key = NULL;
715     }
716   if(cl->public_key->key)
717     free(cl->public_key->key);
718   cl->public_key->length = k->len;
719   cl->public_key->expiry = k->expiry;
720   cl->public_key->key = xmalloc(k->len + 1);
721   strcpy(cl->public_key->key, key);
722
723   ek = make_shared_key(key);
724   if(!cl->key)
725     {
726       cl->key = xmalloc(sizeof(*cl->key));
727       cl->key->key = NULL;
728     }
729   if(cl->key->key)
730     free(cl->key->key);
731   cl->key->length = strlen(ek);
732   cl->key->expiry = k->expiry;
733   cl->key->key = xmalloc(strlen(ek) + 1);
734   strcpy(cl->key->key, ek);
735 cp
736 }
737
738 int ans_key_h(conn_list_t *cl)
739 {
740   key_req_t tmp;
741   conn_list_t *fw, *gk;
742   char *key;
743 cp
744   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-2) <= 0)
745     {
746       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
747       return -1;
748     }
749
750   key = xmalloc(tmp.len);
751
752   if(read(cl->meta_socket, key, tmp.len + 1) <= 0)
753     {
754       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
755       return -1;
756     }
757
758   syslog(LOG_DEBUG, "key = %s", key);
759
760   if(debug_lvl > 3)
761     syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
762            IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
763
764   if(tmp.to == myself->vpn_ip)
765     {  /* hey! that key's for ME! :) */
766       if(debug_lvl > 2)
767         syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
768       gk = lookup_conn(tmp.from);
769
770       if(!gk)
771         {
772           syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
773                  IP_ADDR_V(tmp.from));
774           return -1;
775         }
776
777       set_keys(gk, &tmp, key);
778       gk->status.validkey = 1;
779       gk->status.waitingforkey = 0;
780       flush_queues(gk);
781       return 0;
782     }
783
784   fw = lookup_conn(tmp.to);
785   
786   if(!fw)
787     {
788       syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
789              IP_ADDR_V(tmp.to));
790       return -1;
791     }
792
793   if(debug_lvl > 2)
794     syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
795            IP_ADDR_V(fw->nexthop->vpn_ip));
796   tmp.type = ANS_KEY;
797   if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp) -1) < 0)
798     {
799       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
800       return -1;
801     }
802   if(write(fw->nexthop->meta_socket, key, tmp.len + 1) < 0)
803     {
804       syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
805       return -1;
806     }
807 cp
808   return 0;
809 }
810
811 int key_changed_h(conn_list_t *cl)
812 {
813   key_changed_t tmp;
814   conn_list_t *ik;
815 cp
816   if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
817     {
818       syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
819       return -1;
820     }
821
822   if(debug_lvl > 2)
823     syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
824            IP_ADDR_V(tmp.from));
825
826   ik = lookup_conn(tmp.from);
827
828   if(!ik)
829     {
830       syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
831              IP_ADDR_V(tmp.from));
832       return -1;
833     }
834
835   ik->status.validkey = 0;
836   ik->status.waitingforkey = 0;
837
838   if(debug_lvl > 3)
839     syslog(LOG_DEBUG, "Forwarding key invalidation request");
840
841   notify_others(cl, ik, send_key_changed);
842 cp
843   return 0;
844 }
845
846 int (*request_handlers[256])(conn_list_t*) = {
847   0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
848   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
849   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
850   termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
851   ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
852   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853   add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
854   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
855   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
856   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
857   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
859   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
860   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
861   req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
862   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
863   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
864   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
865   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
866   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  0, 0, 0, 0, 0, 0
867 };