2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999 Ivo Timmermans <zarq@iname.com>
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.
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.
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.
25 #include <sys/socket.h>
37 int send_ack(conn_list_t *cl)
39 unsigned char tmp = ACK;
42 syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
44 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
45 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
47 syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
54 int send_termreq(conn_list_t *cl)
58 memset(&tmp, 0, sizeof(tmp));
60 tmp.vpn_ip = myself->vpn_ip;
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));
66 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
68 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
75 int send_timeout(conn_list_t *cl)
79 memset(&tmp, 0, sizeof(tmp));
80 tmp.type = PINGTIMEOUT;
81 tmp.vpn_ip = myself->vpn_ip;
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));
87 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
89 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
96 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
100 memset(&tmp, 0, sizeof(tmp));
102 tmp.vpn_ip = new_host->vpn_ip;
105 syslog(LOG_DEBUG, "Sending delete host %lx to " IP_ADDR_S,
106 tmp.vpn_ip, IP_ADDR_V(cl->vpn_ip));
108 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
110 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
117 int send_ping(conn_list_t *cl)
119 unsigned char tmp = PING;
122 syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
124 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
126 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
133 int send_pong(conn_list_t *cl)
135 unsigned char tmp = PONG;
137 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
139 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
146 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
150 memset(&tmp, 0, sizeof(tmp));
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;
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));
162 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
164 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
171 int send_key_changed(conn_list_t *cl, conn_list_t *src)
175 memset(&tmp, 0, sizeof(tmp));
176 tmp.type = KEY_CHANGED;
177 tmp.from = src->vpn_ip;
180 syslog(LOG_DEBUG, "Sending KEY_CHANGED (%lx) to " IP_ADDR_S,
181 tmp.from, IP_ADDR_V(cl->vpn_ip));
183 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
185 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
192 void send_key_changed2(void)
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);
202 int send_basic_info(conn_list_t *cl)
206 memset(&tmp, 0, sizeof(tmp));
207 tmp.type = BASIC_INFO;
208 tmp.protocol = PROT_CURRENT;
210 tmp.portnr = myself->port;
211 tmp.vpn_ip = myself->vpn_ip;
212 tmp.vpn_mask = myself->vpn_mask;
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));
219 if((write(cl->meta_socket, &tmp, sizeof(tmp))) < 0)
221 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
228 int send_passphrase(conn_list_t *cl)
232 memset(&tmp, 0, sizeof(tmp));
233 tmp.type = PASSPHRASE;
234 encrypt_passphrase(&tmp);
237 syslog(LOG_DEBUG, "Send PASSPHRASE(%hd,...) to " IP_ADDR_S, tmp.len,
238 IP_ADDR_V(cl->vpn_ip));
240 if((write(cl->meta_socket, &tmp, tmp.len+3)) < 0)
242 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
249 int send_public_key(conn_list_t *cl)
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);
260 syslog(LOG_DEBUG, "Send PUBLIC_KEY(%hd,%s) to " IP_ADDR_S, tmp->len, &tmp->key,
261 IP_ADDR_V(cl->vpn_ip));
263 if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
265 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
272 int send_calculate(conn_list_t *cl, char *k)
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);
282 if((write(cl->meta_socket, tmp, tmp->len+sizeof(*tmp))) < 0)
284 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
291 int send_key_request(ip_t to)
296 tmp = xmalloc(sizeof(*tmp));
297 memset(tmp, 0, sizeof(*tmp));
300 tmp->from = myself->vpn_ip;
303 fw = lookup_conn(to);
306 syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
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)
316 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
319 fw->status.waitingforkey = 1;
324 int send_key_answer(conn_list_t *cl, ip_t to)
329 tmp = xmalloc(sizeof(*tmp)+strlen(my_public_key_base36));
330 memset(tmp, 0, sizeof(*tmp));
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);
338 fw = lookup_conn(to);
342 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
349 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
350 IP_ADDR_V(fw->nexthop->vpn_ip));
352 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
354 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
362 notify all my direct connections of a new host
363 that was added to the vpn, with the exception
364 of the source of the announcement.
366 int notify_others(conn_list_t *new, conn_list_t *source,
367 int (*function)(conn_list_t*, conn_list_t*))
371 for(p = conn_list; p != NULL; p = p->next)
372 if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
379 notify one connection of everything
382 int notify_one(conn_list_t *new)
386 for(p = conn_list; p != NULL; p = p->next)
387 if(p != new && p->protocol_version > PROT_3)
388 send_add_host(new, p);
394 The incoming request handlers
397 int basic_info_h(conn_list_t *cl)
401 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
403 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
407 cl->protocol_version = tmp.protocol;
408 cl->port = tmp.portnr;
409 cl->vpn_ip = tmp.vpn_ip;
410 cl->vpn_mask = tmp.vpn_mask;
412 if(cl->protocol_version < PROT_CURRENT)
414 syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
415 cl->protocol_version);
420 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
421 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
423 syslog(LOG_DEBUG, "Peer uses protocol version %d",
424 cl->protocol_version);
426 if(cl->status.outgoing)
428 if(setup_vpn_connection(cl) < 0)
434 if(setup_vpn_connection(cl) < 0)
439 cl->status.active = 0;
444 int passphrase_h(conn_list_t *cl)
447 unsigned short int len;
449 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
451 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
455 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
457 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
461 cl->pp = xmalloc(len+4);
464 if(read(cl->meta_socket, &(cl->pp->phrase), len) <= 0)
466 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
471 syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", len);
473 if(cl->status.outgoing)
481 int public_key_h(conn_list_t *cl)
484 unsigned short int len;
487 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
489 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
492 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
494 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
498 g_n = xmalloc(len+2);
500 if(read(cl->meta_socket, g_n, len+2) <= 0)
502 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
507 syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", len, g_n);
509 if(verify_passphrase(cl, g_n))
512 syslog(LOG_ERR, "Intruder: passphrase does not match.");
517 syslog(LOG_INFO, "Passphrase OK");
519 if(cl->status.outgoing)
524 cl->status.active = 1;
525 notify_others(cl, NULL, send_add_host);
531 int ack_h(conn_list_t *cl)
535 syslog(LOG_DEBUG, "got ACK");
537 cl->status.active = 1;
538 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
543 int termreq_h(conn_list_t *cl)
546 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
547 cl->status.termreq = 1;
548 terminate_connection(cl);
550 notify_others(cl, NULL, send_del_host);
555 int timeout_h(conn_list_t *cl)
558 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
559 cl->status.termreq = 1;
560 terminate_connection(cl);
565 int del_host_h(conn_list_t *cl)
570 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
572 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
577 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
578 IP_ADDR_V(tmp.vpn_ip));
580 if(!(fw = lookup_conn(tmp.vpn_ip)))
582 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
583 IP_ADDR_V(tmp.vpn_ip));
587 notify_others(cl, fw, send_del_host);
589 fw->status.termreq = 1;
590 terminate_connection(fw);
595 int ping_h(conn_list_t *cl)
599 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
600 cl->status.pinged = 0;
601 cl->status.got_pong = 1;
608 int pong_h(conn_list_t *cl)
612 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
613 cl->status.got_pong = 1;
618 int add_host_h(conn_list_t *cl)
621 conn_list_t *ncn, *fw;
623 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
625 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
630 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
632 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
633 IP_ADDR_V(tmp.vpn_ip), IP_ADDR_V(tmp.vpn_mask), tmp.portnr);
636 Suggestion of Hans Bayle
638 if((fw = lookup_conn(tmp.vpn_ip)))
640 notify_others(fw, cl, send_add_host);
644 ncn = new_conn_list();
645 ncn->real_ip = tmp.real_ip;
646 ncn->vpn_ip = tmp.vpn_ip;
647 ncn->vpn_mask = tmp.vpn_mask;
648 ncn->port = tmp.portnr;
649 ncn->hostname = hostlookup(tmp.real_ip);
651 ncn->next = conn_list;
653 ncn->status.active = 1;
654 notify_others(ncn, cl, send_add_host);
659 int req_key_h(conn_list_t *cl)
664 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
666 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
671 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
672 IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
674 if((tmp.to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
675 { /* hey! they want something from ME! :) */
676 send_key_answer(cl, tmp.from);
680 fw = lookup_conn(tmp.to);
684 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
690 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
691 IP_ADDR_V(fw->nexthop->vpn_ip));
695 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp)) < 0)
697 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
704 void set_keys(conn_list_t *cl, key_req_t *k, char *key)
710 cl->public_key = xmalloc(sizeof(*cl->key));
711 cl->public_key->key = NULL;
713 if(cl->public_key->key)
714 free(cl->public_key->key);
715 cl->public_key->length = k->len;
716 cl->public_key->expiry = k->expiry;
717 cl->public_key->key = xmalloc(k->len + 1);
718 strcpy(cl->public_key->key, key);
720 ek = make_shared_key(key);
723 cl->key = xmalloc(sizeof(*cl->key));
728 cl->key->length = strlen(ek);
729 cl->key->expiry = k->expiry;
730 cl->key->key = xmalloc(strlen(ek) + 1);
731 strcpy(cl->key->key, ek);
735 int ans_key_h(conn_list_t *cl)
738 conn_list_t *fw, *gk;
741 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp) - 3) <= 0)
743 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
747 syslog(LOG_DEBUG, "%08lx %08lx %d %hd", tmp.from, tmp.to, tmp.expiry, tmp.len);
748 key = xmalloc(tmp.len);
750 if(read(cl->meta_socket, key, tmp.len + 2) <= 0)
752 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
755 syslog(LOG_DEBUG, "%s", key);
758 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
759 IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
761 if(tmp.to == myself->vpn_ip)
762 { /* hey! that key's for ME! :) */
764 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
765 gk = lookup_conn(tmp.from);
769 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
770 IP_ADDR_V(tmp.from));
774 set_keys(gk, &tmp, key);
775 gk->status.validkey = 1;
776 gk->status.waitingforkey = 0;
781 fw = lookup_conn(tmp.to);
785 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
791 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
792 IP_ADDR_V(fw->nexthop->vpn_ip));
794 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp) -2) < 0)
796 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
799 if(write(fw->nexthop->meta_socket, key, tmp.len + 1) < 0)
801 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
808 int key_changed_h(conn_list_t *cl)
813 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
815 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
820 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
821 IP_ADDR_V(tmp.from));
823 ik = lookup_conn(tmp.from);
827 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
828 IP_ADDR_V(tmp.from));
832 ik->status.validkey = 0;
833 ik->status.waitingforkey = 0;
836 syslog(LOG_DEBUG, "Forwarding key invalidation request");
838 notify_others(cl, ik, send_key_changed);
843 int (*request_handlers[256])(conn_list_t*) = {
844 0, ack_h, 0, 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,
847 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
848 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
849 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
850 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
851 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
852 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
853 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
857 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
858 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
859 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
862 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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