ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.20
Committed: Thu Oct 16 14:12:00 2003 UTC (20 years, 7 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.19: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 vpn.C -- handle the protocol, encryption, handshaking etc.
3 Copyright (C) 2003 Marc Lehmann <pcg@goof.com>
4
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.
9
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.
14
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. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "config.h"
21
22 #include <list>
23
24 #include <cstdlib>
25 #include <cstring>
26 #include <cstdio>
27
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/wait.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <sys/socket.h>
36
37 #include "netcompat.h"
38
39 #include "pidfile.h"
40
41 #include "connection.h"
42 #include "util.h"
43 #include "vpn.h"
44
45 vpn network; // THE vpn (bad design...)
46
47 /////////////////////////////////////////////////////////////////////////////
48
49 const char *vpn::script_if_up ()
50 {
51 // the tunnel device mtu should be the physical mtu - overhead
52 // the tricky part is rounding to the cipher key blocksize
53 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD;
54 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion
55 mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round
56 mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again
57
58 char *env;
59 asprintf (&env, "CONFBASE=%s", confbase);
60 putenv (env);
61 asprintf (&env, "NODENAME=%s", THISNODE->nodename);
62 putenv (env);
63 asprintf (&env, "NODEID=%d", THISNODE->id);
64 putenv (env);
65 asprintf (&env, "IFNAME=%s", tap->interface ());
66 putenv (env);
67 asprintf (&env, "MTU=%d", mtu);
68 putenv (env);
69 asprintf (&env, "MAC=%02x:%02x:%02x:%02x:%02x:%02x",
70 0xfe, 0xfd, 0x80, 0x00, THISNODE->id >> 8,
71 THISNODE->id & 0xff);
72 putenv (env);
73
74 return ::conf.script_if_up ? ::conf.script_if_up : "if-up";
75 }
76
77 int
78 vpn::setup ()
79 {
80 ipv4_fd = -1;
81
82 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
83 {
84 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
85
86 if (ipv4_fd < 0)
87 return -1;
88
89 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK);
90
91 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
92 // this I really consider a linux bug. I am neither connected
93 // nor do I fragment myself. Linux still sets DF and doesn't
94 // fragment for me sometimes.
95 {
96 int oval = IP_PMTUDISC_DONT;
97 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
98 }
99 #endif
100
101 sockinfo si (THISNODE, PROT_IPv4);
102
103 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
104 {
105 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno));
106 exit (1);
107 }
108
109 ipv4_ev_watcher.start (ipv4_fd, POLLIN);
110 }
111
112 udpv4_fd = -1;
113
114 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
115 {
116 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
117
118 if (udpv4_fd < 0)
119 return -1;
120
121 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK);
122
123 // standard daemon practise...
124 {
125 int oval = 1;
126 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
127 }
128
129 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
130 // this I really consider a linux bug. I am neither connected
131 // nor do I fragment myself. Linux still sets DF and doesn't
132 // fragment for me sometimes.
133 {
134 int oval = IP_PMTUDISC_DONT;
135 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
136 }
137 #endif
138
139 sockinfo si (THISNODE, PROT_UDPv4);
140
141 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
142 {
143 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
144 exit (1);
145 }
146
147 udpv4_ev_watcher.start (udpv4_fd, POLLIN);
148 }
149
150 icmpv4_fd = -1;
151
152 #if ENABLE_ICMP
153 if (THISNODE->protocols & PROT_ICMPv4)
154 {
155 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
156
157 if (icmpv4_fd < 0)
158 return -1;
159
160 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK);
161
162 #ifdef ICMP_FILTER
163 {
164 icmp_filter oval;
165 oval.data = 0xffffffff;
166 if (::conf.icmp_type < 32)
167 oval.data &= ~(1 << ::conf.icmp_type);
168
169 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
170 }
171 #endif
172
173 #if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
174 // this I really consider a linux bug. I am neither connected
175 // nor do I fragment myself. Linux still sets DF and doesn't
176 // fragment for me sometimes.
177 {
178 int oval = IP_PMTUDISC_DONT;
179 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
180 }
181 #endif
182
183 sockinfo si (THISNODE, PROT_ICMPv4);
184
185 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
186 {
187 slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno));
188 exit (1);
189 }
190
191 icmpv4_ev_watcher.start (icmpv4_fd, POLLIN);
192 }
193 #endif
194
195 tcpv4_fd = -1;
196
197 #if ENABLE_TCP
198 if (THISNODE->protocols & PROT_TCPv4 && THISNODE->tcp_port)
199 {
200 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
201
202 if (tcpv4_fd < 0)
203 return -1;
204
205 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK);
206
207 // standard daemon practise...
208 {
209 int oval = 1;
210 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
211 }
212
213 sockinfo si (THISNODE, PROT_TCPv4);
214
215 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
216 {
217 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
218 exit (1);
219 }
220
221 if (listen (tcpv4_fd, 5))
222 {
223 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
224 exit (1);
225 }
226
227 tcpv4_ev_watcher.start (tcpv4_fd, POLLIN);
228 }
229 #endif
230
231 tap = new tap_device ();
232 if (!tap) //D this, of course, never catches
233 {
234 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname);
235 exit (1);
236 }
237
238 run_script (run_script_cb (this, &vpn::script_if_up), true);
239
240 tap_ev_watcher.start (tap->fd, POLLIN);
241
242 reconnect_all ();
243
244 return 0;
245 }
246
247 // send a vpn packet out to other hosts
248 bool
249 vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
250 {
251 switch (si.prot)
252 {
253 case PROT_IPv4:
254 return send_ipv4_packet (pkt, si, tos);
255
256 case PROT_UDPv4:
257 return send_udpv4_packet (pkt, si, tos);
258
259 #if ENABLE_TCP
260 case PROT_TCPv4:
261 return send_tcpv4_packet (pkt, si, tos);
262 #endif
263
264 #if ENABLE_ICMP
265 case PROT_ICMPv4:
266 return send_icmpv4_packet (pkt, si, tos);
267 #endif
268
269 default:
270 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si);
271 return false;
272 }
273 }
274
275 bool
276 vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
277 {
278 #if defined(SOL_IP) && defined(IP_TOS)
279 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
280 #endif
281 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
282
283 return true;
284 }
285
286 static u16
287 ipv4_checksum (u16 *data, unsigned int len)
288 {
289 // use 32 bit accumulator and fold back carry bits at the end
290 u32 sum = 0;
291
292 while (len > 1)
293 {
294 sum += *data++;
295 len -= 2;
296 }
297
298 // odd byte left?
299 if (len)
300 sum += *(u8 *)data;
301
302 // add back carry bits
303 sum = (sum >> 16) + (sum & 0xffff); // lo += hi
304 sum += (sum >> 16); // carry
305
306 return ~sum;
307 }
308
309 #if ENABLE_ICMP
310 bool
311 vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
312 {
313 #if defined(SOL_IP) && defined(IP_TOS)
314 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
315 #endif
316
317 pkt->unshift_hdr (4);
318
319 icmp_header *hdr = (icmp_header *)&((*pkt)[0]);
320 hdr->type = ::conf.icmp_type;
321 hdr->code = 255;
322 hdr->checksum = 0;
323 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len);
324
325 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
326
327 return true;
328 }
329 #endif
330
331 bool
332 vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
333 {
334 #if defined(SOL_IP) && defined(IP_TOS)
335 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
336 #endif
337 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
338
339 return true;
340 }
341
342 void
343 vpn::inject_data_packet (tap_packet *pkt, int dst)
344 {
345 if (dst)
346 {
347 // unicast
348 if (dst != THISNODE->id)
349 conns[dst - 1]->inject_data_packet (pkt);
350 }
351 else
352 {
353 // broadcast, this is ugly, but due to the security policy
354 // we have to connect to all hosts...
355 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
356 if ((*c)->conf != THISNODE)
357 (*c)->inject_data_packet (pkt, true);
358 }
359 }
360
361 void
362 vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
363 {
364 unsigned int src = pkt->src ();
365 unsigned int dst = pkt->dst ();
366
367 slog (L_NOISE, _("<<?/%s received possible vpn packet type %d from %d to %d, length %d"),
368 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
369
370 if (src == 0 || src > conns.size ()
371 || dst > conns.size ()
372 || pkt->typ () >= vpn_packet::PT_MAX)
373 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
374 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
375 else if (dst > conns.size ())
376 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
377 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
378 else
379 {
380 connection *c = conns[src - 1];
381
382 if (dst == 0)
383 slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"),
384 c->conf->nodename, (const char *)rsi);
385 else if (dst != THISNODE->id)
386 {
387 if (THISNODE->routerprio)
388 // the tos setting gets lost here. who cares.
389 conns[dst - 1]->inject_vpn_packet (pkt);
390 else
391 slog (L_WARN,
392 _("%s(%s): forwarding request (=> %s), but we are no router"),
393 c->conf->nodename, (const char *)rsi,
394 conns[dst - 1]->conf->nodename);
395 }
396 else
397 c->recv_vpn_packet (pkt, rsi);
398 }
399 }
400
401 void
402 vpn::ipv4_ev (io_watcher &w, short revents)
403 {
404 if (revents & (POLLIN | POLLERR))
405 {
406 vpn_packet *pkt = new vpn_packet;
407 struct sockaddr_in sa;
408 socklen_t sa_len = sizeof (sa);
409 int len;
410
411 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
412
413 sockinfo si(sa, PROT_IPv4);
414
415 if (len > 0)
416 {
417 pkt->len = len;
418
419 // raw sockets deliver the ipv4, but don't expect it on sends
420 // this is slow, but...
421 pkt->skip_hdr (IP_OVERHEAD);
422
423 recv_vpn_packet (pkt, si);
424 }
425 else
426 {
427 // probably ECONNRESET or somesuch
428 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno));
429 }
430
431 delete pkt;
432 }
433 else if (revents & POLLHUP)
434 {
435 // this cannot ;) happen on udp sockets
436 slog (L_ERR, _("FATAL: POLLHUP on ipv4 fd, terminating."));
437 exit (1);
438 }
439 else
440 {
441 slog (L_ERR,
442 _("FATAL: unknown revents %08x in socket, terminating\n"),
443 revents);
444 exit (1);
445 }
446 }
447
448 #if ENABLE_ICMP
449 void
450 vpn::icmpv4_ev (io_watcher &w, short revents)
451 {
452 if (revents & (POLLIN | POLLERR))
453 {
454 vpn_packet *pkt = new vpn_packet;
455 struct sockaddr_in sa;
456 socklen_t sa_len = sizeof (sa);
457 int len;
458
459 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
460
461 sockinfo si(sa, PROT_ICMPv4);
462
463 if (len > 0)
464 {
465 pkt->len = len;
466
467 icmp_header *hdr = (icmp_header *)&((*pkt)[IP_OVERHEAD]);
468
469 if (hdr->type == ::conf.icmp_type
470 && hdr->code == 255)
471 {
472 // raw sockets deliver the ipv4, but don't expect it on sends
473 // this is slow, but...
474 pkt->skip_hdr (ICMP_OVERHEAD);
475
476 recv_vpn_packet (pkt, si);
477 }
478 }
479 else
480 {
481 // probably ECONNRESET or somesuch
482 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno));
483 }
484
485 delete pkt;
486 }
487 else if (revents & POLLHUP)
488 {
489 // this cannot ;) happen on udp sockets
490 slog (L_ERR, _("FATAL: POLLHUP on icmpv4 fd, terminating."));
491 exit (1);
492 }
493 else
494 {
495 slog (L_ERR,
496 _("FATAL: unknown revents %08x in socket, terminating\n"),
497 revents);
498 exit (1);
499 }
500 }
501 #endif
502
503 void
504 vpn::udpv4_ev (io_watcher &w, short revents)
505 {
506 if (revents & (POLLIN | POLLERR))
507 {
508 vpn_packet *pkt = new vpn_packet;
509 struct sockaddr_in sa;
510 socklen_t sa_len = sizeof (sa);
511 int len;
512
513 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
514
515 sockinfo si(sa, PROT_UDPv4);
516
517 if (len > 0)
518 {
519 pkt->len = len;
520
521 recv_vpn_packet (pkt, si);
522 }
523 else
524 {
525 // probably ECONNRESET or somesuch
526 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno));
527 }
528
529 delete pkt;
530 }
531 else if (revents & POLLHUP)
532 {
533 // this cannot ;) happen on udp sockets
534 slog (L_ERR, _("FATAL: POLLHUP on udp v4 fd, terminating."));
535 exit (1);
536 }
537 else
538 {
539 slog (L_ERR,
540 _("FATAL: unknown revents %08x in socket, terminating\n"),
541 revents);
542 exit (1);
543 }
544 }
545
546 void
547 vpn::tap_ev (io_watcher &w, short revents)
548 {
549 if (revents & POLLIN)
550 {
551 /* process data */
552 tap_packet *pkt;
553
554 pkt = tap->recv ();
555
556 if (!pkt)
557 return;
558
559 if (pkt->len > 14)
560 {
561 int dst = mac2id (pkt->dst);
562 int src = mac2id (pkt->src);
563
564 if (src != THISNODE->id)
565 {
566 slog (L_ERR, _("FATAL: tap packet not originating on current node received, exiting."));
567 exit (1);
568 }
569
570 if (dst == THISNODE->id)
571 {
572 slog (L_ERR, _("FATAL: tap packet destined for current node received, exiting."));
573 exit (1);
574 }
575
576 if (dst > conns.size ())
577 slog (L_ERR, _("tap packet for unknown node %d received, ignoring."), dst);
578 else
579 inject_data_packet (pkt, dst);
580 }
581
582 delete pkt;
583 }
584 else if (revents & (POLLHUP | POLLERR))
585 {
586 slog (L_ERR, _("FATAL: POLLHUP or POLLERR on network device fd, terminating."));
587 exit (1);
588 }
589 else
590 abort ();
591 }
592
593 void
594 vpn::event_cb (time_watcher &w)
595 {
596 if (events)
597 {
598 if (events & EVENT_SHUTDOWN)
599 {
600 slog (L_INFO, _("preparing shutdown..."));
601
602 shutdown_all ();
603
604 remove_pid (pidfilename);
605
606 slog (L_INFO, _("terminating"));
607
608 exit (0);
609 }
610
611 if (events & EVENT_RECONNECT)
612 {
613 slog (L_INFO, _("forced reconnect"));
614
615 reconnect_all ();
616 }
617
618 events = 0;
619 }
620
621 w.at = TSTAMP_CANCEL;
622 }
623
624 void
625 vpn::shutdown_all ()
626 {
627 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
628 (*c)->shutdown ();
629 }
630
631 void
632 vpn::reconnect_all ()
633 {
634 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
635 delete *c;
636
637 conns.clear ();
638
639 connection_init ();
640
641 for (configuration::node_vector::iterator i = conf.nodes.begin ();
642 i != conf.nodes.end (); ++i)
643 {
644 connection *conn = new connection (this);
645
646 conn->conf = *i;
647 conns.push_back (conn);
648
649 conn->establish_connection ();
650 }
651 }
652
653 connection *vpn::find_router ()
654 {
655 u32 prio = 1;
656 connection *router = 0;
657
658 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
659 {
660 connection *c = *i;
661
662 if (c->conf->routerprio > prio
663 && c->connectmode == conf_node::C_ALWAYS // so we don't drop the connection if in use
664 && c->ictx && c->octx
665 && c->conf != THISNODE) // redundant, since ictx==octx==0 always on thisnode
666 {
667 prio = c->conf->routerprio;
668 router = c;
669 }
670 }
671
672 return router;
673 }
674
675 void vpn::send_connect_request (int id)
676 {
677 connection *c = find_router ();
678
679 if (c)
680 c->send_connect_request (id);
681 else
682 // no router found, aggressively connect to all routers
683 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
684 if ((*i)->conf->routerprio && (*i)->conf != THISNODE)
685 (*i)->establish_connection ();
686 }
687
688 void
689 connection::dump_status ()
690 {
691 slog (L_NOTICE, _("node %s (id %d)"), conf->nodename, conf->id);
692 slog (L_NOTICE, _(" connectmode %d (%d) / sockaddr %s / minor %d"),
693 connectmode, conf->connectmode, (const char *)si, (int)prot_minor);
694 slog (L_NOTICE, _(" ictx/octx %08lx/%08lx / oseqno %d / retry_cnt %d"),
695 (long)ictx, (long)octx, (int)oseqno, (int)retry_cnt);
696 slog (L_NOTICE, _(" establish_conn %ld / rekey %ld / keepalive %ld"),
697 (long)(establish_connection.at), (long)(rekey.at), (long)(keepalive.at));
698 }
699
700 void
701 vpn::dump_status ()
702 {
703 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)NOW);
704
705 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
706 (*c)->dump_status ();
707
708 slog (L_NOTICE, _("END status dump"));
709 }
710
711 vpn::vpn (void)
712 : event (this, &vpn::event_cb)
713 , udpv4_ev_watcher (this, &vpn::udpv4_ev)
714 , ipv4_ev_watcher (this, &vpn::ipv4_ev)
715 #if ENABLE_TCP
716 , tcpv4_ev_watcher (this, &vpn::tcpv4_ev)
717 #endif
718 #if ENABLE_ICMP
719 , icmpv4_ev_watcher(this, &vpn::icmpv4_ev)
720 #endif
721 , tap_ev_watcher (this, &vpn::tap_ev)
722 {
723 }
724
725 vpn::~vpn ()
726 {
727 }
728