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);
339 fw = lookup_conn(to);
344 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
350 syslog(LOG_DEBUG, "key sent = %s", tmp->key);
352 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
353 IP_ADDR_V(fw->nexthop->vpn_ip));
355 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
357 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
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.
369 int notify_others(conn_list_t *new, conn_list_t *source,
370 int (*function)(conn_list_t*, conn_list_t*))
374 for(p = conn_list; p != NULL; p = p->next)
375 if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
382 notify one connection of everything
385 int notify_one(conn_list_t *new)
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);
397 The incoming request handlers
400 int basic_info_h(conn_list_t *cl)
404 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
406 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
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;
415 if(cl->protocol_version < PROT_CURRENT)
417 syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
418 cl->protocol_version);
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));
426 syslog(LOG_DEBUG, "Peer uses protocol version %d",
427 cl->protocol_version);
429 if(cl->status.outgoing)
431 if(setup_vpn_connection(cl) < 0)
437 if(setup_vpn_connection(cl) < 0)
442 cl->status.active = 0;
447 int passphrase_h(conn_list_t *cl)
450 unsigned short int len;
452 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
454 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
458 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
460 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
464 cl->pp = xmalloc(len+4);
467 if(read(cl->meta_socket, &(cl->pp->phrase), len) <= 0)
469 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
474 syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", len);
476 if(cl->status.outgoing)
484 int public_key_h(conn_list_t *cl)
487 unsigned short int len;
490 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
492 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
495 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
497 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
501 g_n = xmalloc(len+2);
503 if(read(cl->meta_socket, g_n, len+2) <= 0)
505 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
510 syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", len, g_n);
512 if(verify_passphrase(cl, g_n))
515 syslog(LOG_ERR, "Intruder: passphrase does not match.");
520 syslog(LOG_INFO, "Passphrase OK");
522 if(cl->status.outgoing)
527 cl->status.active = 1;
528 notify_others(cl, NULL, send_add_host);
534 int ack_h(conn_list_t *cl)
538 syslog(LOG_DEBUG, "got ACK");
540 cl->status.active = 1;
541 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
546 int termreq_h(conn_list_t *cl)
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);
553 notify_others(cl, NULL, send_del_host);
558 int timeout_h(conn_list_t *cl)
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);
568 int del_host_h(conn_list_t *cl)
573 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
575 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
580 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
581 IP_ADDR_V(tmp.vpn_ip));
583 if(!(fw = lookup_conn(tmp.vpn_ip)))
585 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
586 IP_ADDR_V(tmp.vpn_ip));
590 notify_others(cl, fw, send_del_host);
592 fw->status.termreq = 1;
593 terminate_connection(fw);
598 int ping_h(conn_list_t *cl)
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;
611 int pong_h(conn_list_t *cl)
615 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
616 cl->status.got_pong = 1;
621 int add_host_h(conn_list_t *cl)
624 conn_list_t *ncn, *fw;
626 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
628 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
633 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
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);
639 Suggestion of Hans Bayle
641 if((fw = lookup_conn(tmp.vpn_ip)))
643 notify_others(fw, cl, send_add_host);
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);
654 ncn->next = conn_list;
656 ncn->status.active = 1;
657 notify_others(ncn, cl, send_add_host);
662 int req_key_h(conn_list_t *cl)
667 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
669 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
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));
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);
683 fw = lookup_conn(tmp.to);
687 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
693 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
694 IP_ADDR_V(fw->nexthop->vpn_ip));
698 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp)) < 0)
700 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
707 void set_keys(conn_list_t *cl, key_req_t *k, char *key)
713 cl->public_key = xmalloc(sizeof(*cl->key));
714 cl->public_key->key = NULL;
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);
723 ek = make_shared_key(key);
726 cl->key = xmalloc(sizeof(*cl->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);
738 int ans_key_h(conn_list_t *cl)
741 conn_list_t *fw, *gk;
744 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-2) <= 0)
746 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
750 key = xmalloc(tmp.len);
752 if(read(cl->meta_socket, key, tmp.len + 1) <= 0)
754 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
758 syslog(LOG_DEBUG, "key = %s", key);
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));
764 if(tmp.to == myself->vpn_ip)
765 { /* hey! that key's for ME! :) */
767 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
768 gk = lookup_conn(tmp.from);
772 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
773 IP_ADDR_V(tmp.from));
777 set_keys(gk, &tmp, key);
778 gk->status.validkey = 1;
779 gk->status.waitingforkey = 0;
784 fw = lookup_conn(tmp.to);
788 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
794 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
795 IP_ADDR_V(fw->nexthop->vpn_ip));
797 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp) -1) < 0)
799 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
802 if(write(fw->nexthop->meta_socket, key, tmp.len + 1) < 0)
804 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
811 int key_changed_h(conn_list_t *cl)
816 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
818 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
823 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
824 IP_ADDR_V(tmp.from));
826 ik = lookup_conn(tmp.from);
830 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
831 IP_ADDR_V(tmp.from));
835 ik->status.validkey = 0;
836 ik->status.waitingforkey = 0;
839 syslog(LOG_DEBUG, "Forwarding key invalidation request");
841 notify_others(cl, ik, send_key_changed);
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