1 | /* |
1 | /* |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
2 | vpn.C -- handle the protocol, encryption, handshaking etc. |
3 | Copyright (C) 2003-2008,2010,2011 Marc Lehmann <gvpe@schmorp.de> |
3 | Copyright (C) 2003-2008,2010,2011,2013 Marc Lehmann <gvpe@schmorp.de> |
4 | |
4 | |
5 | This file is part of GVPE. |
5 | This file is part of GVPE. |
6 | |
6 | |
7 | GVPE is free software; you can redistribute it and/or modify it |
7 | GVPE is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by the |
8 | under the terms of the GNU General Public License as published by the |
… | |
… | |
59 | |
59 | |
60 | vpn network; // THE vpn (bad design...) |
60 | vpn network; // THE vpn (bad design...) |
61 | |
61 | |
62 | ///////////////////////////////////////////////////////////////////////////// |
62 | ///////////////////////////////////////////////////////////////////////////// |
63 | |
63 | |
|
|
64 | // hopefully temporary workaround for rare buffer full conditions |
|
|
65 | // if it happens, usually instantly retrying or retrying ~5ms later |
|
|
66 | // is good enough with current network technologies/kernels |
|
|
67 | |
|
|
68 | static ssize_t |
|
|
69 | xsendto (int fd, const void *buf, size_t len, int flags, |
|
|
70 | const struct sockaddr *sa, socklen_t salen) |
|
|
71 | { |
|
|
72 | ssize_t res; |
|
|
73 | |
|
|
74 | for (int retry = 0; retry <= 13; ++retry) // ~100ms |
|
|
75 | { |
|
|
76 | res = sendto (fd, buf, len, flags, sa, salen); |
|
|
77 | |
|
|
78 | if (res >= 0 || errno != ENOBUFS) |
|
|
79 | break; |
|
|
80 | |
|
|
81 | struct timespec ts = { 0, 1000 * retry }; |
|
|
82 | nanosleep (&ts, 0); |
|
|
83 | } |
|
|
84 | |
|
|
85 | return res; |
|
|
86 | } |
|
|
87 | |
|
|
88 | ///////////////////////////////////////////////////////////////////////////// |
|
|
89 | |
64 | static void inline |
90 | static void inline |
65 | set_tos (int fd, int &tos_prev, int tos) |
91 | set_tos (int fd, int &tos_prev, int tos) |
66 | { |
92 | { |
67 | #if defined(SOL_IP) && defined(IP_TOS) |
93 | #if defined(SOL_IP) && defined(IP_TOS) |
68 | if (tos_prev == tos) |
94 | if (tos_prev == tos) |
… | |
… | |
78 | { |
104 | { |
79 | // the tunnel device mtu should be the physical mtu - overhead |
105 | // the tunnel device mtu should be the physical mtu - overhead |
80 | // the tricky part is rounding to the cipher key blocksize |
106 | // the tricky part is rounding to the cipher key blocksize |
81 | int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD; |
107 | int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD; |
82 | mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion |
108 | mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion |
83 | mtu -= mtu % EVP_CIPHER_block_size (CIPHER); // round |
109 | mtu -= mtu % BLOCK_SIZE (CIPHER); // round |
84 | mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again |
110 | mtu -= ETH_OVERHEAD - 6 - 6; // and get interface mtu again |
85 | |
111 | |
86 | char *env; |
112 | char *env; |
87 | asprintf (&env, "CONFBASE=%s", confbase); putenv (env); |
113 | asprintf (&env, "CONFBASE=%s", confbase); putenv (env); |
88 | asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env); |
114 | asprintf (&env, "IFNAME=%s", tap->interface ()); putenv (env); |
… | |
… | |
113 | inline const char * |
139 | inline const char * |
114 | vpn::script_if_up () |
140 | vpn::script_if_up () |
115 | { |
141 | { |
116 | script_init_env (); |
142 | script_init_env (); |
117 | |
143 | |
118 | char *filename; |
144 | return conf.config_filename (::conf.script_if_up, "if-up"); |
119 | asprintf (&filename, |
|
|
120 | "%s/%s", |
|
|
121 | confbase, |
|
|
122 | ::conf.script_if_up ? ::conf.script_if_up : "if-up"); |
|
|
123 | |
|
|
124 | return filename; |
|
|
125 | } |
145 | } |
126 | |
146 | |
127 | int |
147 | int |
128 | vpn::setup_socket (u8 prot, int family, int type, int proto) |
148 | vpn::setup_socket (u8 prot, int family, int type, int proto) |
129 | { |
149 | { |
… | |
… | |
410 | return false; |
430 | return false; |
411 | } |
431 | } |
412 | |
432 | |
413 | if (mkdir (dir, 0700)) |
433 | if (mkdir (dir, 0700)) |
414 | { |
434 | { |
415 | slog (L_CRIT, _("unable to crate anonymous root directory.")); |
435 | slog (L_CRIT, _("unable to create anonymous root directory.")); |
416 | return false; |
436 | return false; |
417 | } |
437 | } |
418 | |
438 | |
419 | if (chdir (dir)) |
439 | if (chdir (dir)) |
420 | { |
440 | { |
… | |
… | |
466 | |
486 | |
467 | bool |
487 | bool |
468 | vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) |
488 | vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) |
469 | { |
489 | { |
470 | set_tos (ipv4_fd, ipv4_tos, tos); |
490 | set_tos (ipv4_fd, ipv4_tos, tos); |
471 | sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
491 | xsendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
472 | |
492 | |
473 | return true; |
493 | return true; |
474 | } |
494 | } |
475 | |
495 | |
476 | static u16 |
496 | static u16 |
… | |
… | |
507 | hdr->code = 255; |
527 | hdr->code = 255; |
508 | hdr->checksum = 0; |
528 | hdr->checksum = 0; |
509 | hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len); |
529 | hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len); |
510 | |
530 | |
511 | set_tos (icmpv4_fd, icmpv4_tos, tos); |
531 | set_tos (icmpv4_fd, icmpv4_tos, tos); |
512 | sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
532 | xsendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
513 | |
533 | |
514 | return true; |
534 | return true; |
515 | } |
535 | } |
516 | #endif |
536 | #endif |
517 | |
537 | |
518 | bool |
538 | bool |
519 | vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) |
539 | vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) |
520 | { |
540 | { |
521 | set_tos (udpv4_fd, udpv4_tos, tos); |
541 | set_tos (udpv4_fd, udpv4_tos, tos); |
522 | sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
542 | xsendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); |
523 | |
543 | |
524 | return true; |
544 | return true; |
525 | } |
545 | } |
526 | |
546 | |
527 | void |
547 | void |
… | |
… | |
895 | { |
915 | { |
896 | for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) |
916 | for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) |
897 | { |
917 | { |
898 | connection *o = *i; |
918 | connection *o = *i; |
899 | |
919 | |
900 | if (!o->is_direct |
|
|
901 | && o->si.valid () |
920 | if (o->si.valid () |
902 | && c->si != o->si |
921 | && c->si != o->si |
903 | && c == find_router_for (o)) |
922 | && c == find_router_for (o) |
|
|
923 | && !can_direct (THISNODE, o->conf)) |
904 | { |
924 | { |
905 | slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."), |
925 | slog (L_DEBUG, _("%s: can now route packets via %s, re-keying connection."), |
906 | o->conf->nodename, c->conf->nodename); |
926 | o->conf->nodename, c->conf->nodename); |
907 | o->rekey (); |
927 | o->rekey (); |
908 | } |
928 | } |