ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/connection.C
(Generate patch)

Comparing gvpe/src/connection.C (file contents):
Revision 1.31 by pcg, Sun Feb 8 07:24:25 2004 UTC vs.
Revision 1.69 by pcg, Thu Aug 7 17:54:26 2008 UTC

1/* 1/*
2 connection.C -- manage a single connection 2 connection.C -- manage a single connection
3 Copyright (C) 2003-2004 Marc Lehmann <pcg@goof.com> 3 Copyright (C) 2003-2008 Marc Lehmann <gvpe@schmorp.de>
4 4
5 This file is part of GVPE.
6
5 This program is free software; you can redistribute it and/or modify 7 GVPE is free software; you can redistribute it and/or modify it
6 it under the terms of the GNU General Public License as published by 8 under the terms of the GNU General Public License as published by the
7 the Free Software Foundation; either version 2 of the License, or 9 Free Software Foundation; either version 3 of the License, or (at your
8 (at your option) any later version. 10 option) any later version.
9 11
10 This program is distributed in the hope that it will be useful, 12 This program is distributed in the hope that it will be useful, but
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 GNU General Public License for more details. 15 Public License for more details.
14 16
15 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License along
16 along with this program; if not, write to the Free Software 18 with this program; if not, see <http://www.gnu.org/licenses/>.
17 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19
20 Additional permission under GNU GPL version 3 section 7
21
22 If you modify this Program, or any covered work, by linking or
23 combining it with the OpenSSL project's OpenSSL library (or a modified
24 version of that library), containing parts covered by the terms of the
25 OpenSSL or SSLeay licenses, the licensors of this Program grant you
26 additional permission to convey the resulting work. Corresponding
27 Source for a non-source form of such a combination shall include the
28 source code for the parts of OpenSSL used as well as that of the
29 covered work.
18*/ 30*/
19 31
20#include "config.h" 32#include "config.h"
21
22#include <cassert>
23 33
24#include <list> 34#include <list>
25 35
26#include <openssl/rand.h> 36#include <openssl/rand.h>
27#include <openssl/evp.h> 37#include <openssl/evp.h>
28#include <openssl/rsa.h> 38#include <openssl/rsa.h>
29#include <openssl/err.h> 39#include <openssl/err.h>
30
31#include "gettext.h"
32 40
33#include "conf.h" 41#include "conf.h"
34#include "slog.h" 42#include "slog.h"
35#include "device.h" 43#include "device.h"
36#include "vpn.h" 44#include "vpn.h"
84 require (EVP_DigestUpdate(&ctx, &id, sizeof id)); 92 require (EVP_DigestUpdate(&ctx, &id, sizeof id));
85 require (EVP_DigestFinal (&ctx, (unsigned char *)&h, 0)); 93 require (EVP_DigestFinal (&ctx, (unsigned char *)&h, 0));
86 EVP_MD_CTX_cleanup (&ctx); 94 EVP_MD_CTX_cleanup (&ctx);
87} 95}
88 96
89struct rsa_entry { 97struct rsa_entry
98{
90 tstamp expire; 99 tstamp expire;
91 rsaid id; 100 rsaid id;
92 rsachallenge chg; 101 rsachallenge chg;
93}; 102};
94 103
95struct rsa_cache : list<rsa_entry> 104struct rsa_cache : list<rsa_entry>
96{ 105{
97 void cleaner_cb (time_watcher &w); time_watcher cleaner; 106 inline void cleaner_cb (ev::timer &w, int revents); ev::timer cleaner;
98 107
99 bool find (const rsaid &id, rsachallenge &chg) 108 bool find (const rsaid &id, rsachallenge &chg)
100 { 109 {
101 for (iterator i = begin (); i != end (); ++i) 110 for (iterator i = begin (); i != end (); ++i)
102 { 111 {
103 if (!memcmp (&id, &i->id, sizeof id) && i->expire > NOW) 112 if (!memcmp (&id, &i->id, sizeof id) && i->expire > ev_now ())
104 { 113 {
105 memcpy (&chg, &i->chg, sizeof chg); 114 memcpy (&chg, &i->chg, sizeof chg);
106 115
107 erase (i); 116 erase (i);
108 return true; 117 return true;
109 } 118 }
110 } 119 }
111 120
112 if (cleaner.at < NOW) 121 if (!cleaner.is_active ())
113 cleaner.start (NOW + RSA_TTL); 122 cleaner.again ();
114 123
115 return false; 124 return false;
116 } 125 }
117 126
118 void gen (rsaid &id, rsachallenge &chg) 127 void gen (rsaid &id, rsachallenge &chg)
119 { 128 {
120 rsa_entry e; 129 rsa_entry e;
121 130
122 RAND_bytes ((unsigned char *)&id, sizeof id); 131 RAND_bytes ((unsigned char *)&id, sizeof id);
123 RAND_bytes ((unsigned char *)&chg, sizeof chg); 132 RAND_bytes ((unsigned char *)&chg, sizeof chg);
124 133
125 e.expire = NOW + RSA_TTL; 134 e.expire = ev_now () + RSA_TTL;
126 e.id = id; 135 e.id = id;
127 memcpy (&e.chg, &chg, sizeof chg); 136 memcpy (&e.chg, &chg, sizeof chg);
128 137
129 push_back (e); 138 push_back (e);
130 139
131 if (cleaner.at < NOW) 140 if (!cleaner.is_active ())
132 cleaner.start (NOW + RSA_TTL); 141 cleaner.again ();
133 } 142 }
134 143
135 rsa_cache () 144 rsa_cache ()
136 : cleaner (this, &rsa_cache::cleaner_cb) 145 {
137 { } 146 cleaner.set<rsa_cache, &rsa_cache::cleaner_cb> (this);
147 cleaner.set (RSA_TTL, RSA_TTL);
148 }
138 149
139} rsa_cache; 150} rsa_cache;
140 151
141void rsa_cache::cleaner_cb (time_watcher &w) 152void rsa_cache::cleaner_cb (ev::timer &w, int revents)
142{ 153{
143 if (!empty ()) 154 if (empty ())
155 w.stop ();
156 else
144 { 157 {
145 w.start (NOW + RSA_TTL);
146
147 for (iterator i = begin (); i != end (); ) 158 for (iterator i = begin (); i != end (); )
148 if (i->expire <= NOW) 159 if (i->expire <= ev_now ())
149 i = erase (i); 160 i = erase (i);
150 else 161 else
151 ++i; 162 ++i;
152 } 163 }
153} 164}
154 165
155////////////////////////////////////////////////////////////////////////////// 166//////////////////////////////////////////////////////////////////////////////
156 167
157void pkt_queue::put (net_packet *p) 168pkt_queue::pkt_queue (double max_ttl, int max_queue)
169: max_ttl (max_ttl), max_queue (max_queue)
158{ 170{
159 if (queue[i]) 171 queue = new pkt [max_queue];
160 {
161 delete queue[i];
162 j = (j + 1) % QUEUEDEPTH;
163 }
164 172
165 queue[i] = p;
166
167 i = (i + 1) % QUEUEDEPTH;
168}
169
170net_packet *pkt_queue::get ()
171{
172 net_packet *p = queue[j];
173
174 if (p)
175 {
176 queue[j] = 0;
177 j = (j + 1) % QUEUEDEPTH;
178 }
179
180 return p;
181}
182
183pkt_queue::pkt_queue ()
184{
185 memset (queue, 0, sizeof (queue));
186 i = 0; 173 i = 0;
187 j = 0; 174 j = 0;
175
176 expire.set<pkt_queue, &pkt_queue::expire_cb> (this);
188} 177}
189 178
190pkt_queue::~pkt_queue () 179pkt_queue::~pkt_queue ()
191{ 180{
192 for (i = QUEUEDEPTH; --i > 0; ) 181 while (net_packet *p = get ())
182 delete p;
183
193 delete queue[i]; 184 delete [] queue;
194} 185}
195 186
187void pkt_queue::expire_cb (ev::timer &w, int revents)
188{
189 ev_tstamp expire = ev_now () - max_ttl;
190
191 for (;;)
192 {
193 if (empty ())
194 break;
195
196 double diff = queue[j].tstamp - expire;
197
198 if (diff >= 0.)
199 {
200 w.start (diff > 0.5 ? diff : 0.5);
201 break;
202 }
203
204 delete get ();
205 }
206}
207
208void pkt_queue::put (net_packet *p)
209{
210 ev_tstamp now = ev_now ();
211
212 // start expiry timer
213 if (empty ())
214 expire.start (max_ttl);
215
216 int ni = i + 1 == max_queue ? 0 : i + 1;
217
218 if (ni == j)
219 delete get ();
220
221 queue[i].pkt = p;
222 queue[i].tstamp = now;
223
224 i = ni;
225}
226
227net_packet *pkt_queue::get ()
228{
229 if (empty ())
230 return 0;
231
232 net_packet *p = queue[j].pkt;
233 queue[j].pkt = 0;
234
235 j = j + 1 == max_queue ? 0 : j + 1;
236
237 return p;
238}
239
196struct net_rateinfo { 240struct net_rateinfo
241{
197 u32 host; 242 u32 host;
198 double pcnt, diff; 243 double pcnt, diff;
199 tstamp last; 244 tstamp last;
200}; 245};
201 246
202// only do action once every x seconds per host whole allowing bursts. 247// only do action once every x seconds per host whole allowing bursts.
203// this implementation ("splay list" ;) is inefficient, 248// this implementation ("splay list" ;) is inefficient,
204// but low on resources. 249// but low on resources.
205struct net_rate_limiter : list<net_rateinfo> 250struct net_rate_limiter : list<net_rateinfo>
206{ 251{
207 static const double ALPHA = 1. - 1. / 600.; // allow bursts 252# define NRL_ALPHA (1. - 1. / 600.) // allow bursts
208 static const double CUTOFF = 10.; // one event every CUTOFF seconds 253# define NRL_CUTOFF 10. // one event every CUTOFF seconds
209 static const double EXPIRE = CUTOFF * 30.; // expire entries after this time 254# define NRL_EXPIRE (NRL_CUTOFF * 30.) // expire entries after this time
210 static const double MAXDIF = CUTOFF * (1. / (1. - ALPHA)); // maximum diff /count value 255# define NRL_MAXDIF (NRL_CUTOFF * (1. / (1. - NRL_ALPHA))) // maximum diff /count value
211 256
212 bool can (const sockinfo &si) { return can((u32)si.host); } 257 bool can (const sockinfo &si) { return can((u32)si.host); }
213 bool can (u32 host); 258 bool can (u32 host);
214}; 259};
215 260
220 iterator i; 265 iterator i;
221 266
222 for (i = begin (); i != end (); ) 267 for (i = begin (); i != end (); )
223 if (i->host == host) 268 if (i->host == host)
224 break; 269 break;
225 else if (i->last < NOW - EXPIRE) 270 else if (i->last < ev_now () - NRL_EXPIRE)
226 i = erase (i); 271 i = erase (i);
227 else 272 else
228 i++; 273 i++;
229 274
230 if (i == end ()) 275 if (i == end ())
231 { 276 {
232 net_rateinfo ri; 277 net_rateinfo ri;
233 278
234 ri.host = host; 279 ri.host = host;
235 ri.pcnt = 1.; 280 ri.pcnt = 1.;
236 ri.diff = MAXDIF; 281 ri.diff = NRL_MAXDIF;
237 ri.last = NOW; 282 ri.last = ev_now ();
238 283
239 push_front (ri); 284 push_front (ri);
240 285
241 return true; 286 return true;
242 } 287 }
243 else 288 else
244 { 289 {
245 net_rateinfo ri (*i); 290 net_rateinfo ri (*i);
246 erase (i); 291 erase (i);
247 292
248 ri.pcnt = ri.pcnt * ALPHA; 293 ri.pcnt = ri.pcnt * NRL_ALPHA;
249 ri.diff = ri.diff * ALPHA + (NOW - ri.last); 294 ri.diff = ri.diff * NRL_ALPHA + (ev_now () - ri.last);
250 295
251 ri.last = NOW; 296 ri.last = ev_now ();
252 297
253 double dif = ri.diff / ri.pcnt; 298 double dif = ri.diff / ri.pcnt;
254 299
255 bool send = dif > CUTOFF; 300 bool send = dif > NRL_CUTOFF;
256 301
257 if (dif > MAXDIF) 302 if (dif > NRL_MAXDIF)
258 { 303 {
259 ri.pcnt = 1.; 304 ri.pcnt = 1.;
260 ri.diff = MAXDIF; 305 ri.diff = NRL_MAXDIF;
261 } 306 }
262 else if (send) 307 else if (send)
263 ri.pcnt++; 308 ri.pcnt++;
264 309
265 push_front (ri); 310 push_front (ri);
456 u8 flags, challengelen, features, pad3; 501 u8 flags, challengelen, features, pad3;
457 u32 cipher_nid, digest_nid, hmac_nid; 502 u32 cipher_nid, digest_nid, hmac_nid;
458 503
459 void setup (ptype type, int dst); 504 void setup (ptype type, int dst);
460 bool chk_config () const; 505 bool chk_config () const;
506
507 static u8 get_features ()
508 {
509 u8 f = 0;
510#if ENABLE_COMPRESSION
511 f |= FEATURE_COMPRESSION;
512#endif
513#if ENABLE_ROHC
514 f |= FEATURE_ROHC;
515#endif
516#if ENABLE_BRIDGING
517 f |= FEATURE_BRIDGING;
518#endif
519 return f;
520 }
461}; 521};
462
463#define FEATURES ((ENABLE_COMPRESSION ? FEATURE_COMPRESSION : 0) \
464 | (ENABLE_ROHC ? FEATURE_ROHC : 0))
465 522
466void config_packet::setup (ptype type, int dst) 523void config_packet::setup (ptype type, int dst)
467{ 524{
468 prot_major = PROTOCOL_MAJOR; 525 prot_major = PROTOCOL_MAJOR;
469 prot_minor = PROTOCOL_MINOR; 526 prot_minor = PROTOCOL_MINOR;
470 randsize = RAND_SIZE; 527 randsize = RAND_SIZE;
471 hmaclen = HMACLENGTH; 528 hmaclen = HMACLENGTH;
472 flags = ENABLE_COMPRESSION ? 0x81 : 0x80; 529 flags = 0;
473 challengelen = sizeof (rsachallenge); 530 challengelen = sizeof (rsachallenge);
474 features = FEATURES; 531 features = get_features ();
475 532
476 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER)); 533 cipher_nid = htonl (EVP_CIPHER_nid (CIPHER));
477 digest_nid = htonl (EVP_MD_type (RSA_HASH)); 534 digest_nid = htonl (EVP_MD_type (RSA_HASH));
478 hmac_nid = htonl (EVP_MD_type (DIGEST)); 535 hmac_nid = htonl (EVP_MD_type (DIGEST));
479 536
487 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR); 544 slog (L_WARN, _("major version mismatch (remote %d <=> local %d)"), prot_major, PROTOCOL_MAJOR);
488 else if (randsize != RAND_SIZE) 545 else if (randsize != RAND_SIZE)
489 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE); 546 slog (L_WARN, _("rand size mismatch (remote %d <=> local %d)"), randsize, RAND_SIZE);
490 else if (hmaclen != HMACLENGTH) 547 else if (hmaclen != HMACLENGTH)
491 slog (L_WARN, _("hmac length mismatch (remote %d <=> local %d)"), hmaclen, HMACLENGTH); 548 slog (L_WARN, _("hmac length mismatch (remote %d <=> local %d)"), hmaclen, HMACLENGTH);
492#if 0 // this implementation should handle all flag settings
493 else if (flags != curflags ())
494 slog (L_WARN, _("flag mismatch (remote %x <=> local %x)"), flags, curflags ());
495#endif
496 else if (challengelen != sizeof (rsachallenge)) 549 else if (challengelen != sizeof (rsachallenge))
497 slog (L_WARN, _("challenge length mismatch (remote %d <=> local %d)"), challengelen, sizeof (rsachallenge)); 550 slog (L_WARN, _("challenge length mismatch (remote %d <=> local %d)"), challengelen, sizeof (rsachallenge));
498 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER))) 551 else if (cipher_nid != htonl (EVP_CIPHER_nid (CIPHER)))
499 slog (L_WARN, _("cipher mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER)); 552 slog (L_WARN, _("cipher mismatch (remote %x <=> local %x)"), ntohl (cipher_nid), EVP_CIPHER_nid (CIPHER));
500 else if (digest_nid != htonl (EVP_MD_type (RSA_HASH))) 553 else if (digest_nid != htonl (EVP_MD_type (RSA_HASH)))
576///////////////////////////////////////////////////////////////////////////// 629/////////////////////////////////////////////////////////////////////////////
577 630
578void 631void
579connection::connection_established () 632connection::connection_established ()
580{ 633{
634 slog (L_TRACE, _("%s: possible connection establish (ictx %d, octx %d)"), conf->nodename, !!ictx, !!octx);
635
581 if (ictx && octx) 636 if (ictx && octx)
582 { 637 {
583 connectmode = conf->connectmode; 638 // make sure rekeying timeouts are slightly asymmetric
584 639 ev::tstamp rekey_interval = ::conf.rekey + (conf->id > THISNODE->id ? 10 : 0);
585 rekey.start (NOW + ::conf.rekey); 640 rekey.start (rekey_interval, rekey_interval);
586 keepalive.start (NOW + ::conf.keepalive); 641 keepalive.start (::conf.keepalive);
587 642
588 // send queued packets 643 // send queued packets
589 if (ictx && octx) 644 if (ictx && octx)
590 { 645 {
591 while (tap_packet *p = (tap_packet *)data_queue.get ()) 646 while (tap_packet *p = (tap_packet *)data_queue.get ())
592 { 647 {
593 send_data_packet (p); 648 if (p->len) send_data_packet (p);
594 delete p; 649 delete p;
595 } 650 }
596 651
597 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ()) 652 while (vpn_packet *p = (vpn_packet *)vpn_queue.get ())
598 { 653 {
599 send_vpn_packet (p, si, IPTOS_RELIABILITY); 654 if (p->len) send_vpn_packet (p, si, IPTOS_RELIABILITY);
600 delete p; 655 delete p;
601 } 656 }
602 } 657 }
603 } 658 }
604 else 659 else
605 { 660 {
606 retry_cnt = 0; 661 retry_cnt = 0;
607 establish_connection.start (NOW + 5); 662 establish_connection.start (5);
608 keepalive.stop (); 663 keepalive.stop ();
609 rekey.stop (); 664 rekey.stop ();
610 } 665 }
611} 666}
612 667
616 protocol = best_protocol (THISNODE->protocols & conf->protocols); 671 protocol = best_protocol (THISNODE->protocols & conf->protocols);
617 672
618 // mask out protocols we cannot establish 673 // mask out protocols we cannot establish
619 if (!conf->udp_port) protocol &= ~PROT_UDPv4; 674 if (!conf->udp_port) protocol &= ~PROT_UDPv4;
620 if (!conf->tcp_port) protocol &= ~PROT_TCPv4; 675 if (!conf->tcp_port) protocol &= ~PROT_TCPv4;
676 if (!conf->dns_port) protocol &= ~PROT_DNSv4;
677
678 if (protocol
679 && (!conf->can_direct (THISNODE)
680 || !THISNODE->can_direct (conf)))
681 {
682 slog (L_DEBUG, _("%s: direct connection denied"), conf->nodename);
683 protocol = 0;
684 }
621 685
622 si.set (conf, protocol); 686 si.set (conf, protocol);
623} 687}
624 688
625// ensure sockinfo is valid, forward if necessary 689// ensure sockinfo is valid, forward if necessary
630 { 694 {
631 connection *r = vpn->find_router (); 695 connection *r = vpn->find_router ();
632 696
633 if (r) 697 if (r)
634 { 698 {
635 slog (L_DEBUG, _("%s: no common protocol, trying indirectly through %s"), 699 slog (L_DEBUG, _("%s: no common protocol, trying indirectly through %s (%s)"),
636 conf->nodename, r->conf->nodename); 700 conf->nodename, r->conf->nodename, (const char *)r->si);
637 return r->si; 701 return r->si;
638 } 702 }
639 else 703 else
640 slog (L_DEBUG, _("%s: node unreachable, no common protocol"), 704 slog (L_DEBUG, _("%s: node unreachable, no common protocol"),
641 conf->nodename); 705 conf->nodename);
711} 775}
712 776
713void 777void
714connection::send_connect_info (int rid, const sockinfo &rsi, u8 rprotocols) 778connection::send_connect_info (int rid, const sockinfo &rsi, u8 rprotocols)
715{ 779{
716 slog (L_TRACE, ">>%d PT_CONNECT_INFO(%d,%s)\n", 780 slog (L_TRACE, ">>%d PT_CONNECT_INFO(%d,%s)",
717 conf->id, rid, (const char *)rsi); 781 conf->id, rid, (const char *)rsi);
718 782
719 connect_info_packet *r = new connect_info_packet (conf->id, rid, rsi, rprotocols); 783 connect_info_packet *r = new connect_info_packet (conf->id, rid, rsi, rprotocols);
720 784
721 r->hmac_set (octx); 785 r->hmac_set (octx);
722 send_vpn_packet (r, si); 786 send_vpn_packet (r, si);
723 787
724 delete r; 788 delete r;
725} 789}
726 790
727void 791inline void
728connection::establish_connection_cb (time_watcher &w) 792connection::establish_connection_cb (ev::timer &w, int revents)
729{ 793{
730 if (!ictx 794 if (!ictx
731 && conf != THISNODE 795 && conf != THISNODE
732 && connectmode != conf_node::C_NEVER 796 && connectmode != conf_node::C_NEVER
733 && connectmode != conf_node::C_DISABLED 797 && connectmode != conf_node::C_DISABLED
734 && NOW > w.at) 798 && !w.is_active ())
735 { 799 {
736 double retry_int = double (retry_cnt & 3 ? (retry_cnt & 3) : 1 << (retry_cnt >> 2)) * 0.6; 800 // a bit hacky, if ondemand, and packets are no longer queued, then reset the connection
737 801 // and stop trying. should probably be handled by a per-connection expire handler.
738 if (retry_int < 3600 * 8) 802 if (connectmode == conf_node::C_ONDEMAND && vpn_queue.empty () && data_queue.empty ())
803 {
804 reset_connection ();
739 retry_cnt++; 805 return;
806 }
740 807
741 w.start (NOW + retry_int); 808 last_establish_attempt = ev_now ();
809
810 ev::tstamp retry_int = ev::tstamp (retry_cnt & 3
811 ? (retry_cnt & 3) + 1
812 : 1 << (retry_cnt >> 2));
742 813
743 reset_si (); 814 reset_si ();
744 815
816 bool slow = si.prot & PROT_SLOW;
817
745 if (si.prot && !si.host) 818 if (si.prot && !si.host)
819 {
820 slog (L_TRACE, _("%s: connection request (indirect)"), conf->nodename);
821 /*TODO*/ /* start the timer so we don't recurse endlessly */
822 w.start (1);
746 vpn->send_connect_request (conf->id); 823 vpn->send_connect_request (conf->id);
824 }
747 else 825 else
748 { 826 {
827 slog (L_TRACE, _("%s: connection request (direct)"), conf->nodename, !!ictx, !!octx);
828
749 const sockinfo &dsi = forward_si (si); 829 const sockinfo &dsi = forward_si (si);
830
831 slow = slow || (dsi.prot & PROT_SLOW);
750 832
751 if (dsi.valid () && auth_rate_limiter.can (dsi)) 833 if (dsi.valid () && auth_rate_limiter.can (dsi))
752 { 834 {
753 if (retry_cnt < 4) 835 if (retry_cnt < 4)
754 send_auth_request (dsi, true); 836 send_auth_request (dsi, true);
755 else 837 else
756 send_ping (dsi, 0); 838 send_ping (dsi, 0);
757 } 839 }
758 } 840 }
841
842 retry_int *= slow ? 8. : 0.9;
843
844 if (retry_int < conf->max_retry)
845 retry_cnt++;
846 else
847 retry_int = conf->max_retry;
848
849 w.start (retry_int);
759 } 850 }
760} 851}
761 852
762void 853void
763connection::reset_connection () 854connection::reset_connection ()
766 { 857 {
767 slog (L_INFO, _("%s(%s): connection lost"), 858 slog (L_INFO, _("%s(%s): connection lost"),
768 conf->nodename, (const char *)si); 859 conf->nodename, (const char *)si);
769 860
770 if (::conf.script_node_down) 861 if (::conf.script_node_down)
771 run_script (run_script_cb (this, &connection::script_node_down), false); 862 {
863 run_script_cb cb;
864 cb.set<connection, &connection::script_node_down> (this);
865 if (!run_script (cb, false))
866 slog (L_WARN, _("node-down command execution failed, continuing."));
867 }
772 } 868 }
773 869
774 delete ictx; ictx = 0; 870 delete ictx; ictx = 0;
775 delete octx; octx = 0; 871 delete octx; octx = 0;
872#if ENABLE_DNS
873 dnsv4_reset_connection ();
874#endif
776 875
777 si.host= 0; 876 si.host = 0;
778 877
779 last_activity = 0; 878 last_activity = 0;
780 retry_cnt = 0; 879 retry_cnt = 0;
781 880
782 rekey.stop (); 881 rekey.stop ();
791 send_reset (si); 890 send_reset (si);
792 891
793 reset_connection (); 892 reset_connection ();
794} 893}
795 894
796void 895inline void
797connection::rekey_cb (time_watcher &w) 896connection::rekey_cb (ev::timer &w, int revents)
798{ 897{
799 reset_connection (); 898 reset_connection ();
800 establish_connection (); 899 establish_connection ();
801} 900}
802 901
818 if (oseqno > MAX_SEQNO) 917 if (oseqno > MAX_SEQNO)
819 rekey (); 918 rekey ();
820} 919}
821 920
822void 921void
922connection::post_inject_queue ()
923{
924 // force a connection every now and when when packets are sent (max 1/s)
925 if (ev_now () - last_establish_attempt >= 0.95) // arbitrary
926 establish_connection.stop ();
927
928 establish_connection ();
929}
930
931void
823connection::inject_data_packet (tap_packet *pkt, bool broadcast/*TODO DDD*/) 932connection::inject_data_packet (tap_packet *pkt)
824{ 933{
825 if (ictx && octx) 934 if (ictx && octx)
826 send_data_packet (pkt); 935 send_data_packet (pkt);
827 else 936 else
828 { 937 {
829 if (!broadcast)//DDDD
830 data_queue.put (new tap_packet (*pkt)); 938 data_queue.put (new tap_packet (*pkt));
831 939 post_inject_queue ();
832 establish_connection ();
833 } 940 }
834} 941}
835 942
836void connection::inject_vpn_packet (vpn_packet *pkt, int tos) 943void connection::inject_vpn_packet (vpn_packet *pkt, int tos)
837{ 944{
838 if (ictx && octx) 945 if (ictx && octx)
839 send_vpn_packet (pkt, si, tos); 946 send_vpn_packet (pkt, si, tos);
840 else 947 else
841 { 948 {
842 vpn_queue.put ((vpn_packet *)new data_packet (*(data_packet *)pkt)); 949 vpn_queue.put ((vpn_packet *)new data_packet (*(data_packet *)pkt));
843 950 post_inject_queue ();
844 establish_connection ();
845 } 951 }
846} 952}
847 953
848void 954void
849connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 955connection::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
850{ 956{
851 last_activity = NOW; 957 last_activity = ev_now ();
852 958
853 slog (L_NOISE, "<<%d received packet type %d from %d to %d", 959 slog (L_NOISE, "<<%d received packet type %d from %d to %d",
854 conf->id, pkt->typ (), pkt->src (), pkt->dst ()); 960 conf->id, pkt->typ (), pkt->src (), pkt->dst ());
961
962 if (connectmode == conf_node::C_DISABLED)
963 return;
855 964
856 switch (pkt->typ ()) 965 switch (pkt->typ ())
857 { 966 {
858 case vpn_packet::PT_PING: 967 case vpn_packet::PT_PING:
859 // we send pings instead of auth packets after some retries, 968 // we send pings instead of auth packets after some retries,
919 delete octx; 1028 delete octx;
920 1029
921 octx = new crypto_ctx (k, 1); 1030 octx = new crypto_ctx (k, 1);
922 oseqno = ntohl (*(u32 *)&k[CHG_SEQNO]) & 0x7fffffff; 1031 oseqno = ntohl (*(u32 *)&k[CHG_SEQNO]) & 0x7fffffff;
923 1032
924 // compatibility code, remove when no longer required
925 if (p->flags & 1) p->features |= FEATURE_COMPRESSION;
926
927 conf->protocols = p->protocols; 1033 conf->protocols = p->protocols;
928 features = p->features & FEATURES; 1034 features = p->features & config_packet::get_features ();
929 1035
930 send_auth_response (rsi, p->id, k); 1036 send_auth_response (rsi, p->id, k);
931 1037
932 connection_established (); 1038 connection_established ();
933 1039
997 slog (L_INFO, _("%s(%s): connection established, protocol version %d.%d"), 1103 slog (L_INFO, _("%s(%s): connection established, protocol version %d.%d"),
998 conf->nodename, (const char *)rsi, 1104 conf->nodename, (const char *)rsi,
999 p->prot_major, p->prot_minor); 1105 p->prot_major, p->prot_minor);
1000 1106
1001 if (::conf.script_node_up) 1107 if (::conf.script_node_up)
1002 run_script (run_script_cb (this, &connection::script_node_up), false); 1108 {
1109 run_script_cb cb;
1110 cb.set<connection, &connection::script_node_up> (this);
1111 if (!run_script (cb, false))
1112 slog (L_WARN, _("node-up command execution failed, continuing."));
1113 }
1003 1114
1004 break; 1115 break;
1005 } 1116 }
1006 else 1117 else
1007 slog (L_ERR, _("%s(%s): sent and received challenge do not match"), 1118 slog (L_ERR, _("%s(%s): sent and received challenge do not match"),
1041 { 1152 {
1042 vpn->tap->send (d); 1153 vpn->tap->send (d);
1043 1154
1044 if (si != rsi) 1155 if (si != rsi)
1045 { 1156 {
1046 // fast re-sync on connection changes, useful especially for tcp/ip 1157 // fast re-sync on source address changes, useful especially for tcp/ip
1047 si = rsi; 1158 si = rsi;
1048 1159
1049 slog (L_INFO, _("%s(%s): socket address changed to %s"), 1160 slog (L_INFO, _("%s(%s): socket address changed to %s"),
1050 conf->nodename, (const char *)si, (const char *)rsi); 1161 conf->nodename, (const char *)si, (const char *)rsi);
1051 } 1162 }
1052
1053 delete d;
1054
1055 break;
1056 } 1163 }
1164
1165 delete d;
1166 break;
1057 } 1167 }
1058 } 1168 }
1059 1169
1060 send_reset (rsi); 1170 send_reset (rsi);
1061 break; 1171 break;
1063 case vpn_packet::PT_CONNECT_REQ: 1173 case vpn_packet::PT_CONNECT_REQ:
1064 if (ictx && octx && rsi == si && pkt->hmac_chk (ictx)) 1174 if (ictx && octx && rsi == si && pkt->hmac_chk (ictx))
1065 { 1175 {
1066 connect_req_packet *p = (connect_req_packet *) pkt; 1176 connect_req_packet *p = (connect_req_packet *) pkt;
1067 1177
1068 assert (p->id > 0 && p->id <= vpn->conns.size ()); // hmac-auth does not mean we accept anything 1178 if (p->id > 0 && p->id <= vpn->conns.size ())
1069 connection *c = vpn->conns[p->id - 1];
1070 conf->protocols = p->protocols;
1071
1072 slog (L_TRACE, "<<%d PT_CONNECT_REQ(%d) [%d]\n",
1073 conf->id, p->id, c->ictx && c->octx);
1074
1075 if (c->ictx && c->octx)
1076 { 1179 {
1180 connection *c = vpn->conns[p->id - 1];
1181 conf->protocols = p->protocols;
1182
1183 slog (L_TRACE, "<<%d PT_CONNECT_REQ(%d) [%d]",
1184 conf->id, p->id, c->ictx && c->octx);
1185
1186 if (c->ictx && c->octx)
1187 {
1077 // send connect_info packets to both sides, in case one is 1188 // send connect_info packets to both sides, in case one is
1078 // behind a nat firewall (or both ;) 1189 // behind a nat firewall (or both ;)
1079 c->send_connect_info (conf->id, si, conf->protocols); 1190 c->send_connect_info (conf->id, si, conf->protocols);
1080 send_connect_info (c->conf->id, c->si, c->conf->protocols); 1191 send_connect_info (c->conf->id, c->si, c->conf->protocols);
1192 }
1193 else
1194 c->establish_connection ();
1081 } 1195 }
1082 else 1196 else
1083 c->establish_connection (); 1197 slog (L_WARN,
1198 _("received authenticated connection request from unknown node #%d, config file mismatch?"),
1199 p->id);
1084 } 1200 }
1085 1201
1086 break; 1202 break;
1087 1203
1088 case vpn_packet::PT_CONNECT_INFO: 1204 case vpn_packet::PT_CONNECT_INFO:
1089 if (ictx && octx && rsi == si && pkt->hmac_chk (ictx)) 1205 if (ictx && octx && rsi == si && pkt->hmac_chk (ictx))
1090 { 1206 {
1091 connect_info_packet *p = (connect_info_packet *) pkt; 1207 connect_info_packet *p = (connect_info_packet *)pkt;
1092 1208
1093 assert (p->id > 0 && p->id <= vpn->conns.size ()); // hmac-auth does not mean we accept anything 1209 if (p->id > 0 && p->id <= vpn->conns.size ())
1094 1210 {
1095 connection *c = vpn->conns[p->id - 1]; 1211 connection *c = vpn->conns[p->id - 1];
1096 1212
1097 c->conf->protocols = p->protocols; 1213 c->conf->protocols = p->protocols;
1098 protocol = best_protocol (c->conf->protocols & THISNODE->protocols & p->si.supported_protocols (c->conf)); 1214 protocol = best_protocol (c->conf->protocols & THISNODE->protocols & p->si.supported_protocols (c->conf));
1099 p->si.upgrade_protocol (protocol, c->conf); 1215 p->si.upgrade_protocol (protocol, c->conf);
1100 1216
1101 slog (L_TRACE, "<<%d PT_CONNECT_INFO(%d,%s) (%d)", 1217 slog (L_TRACE, "<<%d PT_CONNECT_INFO(%d,%s) (%d)",
1102 conf->id, p->id, (const char *)p->si, !c->ictx && !c->octx); 1218 conf->id, p->id, (const char *)p->si, !c->ictx && !c->octx);
1103 1219
1104 const sockinfo &dsi = forward_si (p->si); 1220 const sockinfo &dsi = forward_si (p->si);
1105 1221
1106 if (dsi.valid ()) 1222 if (dsi.valid ())
1107 c->send_auth_request (dsi, true); 1223 c->send_auth_request (dsi, true);
1224 }
1225 else
1226 slog (L_WARN,
1227 _("received authenticated connection request from unknown node #%d, config file mismatch?"),
1228 p->id);
1108 } 1229 }
1109 1230
1110 break; 1231 break;
1111 1232
1112 default: 1233 default:
1113 send_reset (rsi); 1234 send_reset (rsi);
1114 break; 1235 break;
1115 } 1236 }
1116} 1237}
1117 1238
1118void connection::keepalive_cb (time_watcher &w) 1239inline void
1240connection::keepalive_cb (ev::timer &w, int revents)
1119{ 1241{
1120 if (NOW >= last_activity + ::conf.keepalive + 30) 1242 if (ev_now () >= last_activity + ::conf.keepalive + 30)
1121 { 1243 {
1122 reset_connection (); 1244 reset_connection ();
1123 establish_connection (); 1245 establish_connection ();
1124 } 1246 }
1125 else if (NOW < last_activity + ::conf.keepalive) 1247 else if (ev_now () < last_activity + ::conf.keepalive)
1126 w.start (last_activity + ::conf.keepalive); 1248 w.start (last_activity + ::conf.keepalive - ev::now ());
1127 else if (conf->connectmode != conf_node::C_ONDEMAND 1249 else if (conf->connectmode != conf_node::C_ONDEMAND
1128 || THISNODE->connectmode != conf_node::C_ONDEMAND) 1250 || THISNODE->connectmode != conf_node::C_ONDEMAND)
1129 { 1251 {
1130 send_ping (si); 1252 send_ping (si);
1131 w.start (NOW + 5); 1253 w.start (5);
1132 } 1254 }
1133 else if (NOW < last_activity + ::conf.keepalive + 10) 1255 else if (ev_now () < last_activity + ::conf.keepalive + 10)
1134 // hold ondemand connections implicitly a few seconds longer 1256 // hold ondemand connections implicitly a few seconds longer
1135 // should delete octx, though, or something like that ;) 1257 // should delete octx, though, or something like that ;)
1136 w.start (last_activity + ::conf.keepalive + 10); 1258 w.start (last_activity + ::conf.keepalive + 10 - ev::now ());
1137 else 1259 else
1138 reset_connection (); 1260 reset_connection ();
1139} 1261}
1140 1262
1141void connection::send_connect_request (int id) 1263void connection::send_connect_request (int id)
1147 send_vpn_packet (p, si); 1269 send_vpn_packet (p, si);
1148 1270
1149 delete p; 1271 delete p;
1150} 1272}
1151 1273
1274void connection::script_init_env (const char *ext)
1275{
1276 char *env;
1277 asprintf (&env, "IFUPDATA%s=%s", ext, conf->if_up_data); putenv (env);
1278 asprintf (&env, "NODENAME%s=%s", ext, conf->nodename); putenv (env);
1279 asprintf (&env, "MAC%s=%02x:%02x:%02x:%02x:%02x:%02x", ext,
1280 0xfe, 0xfd, 0x80, 0x00, conf->id >> 8,
1281 conf->id & 0xff); putenv (env);
1282}
1283
1152void connection::script_node () 1284void connection::script_init_connect_env ()
1153{ 1285{
1154 vpn->script_if_up (); 1286 vpn->script_init_env ();
1155 1287
1156 char *env; 1288 char *env;
1157 asprintf (&env, "DESTID=%d", conf->id); putenv (env); 1289 asprintf (&env, "DESTID=%d", conf->id); putenv (env);
1158 asprintf (&env, "DESTNODE=%s", conf->nodename); putenv (env); 1290 asprintf (&env, "DESTNODE=%s", conf->nodename); putenv (env);
1159 asprintf (&env, "DESTIP=%s", si.ntoa ()); putenv (env); 1291 asprintf (&env, "DESTIP=%s", si.ntoa ()); putenv (env);
1160 asprintf (&env, "DESTPORT=%d", ntohs (si.port)); putenv (env); 1292 asprintf (&env, "DESTPORT=%d", ntohs (si.port)); putenv (env);
1161} 1293}
1162 1294
1295inline const char *
1163const char *connection::script_node_up () 1296connection::script_node_up ()
1164{ 1297{
1165 script_node (); 1298 script_init_connect_env ();
1166 1299
1167 putenv ("STATE=up"); 1300 putenv ((char *)"STATE=up");
1168 1301
1302 char *filename;
1303 asprintf (&filename,
1304 "%s/%s",
1305 confbase,
1169 return ::conf.script_node_up ? ::conf.script_node_up : "node-up"; 1306 ::conf.script_node_up ? ::conf.script_node_up : "node-up");
1170}
1171 1307
1308 return filename;
1309}
1310
1311inline const char *
1172const char *connection::script_node_down () 1312connection::script_node_down ()
1173{ 1313{
1174 script_node (); 1314 script_init_connect_env ();
1175 1315
1176 putenv ("STATE=down"); 1316 putenv ((char *)"STATE=down");
1177 1317
1178 return ::conf.script_node_up ? ::conf.script_node_down : "node-down"; 1318 char *filename;
1179} 1319 asprintf (&filename,
1320 "%s/%s",
1321 confbase,
1322 ::conf.script_node_down ? ::conf.script_node_down : "node-down");
1180 1323
1324 return filename;
1325}
1326
1181connection::connection(struct vpn *vpn_) 1327connection::connection (struct vpn *vpn, conf_node *conf)
1182: vpn(vpn_) 1328: vpn(vpn), conf(conf),
1183, rekey (this, &connection::rekey_cb) 1329#if ENABLE_DNS
1184, keepalive (this, &connection::keepalive_cb) 1330 dns (0),
1331#endif
1332 data_queue(conf->max_ttl, conf->max_queue),
1333 vpn_queue(conf->max_ttl, conf->max_queue)
1334{
1335 rekey .set<connection, &connection::rekey_cb > (this);
1336 keepalive .set<connection, &connection::keepalive_cb > (this);
1185, establish_connection (this, &connection::establish_connection_cb) 1337 establish_connection.set<connection, &connection::establish_connection_cb> (this);
1186{ 1338
1339 last_establish_attempt = 0.;
1187 octx = ictx = 0; 1340 octx = ictx = 0;
1188 retry_cnt = 0;
1189 1341
1190 connectmode = conf_node::C_ALWAYS; // initial setting 1342 if (!conf->protocols) // make sure some protocol is enabled
1343 conf->protocols = PROT_UDPv4;
1344
1345 connectmode = conf->connectmode;
1346
1347 // queue a dummy packet to force an initial connection attempt
1348 if (connectmode != conf_node::C_ALWAYS && connectmode != conf_node::C_DISABLED)
1349 vpn_queue.put (new net_packet);
1350
1191 reset_connection (); 1351 reset_connection ();
1192} 1352}
1193 1353
1194connection::~connection () 1354connection::~connection ()
1195{ 1355{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines