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.50 by pcg, Sun Aug 10 02:49:21 2008 UTC vs.
Revision 1.57 by root, Tue Feb 8 23:13:48 2011 UTC

120 120
121 return filename; 121 return filename;
122} 122}
123 123
124int 124int
125vpn::setup_socket (u8 prot, int family, int type, int proto)
126{
127 int fd = socket (family, type, proto);
128
129 if (fd < 0)
130 {
131 slog (L_ERR, _("unable to create %s socket: %s."), strprotocol (prot), strerror (errno));
132 return fd;
133 }
134
135 fcntl (fd, F_SETFL, O_NONBLOCK);
136 fcntl (fd, F_SETFD, FD_CLOEXEC);
137
138#ifdef SO_MARK
139 if (::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));
142#endif
143
144 return fd;
145}
146
147int
125vpn::setup () 148vpn::setup ()
126{ 149{
150 int success = 0;
151
127 ipv4_tos = -1; 152 ipv4_tos = -1;
128 ipv4_fd = -1; 153 ipv4_fd = -1;
129 154
130 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 155 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
131 { 156 {
132 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto); 157 ipv4_fd = setup_socket (PROT_IPv4, PF_INET, SOCK_RAW, ::conf.ip_proto);
133 158
134 if (ipv4_fd < 0) 159 if (ipv4_fd < 0)
135 return -1; 160 return -1;
136
137 fcntl (ipv4_fd, F_SETFL, O_NONBLOCK);
138 fcntl (ipv4_fd, F_SETFD, FD_CLOEXEC);
139 161
140#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 162#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
141 // this I really consider a linux bug. I am neither connected 163 // this I really consider a linux bug. I am neither connected
142 // nor do I fragment myself. Linux still sets DF and doesn't 164 // nor do I fragment myself. Linux still sets DF and doesn't
143 // fragment for me sometimes. 165 // fragment for me sometimes.
150 sockinfo si (THISNODE, PROT_IPv4); 172 sockinfo si (THISNODE, PROT_IPv4);
151 173
152 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 174 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
153 { 175 {
154 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno)); 176 slog (L_ERR, _("can't bind ipv4 socket on %s: %s, exiting."), (const char *)si, strerror (errno));
155 exit (EXIT_FAILURE); 177 return -1;
156 } 178 }
157 179
158 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 180 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
181 ++success;
159 } 182 }
183 else
184 THISNODE->protocols &= ~PROT_IPv4;
160 185
161 udpv4_tos = -1; 186 udpv4_tos = -1;
162 udpv4_fd = -1; 187 udpv4_fd = -1;
163 188
164 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 189 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
165 { 190 {
166 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 191 udpv4_fd = setup_socket (PROT_UDPv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP);
167 192
168 if (udpv4_fd < 0) 193 if (udpv4_fd < 0)
169 return -1; 194 return -1;
170
171 fcntl (udpv4_fd, F_SETFL, O_NONBLOCK);
172 fcntl (udpv4_fd, F_SETFD, FD_CLOEXEC);
173 195
174 // standard daemon practise... 196 // standard daemon practise...
175 { 197 {
176 int oval = 1; 198 int oval = 1;
177 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 199 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
190 sockinfo si (THISNODE, PROT_UDPv4); 212 sockinfo si (THISNODE, PROT_UDPv4);
191 213
192 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 214 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
193 { 215 {
194 slog (L_ERR, _("can't bind udpv4 on %s: %s, exiting."), (const char *)si, strerror (errno)); 216 slog (L_ERR, _("can't bind udpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
195 exit (EXIT_FAILURE); 217 return -1;
196 } 218 }
197 219
198 udpv4_ev_watcher.start (udpv4_fd, EV_READ); 220 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
221 ++success;
199 } 222 }
223 else
224 THISNODE->protocols &= ~PROT_UDPv4;
200 225
201 icmpv4_tos = -1; 226 icmpv4_tos = -1;
202 icmpv4_fd = -1; 227 icmpv4_fd = -1;
203 228
204#if ENABLE_ICMP 229#if ENABLE_ICMP
205 if (THISNODE->protocols & PROT_ICMPv4) 230 if (THISNODE->protocols & PROT_ICMPv4)
206 { 231 {
207 icmpv4_fd = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP); 232 icmpv4_fd = setup_socket (PROT_ICMPv4, PF_INET, SOCK_RAW, IPPROTO_ICMP);
208 233
209 if (icmpv4_fd < 0) 234 if (icmpv4_fd < 0)
210 return -1; 235 return -1;
211
212 fcntl (icmpv4_fd, F_SETFL, O_NONBLOCK);
213 fcntl (icmpv4_fd, F_SETFD, FD_CLOEXEC);
214 236
215#ifdef ICMP_FILTER 237#ifdef ICMP_FILTER
216 { 238 {
217 icmp_filter oval; 239 icmp_filter oval;
218 oval.data = 0xffffffff; 240 oval.data = 0xffffffff;
236 sockinfo si (THISNODE, PROT_ICMPv4); 258 sockinfo si (THISNODE, PROT_ICMPv4);
237 259
238 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ())) 260 if (bind (icmpv4_fd, si.sav4 (), si.salenv4 ()))
239 { 261 {
240 slog (L_ERR, _("can't bind icmpv4 on %s: %s, exiting."), (const char *)si, strerror (errno)); 262 slog (L_ERR, _("can't bind icmpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
241 exit (EXIT_FAILURE); 263 return -1;
242 } 264 }
243 265
244 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ); 266 icmpv4_ev_watcher.start (icmpv4_fd, EV_READ);
267 ++success;
245 } 268 }
246#endif 269#endif
247 270
248 tcpv4_fd = -1; 271 tcpv4_fd = -1;
249 272
250#if ENABLE_TCP 273#if ENABLE_TCP
251 if (THISNODE->protocols & PROT_TCPv4 && THISNODE->tcp_port) 274 if (THISNODE->protocols & PROT_TCPv4 && THISNODE->tcp_port)
252 { 275 {
253 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); 276 tcpv4_fd = setup_socket (PROT_TCPv4, PF_INET, SOCK_STREAM, IPPROTO_TCP);
254 277
255 if (tcpv4_fd < 0) 278 if (tcpv4_fd < 0)
256 return -1; 279 return -1;
257
258 fcntl (tcpv4_fd, F_SETFL, O_NONBLOCK);
259 fcntl (tcpv4_fd, F_SETFD, FD_CLOEXEC);
260 280
261 // standard daemon practise... 281 // standard daemon practise...
262 { 282 {
263 int oval = 1; 283 int oval = 1;
264 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 284 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
267 sockinfo si (THISNODE, PROT_TCPv4); 287 sockinfo si (THISNODE, PROT_TCPv4);
268 288
269 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ())) 289 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
270 { 290 {
271 slog (L_ERR, _("can't bind tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno)); 291 slog (L_ERR, _("can't bind tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
272 exit (EXIT_FAILURE); 292 return -1;
273 } 293 }
274 294
275 if (listen (tcpv4_fd, 5)) 295 if (listen (tcpv4_fd, 5))
276 { 296 {
277 slog (L_ERR, _("can't listen tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno)); 297 slog (L_ERR, _("can't listen tcpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
278 exit (EXIT_FAILURE); 298 return -1;
279 } 299 }
280 300
281 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ); 301 tcpv4_ev_watcher.start (tcpv4_fd, EV_READ);
302 ++success;
282 } 303 }
304 else
305 THISNODE->protocols &= ~PROT_TCPv4;
283#endif 306#endif
284 307
285 dnsv4_tos = -1; 308 dnsv4_tos = -1;
286 dnsv4_fd = -1; 309 dnsv4_fd = -1;
287 310
288#if ENABLE_DNS 311#if ENABLE_DNS
289 if (THISNODE->protocols & PROT_DNSv4) 312 if (THISNODE->protocols & PROT_DNSv4)
290 { 313 {
291 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4); 314 dns_forwarder.set (::conf.dns_forw_host, ::conf.dns_forw_port, PROT_DNSv4);
292 315
293 dnsv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 316 dnsv4_fd = setup_socket (PROT_DNSv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP);
294 317
295 if (dnsv4_fd < 0) 318 if (dnsv4_fd < 0)
296 return -1; 319 return -1;
297
298 fcntl (dnsv4_fd, F_SETFL, O_NONBLOCK);
299 fcntl (dnsv4_fd, F_SETFD, FD_CLOEXEC);
300 320
301# if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 321# if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
302 // this I really consider a linux bug. I am neither connected 322 // this I really consider a linux bug. I am neither connected
303 // nor do I fragment myself. Linux still sets DF and doesn't 323 // nor do I fragment myself. Linux still sets DF and doesn't
304 // fragment for me sometimes. 324 // fragment for me sometimes.
319 PROT_DNSv4); 339 PROT_DNSv4);
320 340
321 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ())) 341 if (bind (dnsv4_fd, si.sav4 (), si.salenv4 ()))
322 { 342 {
323 slog (L_ERR, _("can't bind dnsv4 on %s: %s, exiting."), (const char *)si, strerror (errno)); 343 slog (L_ERR, _("can't bind dnsv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
324 exit (EXIT_FAILURE); 344 return -1;
325 } 345 }
326 346
327 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ); 347 dnsv4_ev_watcher.start (dnsv4_fd, EV_READ);
348 ++success;
328 } 349 }
329#endif 350#endif
330 351
331 ///////////////////////////////////////////////////////////////////////////// 352 /////////////////////////////////////////////////////////////////////////////
353
354 if (!success)
355 {
356 slog (L_ERR, _("no protocols enabled."));
357 return -1;
358 }
332 359
333 reconnect_all (); 360 reconnect_all ();
334 361
335 ///////////////////////////////////////////////////////////////////////////// 362 /////////////////////////////////////////////////////////////////////////////
336 363
337 tap = new tap_device (); 364 tap = new tap_device ();
338 if (!tap) //D this, of course, never catches 365 if (!tap) //D this, of course, never catches
339 { 366 {
340 slog (L_ERR, _("cannot create network interface '%s', exiting."), conf.ifname); 367 slog (L_ERR, _("cannot create network interface '%s'."), conf.ifname);
341 exit (EXIT_FAILURE); 368 return -1;
342 } 369 }
343 370
344 fcntl (tap->fd, F_SETFD, FD_CLOEXEC); 371 fcntl (tap->fd, F_SETFD, FD_CLOEXEC);
345 372
346 run_script_cb cb; 373 run_script_cb cb;
347 cb.set<vpn, &vpn::script_if_init> (this); 374 cb.set<vpn, &vpn::script_if_init> (this);
348 375
349 if (tap->if_up () && 376 if (tap->if_up () &&
350 !run_script (cb, true)) 377 !run_script (cb, true))
351 { 378 {
352 slog (L_ERR, _("interface initialization command '%s' failed, exiting."), 379 slog (L_ERR, _("interface initialization command '%s' failed."),
353 tap->if_up ()); 380 tap->if_up ());
354 exit (EXIT_FAILURE); 381 return -1;
355 } 382 }
356 383
357 cb.set<vpn, &vpn::script_if_up> (this); 384 cb.set<vpn, &vpn::script_if_up> (this);
358 if (!run_script (cb, true)) 385 if (!run_script (cb, true))
359 { 386 {
360 slog (L_ERR, _("if-up command execution failed, exiting.")); 387 slog (L_ERR, _("if-up command execution failed."));
361 exit (EXIT_FAILURE); 388 return -1;
362 } 389 }
363 390
364 tap_ev_watcher.start (tap->fd, EV_READ); 391 tap_ev_watcher.start (tap->fd, EV_READ);
365 392
366 return 0; 393 return 0;
494 return send_ipv4_packet (pkt, si, tos); 521 return send_ipv4_packet (pkt, si, tos);
495 522
496 case PROT_UDPv4: 523 case PROT_UDPv4:
497 return send_udpv4_packet (pkt, si, tos); 524 return send_udpv4_packet (pkt, si, tos);
498 525
499#if ENABLE_TCP 526#if ENABLE_TCP
500 case PROT_TCPv4: 527 case PROT_TCPv4:
501 return send_tcpv4_packet (pkt, si, tos); 528 return send_tcpv4_packet (pkt, si, tos);
502#endif 529#endif
503#if ENABLE_ICMP 530#if ENABLE_ICMP
504 case PROT_ICMPv4: 531 case PROT_ICMPv4:
731 758
732 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c) 759 for (conns_vector::iterator c = conns.begin (); c != conns.end (); ++c)
733 (*c)->establish_connection (); 760 (*c)->establish_connection ();
734} 761}
735 762
763bool
736bool vpn::can_direct (conf_node *src, conf_node *dst) const 764vpn::can_direct (conf_node *src, conf_node *dst) const
737{ 765{
738 return src != dst 766 return src != dst
739 && src->may_direct (dst) 767 && src->may_direct (dst)
740 && dst->may_direct (src) 768 && dst->may_direct (src)
741 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS) 769 && (((src->protocols & dst->protocols) && src->connectmode == conf_node::C_ALWAYS)
742 || (src->protocols & dst->connectable_protocols ())); 770 || (src->protocols & dst->connectable_protocols ()));
743} 771}
744 772
745// only works for indirect and routed connections: find a router 773// only works for indirect and routed connections: find a router
746// from THISNODE to dst 774// from THISNODE to dst
775connection *
747connection *vpn::find_router_for (const connection *dst) 776vpn::find_router_for (const connection *dst)
748{ 777{
749 connection *router = 0; 778 connection *router = 0;
750 779
751 // first try to find a router with a direct connection 780 // first try to find a router with a direct connection, route there
781 // regardless of any other considerations.
752 { 782 {
753 u32 prio = 1; 783 u32 prio = 1;
754 784
755 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 785 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
756 { 786 {
757 connection *c = *i; 787 connection *c = *i;
758 788
759 if (c->conf->routerprio > prio 789 if (c->conf->routerprio > prio
760 && c->conf != THISNODE 790 && c->conf != THISNODE
761 && c != dst
762 && can_direct (c->conf, dst->conf)) 791 && can_direct (c->conf, dst->conf)
792 && c->ictx && c->octx)
763 { 793 {
764 if (c->ictx && c->octx)
765 {
766 prio = c->conf->routerprio; 794 prio = c->conf->routerprio;
767 router = c; 795 router = c;
768 }
769 else
770 c->establish_connection ();
771 } 796 }
772 } 797 }
773 } 798 }
774 799
775 if (router) 800 if (router)
776 return router; 801 return router;
777 802
778 // second try find the router with the highest priority higher than ours 803 // second try find the router with the highest priority, higher than ours
779 { 804 {
780 u32 prio = 1; 805 u32 prio = THISNODE->routerprio ? THISNODE->routerprio : 1;
781 806
782 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 807 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
783 { 808 {
784 connection *c = *i; 809 connection *c = *i;
785 810
786 if (c->conf->routerprio > prio 811 if (c->conf->routerprio > prio
787 && c->conf->routerprio > THISNODE->routerprio
788 && c != dst 812 && c != dst
789 && c->conf != THISNODE) 813 && c->conf != THISNODE
814 && c->ictx && c->octx)
790 { 815 {
791 if (c->ictx && c->octx)
792 {
793 prio = c->conf->routerprio; 816 prio = c->conf->routerprio;
794 router = c; 817 router = c;
795 }
796 else
797 c->establish_connection ();
798 } 818 }
799 } 819 }
800 } 820 }
821
801 return router; 822 return router;
802} 823}
803 824
825void
804void vpn::connection_established (connection *c) 826vpn::connection_established (connection *c)
805{ 827{
806 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 828 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
807 { 829 {
808 connection *o = *i; 830 connection *o = *i;
809 831
817 o->rekey (); 839 o->rekey ();
818 } 840 }
819 } 841 }
820} 842}
821 843
844void
822void vpn::send_connect_request (connection *c) 845vpn::send_connect_request (connection *c)
823{ 846{
824 connection *r = find_router_for (c); 847 connection *r = find_router_for (c);
825 848
826 if (r) 849 if (r)
827 { 850 {
828 slog (L_TRACE, _("%s: no way to connect, sending mediated connection request via %s."), 851 slog (L_TRACE, _("%s: no address known, sending mediated connection request via %s."),
829 c->conf->nodename, r->conf->nodename); 852 c->conf->nodename, r->conf->nodename);
830 r->send_connect_request (c->conf->id); 853 r->send_connect_request (c->conf->id);
831 } 854 }
832 else 855 else
833 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect."), 856 slog (L_DEBUG, _("%s: no way to connect and no router found: unable to connect at this time."),
834 c->conf->nodename); 857 c->conf->nodename);
835} 858}
836 859
837void 860void
838connection::dump_status () 861connection::dump_status ()

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines