2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999,2000 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.
22 #include <sys/types.h>
27 #include <sys/socket.h>
40 char buffer[MAXBUFSIZE+1];
43 /* Outgoing request routines */
45 int send_ack(conn_list_t *cl)
49 syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
51 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
53 if((write(cl->meta_socket, buffer, buflen)) < 0)
55 syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
59 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
64 int send_termreq(conn_list_t *cl)
68 syslog(LOG_DEBUG, "Send TERMREQ to " IP_ADDR_S,
69 IP_ADDR_V(cl->vpn_ip));
71 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
73 if(write(cl->meta_socket, buffer, buflen) < 0)
76 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
83 int send_timeout(conn_list_t *cl)
87 syslog(LOG_DEBUG, "Send TIMEOUT to " IP_ADDR_S,
88 IP_ADDR_V(cl->vpn_ip));
90 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
92 if((write(cl->meta_socket, buffer, buflen)) < 0)
94 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
101 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
105 syslog(LOG_DEBUG, "Sending delete host " IP_ADDR_S " to " IP_ADDR_S,
106 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip));
108 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
110 if((write(cl->meta_socket, buffer, buflen)) < 0)
112 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
119 int send_ping(conn_list_t *cl)
123 syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
125 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
127 if((write(cl->meta_socket, buffer, buflen)) < 0)
129 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
136 int send_pong(conn_list_t *cl)
139 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
141 if((write(cl->meta_socket, buffer, buflen)) < 0)
143 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
150 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
154 syslog(LOG_DEBUG, "Sending add host to " IP_ADDR_S,
155 IP_ADDR_V(cl->vpn_ip));
157 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x\n", ADD_HOST, new_host->real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port);
159 if((write(cl->meta_socket, buffer, buflen)) < 0)
161 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
168 int send_key_changed(conn_list_t *cl, conn_list_t *src)
172 syslog(LOG_DEBUG, "Sending KEY_CHANGED to " IP_ADDR_S,
173 IP_ADDR_V(cl->vpn_ip));
175 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
177 if((write(cl->meta_socket, buffer, buflen)) < 0)
179 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
186 void send_key_changed_all(void)
190 for(p = conn_list; p != NULL; p = p->next)
191 if(p->status.meta && p->active)
192 send_key_changed(p, myself);
196 int send_basic_info(conn_list_t *cl)
200 syslog(LOG_DEBUG, "Send BASIC_INFO to " IP_ADDR_S,
201 IP_ADDR_V(cl->real_ip));
203 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port);
205 if((write(cl->meta_socket, buffer, buflen)) < 0)
207 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
214 int send_passphrase(conn_list_t *cl)
218 encrypt_passphrase(&tmp);
221 syslog(LOG_DEBUG, "Send PASSPHRASE %s to " IP_ADDR_S,
222 tmp.phrase, IP_ADDR_V(cl->vpn_ip));
224 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
226 if((write(cl->meta_socket, buffer, buflen)) < 0)
228 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
235 int send_public_key(conn_list_t *cl)
239 syslog(LOG_DEBUG, "Send PUBLIC_KEY %s to " IP_ADDR_S,
240 my_public_key_base36, IP_ADDR_V(cl->vpn_ip));
242 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
244 if((write(cl->meta_socket, buffer, buflen)) < 0)
246 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
253 int send_calculate(conn_list_t *cl, char *k)
256 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
258 if((write(cl->meta_socket, buffer, buflen)) < 0)
260 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
267 int send_key_request(ip_t to)
271 fw = lookup_conn(to);
274 syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
280 syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
281 IP_ADDR_V(fw->nexthop->vpn_ip));
283 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
285 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
287 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
290 fw->status.waitingforkey = 1;
295 int send_key_answer(conn_list_t *cl, ip_t to)
300 fw = lookup_conn(to);
304 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
310 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
311 IP_ADDR_V(fw->nexthop->vpn_ip));
313 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
315 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
317 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
325 notify all my direct connections of a new host
326 that was added to the vpn, with the exception
327 of the source of the announcement.
329 int notify_others(conn_list_t *new, conn_list_t *source,
330 int (*function)(conn_list_t*, conn_list_t*))
334 for(p = conn_list; p != NULL; p = p->next)
335 if(p != new && p != source && p->status.meta && p->active)
342 notify one connection of everything
345 int notify_one(conn_list_t *new)
349 for(p = conn_list; p != NULL; p = p->next)
350 if(p != new && p->active)
351 send_add_host(new, p);
357 The incoming request handlers
360 int basic_info_h(conn_list_t *cl)
363 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port) != 4)
365 syslog(LOG_ERR, "got bad BASIC_INFO request: %s", cl->buffer);
369 if(cl->protocol_version != PROT_CURRENT)
371 syslog(LOG_ERR, "Peer uses incompatible protocol version %d.",
372 cl->protocol_version);
377 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
378 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
380 syslog(LOG_DEBUG, "Peer uses protocol version %d",
381 cl->protocol_version);
383 if(cl->status.outgoing)
385 if(setup_vpn_connection(cl) < 0)
391 if(setup_vpn_connection(cl) < 0)
399 int passphrase_h(conn_list_t *cl)
402 cl->pp = xmalloc(sizeof(*(cl->pp)));
404 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
406 syslog(LOG_ERR, "got bad PASSPHRASE request: %s", cl->buffer);
409 cl->pp->len = strlen(cl->pp->phrase);
412 syslog(LOG_DEBUG, "got PASSPHRASE");
414 if(cl->status.outgoing)
422 int public_key_h(conn_list_t *cl)
427 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
429 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
434 syslog(LOG_DEBUG, "got PUBLIC_KEY %s", g_n);
436 if(verify_passphrase(cl, g_n))
439 syslog(LOG_ERR, "Intruder: passphrase does not match.");
444 syslog(LOG_INFO, "Passphrase OK");
446 if(cl->status.outgoing)
451 /* Okay, before we active the connection, we check if there is another entry
452 in the connection list with the same vpn_ip. If so, it presumably is an
453 old connection that has timed out but we don't know it yet. Because our
454 conn_list entry is not active, lookup_conn will skip ourself. */
456 if(old=lookup_conn(cl->vpn_ip))
457 terminate_connection(old);
459 cl->status.active = 1;
460 notify_others(cl, NULL, send_add_host);
466 int ack_h(conn_list_t *cl)
470 syslog(LOG_DEBUG, "got ACK");
472 cl->status.active = 1;
473 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
478 int termreq_h(conn_list_t *cl)
481 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
482 cl->status.termreq = 1;
483 terminate_connection(cl);
485 notify_others(cl, NULL, send_del_host);
490 int timeout_h(conn_list_t *cl)
493 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
494 cl->status.termreq = 1;
495 terminate_connection(cl);
500 int del_host_h(conn_list_t *cl)
505 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
507 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
512 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
515 if(!(fw = lookup_conn(vpn_ip)))
517 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
522 notify_others(cl, fw, send_del_host);
524 fw->status.termreq = 1;
525 terminate_connection(fw);
530 int ping_h(conn_list_t *cl)
534 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
535 cl->status.pinged = 0;
536 cl->status.got_pong = 1;
543 int pong_h(conn_list_t *cl)
547 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
548 cl->status.got_pong = 1;
553 int add_host_h(conn_list_t *cl)
559 conn_list_t *ncn, *fw;
561 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
563 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
568 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
570 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
571 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
574 Suggestion of Hans Bayle
576 if((fw = lookup_conn(vpn_ip)))
578 notify_others(fw, cl, send_add_host);
582 ncn = new_conn_list();
583 ncn->real_ip = real_ip;
584 ncn->vpn_ip = vpn_ip;
585 ncn->vpn_mask = vpn_mask;
587 ncn->hostname = hostlookup(real_ip);
589 ncn->next = conn_list;
591 ncn->status.active = 1;
592 notify_others(ncn, cl, send_add_host);
597 int req_key_h(conn_list_t *cl)
603 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
605 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
610 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
611 IP_ADDR_V(from), IP_ADDR_V(to));
613 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
614 { /* hey! they want something from ME! :) */
615 send_key_answer(cl, from);
619 fw = lookup_conn(to);
623 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
629 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
630 IP_ADDR_V(fw->nexthop->vpn_ip));
632 cl->buffer[cl->reqlen-1] = '\n';
634 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
636 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
643 void set_keys(conn_list_t *cl, int expiry, char *key)
649 cl->public_key = xmalloc(sizeof(*cl->key));
650 cl->public_key->key = NULL;
653 if(cl->public_key->key)
654 free(cl->public_key->key);
655 cl->public_key->length = strlen(key);
656 cl->public_key->expiry = expiry;
657 cl->public_key->key = xmalloc(cl->public_key->length + 1);
658 strcpy(cl->public_key->key, key);
660 ek = make_shared_key(key);
664 cl->key = xmalloc(sizeof(*cl->key));
671 cl->key->length = strlen(ek);
672 cl->key->expiry = expiry;
673 cl->key->key = xmalloc(cl->key->length + 1);
674 strcpy(cl->key->key, ek);
678 int ans_key_h(conn_list_t *cl)
684 conn_list_t *fw, *gk;
686 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
688 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
693 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
694 IP_ADDR_V(from), IP_ADDR_V(to));
696 if(to == myself->vpn_ip)
697 { /* hey! that key's for ME! :) */
699 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
700 gk = lookup_conn(from);
704 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
709 set_keys(gk, expiry, key);
710 gk->status.validkey = 1;
711 gk->status.waitingforkey = 0;
716 fw = lookup_conn(to);
720 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
726 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
727 IP_ADDR_V(fw->nexthop->vpn_ip));
729 cl->buffer[cl->reqlen-1] = '\n';
731 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
733 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
740 int key_changed_h(conn_list_t *cl)
745 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
747 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
752 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
755 ik = lookup_conn(from);
759 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
764 ik->status.validkey = 0;
765 ik->status.waitingforkey = 0;
768 syslog(LOG_DEBUG, "Forwarding key invalidation request");
770 notify_others(cl, ik, send_key_changed);
775 int (*request_handlers[256])(conn_list_t*) = {
776 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
777 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
780 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
782 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
783 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
785 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
790 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
791 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
792 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
793 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
794 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
795 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0