2 protocol.c -- handle the meta-protocol
3 Copyright (C) 1999,2000 Ivo Timmermans <itimmermans@bigfoot.com>,
4 2000 Guus Sliepen <guus@sliepen.warande.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 $Id: protocol.c,v 1.28.4.15 2000/06/29 13:04:15 guus Exp $
25 #include <sys/types.h>
30 #include <sys/socket.h>
45 char buffer[MAXBUFSIZE+1];
48 /* Outgoing request routines */
50 int send_ack(conn_list_t *cl)
54 syslog(LOG_DEBUG, _("Sending ACK to %s (%s)"),
55 cl->vpn_hostname, cl->real_hostname);
57 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", ACK);
59 if((write(cl->meta_socket, buffer, buflen)) < 0)
61 syslog(LOG_ERR, _("Send failed: %d:%d: %m"), __FILE__, __LINE__);
68 int send_termreq(conn_list_t *cl)
72 syslog(LOG_DEBUG, _("Sending TERMREQ to %s (%s)"),
73 cl->vpn_hostname, cl->real_hostname);
75 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", TERMREQ, myself->vpn_ip);
77 if(write(cl->meta_socket, buffer, buflen) < 0)
80 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
87 int send_timeout(conn_list_t *cl)
91 syslog(LOG_DEBUG, _("Sending TIMEOUT to %s (%s)"),
92 cl->vpn_hostname, cl->real_hostname);
94 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", PINGTIMEOUT, myself->vpn_ip);
96 if((write(cl->meta_socket, buffer, buflen)) < 0)
98 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
105 int send_del_host(conn_list_t *cl, conn_list_t *new_host)
109 syslog(LOG_DEBUG, _("Sending DEL_HOST for %s (%s) to %s (%s)"),
110 new_host->vpn_hostname, new_host->real_hostname, cl->vpn_hostname, cl->real_hostname);
112 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", DEL_HOST, new_host->vpn_ip);
114 if((write(cl->meta_socket, buffer, buflen)) < 0)
116 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
123 int send_ping(conn_list_t *cl)
127 syslog(LOG_DEBUG, _("Sending PING to %s (%s)"),
128 cl->vpn_hostname, cl->real_hostname);
130 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PING);
132 if((write(cl->meta_socket, buffer, buflen)) < 0)
134 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
141 int send_pong(conn_list_t *cl)
145 syslog(LOG_DEBUG, _("Sending PONG to %s (%s)"),
146 cl->vpn_hostname, cl->real_hostname);
148 buflen = snprintf(buffer, MAXBUFSIZE, "%d\n", PONG);
150 if((write(cl->meta_socket, buffer, buflen)) < 0)
152 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
159 int send_add_host(conn_list_t *cl, conn_list_t *new_host)
165 real_ip = new_host->real_ip;
166 hostname = new_host->real_hostname;
167 flags = new_host->flags;
169 /* If we need to propagate information about a new host that wants us to export
170 * it's indirectdata flag, we set the INDIRECTDATA flag and unset the EXPORT...
171 * flag, and set it's real_ip to our vpn_ip, so that net.c send_packet() will
175 if(flags & EXPORTINDIRECTDATA)
177 flags &= ~EXPORTINDIRECTDATA;
178 flags |= INDIRECTDATA;
179 real_ip = myself->vpn_ip;
180 hostname = myself->real_hostname;
184 syslog(LOG_DEBUG, _("Sending ADD_HOST for %s (%s) to %s (%s)"),
185 new_host->vpn_hostname, hostname, cl->vpn_hostname, cl->real_hostname);
187 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx/%lx:%x %d\n", ADD_HOST, real_ip, new_host->vpn_ip, new_host->vpn_mask, new_host->port, flags);
189 if((write(cl->meta_socket, buffer, buflen)) < 0)
191 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
198 int send_key_changed(conn_list_t *cl, conn_list_t *src)
202 syslog(LOG_DEBUG, _("Sending KEY_CHANGED origin %s to %s (%s)"),
203 src->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
205 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx\n", KEY_CHANGED, src->vpn_ip);
207 if((write(cl->meta_socket, buffer, buflen)) < 0)
209 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
216 void send_key_changed_all(void)
220 for(p = conn_list; p != NULL; p = p->next)
221 if(p->status.meta && p->status.active)
222 send_key_changed(p, myself);
226 int send_basic_info(conn_list_t *cl)
230 syslog(LOG_DEBUG, _("Sending BASIC_INFO to %s"),
233 buflen = snprintf(buffer, MAXBUFSIZE, "%d %d %lx/%lx:%x %d\n", BASIC_INFO, PROT_CURRENT, myself->vpn_ip, myself->vpn_mask, myself->port, myself->flags);
235 if((write(cl->meta_socket, buffer, buflen)) < 0)
237 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
244 int send_passphrase(conn_list_t *cl)
248 encrypt_passphrase(&tmp);
251 syslog(LOG_DEBUG, _("Sending PASSPHRASE to %s (%s)"),
252 cl->vpn_hostname, cl->real_hostname);
254 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PASSPHRASE, tmp.phrase);
256 if((write(cl->meta_socket, buffer, buflen)) < 0)
258 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
265 int send_public_key(conn_list_t *cl)
269 syslog(LOG_DEBUG, _("Sending PUBLIC_KEY to %s (%s)"),
270 cl->vpn_hostname, cl->real_hostname);
272 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", PUBLIC_KEY, my_public_key_base36);
274 if((write(cl->meta_socket, buffer, buflen)) < 0)
276 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
283 /* WDN doet deze functie? (GS)
284 int send_calculate(conn_list_t *cl, char *k)
287 buflen = snprintf(buffer, MAXBUFSIZE, "%d %s\n", CALCULATE, k);
289 if((write(cl->meta_socket, buffer, buflen)) < 0)
291 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
299 int send_key_request(ip_t to)
303 fw = lookup_conn(to);
306 syslog(LOG_ERR, _("Attempting to send REQ_KEY to %d.%d.%d.%d, which does not exist?"),
312 syslog(LOG_DEBUG, _("Sending REQ_KEY to %s (%s)"),
313 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
315 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx\n", REQ_KEY, to, myself->vpn_ip);
317 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
319 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
322 fw->status.waitingforkey = 1;
327 int send_key_answer(conn_list_t *cl, ip_t to)
332 fw = lookup_conn(to);
336 syslog(LOG_ERR, _("Attempting to send ANS_KEY to %d.%d.%d.%d, which does not exist?"),
342 syslog(LOG_DEBUG, _("Sending ANS_KEY to %s (%s)"),
343 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
345 buflen = snprintf(buffer, MAXBUFSIZE, "%d %lx %lx %d %s\n", ANS_KEY, to, myself->vpn_ip, my_key_expiry, my_public_key_base36);
347 if((write(fw->nexthop->meta_socket, buffer, buflen)) < 0)
349 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
357 notify all my direct connections of a new host
358 that was added to the vpn, with the exception
359 of the source of the announcement.
361 int notify_others(conn_list_t *new, conn_list_t *source,
362 int (*function)(conn_list_t*, conn_list_t*))
366 for(p = conn_list; p != NULL; p = p->next)
367 if(p != new && p != source && p->status.meta && p->status.active)
374 notify one connection of everything
377 int notify_one(conn_list_t *new)
381 for(p = conn_list; p != NULL; p = p->next)
382 if(p != new && p->status.active)
383 send_add_host(new, p);
389 The incoming request handlers
392 int basic_info_h(conn_list_t *cl)
396 syslog(LOG_DEBUG, _("Got BASIC_INFO from %s"), cl->real_hostname);
398 if(sscanf(cl->buffer, "%*d %d %lx/%lx:%hx %d", &cl->protocol_version, &cl->vpn_ip, &cl->vpn_mask, &cl->port, &cl->flags) != 5)
400 syslog(LOG_ERR, _("Got bad BASIC_INFO from %s"),
405 cl->vpn_hostname = hostlookup(htonl(cl->vpn_ip));
407 if(cl->protocol_version != PROT_CURRENT)
409 syslog(LOG_ERR, _("Peer uses incompatible protocol version %d"),
410 cl->protocol_version);
414 if(cl->status.outgoing)
416 if(setup_vpn_connection(cl) < 0)
422 if(setup_vpn_connection(cl) < 0)
430 int passphrase_h(conn_list_t *cl)
433 cl->pp = xmalloc(sizeof(*(cl->pp)));
435 if(sscanf(cl->buffer, "%*d %as", &(cl->pp->phrase)) != 1)
437 syslog(LOG_ERR, _("Got bad PASSPHRASE from %s (%s)"),
438 cl->vpn_hostname, cl->real_hostname);
441 cl->pp->len = strlen(cl->pp->phrase);
444 syslog(LOG_DEBUG, _("Got PASSPHRASE from %s (%s)"),
445 cl->vpn_hostname, cl->real_hostname);
447 if(cl->status.outgoing)
455 int public_key_h(conn_list_t *cl)
460 if(sscanf(cl->buffer, "%*d %as", &g_n) != 1)
462 syslog(LOG_ERR, _("Got bad PUBLIC_KEY from %s (%s)"),
463 cl->vpn_hostname, cl->real_hostname);
468 syslog(LOG_DEBUG, _("Got PUBLIC_KEY from %s (%s)"),
469 cl->vpn_hostname, cl->real_hostname);
471 if(verify_passphrase(cl, g_n))
474 syslog(LOG_ERR, _("Intruder: passphrase does not match!"));
478 if(cl->status.outgoing)
484 /* Okay, before we active the connection, we check if there is another entry
485 in the connection list with the same vpn_ip. If so, it presumably is an
486 old connection that has timed out but we don't know it yet. Because our
487 conn_list entry is not active, lookup_conn will skip ourself. */
489 while(old = lookup_conn(cl->vpn_ip))
490 terminate_connection(old);
492 cl->status.active = 1;
495 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
496 cl->vpn_hostname, cl->real_hostname);
498 notify_others(cl, NULL, send_add_host);
505 int ack_h(conn_list_t *cl)
509 syslog(LOG_DEBUG, _("Got ACK from %s (%s)"),
510 cl->vpn_hostname, cl->real_hostname);
512 cl->status.active = 1;
514 syslog(LOG_NOTICE, _("Connection with %s (%s) activated"),
515 cl->vpn_hostname, cl->real_hostname);
517 notify_others(cl, NULL, send_add_host);
525 int termreq_h(conn_list_t *cl)
528 if(!cl->status.active)
530 syslog(LOG_ERR, _("Got unauthorized TERMREQ from %s (%s)"),
531 cl->vpn_hostname, cl->real_hostname);
536 syslog(LOG_DEBUG, _("Got TERMREQ from %s (%s)"),
537 cl->vpn_hostname, cl->real_hostname);
539 cl->status.termreq = 1;
541 if(cl->status.active)
542 notify_others(cl, NULL, send_del_host);
544 cl->status.active = 0;
546 terminate_connection(cl);
551 int timeout_h(conn_list_t *cl)
554 if(!cl->status.active)
556 syslog(LOG_ERR, _("Got unauthorized TIMEOUT from %s (%s)"),
557 cl->vpn_hostname, cl->real_hostname);
562 syslog(LOG_DEBUG, _("Got TIMEOUT from %s (%s)"),
563 cl->vpn_hostname, cl->real_hostname);
565 cl->status.termreq = 1;
566 terminate_connection(cl);
571 int del_host_h(conn_list_t *cl)
576 if(!cl->status.active)
578 syslog(LOG_ERR, _("Got unauthorized DEL_HOST from %s (%s)"),
579 cl->vpn_hostname, cl->real_hostname);
583 if(sscanf(cl->buffer, "%*d %lx", &vpn_ip) != 1)
585 syslog(LOG_ERR, _("Got bad DEL_HOST from %s (%s)"),
586 cl->vpn_hostname, cl->real_hostname);
590 if(!(fw = lookup_conn(vpn_ip)))
592 syslog(LOG_ERR, _("Got DEL_HOST for %d.%d.%d.%d from %s (%s) which does not exist?"),
593 IP_ADDR_V(vpn_ip), cl->vpn_hostname, cl->real_hostname);
598 syslog(LOG_DEBUG, _("Got DEL_HOST for %s (%s) from %s (%s)"),
599 fw->vpn_hostname, fw->real_hostname, cl->vpn_hostname, cl->real_hostname);
601 notify_others(fw, cl, send_del_host);
603 fw->status.termreq = 1;
604 fw->status.active = 0;
606 terminate_connection(fw);
611 int ping_h(conn_list_t *cl)
614 if(!cl->status.active)
616 syslog(LOG_ERR, _("Got unauthorized PING from %s (%s)"),
617 cl->vpn_hostname, cl->real_hostname);
622 syslog(LOG_DEBUG, _("Got PING from %s (%s)"),
623 cl->vpn_hostname, cl->real_hostname);
625 cl->status.pinged = 0;
626 cl->status.got_pong = 1;
633 int pong_h(conn_list_t *cl)
636 if(!cl->status.active)
638 syslog(LOG_ERR, _("Got unauthorized PONG from %s (%s)"),
639 cl->vpn_hostname, cl->real_hostname);
644 syslog(LOG_DEBUG, _("Got PONG from %s (%s)"),
645 cl->vpn_hostname, cl->real_hostname);
647 cl->status.got_pong = 1;
652 int add_host_h(conn_list_t *cl)
659 conn_list_t *ncn, *old;
661 if(!cl->status.active)
663 syslog(LOG_ERR, _("Got unauthorized ADD_HOST from %s (%s)"),
664 cl->vpn_hostname, cl->real_hostname);
668 if(sscanf(cl->buffer, "%*d %lx %lx/%lx:%hx %d", &real_ip, &vpn_ip, &vpn_mask, &port, &flags) != 5)
670 syslog(LOG_ERR, _("Got bad ADD_HOST from %s (%s)"),
671 cl->vpn_hostname, cl->real_hostname);
675 while(old = lookup_conn(vpn_ip))
676 terminate_connection(old);
678 ncn = new_conn_list();
679 ncn->real_ip = real_ip;
680 ncn->real_hostname = hostlookup(htonl(real_ip));
681 ncn->vpn_ip = vpn_ip;
682 ncn->vpn_mask = vpn_mask;
683 ncn->vpn_hostname = hostlookup(htonl(vpn_ip));
687 ncn->next = conn_list;
689 ncn->status.active = 1;
692 syslog(LOG_DEBUG, _("Got ADD_HOST for %s (%s) from %s (%s)"),
693 ncn->vpn_hostname, ncn->real_hostname, cl->vpn_hostname, cl->real_hostname);
695 notify_others(ncn, cl, send_add_host);
700 int req_key_h(conn_list_t *cl)
706 if(!cl->status.active)
708 syslog(LOG_ERR, _("Got unauthorized REQ_KEY from %s (%s)"),
709 cl->vpn_hostname, cl->real_hostname);
713 if(sscanf(cl->buffer, "%*d %lx %lx", &to, &from) != 2)
715 syslog(LOG_ERR, _("Got bad REQ_KEY from %s (%s)"),
716 cl->vpn_hostname, cl->real_hostname);
721 syslog(LOG_DEBUG, _("Got REQ_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
722 IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
724 if((to & myself->vpn_mask) == (myself->vpn_ip & myself->vpn_mask))
725 { /* hey! they want something from ME! :) */
726 send_key_answer(cl, from);
730 fw = lookup_conn(to);
734 syslog(LOG_ERR, _("Attempting to forward REQ_KEY to %d.%d.%d.%d, which does not exist?"),
740 syslog(LOG_DEBUG, _("Forwarding REQ_KEY to %s (%s)"),
741 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
743 cl->buffer[cl->reqlen-1] = '\n';
745 if(write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen) < 0)
747 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
754 void set_keys(conn_list_t *cl, int expiry, char *key)
760 cl->public_key = xmalloc(sizeof(*cl->key));
761 cl->public_key->key = NULL;
764 if(cl->public_key->key)
765 free(cl->public_key->key);
766 cl->public_key->length = strlen(key);
767 cl->public_key->expiry = expiry;
768 cl->public_key->key = xmalloc(cl->public_key->length + 1);
769 strcpy(cl->public_key->key, key);
771 ek = make_shared_key(key);
775 cl->key = xmalloc(sizeof(*cl->key));
782 cl->key->length = strlen(ek);
783 cl->key->expiry = expiry;
784 cl->key->key = xmalloc(cl->key->length + 1);
785 strcpy(cl->key->key, ek);
789 int ans_key_h(conn_list_t *cl)
795 conn_list_t *fw, *gk;
797 if(!cl->status.active)
799 syslog(LOG_ERR, _("Got unauthorized ANS_KEY from %s (%s)"),
800 cl->vpn_hostname, cl->real_hostname);
804 if(sscanf(cl->buffer, "%*d %lx %lx %d %as", &to, &from, &expiry, &key) != 4)
806 syslog(LOG_ERR, _("Got bad ANS_KEY from %s (%s)"),
807 cl->vpn_hostname, cl->real_hostname);
812 syslog(LOG_DEBUG, _("Got ANS_KEY origin %d.%d.%d.%d destination %d.%d.%d.%d from %s (%s)"),
813 IP_ADDR_V(from), IP_ADDR_V(to), cl->vpn_hostname, cl->real_hostname);
815 if(to == myself->vpn_ip)
816 { /* hey! that key's for ME! :) */
817 gk = lookup_conn(from);
821 syslog(LOG_ERR, _("Receiving ANS_KEY origin %d.%d.%d.%d from %s (%s), which does not exist?"),
822 IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
826 set_keys(gk, expiry, key);
827 gk->status.validkey = 1;
828 gk->status.waitingforkey = 0;
833 fw = lookup_conn(to);
837 syslog(LOG_ERR, _("Attempting to forward ANS_KEY to %d.%d.%d.%d, which does not exist?"),
843 syslog(LOG_DEBUG, _("Forwarding ANS_KEY to %s (%s)"),
844 fw->nexthop->vpn_hostname, fw->nexthop->real_hostname);
846 cl->buffer[cl->reqlen-1] = '\n';
848 if((write(fw->nexthop->meta_socket, cl->buffer, cl->reqlen)) < 0)
850 syslog(LOG_ERR, _("Send failed: %s:%d: %m"), __FILE__, __LINE__);
857 int key_changed_h(conn_list_t *cl)
862 if(!cl->status.active)
864 syslog(LOG_ERR, _("Got unauthorized KEY_CHANGED from %s (%s)"),
865 cl->vpn_hostname, cl->real_hostname);
869 if(sscanf(cl->buffer, "%*d %lx", &from) != 1)
871 syslog(LOG_ERR, _("Got bad KEY_CHANGED from %s (%s)"),
872 cl->vpn_hostname, cl->real_hostname);
876 ik = lookup_conn(from);
880 syslog(LOG_ERR, _("Got KEY_CHANGED origin %d.%d.%d.%d from %s (%s), which does not exist?"),
881 IP_ADDR_V(from), cl->vpn_hostname, cl->real_hostname);
886 syslog(LOG_DEBUG, _("Got KEY_CHANGED origin %s from %s (%s)"),
887 ik->vpn_hostname, cl->vpn_hostname, cl->real_hostname);
889 ik->status.validkey = 0;
890 ik->status.waitingforkey = 0;
892 notify_others(ik, cl, send_key_changed);
897 int (*request_handlers[256])(conn_list_t*) = {
898 0, ack_h, 0, 0, 0, 0, 0, 0, 0, 0,
899 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
900 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
901 termreq_h, timeout_h, del_host_h, 0, 0, 0, 0, 0, 0, 0,
902 ping_h, pong_h, 0, 0, 0, 0, 0, 0, 0, 0,
903 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
904 add_host_h, basic_info_h, passphrase_h, public_key_h, 0, 0, 0, 0, 0, 0,
905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
906 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
908 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
909 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
910 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
911 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
912 req_key_h, ans_key_h, key_changed_h, 0, 0, 0, 0, 0, 0, 0,
913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
916 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0