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)
75 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
82 int send_timeout(conn_list_t *cl)
86 syslog(LOG_DEBUG, "Send TIMEOUT to " IP_ADDR_S,
87 IP_ADDR_V(cl->vpn_ip));
89 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
91 if((write(cl->meta_socket, buffer, buflen)) < 0)
93 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
100 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
104 syslog(LOG_DEBUG, "Sending delete host " IP_ADDR_S " to " IP_ADDR_S,
105 IP_ADDR_V(new_host->vpn_ip), IP_ADDR_V(cl->vpn_ip));
107 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
109 if((write(cl->meta_socket, buffer, buflen)) < 0)
111 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
118 int send_ping(conn_list_t *cl)
122 syslog(LOG_DEBUG, "pinging " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
124 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
126 if((write(cl->meta_socket, buffer, buflen)) < 0)
128 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
135 int send_pong(conn_list_t *cl)
138 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
140 if((write(cl->meta_socket, buffer, buflen)) < 0)
142 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
149 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
153 syslog(LOG_DEBUG, "Sending add host to " IP_ADDR_S,
154 IP_ADDR_V(cl->vpn_ip));
156 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);
158 if((write(cl->meta_socket, buffer, buflen)) < 0)
160 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
167 int send_key_changed(conn_list_t *cl, conn_list_t *src)
171 syslog(LOG_DEBUG, "Sending KEY_CHANGED to " IP_ADDR_S,
172 IP_ADDR_V(cl->vpn_ip));
174 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
176 if((write(cl->meta_socket, buffer, buflen)) < 0)
178 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
185 void send_key_changed_all(void)
189 for(p = conn_list; p != NULL; p = p->next)
190 if(p->status.meta && p->protocol_version > PROT_3)
191 send_key_changed(p, myself);
195 int send_basic_info(conn_list_t *cl)
199 syslog(LOG_DEBUG, "Send BASIC_INFO to " IP_ADDR_S,
200 IP_ADDR_V(cl->real_ip));
202 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port);
204 if((write(cl->meta_socket, buffer, buflen)) < 0)
206 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
213 int send_passphrase(conn_list_t *cl)
217 encrypt_passphrase(&tmp);
220 syslog(LOG_DEBUG, "Send PASSPHRASE %s to " IP_ADDR_S,
221 tmp.phrase, IP_ADDR_V(cl->vpn_ip));
223 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
225 if((write(cl->meta_socket, buffer, buflen)) < 0)
227 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
234 int send_public_key(conn_list_t *cl)
238 syslog(LOG_DEBUG, "Send PUBLIC_KEY %s to " IP_ADDR_S,
239 my_public_key_base36, IP_ADDR_V(cl->vpn_ip));
241 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
243 if((write(cl->meta_socket, buffer, buflen)) < 0)
245 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
252 int send_calculate(conn_list_t *cl, char *k)
255 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
257 if((write(cl->meta_socket, buffer, buflen)) < 0)
259 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
266 int send_key_request(ip_t to)
270 fw = lookup_conn(to);
273 syslog(LOG_ERR, "Attempting to send key request to " IP_ADDR_S ", which does not exist?",
279 syslog(LOG_DEBUG, "Sending out request for public key to " IP_ADDR_S,
280 IP_ADDR_V(fw->nexthop->vpn_ip));
282 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
284 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
286 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
289 fw->status.waitingforkey = 1;
294 int send_key_answer(conn_list_t *cl, ip_t to)
299 fw = lookup_conn(to);
303 syslog(LOG_ERR, "Attempting to send key answer to " IP_ADDR_S ", which does not exist?",
309 syslog(LOG_DEBUG, "Sending public key to " IP_ADDR_S,
310 IP_ADDR_V(fw->nexthop->vpn_ip));
312 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
314 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
316 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
324 notify all my direct connections of a new host
325 that was added to the vpn, with the exception
326 of the source of the announcement.
328 int notify_others(conn_list_t *new, conn_list_t *source,
329 int (*function)(conn_list_t*, conn_list_t*))
333 for(p = conn_list; p != NULL; p = p->next)
334 if(p != new && p != source && p->status.meta)
341 notify one connection of everything
344 int notify_one(conn_list_t *new)
348 for(p = conn_list; p != NULL; p = p->next)
349 if(p != new && p->protocol_version > PROT_3)
350 send_add_host(new, p);
356 The incoming request handlers
359 int basic_info_h(conn_list_t *cl)
362 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port) != 4)
364 syslog(LOG_ERR, "got bad BASIC_INFO request: %s", cl->buffer);
368 if(cl->protocol_version != PROT_CURRENT)
370 syslog(LOG_ERR, "Peer uses incompatible protocol version %d.",
371 cl->protocol_version);
376 syslog(LOG_DEBUG, "got BASIC_INFO(%hd," IP_ADDR_S "," IP_ADDR_S ")", cl->port,
377 IP_ADDR_V(cl->vpn_ip), IP_ADDR_V(cl->vpn_mask));
379 syslog(LOG_DEBUG, "Peer uses protocol version %d",
380 cl->protocol_version);
382 if(cl->status.outgoing)
384 if(setup_vpn_connection(cl) < 0)
390 if(setup_vpn_connection(cl) < 0)
395 cl->status.active = 0;
400 int passphrase_h(conn_list_t *cl)
403 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)
426 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
428 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
433 syslog(LOG_DEBUG, "got PUBLIC_KEY %s", g_n);
435 if(verify_passphrase(cl, g_n))
438 syslog(LOG_ERR, "Intruder: passphrase does not match.");
443 syslog(LOG_INFO, "Passphrase OK");
445 if(cl->status.outgoing)
450 cl->status.active = 1;
451 notify_others(cl, NULL, send_add_host);
457 int ack_h(conn_list_t *cl)
461 syslog(LOG_DEBUG, "got ACK");
463 cl->status.active = 1;
464 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
469 int termreq_h(conn_list_t *cl)
472 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
473 cl->status.termreq = 1;
474 terminate_connection(cl);
476 notify_others(cl, NULL, send_del_host);
481 int timeout_h(conn_list_t *cl)
484 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
485 cl->status.termreq = 1;
486 terminate_connection(cl);
491 int del_host_h(conn_list_t *cl)
496 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
498 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
503 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
506 if(!(fw = lookup_conn(vpn_ip)))
508 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
513 notify_others(cl, fw, send_del_host);
515 fw->status.termreq = 1;
516 terminate_connection(fw);
521 int ping_h(conn_list_t *cl)
525 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
526 cl->status.pinged = 0;
527 cl->status.got_pong = 1;
534 int pong_h(conn_list_t *cl)
538 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
539 cl->status.got_pong = 1;
544 int add_host_h(conn_list_t *cl)
550 conn_list_t *ncn, *fw;
552 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
554 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
559 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
561 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
562 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
565 Suggestion of Hans Bayle
567 if((fw = lookup_conn(vpn_ip)))
569 notify_others(fw, cl, send_add_host);
573 ncn = new_conn_list();
574 ncn->real_ip = real_ip;
575 ncn->vpn_ip = vpn_ip;
576 ncn->vpn_mask = vpn_mask;
578 ncn->hostname = hostlookup(real_ip);
580 ncn->next = conn_list;
582 ncn->status.active = 1;
583 notify_others(ncn, cl, send_add_host);
588 int req_key_h(conn_list_t *cl)
594 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
596 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
601 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
602 IP_ADDR_V(from), IP_ADDR_V(to));
604 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
605 { /* hey! they want something from ME! :) */
606 send_key_answer(cl, from);
610 fw = lookup_conn(to);
614 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
620 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
621 IP_ADDR_V(fw->nexthop->vpn_ip));
623 cl->buffer[cl->reqlen-1] = '\n';
625 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
627 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
634 void set_keys(conn_list_t *cl, int expiry, char *key)
640 cl->public_key = xmalloc(sizeof(*cl->key));
641 cl->public_key->key = NULL;
644 if(cl->public_key->key)
645 free(cl->public_key->key);
646 cl->public_key->length = strlen(key);
647 cl->public_key->expiry = expiry;
648 cl->public_key->key = xmalloc(cl->public_key->length + 1);
649 strcpy(cl->public_key->key, key);
651 ek = make_shared_key(key);
655 cl->key = xmalloc(sizeof(*cl->key));
662 cl->key->length = strlen(ek);
663 cl->key->expiry = expiry;
664 cl->key->key = xmalloc(cl->key->length + 1);
665 strcpy(cl->key->key, ek);
669 int ans_key_h(conn_list_t *cl)
675 conn_list_t *fw, *gk;
677 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
679 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
684 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
685 IP_ADDR_V(from), IP_ADDR_V(to));
687 if(to == myself->vpn_ip)
688 { /* hey! that key's for ME! :) */
690 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
691 gk = lookup_conn(from);
695 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
700 set_keys(gk, expiry, key);
701 gk->status.validkey = 1;
702 gk->status.waitingforkey = 0;
707 fw = lookup_conn(to);
711 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
717 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
718 IP_ADDR_V(fw->nexthop->vpn_ip));
720 cl->buffer[cl->reqlen-1] = '\n';
722 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
724 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
731 int key_changed_h(conn_list_t *cl)
736 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
738 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
743 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
746 ik = lookup_conn(from);
750 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
755 ik->status.validkey = 0;
756 ik->status.waitingforkey = 0;
759 syslog(LOG_DEBUG, "Forwarding key invalidation request");
761 notify_others(cl, ik, send_key_changed);
766 int (*request_handlers[256])(conn_list_t*) = {
767 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
771 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
772 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
773 add_host_h, basic_info_h, passphrase_h, public_key_h, 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,
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 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
782 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, 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