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?",
348 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
349 IP_ADDR_V(fw->nexthop->vpn_ip));
350 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
352 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
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.
364 int notify_others(conn_list_t *new, conn_list_t *source,
365 int (*function)(conn_list_t*, conn_list_t*))
369 for(p = conn_list; p != NULL; p = p->next)
370 if(p != new && p != source && p->status.meta && p->protocol_version > PROT_3)
377 notify one connection of everything
380 int notify_one(conn_list_t *new)
384 for(p = conn_list; p != NULL; p = p->next)
385 if(p != new && p->protocol_version > PROT_3)
386 send_add_host(new, p);
392 The incoming request handlers
395 int basic_info_h(conn_list_t *cl, unsigned char *d, int len)
397 basic_info_t *tmp = (basic_info_t*)d;
399 cl->protocol_version = tmp->protocol;
400 cl->port = tmp->portnr;
401 cl->vpn_ip = tmp->vpn_ip;
402 cl->vpn_mask = tmp->vpn_mask;
404 if(cl->protocol_version < PROT_CURRENT)
406 syslog(LOG_ERR, "Peer uses protocol version %d which is too old.",
407 cl->protocol_version);
412 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
413 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
415 syslog(LOG_DEBUG, "Peer uses protocol version %d",
416 cl->protocol_version);
418 if(cl->status.outgoing)
420 if(setup_vpn_connection(cl) < 0)
426 if(setup_vpn_connection(cl) < 0)
431 cl->status.active = 0;
436 int passphrase_h(conn_list_t *cl, unsigned char *d, int len)
438 passphrase_t *tmp = (passphrase_t*)d;
440 cl->pp = xmalloc(tmp->len+3);
441 memcpy(cl->pp, tmp, tmp->len+3);
444 syslog(LOG_DEBUG, "got PASSPHRASE(%hd,...)", cl->pp->len);
446 if(cl->status.outgoing)
454 int public_key_h(conn_list_t *cl, unsigned char *d, int len)
457 public_key_t *tmp = (public_key_t*)d;
460 syslog(LOG_DEBUG, "got PUBLIC_KEY(%hd,%s)", tmp->len, &tmp->key);
462 g_n = xmalloc(tmp->len+1);
463 strcpy(g_n, &tmp->key);
465 if(verify_passphrase(cl, g_n))
468 syslog(LOG_ERR, "Intruder: passphrase does not match.");
473 syslog(LOG_INFO, "Passphrase OK");
475 if(cl->status.outgoing)
480 cl->status.active = 1;
481 notify_others(cl, NULL, send_add_host);
487 int ack_h(conn_list_t *cl, unsigned char *d, int len)
491 syslog(LOG_DEBUG, "got ACK");
493 cl->status.active = 1;
494 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
499 int termreq_h(conn_list_t *cl, unsigned char *d, int len)
502 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
503 cl->status.termreq = 1;
504 terminate_connection(cl);
506 notify_others(cl, NULL, send_del_host);
511 int timeout_h(conn_list_t *cl, unsigned char *d, int len)
514 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
515 cl->status.termreq = 1;
516 terminate_connection(cl);
521 int del_host_h(conn_list_t *cl, unsigned char *d, int len)
523 del_host_t *tmp = (del_host_t*)d;
527 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
528 IP_ADDR_V(tmp->vpn_ip));
530 if(!(fw = lookup_conn(tmp->vpn_ip)))
532 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
533 IP_ADDR_V(tmp->vpn_ip));
537 notify_others(cl, fw, send_del_host);
539 fw->status.termreq = 1;
540 terminate_connection(fw);
545 int ping_h(conn_list_t *cl, unsigned char *d, int len)
549 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
550 cl->status.pinged = 0;
551 cl->status.got_pong = 1;
558 int pong_h(conn_list_t *cl, unsigned char *d, int len)
562 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
563 cl->status.got_pong = 1;
568 int add_host_h(conn_list_t *cl, unsigned char *d, int len)
570 add_host_t *tmp = (add_host_t*)d;
571 conn_list_t *ncn, *fw;
574 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
576 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
577 IP_ADDR_V(tmp->vpn_ip), IP_ADDR_V(tmp->vpn_mask), tmp->portnr);
580 Suggestion of Hans Bayle
582 if((fw = lookup_conn(tmp->vpn_ip)))
584 notify_others(fw, cl, send_add_host);
588 ncn = new_conn_list();
589 ncn->real_ip = tmp->real_ip;
590 ncn->vpn_ip = tmp->vpn_ip;
591 ncn->vpn_mask = tmp->vpn_mask;
592 ncn->port = tmp->portnr;
593 ncn->hostname = hostlookup(tmp->real_ip);
595 ncn->next = conn_list;
597 ncn->status.active = 1;
598 notify_others(ncn, cl, send_add_host);
603 int req_key_h(conn_list_t *cl, unsigned char *d, int len)
605 key_req_t *tmp = (key_req_t*)d;
609 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
610 IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
612 if((tmp->to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
613 { /* hey! they want something from ME! :) */
614 send_key_answer(cl, tmp->from);
618 fw = lookup_conn(tmp->to);
622 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
628 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
629 IP_ADDR_V(fw->nexthop->vpn_ip));
630 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)) < 0)
632 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
639 void set_keys(conn_list_t *cl, key_req_t *k)
645 cl->public_key = xmalloc(sizeof(*cl->key));
646 cl->public_key->key = NULL;
648 if(cl->public_key->key)
649 free(cl->public_key->key);
650 cl->public_key->length = k->len;
651 cl->public_key->expiry = k->expiry;
652 cl->public_key->key = xmalloc(k->len + 1);
653 strcpy(cl->public_key->key, &(k->key));
655 ek = make_shared_key(&(k->key));
658 cl->key = xmalloc(sizeof(*cl->key));
663 cl->key->length = strlen(ek);
664 cl->key->expiry = k->expiry;
665 cl->key->key = xmalloc(strlen(ek) + 1);
666 strcpy(cl->key->key, ek);
670 int ans_key_h(conn_list_t *cl, unsigned char *d, int len)
672 key_req_t *tmp = (key_req_t*)d;
673 conn_list_t *fw, *gk;
676 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
677 IP_ADDR_V(tmp->from), IP_ADDR_V(tmp->to));
679 if(tmp->to == myself->vpn_ip)
680 { /* hey! that key's for ME! :) */
682 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
683 gk = lookup_conn(tmp->from);
687 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
688 IP_ADDR_V(tmp->from));
693 gk->status.validkey = 1;
694 gk->status.waitingforkey = 0;
699 fw = lookup_conn(tmp->to);
703 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
709 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
710 IP_ADDR_V(fw->nexthop->vpn_ip));
711 if(write(fw->nexthop->meta_socket, tmp, sizeof(*tmp)+tmp->len) < 0)
713 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
720 int key_changed_h(conn_list_t *cl, unsigned char *d, int len)
722 key_changed_t *tmp = (key_changed_t*)d;
726 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
727 IP_ADDR_V(tmp->from));
729 ik = lookup_conn(tmp->from);
733 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
734 IP_ADDR_V(tmp->from));
738 ik->status.validkey = 0;
739 ik->status.waitingforkey = 0;
742 syslog(LOG_DEBUG, "Forwarding key invalidation request");
744 notify_others(cl, ik, send_key_changed);
749 int (*request_handlers[256])(conn_list_t*, unsigned char*, int) = {
750 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
751 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
752 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
753 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
754 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
755 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
756 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
757 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
758 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
759 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
760 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
761 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
763 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
764 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0