1 | /* |
1 | /* |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
|
|
3 | Copyright (C) 2003 Marc Lehmann <pcg@goof.com> |
3 | |
4 | |
4 | This program is free software; you can redistribute it and/or modify |
5 | 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 | 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 | the Free Software Foundation; either version 2 of the License, or |
7 | (at your option) any later version. |
8 | (at your option) any later version. |
… | |
… | |
24 | #include <cstring> |
25 | #include <cstring> |
25 | #include <cstdio> |
26 | #include <cstdio> |
26 | |
27 | |
27 | #include <sys/types.h> |
28 | #include <sys/types.h> |
28 | #include <sys/socket.h> |
29 | #include <sys/socket.h> |
29 | #include <sys/poll.h> |
|
|
30 | #include <sys/wait.h> |
30 | #include <sys/wait.h> |
31 | #include <errno.h> |
31 | #include <errno.h> |
32 | #include <time.h> |
32 | #include <time.h> |
33 | #include <unistd.h> |
33 | #include <unistd.h> |
34 | #include <fcntl.h> |
34 | #include <fcntl.h> |
… | |
… | |
40 | |
40 | |
41 | #include "connection.h" |
41 | #include "connection.h" |
42 | #include "util.h" |
42 | #include "util.h" |
43 | #include "vpn.h" |
43 | #include "vpn.h" |
44 | |
44 | |
|
|
45 | vpn network; // THE vpn (bad design...) |
|
|
46 | |
45 | ///////////////////////////////////////////////////////////////////////////// |
47 | ///////////////////////////////////////////////////////////////////////////// |
46 | |
48 | |
47 | const char *vpn::script_if_up () |
49 | const char *vpn::script_if_up () |
48 | { |
50 | { |
49 | // the tunnel device mtu should be the physical mtu - overhead |
51 | // the tunnel device mtu should be the physical mtu - overhead |
… | |
… | |
52 | mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion |
54 | mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion |
53 | mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round |
55 | mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round |
54 | mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again |
56 | mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again |
55 | |
57 | |
56 | char *env; |
58 | char *env; |
57 | asprintf (&env, "CONFBASE=%s", confbase); |
59 | asprintf (&env, "CONFBASE=%s", confbase); putenv (env); |
58 | putenv (env); |
|
|
59 | asprintf (&env, "NODENAME=%s", THISNODE->nodename); |
60 | asprintf (&env, "NODENAME=%s", THISNODE->nodename); putenv (env); |
60 | putenv (env); |
|
|
61 | asprintf (&env, "NODEID=%d", THISNODE->id); |
61 | asprintf (&env, "NODEID=%d", THISNODE->id); putenv (env); |
62 | putenv (env); |
|
|
63 | asprintf (&env, "IFNAME=%s", tap->interface ()); |
62 | asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env); |
64 | putenv (env); |
63 | asprintf (&env, "IFTYPE=%s", IFTYPE); putenv (env); |
|
|
64 | asprintf (&env, "IFSUBTYPE=%s", IFSUBTYPE); putenv (env); |
65 | asprintf (&env, "MTU=%d", mtu); |
65 | asprintf (&env, "MTU=%d", mtu); putenv (env); |
66 | putenv (env); |
|
|
67 | asprintf (&env, "MAC=%02x:%02x:%02x:%02x:%02x:%02x", |
66 | asprintf (&env, "MAC=%02x:%02x:%02x:%02x:%02x:%02x", |
68 | 0xfe, 0xfd, 0x80, 0x00, THISNODE->id >> 8, |
67 | 0xfe, 0xfd, 0x80, 0x00, THISNODE->id >> 8, |
69 | THISNODE->id & 0xff); |
68 | THISNODE->id & 0xff); |
70 | putenv (env); |
69 | putenv (env); |
71 | |
70 | |
… | |
… | |
333 | setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); |
332 | setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); |
334 | #endif |
333 | #endif |
335 | sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
334 | sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
336 | |
335 | |
337 | return true; |
336 | return true; |
|
|
337 | } |
|
|
338 | |
|
|
339 | void |
|
|
340 | vpn::inject_data_packet (tap_packet *pkt, int dst) |
|
|
341 | { |
|
|
342 | if (dst) |
|
|
343 | { |
|
|
344 | // unicast |
|
|
345 | if (dst != THISNODE->id) |
|
|
346 | conns[dst - 1]->inject_data_packet (pkt); |
|
|
347 | } |
|
|
348 | else |
|
|
349 | { |
|
|
350 | // broadcast, this is ugly, but due to the security policy |
|
|
351 | // we have to connect to all hosts... |
|
|
352 | for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) |
|
|
353 | if ((*c)->conf != THISNODE) |
|
|
354 | (*c)->inject_data_packet (pkt, true); |
|
|
355 | } |
338 | } |
356 | } |
339 | |
357 | |
340 | void |
358 | void |
341 | vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) |
359 | vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) |
342 | { |
360 | { |
… | |
… | |
359 | connection *c = conns[src - 1]; |
377 | connection *c = conns[src - 1]; |
360 | |
378 | |
361 | if (dst == 0) |
379 | if (dst == 0) |
362 | slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"), |
380 | slog (L_WARN, _("%s(%s): received broadcast (protocol violation)"), |
363 | c->conf->nodename, (const char *)rsi); |
381 | c->conf->nodename, (const char *)rsi); |
364 | else if (dst != 0 && dst != THISNODE->id) |
382 | else if (dst != THISNODE->id) |
365 | { |
383 | { |
366 | if (THISNODE->routerprio) |
384 | if (THISNODE->routerprio) |
367 | // the tos setting gets lost here. who cares. |
385 | // the tos setting gets lost here. who cares. |
368 | conns[dst - 1]->inject_vpn_packet (pkt); |
386 | conns[dst - 1]->inject_vpn_packet (pkt); |
369 | else |
387 | else |
… | |
… | |
530 | /* process data */ |
548 | /* process data */ |
531 | tap_packet *pkt; |
549 | tap_packet *pkt; |
532 | |
550 | |
533 | pkt = tap->recv (); |
551 | pkt = tap->recv (); |
534 | |
552 | |
|
|
553 | if (!pkt) |
|
|
554 | return; |
|
|
555 | |
|
|
556 | if (pkt->len > 14) |
|
|
557 | { |
535 | int dst = mac2id (pkt->dst); |
558 | int dst = mac2id (pkt->dst); |
536 | int src = mac2id (pkt->src); |
559 | int src = mac2id (pkt->src); |
537 | |
560 | |
538 | if (src != THISNODE->id) |
561 | if (src != THISNODE->id) |
539 | { |
|
|
540 | slog (L_ERR, _("FATAL: tap packet not originating on current node received, exiting.")); |
|
|
541 | exit (1); |
|
|
542 | } |
|
|
543 | |
|
|
544 | if (dst == THISNODE->id) |
|
|
545 | { |
|
|
546 | slog (L_ERR, _("FATAL: tap packet destined for current node received, exiting.")); |
|
|
547 | exit (1); |
|
|
548 | } |
|
|
549 | |
|
|
550 | if (dst > conns.size ()) |
|
|
551 | slog (L_ERR, _("tap packet for unknown node %d received, ignoring."), dst); |
|
|
552 | else |
|
|
553 | { |
|
|
554 | if (dst) |
|
|
555 | { |
562 | { |
556 | // unicast |
563 | slog (L_ERR, _("FATAL: tap packet not originating on current node received, exiting.")); |
557 | if (dst != THISNODE->id) |
564 | exit (1); |
558 | conns[dst - 1]->inject_data_packet (pkt); |
|
|
559 | } |
565 | } |
|
|
566 | |
|
|
567 | if (dst == THISNODE->id) |
|
|
568 | { |
|
|
569 | slog (L_ERR, _("FATAL: tap packet destined for current node received, exiting.")); |
|
|
570 | exit (1); |
|
|
571 | } |
|
|
572 | |
|
|
573 | if (dst > conns.size ()) |
|
|
574 | slog (L_ERR, _("tap packet for unknown node %d received, ignoring."), dst); |
560 | else |
575 | else |
561 | { |
|
|
562 | // broadcast, this is ugly, but due to the security policy |
|
|
563 | // we have to connect to all hosts... |
|
|
564 | for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) |
|
|
565 | if ((*c)->conf != THISNODE) |
|
|
566 | (*c)->inject_data_packet (pkt); |
576 | inject_data_packet (pkt, dst); |
567 | } |
|
|
568 | } |
577 | } |
569 | |
578 | |
570 | delete pkt; |
579 | delete pkt; |
571 | } |
580 | } |
572 | else if (revents & (POLLHUP | POLLERR)) |
581 | else if (revents & (POLLHUP | POLLERR)) |