ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn.C
Revision: 1.14
Committed: Tue Oct 14 03:22:09 2003 UTC (20 years, 7 months ago) by pcg
Content type: text/plain
Branch: MAIN
Changes since 1.13: +49 -9 lines
Log Message:
*** empty log message ***

File Contents

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