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.
22 #include <sys/types.h>
27 #include <sys/socket.h>
40 char buffer[MAXBUFSIZE+1];
43 int send_ack(conn_list_t *cl)
47 syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
49 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
51 if((write(cl->meta_socket, buffer, buflen)) < 0)
53 syslog(LOG_ERR, "send failed: %d:%d: %m", __FILE__, __LINE__);
57 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
62 int send_termreq(conn_list_t *cl)
66 syslog(LOG_DEBUG, "Send TERMREQ to " IP_ADDR_S,
67 IP_ADDR_V(cl->vpn_ip));
69 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
71 if((write(cl->meta_socket, buffer, buflen)) < 0)
73 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
80 int send_timeout(conn_list_t *cl)
84 syslog(LOG_DEBUG, "Send TIMEOUT to " IP_ADDR_S,
85 IP_ADDR_V(cl->vpn_ip));
87 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
89 if((write(cl->meta_socket, buffer, buflen)) < 0)
91 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
98 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
102 syslog(LOG_DEBUG, "Sending delete host " IP_ADDR_S " to " IP_ADDR_S,
103 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip));
105 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
107 if((write(cl->meta_socket, buffer, buflen)) < 0)
109 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
116 int send_ping(conn_list_t *cl)
120 syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
122 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
124 if((write(cl->meta_socket, buffer, buflen)) < 0)
126 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
133 int send_pong(conn_list_t *cl)
136 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
138 if((write(cl->meta_socket, buffer, buflen)) < 0)
140 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
147 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
151 syslog(LOG_DEBUG, "Sending add host to " IP_ADDR_S,
152 IP_ADDR_V(cl->vpn_ip));
154 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);
156 if((write(cl->meta_socket, buffer, buflen)) < 0)
158 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
165 int send_key_changed(conn_list_t *cl, conn_list_t *src)
169 syslog(LOG_DEBUG, "Sending KEY_CHANGED to " IP_ADDR_S,
170 IP_ADDR_V(cl->vpn_ip));
172 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
174 if((write(cl->meta_socket, buffer, buflen)) < 0)
176 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
183 void send_key_changed2(void)
187 for(p = conn_list; p != NULL; p = p->next)
188 if(p->status.meta && p->protocol_version > PROT_3)
189 send_key_changed(p, myself);
193 int send_basic_info(conn_list_t *cl)
197 syslog(LOG_DEBUG, "Send BASIC_INFO to " IP_ADDR_S,
198 IP_ADDR_V(cl->real_ip));
200 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port);
202 if((write(cl->meta_socket, buffer, buflen)) < 0)
204 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
211 int send_passphrase(conn_list_t *cl)
215 encrypt_passphrase(&tmp);
218 syslog(LOG_DEBUG, "Send PASSPHRASE %s to " IP_ADDR_S,
219 tmp.phrase, IP_ADDR_V(cl->vpn_ip));
221 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
223 if((write(cl->meta_socket, buffer, buflen)) < 0)
225 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
232 int send_public_key(conn_list_t *cl)
236 syslog(LOG_DEBUG, "Send PUBLIC_KEY %s to " IP_ADDR_S,
237 my_public_key_base36, IP_ADDR_V(cl->vpn_ip));
239 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
241 if((write(cl->meta_socket, buffer, buflen)) < 0)
243 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
250 int send_calculate(conn_list_t *cl, char *k)
253 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
255 if((write(cl->meta_socket, buffer, buflen)) < 0)
257 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
264 int send_key_request(ip_t to)
268 fw = lookup_conn(to);
271 syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
277 syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
278 IP_ADDR_V(fw->nexthop->vpn_ip));
280 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
282 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
284 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
287 fw->status.waitingforkey = 1;
292 int send_key_answer(conn_list_t *cl, ip_t to)
297 fw = lookup_conn(to);
301 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
307 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
308 IP_ADDR_V(fw->nexthop->vpn_ip));
310 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
312 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
314 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
322 notify all my direct connections of a new host
323 that was added to the vpn, with the exception
324 of the source of the announcement.
326 int notify_others(conn_list_t *new, conn_list_t *source,
327 int (*function)(conn_list_t*, conn_list_t*))
331 for(p = conn_list; p != NULL; p = p->next)
332 if(p != new && p != source && p->status.meta)
339 notify one connection of everything
342 int notify_one(conn_list_t *new)
346 for(p = conn_list; p != NULL; p = p->next)
347 if(p != new && p->protocol_version > PROT_3)
348 send_add_host(new, p);
354 The incoming request handlers
357 int basic_info_h(conn_list_t *cl)
360 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port) != 4)
362 syslog(LOG_ERR, "got bad BASIC_INFO request: %s", cl->buffer);
366 if(cl->protocol_version != PROT_CURRENT)
368 syslog(LOG_ERR, "Peer uses incompatible protocol version %d.",
369 cl->protocol_version);
374 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
375 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
377 syslog(LOG_DEBUG, "Peer uses protocol version %d",
378 cl->protocol_version);
380 if(cl->status.outgoing)
382 if(setup_vpn_connection(cl) < 0)
388 if(setup_vpn_connection(cl) < 0)
393 cl->status.active = 0;
398 int passphrase_h(conn_list_t *cl)
401 cl->pp=xmalloc(sizeof(*(cl->pp)));
402 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
404 syslog(LOG_ERR, "got bad PASSPHRASE request: %s", cl->buffer);
407 cl->pp->len = strlen(cl->pp->phrase);
410 syslog(LOG_DEBUG, "got PASSPHRASE");
412 if(cl->status.outgoing)
420 int public_key_h(conn_list_t *cl)
424 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
426 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
431 syslog(LOG_DEBUG, "got PUBLIC_KEY %s", g_n);
433 if(verify_passphrase(cl, g_n))
436 syslog(LOG_ERR, "Intruder: passphrase does not match.");
441 syslog(LOG_INFO, "Passphrase OK");
443 if(cl->status.outgoing)
448 cl->status.active = 1;
449 notify_others(cl, NULL, send_add_host);
455 int ack_h(conn_list_t *cl)
459 syslog(LOG_DEBUG, "got ACK");
461 cl->status.active = 1;
462 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
467 int termreq_h(conn_list_t *cl)
470 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
471 cl->status.termreq = 1;
472 terminate_connection(cl);
474 notify_others(cl, NULL, send_del_host);
479 int timeout_h(conn_list_t *cl)
482 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
483 cl->status.termreq = 1;
484 terminate_connection(cl);
489 int del_host_h(conn_list_t *cl)
494 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
496 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
501 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
504 if(!(fw = lookup_conn(vpn_ip)))
506 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
511 notify_others(cl, fw, send_del_host);
513 fw->status.termreq = 1;
514 terminate_connection(fw);
519 int ping_h(conn_list_t *cl)
523 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
524 cl->status.pinged = 0;
525 cl->status.got_pong = 1;
532 int pong_h(conn_list_t *cl)
536 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
537 cl->status.got_pong = 1;
542 int add_host_h(conn_list_t *cl)
548 conn_list_t *ncn, *fw;
550 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
552 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
557 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
559 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
560 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
563 Suggestion of Hans Bayle
565 if((fw = lookup_conn(vpn_ip)))
567 notify_others(fw, cl, send_add_host);
571 ncn = new_conn_list();
572 ncn->real_ip = real_ip;
573 ncn->vpn_ip = vpn_ip;
574 ncn->vpn_mask = vpn_mask;
576 ncn->hostname = hostlookup(real_ip);
578 ncn->next = conn_list;
580 ncn->status.active = 1;
581 notify_others(ncn, cl, send_add_host);
586 int req_key_h(conn_list_t *cl)
592 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
594 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
599 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
600 IP_ADDR_V(from), IP_ADDR_V(to));
602 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
603 { /* hey! they want something from ME! :) */
604 send_key_answer(cl, from);
608 fw = lookup_conn(to);
612 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
618 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
619 IP_ADDR_V(fw->nexthop->vpn_ip));
621 cl->buffer[cl->reqlen-1] = '\n';
623 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
625 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
632 void set_keys(conn_list_t *cl, int expiry, char *key)
638 cl->public_key = xmalloc(sizeof(*cl->key));
639 cl->public_key->key = NULL;
642 if(cl->public_key->key)
643 free(cl->public_key->key);
644 cl->public_key->length = strlen(key);
645 cl->public_key->expiry = expiry;
646 cl->public_key->key = xmalloc(cl->public_key->length + 1);
647 strcpy(cl->public_key->key, key);
649 ek = make_shared_key(key);
653 cl->key = xmalloc(sizeof(*cl->key));
660 cl->key->length = strlen(ek);
661 cl->key->expiry = expiry;
662 cl->key->key = xmalloc(cl->key->length + 1);
663 strcpy(cl->key->key, ek);
667 int ans_key_h(conn_list_t *cl)
673 conn_list_t *fw, *gk;
675 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
677 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
682 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
683 IP_ADDR_V(from), IP_ADDR_V(to));
685 if(to == myself->vpn_ip)
686 { /* hey! that key's for ME! :) */
688 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
689 gk = lookup_conn(from);
693 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
698 set_keys(gk, expiry, key);
699 gk->status.validkey = 1;
700 gk->status.waitingforkey = 0;
705 fw = lookup_conn(to);
709 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
715 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
716 IP_ADDR_V(fw->nexthop->vpn_ip));
718 cl->buffer[cl->reqlen-1] = '\n';
720 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
722 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
729 int key_changed_h(conn_list_t *cl)
734 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
736 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
741 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
744 ik = lookup_conn(from);
748 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
753 ik->status.validkey = 0;
754 ik->status.waitingforkey = 0;
757 syslog(LOG_DEBUG, "Forwarding key invalidation request");
759 notify_others(cl, ik, send_key_changed);
764 int (*request_handlers[256])(conn_list_t*) = {
765 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
768 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
769 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
776 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
777 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
780 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, 0, 0, 0, 0,
783 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
784 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0