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];
41 int send_ack(conn_list_t *cl)
45 syslog(LOG_DEBUG, "Send ACK to %s", cl->hostname);
47 buflen = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 to " IP_ADDR_S,
217 IP_ADDR_V(cl->vpn_ip));
219 buflen = sprintf(buffer, "%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 to " IP_ADDR_S,
235 IP_ADDR_V(cl->vpn_ip));
237 buflen = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 = sprintf(buffer, "%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 if(sscanf(cl->buffer, "%*d %s", cl->pp) != 1)
401 syslog(LOG_ERR, "got bad PASSPHRASE request: %s", cl->buffer);
406 syslog(LOG_DEBUG, "got PASSPHRASE");
408 if(cl->status.outgoing)
416 int public_key_h(conn_list_t *cl)
420 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
422 syslog(LOG_ERR, "got bad PUBLIC_KEY request: %s", cl->buffer);
427 syslog(LOG_DEBUG, "got PUBLIC_KEY");
429 if(verify_passphrase(cl, g_n))
432 syslog(LOG_ERR, "Intruder: passphrase does not match.");
437 syslog(LOG_INFO, "Passphrase OK");
439 if(cl->status.outgoing)
444 cl->status.active = 1;
445 notify_others(cl, NULL, send_add_host);
451 int ack_h(conn_list_t *cl)
455 syslog(LOG_DEBUG, "got ACK");
457 cl->status.active = 1;
458 syslog(LOG_NOTICE, "Connection with %s activated.", cl->hostname);
463 int termreq_h(conn_list_t *cl)
466 syslog(LOG_NOTICE, IP_ADDR_S " wants to quit", IP_ADDR_V(cl->vpn_ip));
467 cl->status.termreq = 1;
468 terminate_connection(cl);
470 notify_others(cl, NULL, send_del_host);
475 int timeout_h(conn_list_t *cl)
478 syslog(LOG_NOTICE, IP_ADDR_S " says it's gotten a timeout from us", IP_ADDR_V(cl->vpn_ip));
479 cl->status.termreq = 1;
480 terminate_connection(cl);
485 int del_host_h(conn_list_t *cl)
490 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
492 syslog(LOG_ERR, "got bad DEL_HOST request: %s", cl->buffer);
497 syslog(LOG_DEBUG, "got DEL_HOST for " IP_ADDR_S,
500 if(!(fw = lookup_conn(vpn_ip)))
502 syslog(LOG_ERR, "Somebody wanted to delete " IP_ADDR_S " which does not exist?",
507 notify_others(cl, fw, send_del_host);
509 fw->status.termreq = 1;
510 terminate_connection(fw);
515 int ping_h(conn_list_t *cl)
519 syslog(LOG_DEBUG, "responding to ping from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
520 cl->status.pinged = 0;
521 cl->status.got_pong = 1;
528 int pong_h(conn_list_t *cl)
532 syslog(LOG_DEBUG, "ok, got pong from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
533 cl->status.got_pong = 1;
538 int add_host_h(conn_list_t *cl)
544 conn_list_t *ncn, *fw;
546 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx", &real_ip, &vpn_ip, &vpn_mask, &port) != 4)
548 syslog(LOG_ERR, "got bad ADD_HOST request: %s", cl->buffer);
553 syslog(LOG_DEBUG, "Add host request from " IP_ADDR_S, IP_ADDR_V(cl->vpn_ip));
555 syslog(LOG_DEBUG, "got ADD_HOST(" IP_ADDR_S "," IP_ADDR_S ",%hd)",
556 IP_ADDR_V(vpn_ip), IP_ADDR_V(vpn_mask), port);
559 Suggestion of Hans Bayle
561 if((fw = lookup_conn(vpn_ip)))
563 notify_others(fw, cl, send_add_host);
567 ncn = new_conn_list();
568 ncn->real_ip = real_ip;
569 ncn->vpn_ip = vpn_ip;
570 ncn->vpn_mask = vpn_mask;
572 ncn->hostname = hostlookup(real_ip);
574 ncn->next = conn_list;
576 ncn->status.active = 1;
577 notify_others(ncn, cl, send_add_host);
582 int req_key_h(conn_list_t *cl)
588 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
590 syslog(LOG_ERR, "got bad request: %s", cl->buffer);
595 syslog(LOG_DEBUG, "got REQ_KEY from " IP_ADDR_S " for " IP_ADDR_S,
596 IP_ADDR_V(from), IP_ADDR_V(to));
598 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
599 { /* hey! they want something from ME! :) */
600 send_key_answer(cl, from);
604 fw = lookup_conn(to);
608 syslog(LOG_ERR, "Attempting to forward key request to " IP_ADDR_S ", which does not exist?",
614 syslog(LOG_DEBUG, "Forwarding request for public key to " IP_ADDR_S,
615 IP_ADDR_V(fw->nexthop->vpn_ip));
617 if(write(fw->nexthop->meta_socket, cl->buffer, strlen(cl->buffer)) < 0)
619 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
626 void set_keys(conn_list_t *cl, int expiry, char *key)
632 cl->public_key = xmalloc(sizeof(*cl->key));
633 cl->public_key->key = NULL;
636 if(cl->public_key->key)
637 free(cl->public_key->key);
638 cl->public_key->length = strlen(key);
639 cl->public_key->expiry = expiry;
640 cl->public_key->key = xmalloc(cl->public_key->length + 1);
641 strcpy(cl->public_key->key, key);
643 ek = make_shared_key(key);
647 cl->key = xmalloc(sizeof(*cl->key));
654 cl->key->length = strlen(ek);
655 cl->key->expiry = expiry;
656 cl->key->key = xmalloc(cl->key->length + 1);
657 strcpy(cl->key->key, ek);
661 int ans_key_h(conn_list_t *cl)
667 conn_list_t *fw, *gk;
669 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
671 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
676 syslog(LOG_DEBUG, "got ANS_KEY from " IP_ADDR_S " for " IP_ADDR_S,
677 IP_ADDR_V(from), IP_ADDR_V(to));
679 if(to == myself->vpn_ip)
680 { /* hey! that key's for ME! :) */
682 syslog(LOG_DEBUG, "Yeah! key arrived. Now do something with it.");
683 gk = lookup_conn(from);
687 syslog(LOG_ERR, "Receiving key from " IP_ADDR_S ", which does not exist?",
692 set_keys(gk, expiry, key);
693 gk->status.validkey = 1;
694 gk->status.waitingforkey = 0;
699 fw = lookup_conn(to);
703 syslog(LOG_ERR, "Attempting to forward key to " IP_ADDR_S ", which does not exist?",
709 syslog(LOG_DEBUG, "Forwarding public key to " IP_ADDR_S,
710 IP_ADDR_V(fw->nexthop->vpn_ip));
712 if((write(fw->nexthop->meta_socket, cl->buffer, strlen(cl->buffer))) < 0)
714 syslog(LOG_ERR, "send failed: %s:%d: %m", __FILE__, __LINE__);
721 int key_changed_h(conn_list_t *cl)
726 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
728 syslog(LOG_ERR, "got bad ANS_KEY request: %s", cl->buffer);
733 syslog(LOG_DEBUG, "got KEY_CHANGED from " IP_ADDR_S,
736 ik = lookup_conn(from);
740 syslog(LOG_ERR, "Got changed key from " IP_ADDR_S ", which does not exist?",
745 ik->status.validkey = 0;
746 ik->status.waitingforkey = 0;
749 syslog(LOG_DEBUG, "Forwarding key invalidation request");
751 notify_others(cl, ik, send_key_changed);
756 int (*request_handlers[256])(conn_list_t*) = {
757 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
758 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
759 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
760 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
761 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
762 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
763 add_host_h, basic_info_h, passphrase_h, public_key_h, 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 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
767 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
771 req_key_h, ans_key_h, key_changed_h, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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