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->protocol_version > PROT_3)
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)
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->protocol_version > PROT_3)
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)
396 cl->status.active = 0;
401 int passphrase_h(conn_list_t *cl)
404 cl->pp = xmalloc(sizeof(*(cl->pp)));
406 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
408 syslog(LOG_ERR, "got bad PASSPHRASE request: %s", cl->buffer);
411 cl->pp->len = strlen(cl->pp->phrase);
414 syslog(LOG_DEBUG, "got PASSPHRASE");
416 if(cl->status.outgoing)
424 int public_key_h(conn_list_t *cl)
428 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
430 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
435 syslog(LOG_DEBUG, "got PUBLIC_KEY %s", g_n);
437 if(verify_passphrase(cl, g_n))
440 syslog(LOG_ERR, "Intruder: passphrase does not match.");
445 syslog(LOG_INFO, "Passphrase OK");
447 if(cl->status.outgoing)
452 cl->status.active = 1;
453 notify_others(cl, NULL, send_add_host);
459 int ack_h(conn_list_t *cl)
463 syslog(LOG_DEBUG, "got ACK");
465 cl->status.active = 1;
466 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
471 int termreq_h(conn_list_t *cl)
474 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
475 cl->status.termreq = 1;
476 terminate_connection(cl);
478 notify_others(cl, NULL, send_del_host);
483 int timeout_h(conn_list_t *cl)
486 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
487 cl->status.termreq = 1;
488 terminate_connection(cl);
493 int del_host_h(conn_list_t *cl)
498 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
500 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
505 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
508 if(!(fw = lookup_conn(vpn_ip)))
510 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
515 notify_others(cl, fw, send_del_host);
517 fw->status.termreq = 1;
518 terminate_connection(fw);
523 int ping_h(conn_list_t *cl)
527 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
528 cl->status.pinged = 0;
529 cl->status.got_pong = 1;
536 int pong_h(conn_list_t *cl)
540 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
541 cl->status.got_pong = 1;
546 int add_host_h(conn_list_t *cl)
552 conn_list_t *ncn, *fw;
554 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
556 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
561 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
563 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
564 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
567 Suggestion of Hans Bayle
569 if((fw = lookup_conn(vpn_ip)))
571 notify_others(fw, cl, send_add_host);
575 ncn = new_conn_list();
576 ncn->real_ip = real_ip;
577 ncn->vpn_ip = vpn_ip;
578 ncn->vpn_mask = vpn_mask;
580 ncn->hostname = hostlookup(real_ip);
582 ncn->next = conn_list;
584 ncn->status.active = 1;
585 notify_others(ncn, cl, send_add_host);
590 int req_key_h(conn_list_t *cl)
596 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
598 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
603 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
604 IP_ADDR_V(from), IP_ADDR_V(to));
606 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
607 { /* hey! they want something from ME! :) */
608 send_key_answer(cl, from);
612 fw = lookup_conn(to);
616 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
622 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
623 IP_ADDR_V(fw->nexthop->vpn_ip));
625 cl->buffer[cl->reqlen-1] = '\n';
627 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
629 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
636 void set_keys(conn_list_t *cl, int expiry, char *key)
642 cl->public_key = xmalloc(sizeof(*cl->key));
643 cl->public_key->key = NULL;
646 if(cl->public_key->key)
647 free(cl->public_key->key);
648 cl->public_key->length = strlen(key);
649 cl->public_key->expiry = expiry;
650 cl->public_key->key = xmalloc(cl->public_key->length + 1);
651 strcpy(cl->public_key->key, key);
653 ek = make_shared_key(key);
657 cl->key = xmalloc(sizeof(*cl->key));
664 cl->key->length = strlen(ek);
665 cl->key->expiry = expiry;
666 cl->key->key = xmalloc(cl->key->length + 1);
667 strcpy(cl->key->key, ek);
671 int ans_key_h(conn_list_t *cl)
677 conn_list_t *fw, *gk;
679 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
681 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
686 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
687 IP_ADDR_V(from), IP_ADDR_V(to));
689 if(to == myself->vpn_ip)
690 { /* hey! that key's for ME! :) */
692 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
693 gk = lookup_conn(from);
697 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
702 set_keys(gk, expiry, key);
703 gk->status.validkey = 1;
704 gk->status.waitingforkey = 0;
709 fw = lookup_conn(to);
713 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
719 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
720 IP_ADDR_V(fw->nexthop->vpn_ip));
722 cl->buffer[cl->reqlen-1] = '\n';
724 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
726 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
733 int key_changed_h(conn_list_t *cl)
738 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
740 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
745 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
748 ik = lookup_conn(from);
752 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
757 ik->status.validkey = 0;
758 ik->status.waitingforkey = 0;
761 syslog(LOG_DEBUG, "Forwarding key invalidation request");
763 notify_others(cl, ik, send_key_changed);
768 int (*request_handlers[256])(conn_list_t*) = {
769 0, ack_h, 0, 0, 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 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
773 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
775 add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
778 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
779 0, 0, 0, 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 req_key_h, ans_key_h, key_changed_h, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
786 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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