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.35 by pcg, Fri Apr 8 16:12:49 2005 UTC vs.
Revision 1.41 by pcg, Sun Dec 2 00:20:19 2007 UTC

14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details. 15 GNU General Public License for more details.
16 16
17 You should have received a copy of the GNU General Public License 17 You should have received a copy of the GNU General Public License
18 along with gvpe; if not, write to the Free Software 18 along with gvpe; if not, write to the Free Software
19 Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20*/ 20*/
21 21
22#include "config.h" 22#include "config.h"
23 23
24#include <list> 24#include <list>
46 46
47vpn network; // THE vpn (bad design...) 47vpn network; // THE vpn (bad design...)
48 48
49///////////////////////////////////////////////////////////////////////////// 49/////////////////////////////////////////////////////////////////////////////
50 50
51static void inline
52set_tos (int fd, int &tos_prev, int tos)
53{
54#if defined(SOL_IP) && defined(IP_TOS)
55 if (tos_prev == tos)
56 return;
57
58 tos_prev = tos;
59 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos);
60#endif
61}
62
51void 63void
52vpn::script_init_env () 64vpn::script_init_env ()
53{ 65{
54 // the tunnel device mtu should be the physical mtu - overhead 66 // the tunnel device mtu should be the physical mtu - overhead
55 // the tricky part is rounding to the cipher key blocksize 67 // the tricky part is rounding to the cipher key blocksize
98} 110}
99 111
100int 112int
101vpn::setup () 113vpn::setup ()
102{ 114{
115 ipv4_tos = -1;
103 ipv4_fd = -1; 116 ipv4_fd = -1;
104 117
105 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 118 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
106 { 119 {
107 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto); 120 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
108 121
109 if (ipv4_fd < 0) 122 if (ipv4_fd < 0)
110 return -1; 123 return -1;
111 124
112 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK); 125 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK);
126 fcntl (ipv4_fd, F_SETFD, FD_CLOEXEC);
113 127
114#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 128#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
115 // this I really consider a linux bug. I am neither connected 129 // this I really consider a linux bug. I am neither connected
116 // nor do I fragment myself. Linux still sets DF and doesn't 130 // nor do I fragment myself. Linux still sets DF and doesn't
117 // fragment for me sometimes. 131 // fragment for me sometimes.
127 { 141 {
128 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno)); 142 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno));
129 exit (EXIT_FAILURE); 143 exit (EXIT_FAILURE);
130 } 144 }
131 145
132 ipv4_ev_watcher.start (ipv4_fd, EVENT_READ); 146 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
133 } 147 }
134 148
149 udpv4_tos = -1;
135 udpv4_fd = -1; 150 udpv4_fd = -1;
136 151
137 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 152 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
138 { 153 {
139 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 154 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
140 155
141 if (udpv4_fd < 0) 156 if (udpv4_fd < 0)
142 return -1; 157 return -1;
143 158
144 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK); 159 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK);
160 fcntl (udpv4_fd, F_SETFD, FD_CLOEXEC);
145 161
146 // standard daemon practise... 162 // standard daemon practise...
147 { 163 {
148 int oval = 1; 164 int oval = 1;
149 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 165 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
165 { 181 {
166 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno)); 182 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
167 exit (EXIT_FAILURE); 183 exit (EXIT_FAILURE);
168 } 184 }
169 185
170 udpv4_ev_watcher.start (udpv4_fd, EVENT_READ); 186 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
171 } 187 }
172 188
189 icmpv4_tos = -1;
173 icmpv4_fd = -1; 190 icmpv4_fd = -1;
174 191
175#if ENABLE_ICMP 192#if ENABLE_ICMP
176 if (THISNODE->protocols & PROT_ICMPv4) 193 if (THISNODE->protocols & PROT_ICMPv4)
177 { 194 {
178 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP); 195 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
179 196
180 if (icmpv4_fd < 0) 197 if (icmpv4_fd < 0)
181 return -1; 198 return -1;
182 199
183 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK); 200 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK);
201 fcntl (icmpv4_fd, F_SETFD, FD_CLOEXEC);
184 202
185#ifdef ICMP_FILTER 203#ifdef ICMP_FILTER
186 { 204 {
187 icmp_filter oval; 205 icmp_filter oval;
188 oval.data = 0xffffffff; 206 oval.data = 0xffffffff;
197 // this I really consider a linux bug. I am neither connected 215 // this I really consider a linux bug. I am neither connected
198 // nor do I fragment myself. Linux still sets DF and doesn't 216 // nor do I fragment myself. Linux still sets DF and doesn't
199 // fragment for me sometimes. 217 // fragment for me sometimes.
200 { 218 {
201 int oval = IP_PMTUDISC_DONT; 219 int oval = IP_PMTUDISC_DONT;
202 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 220 setsockopt (icmpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
203 } 221 }
204#endif 222#endif
205 223
206 sockinfo si (THISNODE, PROT_ICMPv4); 224 sockinfo si (THISNODE, PROT_ICMPv4);
207 225
209 { 227 {
210 slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno)); 228 slog (L_ERR, _("can't bind icmpv4 on %s: %s"), (const char *)si, strerror (errno));
211 exit (EXIT_FAILURE); 229 exit (EXIT_FAILURE);
212 } 230 }
213 231
214 icmpv4_ev_watcher.start (icmpv4_fd, EVENT_READ); 232 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
215 } 233 }
216#endif 234#endif
217 235
218 tcpv4_fd = -1; 236 tcpv4_fd = -1;
219 237
224 242
225 if (tcpv4_fd < 0) 243 if (tcpv4_fd < 0)
226 return -1; 244 return -1;
227 245
228 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK); 246 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK);
247 fcntl (tcpv4_fd, F_SETFD, FD_CLOEXEC);
229 248
230 // standard daemon practise... 249 // standard daemon practise...
231 { 250 {
232 int oval = 1; 251 int oval = 1;
233 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 252 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
245 { 264 {
246 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno)); 265 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
247 exit (EXIT_FAILURE); 266 exit (EXIT_FAILURE);
248 } 267 }
249 268
250 tcpv4_ev_watcher.start (tcpv4_fd, EVENT_READ); 269 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ);
251 } 270 }
252#endif 271#endif
272
273 dnsv4_tos = -1;
274 dnsv4_fd = -1;
253 275
254#if ENABLE_DNS 276#if ENABLE_DNS
255 if (THISNODE->protocols & PROT_DNSv4) 277 if (THISNODE->protocols & PROT_DNSv4)
256 { 278 {
257 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4); 279 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
258 280
259 dnsv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 281 dnsv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
260 282
261 if (dnsv4_fd < 0) 283 if (dnsv4_fd < 0)
262 return -1; 284 return -1;
285
286 fcntl (dnsv4_fd, F_SETFL, O_NONBLOCK);
287 fcntl (dnsv4_fd, F_SETFD, FD_CLOEXEC);
263 288
264# if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 289# if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
265 // this I really consider a linux bug. I am neither connected 290 // this I really consider a linux bug. I am neither connected
266 // nor do I fragment myself. Linux still sets DF and doesn't 291 // nor do I fragment myself. Linux still sets DF and doesn't
267 // fragment for me sometimes. 292 // fragment for me sometimes.
285 { 310 {
286 slog (L_ERR, _("can't bind dnsv4 on %s: %s"), (const char *)si, strerror (errno)); 311 slog (L_ERR, _("can't bind dnsv4 on %s: %s"), (const char *)si, strerror (errno));
287 exit (EXIT_FAILURE); 312 exit (EXIT_FAILURE);
288 } 313 }
289 314
290 dnsv4_ev_watcher.start (dnsv4_fd, EVENT_READ); 315 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
291 } 316 }
292#endif 317#endif
293 318
294 ///////////////////////////////////////////////////////////////////////////// 319 /////////////////////////////////////////////////////////////////////////////
295 320
302 { 327 {
303 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 328 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname);
304 exit (EXIT_FAILURE); 329 exit (EXIT_FAILURE);
305 } 330 }
306 331
332 fcntl (tap->fd, F_SETFD, FD_CLOEXEC);
333
307 if (tap->if_up () && 334 if (tap->if_up () &&
308 !run_script (run_script_cb (this, &vpn::script_if_init), true)) 335 !run_script (run_script_cb (this, &vpn::script_if_init), true))
309 { 336 {
310 slog (L_ERR, _("interface initialization command '%s' failed, exiting."), 337 slog (L_ERR, _("interface initialization command '%s' failed, exiting."),
311 tap->if_up ()); 338 tap->if_up ());
316 { 343 {
317 slog (L_ERR, _("if-up command execution failed, exiting.")); 344 slog (L_ERR, _("if-up command execution failed, exiting."));
318 exit (EXIT_FAILURE); 345 exit (EXIT_FAILURE);
319 } 346 }
320 347
321 tap_ev_watcher.start (tap->fd, EVENT_READ); 348 tap_ev_watcher.start (tap->fd, EV_READ);
322 349
323 return 0; 350 return 0;
324} 351}
325 352
326bool 353bool
327vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 354vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
328{ 355{
329#if defined(SOL_IP) && defined(IP_TOS) 356 set_tos (ipv4_fd, ipv4_tos, tos);
330 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
331#endif
332 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 357 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
333 358
334 return true; 359 return true;
335} 360}
336 361
359 384
360#if ENABLE_ICMP 385#if ENABLE_ICMP
361bool 386bool
362vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 387vpn::send_icmpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
363{ 388{
364#if defined(SOL_IP) && defined(IP_TOS)
365 setsockopt (icmpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
366#endif
367
368 pkt->unshift_hdr (4); 389 pkt->unshift_hdr (4);
369 390
370 icmp_header *hdr = (icmp_header *)&((*pkt)[0]); 391 icmp_header *hdr = (icmp_header *)&((*pkt)[0]);
371 hdr->type = ::conf.icmp_type; 392 hdr->type = ::conf.icmp_type;
372 hdr->code = 255; 393 hdr->code = 255;
373 hdr->checksum = 0; 394 hdr->checksum = 0;
374 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len); 395 hdr->checksum = ipv4_checksum ((u16 *)hdr, pkt->len);
375 396
397 set_tos (icmpv4_fd, icmpv4_tos, tos);
376 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 398 sendto (icmpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
377 399
378 return true; 400 return true;
379} 401}
380#endif 402#endif
381 403
382bool 404bool
383vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 405vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
384{ 406{
385#if defined(SOL_IP) && defined(IP_TOS) 407 set_tos (udpv4_fd, udpv4_tos, tos);
386 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
387#endif
388 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 408 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
389 409
390 return true; 410 return true;
391} 411}
392 412
454{ 474{
455 switch (si.prot) 475 switch (si.prot)
456 { 476 {
457 case PROT_IPv4: 477 case PROT_IPv4:
458 return send_ipv4_packet (pkt, si, tos); 478 return send_ipv4_packet (pkt, si, tos);
479
459 case PROT_UDPv4: 480 case PROT_UDPv4:
460 return send_udpv4_packet (pkt, si, tos); 481 return send_udpv4_packet (pkt, si, tos);
482
461#if ENABLE_TCP 483#if ENABLE_TCP
462 case PROT_TCPv4: 484 case PROT_TCPv4:
463 return send_tcpv4_packet (pkt, si, tos); 485 return send_tcpv4_packet (pkt, si, tos);
464#endif 486#endif
465#if ENABLE_ICMP 487#if ENABLE_ICMP
468#endif 490#endif
469#if ENABLE_DNS 491#if ENABLE_DNS
470 case PROT_DNSv4: 492 case PROT_DNSv4:
471 return send_dnsv4_packet (pkt, si, tos); 493 return send_dnsv4_packet (pkt, si, tos);
472#endif 494#endif
473
474 default: 495 default:
475 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si); 496 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si);
476 } 497 }
477 498
478 return false; 499 return false;
479} 500}
480 501
481void 502void
482vpn::ipv4_ev (io_watcher &w, short revents) 503vpn::ipv4_ev (ev::io &w, int revents)
483{ 504{
484 if (revents & EVENT_READ) 505 if (revents & EV_READ)
485 { 506 {
486 vpn_packet *pkt = new vpn_packet; 507 vpn_packet *pkt = new vpn_packet;
487 struct sockaddr_in sa; 508 struct sockaddr_in sa;
488 socklen_t sa_len = sizeof (sa); 509 socklen_t sa_len = sizeof (sa);
489 int len; 510 int len;
518 } 539 }
519} 540}
520 541
521#if ENABLE_ICMP 542#if ENABLE_ICMP
522void 543void
523vpn::icmpv4_ev (io_watcher &w, short revents) 544vpn::icmpv4_ev (ev::io &w, int revents)
524{ 545{
525 if (revents & EVENT_READ) 546 if (revents & EV_READ)
526 { 547 {
527 vpn_packet *pkt = new vpn_packet; 548 vpn_packet *pkt = new vpn_packet;
528 struct sockaddr_in sa; 549 struct sockaddr_in sa;
529 socklen_t sa_len = sizeof (sa); 550 socklen_t sa_len = sizeof (sa);
530 int len; 551 int len;
566 } 587 }
567} 588}
568#endif 589#endif
569 590
570void 591void
571vpn::udpv4_ev (io_watcher &w, short revents) 592vpn::udpv4_ev (ev::io &w, int revents)
572{ 593{
573 if (revents & EVENT_READ) 594 if (revents & EV_READ)
574 { 595 {
575 vpn_packet *pkt = new vpn_packet; 596 vpn_packet *pkt = new vpn_packet;
576 struct sockaddr_in sa; 597 struct sockaddr_in sa;
577 socklen_t sa_len = sizeof (sa); 598 socklen_t sa_len = sizeof (sa);
578 int len; 599 int len;
603 exit (EXIT_FAILURE); 624 exit (EXIT_FAILURE);
604 } 625 }
605} 626}
606 627
607void 628void
608vpn::tap_ev (io_watcher &w, short revents) 629vpn::tap_ev (ev::io &w, int revents)
609{ 630{
610 if (revents & EVENT_READ) 631 if (revents & EV_READ)
611 { 632 {
612 /* process data */ 633 /* process data */
613 tap_packet *pkt; 634 tap_packet *pkt;
614 635
615 pkt = tap->recv (); 636 pkt = tap->recv ();
645 else 666 else
646 abort (); 667 abort ();
647} 668}
648 669
649void 670void
650vpn::event_cb (time_watcher &w) 671vpn::event_cb (ev::timer &w, int)
651{ 672{
652 if (events) 673 if (events)
653 { 674 {
654 if (events & EVENT_SHUTDOWN) 675 if (events & EVENT_SHUTDOWN)
655 { 676 {
746} 767}
747 768
748void 769void
749vpn::dump_status () 770vpn::dump_status ()
750{ 771{
751 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)NOW); 772 slog (L_NOTICE, _("BEGIN status dump (%ld)"), (long)ev_now ());
752 773
753 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 774 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
754 (*c)->dump_status (); 775 (*c)->dump_status ();
755 776
756 slog (L_NOTICE, _("END status dump")); 777 slog (L_NOTICE, _("END status dump"));

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines