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 syslog(LOG_DEBUG, "key sent = %s", my_public_key_base36);
341 fw = lookup_conn(to);
346 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
351 syslog(LOG_DEBUG, "key sent = %s", &(tmp->key));
355 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
356 IP_ADDR_V(fw->nexthop->vpn_ip));
358 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
360 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
368 notify all my direct connections of a new host
369 that was added to the vpn, with the exception
370 of the source of the announcement.
372 int notify_others(conn_list_t *new, conn_list_t *source,
373 int (*function)(conn_list_t*, conn_list_t*))
377 for(p = conn_list; p != NULL; p = p->next)
378 if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
385 notify one connection of everything
388 int notify_one(conn_list_t *new)
392 for(p = conn_list; p != NULL; p = p->next)
393 if(p != new && p->protocol_version > PROT_3)
394 send_add_host(new, p);
400 The incoming request handlers
403 int basic_info_h(conn_list_t *cl)
407 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
409 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
413 cl->protocol_version = tmp.protocol;
414 cl->port = tmp.portnr;
415 cl->vpn_ip = tmp.vpn_ip;
416 cl->vpn_mask = tmp.vpn_mask;
418 if(cl->protocol_version < PROT_CURRENT)
420 syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
421 cl->protocol_version);
426 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
427 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
429 syslog(LOG_DEBUG, "Peer uses protocol version %d",
430 cl->protocol_version);
432 if(cl->status.outgoing)
434 if(setup_vpn_connection(cl) < 0)
440 if(setup_vpn_connection(cl) < 0)
445 cl->status.active = 0;
450 int passphrase_h(conn_list_t *cl)
453 unsigned short int len;
455 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
457 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
461 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
463 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
467 cl->pp = xmalloc(len+4);
470 if(read(cl->meta_socket, &(cl->pp->phrase), len) <= 0)
472 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
477 syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", len);
479 if(cl->status.outgoing)
487 int public_key_h(conn_list_t *cl)
490 unsigned short int len;
493 if(read(cl->meta_socket, &unused, sizeof(unused)) <= 0)
495 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
498 if(read(cl->meta_socket, &len, sizeof(len)) <= 0)
500 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
504 g_n = xmalloc(len+2);
506 if(read(cl->meta_socket, g_n, len+2) <= 0)
508 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
513 syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", len, g_n);
515 if(verify_passphrase(cl, g_n))
518 syslog(LOG_ERR, "Intruder: passphrase does not match.");
523 syslog(LOG_INFO, "Passphrase OK");
525 if(cl->status.outgoing)
530 cl->status.active = 1;
531 notify_others(cl, NULL, send_add_host);
537 int ack_h(conn_list_t *cl)
541 syslog(LOG_DEBUG, "got ACK");
543 cl->status.active = 1;
544 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
549 int termreq_h(conn_list_t *cl)
552 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
553 cl->status.termreq = 1;
554 terminate_connection(cl);
556 notify_others(cl, NULL, send_del_host);
561 int timeout_h(conn_list_t *cl)
564 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
565 cl->status.termreq = 1;
566 terminate_connection(cl);
571 int del_host_h(conn_list_t *cl)
576 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
578 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
583 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
584 IP_ADDR_V(tmp.vpn_ip));
586 if(!(fw = lookup_conn(tmp.vpn_ip)))
588 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
589 IP_ADDR_V(tmp.vpn_ip));
593 notify_others(cl, fw, send_del_host);
595 fw->status.termreq = 1;
596 terminate_connection(fw);
601 int ping_h(conn_list_t *cl)
605 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
606 cl->status.pinged = 0;
607 cl->status.got_pong = 1;
614 int pong_h(conn_list_t *cl)
618 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
619 cl->status.got_pong = 1;
624 int add_host_h(conn_list_t *cl)
627 conn_list_t *ncn, *fw;
629 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
631 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
636 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
638 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
639 IP_ADDR_V(tmp.vpn_ip), IP_ADDR_V(tmp.vpn_mask), tmp.portnr);
642 Suggestion of Hans Bayle
644 if((fw = lookup_conn(tmp.vpn_ip)))
646 notify_others(fw, cl, send_add_host);
650 ncn = new_conn_list();
651 ncn->real_ip = tmp.real_ip;
652 ncn->vpn_ip = tmp.vpn_ip;
653 ncn->vpn_mask = tmp.vpn_mask;
654 ncn->port = tmp.portnr;
655 ncn->hostname = hostlookup(tmp.real_ip);
657 ncn->next = conn_list;
659 ncn->status.active = 1;
660 notify_others(ncn, cl, send_add_host);
665 int req_key_h(conn_list_t *cl)
670 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
672 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
677 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
678 IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
680 if((tmp.to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
681 { /* hey! they want something from ME! :) */
682 send_key_answer(cl, tmp.from);
686 fw = lookup_conn(tmp.to);
690 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
696 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
697 IP_ADDR_V(fw->nexthop->vpn_ip));
701 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp)) < 0)
703 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
710 void set_keys(conn_list_t *cl, key_req_t *k, char *key)
716 cl->public_key = xmalloc(sizeof(*cl->key));
717 cl->public_key->key = NULL;
719 if(cl->public_key->key)
720 free(cl->public_key->key);
721 cl->public_key->length = k->len;
722 cl->public_key->expiry = k->expiry;
723 cl->public_key->key = xmalloc(k->len + 1);
724 strcpy(cl->public_key->key, key);
726 ek = make_shared_key(key);
729 cl->key = xmalloc(sizeof(*cl->key));
734 cl->key->length = strlen(ek);
735 cl->key->expiry = k->expiry;
736 cl->key->key = xmalloc(strlen(ek) + 1);
737 strcpy(cl->key->key, ek);
741 int ans_key_h(conn_list_t *cl)
744 conn_list_t *fw, *gk;
747 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-2) <= 0)
749 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
753 key = xmalloc(tmp.len);
755 if(read(cl->meta_socket, key, tmp.len + 1) <= 0)
757 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
761 syslog(LOG_DEBUG, "key = %s", key);
764 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
765 IP_ADDR_V(tmp.from), IP_ADDR_V(tmp.to));
767 if(tmp.to == myself->vpn_ip)
768 { /* hey! that key's for ME! :) */
770 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
771 gk = lookup_conn(tmp.from);
775 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
776 IP_ADDR_V(tmp.from));
780 set_keys(gk, &tmp, key);
781 gk->status.validkey = 1;
782 gk->status.waitingforkey = 0;
787 fw = lookup_conn(tmp.to);
791 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
797 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
798 IP_ADDR_V(fw->nexthop->vpn_ip));
800 if(write(fw->nexthop->meta_socket, &tmp, sizeof(tmp) -1) < 0)
802 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
805 if(write(fw->nexthop->meta_socket, key, tmp.len + 1) < 0)
807 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
814 int key_changed_h(conn_list_t *cl)
819 if(read(cl->meta_socket, &((char*)(&tmp))[1], sizeof(tmp)-1) <= 0)
821 syslog(LOG_ERR, "%d: Receive failed: %m", __LINE__);
826 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
827 IP_ADDR_V(tmp.from));
829 ik = lookup_conn(tmp.from);
833 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
834 IP_ADDR_V(tmp.from));
838 ik->status.validkey = 0;
839 ik->status.waitingforkey = 0;
842 syslog(LOG_DEBUG, "Forwarding key invalidation request");
844 notify_others(cl, ik, send_key_changed);
849 int (*request_handlers[256])(conn_list_t*) = {
850 0, ack_h, 0, 0, 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 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
854 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
855 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
856 add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
860 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
861 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, 0, 0, 0, 0,
864 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
865 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, 0, 0, 0, 0,
867 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
868 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
869 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0