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

Comparing gvpe/src/vpn.C (file contents):
Revision 1.54 by pcg, Mon Mar 23 15:22:00 2009 UTC vs.
Revision 1.62 by root, Sat Dec 17 22:05:34 2011 UTC

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 Marc Lehmann <gvpe@schmorp.de> 3 Copyright (C) 2003-2008,2010,2011 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
135 fcntl (fd, F_SETFL, O_NONBLOCK); 135 fcntl (fd, F_SETFL, O_NONBLOCK);
136 fcntl (fd, F_SETFD, FD_CLOEXEC); 136 fcntl (fd, F_SETFD, FD_CLOEXEC);
137 137
138#ifdef SO_MARK 138#ifdef SO_MARK
139 if (::conf.nfmark) 139 if (::conf.nfmark)
140 setsockopt (ipv4_fd, SOL_SOCKET, SO_MARK, &::conf.nfmark, sizeof ::conf.nfmark); 140 if (setsockopt (fd, SOL_SOCKET, SO_MARK, &::conf.nfmark, sizeof ::conf.nfmark))
141 slog (L_WARN, _("unable to set nfmark on %s socket: %s"), strprotocol (prot), strerror (errno));
141#endif 142#endif
142 143
143 return fd; 144 return fd;
144} 145}
145 146
146int 147int
147vpn::setup () 148vpn::setup ()
148{ 149{
149 int success = 0; 150 int success = 0;
150 151
152#if 1//D2
151 ipv4_tos = -1; 153 ipv42_tos = -1;
152 ipv4_fd = -1; 154 ipv42_fd = -1;
153 155
154 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 156 if (THISNODE->protocols & PROT_IPv42 && ::conf.ip_proto)
155 { 157 {
156 ipv4_fd = setup_socket (PROT_IPv4, PF_INET, SOCK_RAW, ::conf.ip_proto); 158 ipv42_fd = setup_socket (PROT_IPv42, PF_INET, SOCK_RAW, ::conf.ip2_proto);
157 159
158 if (ipv4_fd < 0) 160 if (ipv42_fd < 0)
159 return -1; 161 return -1;
160 162
161#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 163#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
162 // this I really consider a linux bug. I am neither connected 164 // this I really consider a linux bug. I am neither connected
163 // nor do I fragment myself. Linux still sets DF and doesn't 165 // nor do I fragment myself. Linux still sets DF and doesn't
164 // fragment for me sometimes. 166 // fragment for me sometimes.
165 { 167 {
166 int oval = IP_PMTUDISC_DONT; 168 int oval = IP_PMTUDISC_DONT;
167 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 169 setsockopt (ipv42_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
168 } 170 }
169#endif 171#endif
170 172
171 sockinfo si (THISNODE, PROT_IPv4); 173 sockinfo si (THISNODE, PROT_IPv42);
172 174
173 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 175 if (bind (ipv42_fd, si.sav4 (), si.salenv4 ()))
174 { 176 {
175 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno)); 177 slog (L_ERR, _("can't bind ipv42 socket on %s: %s, exiting."), (const char *)si, strerror (errno));
176 return -1; 178 return -1;
177 } 179 }
178 180
179 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 181 ipv42_ev_watcher.start (ipv42_fd, EV_READ);
180 ++success; 182 ++success;
181 } 183 }
182 else 184 else
183 THISNODE->protocols &= ~PROT_IPv4; 185 THISNODE->protocols &= ~PROT_IPv42;
186#endif
184 187
185 udpv4_tos = -1; 188 ipv4_tos = -1;
186 udpv4_fd = -1; 189 ipv4_fd = -1;
187 190
188 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 191 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
189 { 192 {
190 udpv4_fd = setup_socket (PROT_UDPv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP); 193 ipv4_fd = setup_socket (PROT_IPv4, PF_INET, SOCK_RAW, ::conf.ip_proto);
191 194
192 if (udpv4_fd < 0) 195 if (ipv4_fd < 0)
193 return -1; 196 return -1;
194
195 // standard daemon practise...
196 {
197 int oval = 1;
198 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
199 }
200 197
201#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 198#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
202 // this I really consider a linux bug. I am neither connected 199 // this I really consider a linux bug. I am neither connected
203 // nor do I fragment myself. Linux still sets DF and doesn't 200 // nor do I fragment myself. Linux still sets DF and doesn't
204 // fragment for me sometimes. 201 // fragment for me sometimes.
205 { 202 {
206 int oval = IP_PMTUDISC_DONT; 203 int oval = IP_PMTUDISC_DONT;
204 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
205 }
206#endif
207
208 sockinfo si (THISNODE, PROT_IPv4);
209
210 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
211 {
212 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno));
213 return -1;
214 }
215
216 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
217 ++success;
218 }
219 else
220 THISNODE->protocols &= ~PROT_IPv4;
221
222 udpv4_tos = -1;
223 udpv4_fd = -1;
224
225 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
226 {
227 udpv4_fd = setup_socket (PROT_UDPv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP);
228
229 if (udpv4_fd < 0)
230 return -1;
231
232 // standard daemon practise...
233 {
234 int oval = 1;
235 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
236 }
237
238#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
239 // this I really consider a linux bug. I am neither connected
240 // nor do I fragment myself. Linux still sets DF and doesn't
241 // fragment for me sometimes.
242 {
243 int oval = IP_PMTUDISC_DONT;
207 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 244 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
208 } 245 }
209#endif 246#endif
210 247
211 sockinfo si (THISNODE, PROT_UDPv4); 248 sockinfo si (THISNODE, PROT_UDPv4);
398 set_tos (ipv4_fd, ipv4_tos, tos); 435 set_tos (ipv4_fd, ipv4_tos, tos);
399 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 436 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
400 437
401 return true; 438 return true;
402} 439}
440
441#if 1 //D
442bool
443vpn::send_ipv42_packet (vpn_packet *pkt, const sockinfo &si, int tos)
444{
445 set_tos (ipv42_fd, ipv42_tos, tos);
446 sendto (ipv42_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
447
448 return true;
449}
450#endif
403 451
404static u16 452static u16
405ipv4_checksum (u16 *data, unsigned int len) 453ipv4_checksum (u16 *data, unsigned int len)
406{ 454{
407 // use 32 bit accumulator and fold back carry bits at the end 455 // use 32 bit accumulator and fold back carry bits at the end
481 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len); 529 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst (), pkt->len);
482 530
483 if (src == 0 || src > conns.size () 531 if (src == 0 || src > conns.size ()
484 || dst > conns.size () 532 || dst > conns.size ()
485 || pkt->typ () >= vpn_packet::PT_MAX) 533 || pkt->typ () >= vpn_packet::PT_MAX)
486 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
487 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
488 else if (dst > conns.size ())
489 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."), 534 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)."),
490 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 535 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
491 else 536 else
492 { 537 {
493 connection *c = conns[src - 1]; 538 connection *c = conns[src - 1];
514bool 559bool
515vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos) 560vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
516{ 561{
517 switch (si.prot) 562 switch (si.prot)
518 { 563 {
564#if 1//D2
565 case PROT_IPv42:
566 return send_ipv42_packet (pkt, si, tos);
567#endif
568
519 case PROT_IPv4: 569 case PROT_IPv4:
520 return send_ipv4_packet (pkt, si, tos); 570 return send_ipv4_packet (pkt, si, tos);
521 571
522 case PROT_UDPv4: 572 case PROT_UDPv4:
523 return send_udpv4_packet (pkt, si, tos); 573 return send_udpv4_packet (pkt, si, tos);
524 574
525#if ENABLE_TCP 575#if ENABLE_TCP
526 case PROT_TCPv4: 576 case PROT_TCPv4:
527 return send_tcpv4_packet (pkt, si, tos); 577 return send_tcpv4_packet (pkt, si, tos);
528#endif 578#endif
529#if ENABLE_ICMP 579#if ENABLE_ICMP
530 case PROT_ICMPv4: 580 case PROT_ICMPv4:
539 } 589 }
540 590
541 return false; 591 return false;
542} 592}
543 593
594#if 1//D2
544inline void 595inline void
545vpn::ipv4_ev (ev::io &w, int revents) 596vpn::ipv42_ev (ev::io &w, int revents)
546{ 597{
547 if (revents & EV_READ) 598 if (revents & EV_READ)
548 { 599 {
549 vpn_packet *pkt = new vpn_packet; 600 vpn_packet *pkt = new vpn_packet;
550 struct sockaddr_in sa; 601 struct sockaddr_in sa;
551 socklen_t sa_len = sizeof (sa); 602 socklen_t sa_len = sizeof (sa);
552 int len; 603 int len;
553 604
554 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 605 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
555 606
607 sockinfo si(sa, PROT_IPv42);
608
609 if (len > 0)
610 {
611 pkt->len = len;
612
613 // raw sockets deliver the ipv4 header, but don't expect it on sends
614 pkt->skip_hdr (pkt->ipv4_hdr_len ());
615
616 recv_vpn_packet (pkt, si);
617 }
618 else
619 {
620 // probably ECONNRESET or somesuch
621 slog (L_DEBUG, _("%s: %s."), (const char *)si, strerror (errno));
622 }
623
624 delete pkt;
625 }
626 else
627 {
628 slog (L_ERR,
629 _("FATAL: unknown revents %08x in socket, exiting.\n"),
630 revents);
631 exit (EXIT_FAILURE);
632 }
633}
634#endif
635
636inline void
637vpn::ipv4_ev (ev::io &w, int revents)
638{
639 if (revents & EV_READ)
640 {
641 vpn_packet *pkt = new vpn_packet;
642 struct sockaddr_in sa;
643 socklen_t sa_len = sizeof (sa);
644 int len;
645
646 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
647
556 sockinfo si(sa, PROT_IPv4); 648 sockinfo si(sa, PROT_IPv4);
557 649
558 if (len > 0) 650 if (len > 0)
559 { 651 {
560 pkt->len = len; 652 pkt->len = len;
561 653
562 // raw sockets deliver the ipv4 header, but don't expect it on sends 654 // raw sockets deliver the ipv4 header, but don't expect it on sends
563 pkt->skip_hdr (IP_OVERHEAD); 655 pkt->skip_hdr (pkt->ipv4_hdr_len ());
564 656
565 recv_vpn_packet (pkt, si); 657 recv_vpn_packet (pkt, si);
566 } 658 }
567 else 659 else
568 { 660 {
605 if (hdr->type == ::conf.icmp_type 697 if (hdr->type == ::conf.icmp_type
606 && hdr->code == 255) 698 && hdr->code == 255)
607 { 699 {
608 // raw sockets deliver the ipv4, but don't expect it on sends 700 // raw sockets deliver the ipv4, but don't expect it on sends
609 // this is slow, but... 701 // this is slow, but...
610 pkt->skip_hdr (ICMP_OVERHEAD); 702 pkt->skip_hdr (pkt->ipv4_hdr_len () + (ICMP_OVERHEAD - IP_OVERHEAD));
611 703
612 recv_vpn_packet (pkt, si); 704 recv_vpn_packet (pkt, si);
613 } 705 }
614 } 706 }
615 else 707 else
757 849
758 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 850 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
759 (*c)->establish_connection (); 851 (*c)->establish_connection ();
760} 852}
761 853
854bool
762bool vpn::can_direct (conf_node *src, conf_node *dst) const 855vpn::can_direct (conf_node *src, conf_node *dst) const
763{ 856{
764 return src != dst 857 return src != dst
765 && src->may_direct (dst) 858 && src->may_direct (dst)
766 && dst->may_direct (src) 859 && dst->may_direct (src)
767 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS) 860 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
768 || (src->protocols & dst->connectable_protocols ())); 861 || (src->protocols & dst->connectable_protocols ()));
769} 862}
770 863
771// only works for indirect and routed connections: find a router 864// only works for indirect and routed connections: find a router
772// from THISNODE to dst 865// from THISNODE to dst
866connection *
773connection *vpn::find_router_for (const connection *dst) 867vpn::find_router_for (const connection *dst)
774{ 868{
775 connection *router = 0; 869 connection *router = 0;
776 870
777 // first try to find a router with a direct connection, route there 871 // first try to find a router with a direct connection, route there
778 // regardless of any other considerations. 872 // regardless of any other considerations.
817 } 911 }
818 912
819 return router; 913 return router;
820} 914}
821 915
916void
822void vpn::connection_established (connection *c) 917vpn::connection_established (connection *c)
823{ 918{
824 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 919 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
825 { 920 {
826 connection *o = *i; 921 connection *o = *i;
827 922
835 o->rekey (); 930 o->rekey ();
836 } 931 }
837 } 932 }
838} 933}
839 934
935void
840void vpn::send_connect_request (connection *c) 936vpn::send_connect_request (connection *c)
841{ 937{
842 connection *r = find_router_for (c); 938 connection *r = find_router_for (c);
843 939
844 if (r) 940 if (r)
845 { 941 {
876vpn::vpn (void) 972vpn::vpn (void)
877{ 973{
878 event .set<vpn, &vpn::event_cb > (this); 974 event .set<vpn, &vpn::event_cb > (this);
879 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this); 975 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
880 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this); 976 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this);
977#if 1//D2
978 ipv42_ev_watcher .set<vpn, &vpn::ipv42_ev > (this);
979#endif
881#if ENABLE_TCP 980#if ENABLE_TCP
882 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this); 981 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
883#endif 982#endif
884#if ENABLE_ICMP 983#if ENABLE_ICMP
885 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this); 984 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines