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>
38 char buffer[MAXBUFSIZE+1];
41 int send_ack(conn_list_t *cl)
45 syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
47 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
49 if((write(cl->meta_socket, buffer, buflen)) < 0)
51 syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
55 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
60 int send_termreq(conn_list_t *cl)
64 syslog(LOG_DEBUG, "Send TERMREQ to " IP_ADDR_S,
65 IP_ADDR_V(cl->vpn_ip));
67 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
69 if((write(cl->meta_socket, buffer, buflen)) < 0)
71 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
78 int send_timeout(conn_list_t *cl)
82 syslog(LOG_DEBUG, "Send TIMEOUT to " IP_ADDR_S,
83 IP_ADDR_V(cl->vpn_ip));
85 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
87 if((write(cl->meta_socket, buffer, buflen)) < 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 syslog(LOG_DEBUG, "Sending delete host " IP_ADDR_S " to " IP_ADDR_S,
101 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip));
103 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
105 if((write(cl->meta_socket, buffer, buflen)) < 0)
107 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
114 int send_ping(conn_list_t *cl)
118 syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
120 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
122 if((write(cl->meta_socket, buffer, buflen)) < 0)
124 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
131 int send_pong(conn_list_t *cl)
134 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
136 if((write(cl->meta_socket, buffer, buflen)) < 0)
138 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
145 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
149 syslog(LOG_DEBUG, "Sending add host to " IP_ADDR_S,
150 IP_ADDR_V(cl->vpn_ip));
152 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);
154 if((write(cl->meta_socket, buffer, buflen)) < 0)
156 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
163 int send_key_changed(conn_list_t *cl, conn_list_t *src)
167 syslog(LOG_DEBUG, "Sending KEY_CHANGED to " IP_ADDR_S,
168 IP_ADDR_V(cl->vpn_ip));
170 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
172 if((write(cl->meta_socket, buffer, buflen)) < 0)
174 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
181 void send_key_changed2(void)
185 for(p = conn_list; p != NULL; p = p->next)
186 if(p->status.meta && p->protocol_version > PROT_3)
187 send_key_changed(p, myself);
191 int send_basic_info(conn_list_t *cl)
195 syslog(LOG_DEBUG, "Send BASIC_INFO to " IP_ADDR_S,
196 IP_ADDR_V(cl->real_ip));
198 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port);
200 if((write(cl->meta_socket, buffer, buflen)) < 0)
202 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
209 int send_passphrase(conn_list_t *cl)
213 encrypt_passphrase(&tmp);
216 syslog(LOG_DEBUG, "Send PASSPHRASE %s to " IP_ADDR_S,
217 tmp.phrase, IP_ADDR_V(cl->vpn_ip));
219 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
221 if((write(cl->meta_socket, buffer, buflen)) < 0)
223 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
230 int send_public_key(conn_list_t *cl)
234 syslog(LOG_DEBUG, "Send PUBLIC_KEY %s to " IP_ADDR_S,
235 my_public_key_base36, IP_ADDR_V(cl->vpn_ip));
237 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
239 if((write(cl->meta_socket, buffer, buflen)) < 0)
241 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
248 int send_calculate(conn_list_t *cl, char *k)
251 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
253 if((write(cl->meta_socket, buffer, buflen)) < 0)
255 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
262 int send_key_request(ip_t to)
266 fw = lookup_conn(to);
269 syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
275 syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
276 IP_ADDR_V(fw->nexthop->vpn_ip));
278 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
280 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
282 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
285 fw->status.waitingforkey = 1;
290 int send_key_answer(conn_list_t *cl, ip_t to)
295 fw = lookup_conn(to);
299 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
305 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
306 IP_ADDR_V(fw->nexthop->vpn_ip));
308 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
310 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
312 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
320 notify all my direct connections of a new host
321 that was added to the vpn, with the exception
322 of the source of the announcement.
324 int notify_others(conn_list_t *new, conn_list_t *source,
325 int (*function)(conn_list_t*, conn_list_t*))
329 for(p = conn_list; p != NULL; p = p->next)
330 if(p != new && p != source && p->status.meta)
337 notify one connection of everything
340 int notify_one(conn_list_t *new)
344 for(p = conn_list; p != NULL; p = p->next)
345 if(p != new && p->protocol_version > PROT_3)
346 send_add_host(new, p);
352 The incoming request handlers
355 int basic_info_h(conn_list_t *cl)
358 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port) != 4)
360 syslog(LOG_ERR, "got bad BASIC_INFO request: %s", cl->buffer);
364 if(cl->protocol_version != PROT_CURRENT)
366 syslog(LOG_ERR, "Peer uses incompatible protocol version %d.",
367 cl->protocol_version);
372 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
373 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
375 syslog(LOG_DEBUG, "Peer uses protocol version %d",
376 cl->protocol_version);
378 if(cl->status.outgoing)
380 if(setup_vpn_connection(cl) < 0)
386 if(setup_vpn_connection(cl) < 0)
391 cl->status.active = 0;
396 int passphrase_h(conn_list_t *cl)
399 cl->pp=xmalloc(sizeof(*(cl->pp)));
400 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
402 syslog(LOG_ERR, "got bad PASSPHRASE request: %s", cl->buffer);
405 cl->pp->len = strlen(cl->pp->phrase);
408 syslog(LOG_DEBUG, "got PASSPHRASE");
410 if(cl->status.outgoing)
418 int public_key_h(conn_list_t *cl)
422 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
424 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
429 syslog(LOG_DEBUG, "got PUBLIC_KEY %s", g_n);
431 if(verify_passphrase(cl, g_n))
434 syslog(LOG_ERR, "Intruder: passphrase does not match.");
439 syslog(LOG_INFO, "Passphrase OK");
441 if(cl->status.outgoing)
446 cl->status.active = 1;
447 notify_others(cl, NULL, send_add_host);
453 int ack_h(conn_list_t *cl)
457 syslog(LOG_DEBUG, "got ACK");
459 cl->status.active = 1;
460 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
465 int termreq_h(conn_list_t *cl)
468 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
469 cl->status.termreq = 1;
470 terminate_connection(cl);
472 notify_others(cl, NULL, send_del_host);
477 int timeout_h(conn_list_t *cl)
480 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
481 cl->status.termreq = 1;
482 terminate_connection(cl);
487 int del_host_h(conn_list_t *cl)
492 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
494 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
499 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
502 if(!(fw = lookup_conn(vpn_ip)))
504 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
509 notify_others(cl, fw, send_del_host);
511 fw->status.termreq = 1;
512 terminate_connection(fw);
517 int ping_h(conn_list_t *cl)
521 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
522 cl->status.pinged = 0;
523 cl->status.got_pong = 1;
530 int pong_h(conn_list_t *cl)
534 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
535 cl->status.got_pong = 1;
540 int add_host_h(conn_list_t *cl)
546 conn_list_t *ncn, *fw;
548 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
550 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
555 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
557 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
558 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
561 Suggestion of Hans Bayle
563 if((fw = lookup_conn(vpn_ip)))
565 notify_others(fw, cl, send_add_host);
569 ncn = new_conn_list();
570 ncn->real_ip = real_ip;
571 ncn->vpn_ip = vpn_ip;
572 ncn->vpn_mask = vpn_mask;
574 ncn->hostname = hostlookup(real_ip);
576 ncn->next = conn_list;
578 ncn->status.active = 1;
579 notify_others(ncn, cl, send_add_host);
584 int req_key_h(conn_list_t *cl)
590 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
592 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
597 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
598 IP_ADDR_V(from), IP_ADDR_V(to));
600 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
601 { /* hey! they want something from ME! :) */
602 send_key_answer(cl, from);
606 fw = lookup_conn(to);
610 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
616 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
617 IP_ADDR_V(fw->nexthop->vpn_ip));
619 cl->buffer[cl->reqlen-1] = '\n';
621 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
623 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
630 void set_keys(conn_list_t *cl, int expiry, char *key)
636 cl->public_key = xmalloc(sizeof(*cl->key));
637 cl->public_key->key = NULL;
640 if(cl->public_key->key)
641 free(cl->public_key->key);
642 cl->public_key->length = strlen(key);
643 cl->public_key->expiry = expiry;
644 cl->public_key->key = xmalloc(cl->public_key->length + 1);
645 strcpy(cl->public_key->key, key);
647 ek = make_shared_key(key);
651 cl->key = xmalloc(sizeof(*cl->key));
658 cl->key->length = strlen(ek);
659 cl->key->expiry = expiry;
660 cl->key->key = xmalloc(cl->key->length + 1);
661 strcpy(cl->key->key, ek);
665 int ans_key_h(conn_list_t *cl)
671 conn_list_t *fw, *gk;
673 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
675 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
680 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
681 IP_ADDR_V(from), IP_ADDR_V(to));
683 if(to == myself->vpn_ip)
684 { /* hey! that key's for ME! :) */
686 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
687 gk = lookup_conn(from);
691 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
696 set_keys(gk, expiry, key);
697 gk->status.validkey = 1;
698 gk->status.waitingforkey = 0;
703 fw = lookup_conn(to);
707 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
713 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
714 IP_ADDR_V(fw->nexthop->vpn_ip));
716 cl->buffer[cl->reqlen-1] = '\n';
718 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
720 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
727 int key_changed_h(conn_list_t *cl)
732 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
734 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
739 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
742 ik = lookup_conn(from);
746 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
751 ik->status.validkey = 0;
752 ik->status.waitingforkey = 0;
755 syslog(LOG_DEBUG, "Forwarding key invalidation request");
757 notify_others(cl, ik, send_key_changed);
762 int (*request_handlers[256])(conn_list_t*) = {
763 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
766 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
767 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
775 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
776 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
777 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
780 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
781 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
782 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0