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.1 by pcg, Wed Apr 2 03:25:17 2003 UTC vs.
Revision 1.8 by pcg, Mon Apr 7 01:28:56 2003 UTC

40#include "util.h" 40#include "util.h"
41#include "vpn.h" 41#include "vpn.h"
42 42
43///////////////////////////////////////////////////////////////////////////// 43/////////////////////////////////////////////////////////////////////////////
44 44
45const char *vpn::script_if_up (int) 45const char *vpn::script_if_up ()
46{ 46{
47 // the tunnel device mtu should be the physical mtu - overhead 47 // the tunnel device mtu should be the physical mtu - overhead
48 // the tricky part is rounding to the cipher key blocksize 48 // the tricky part is rounding to the cipher key blocksize
49 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD; 49 int mtu = conf.mtu - ETH_OVERHEAD - VPE_OVERHEAD - MAX_OVERHEAD;
50 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion 50 mtu += ETH_OVERHEAD - 6 - 6; // now we have the data portion
71} 71}
72 72
73int 73int
74vpn::setup () 74vpn::setup ()
75{ 75{
76 sockinfo si; 76 ipv4_fd = -1;
77 77
78 si.set (THISNODE); 78 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
79 {
80 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
81
82 if (ipv4_fd < 0)
83 return -1;
84
85 sockinfo si (THISNODE, PROT_IPv4);
86
87 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
88 {
89 slog (L_ERR, _("can't bind ipv4 socket on %s: %s"), (const char *)si, strerror (errno));
90 exit (1);
91 }
92
93#ifdef IP_MTU_DISCOVER
94 // this I really consider a linux bug. I am neither connected
95 // nor do I fragment myself. Linux still sets DF and doesn't
96 // fragment for me sometimes.
97 {
98 int oval = IP_PMTUDISC_DONT;
99 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
100 }
101#endif
102
103 ipv4_ev_watcher.start (ipv4_fd, POLLIN);
104 }
79 105
80 udpv4_fd = -1; 106 udpv4_fd = -1;
81 107
82 if (THISNODE->protocols & PROT_UDPv4) 108 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
83 { 109 {
84 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); 110 udpv4_fd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);
85 111
86 if (udpv4_fd < 0) 112 if (udpv4_fd < 0)
87 return -1; 113 return -1;
88 114
115 // standard daemon practise...
116 {
117 int oval = 1;
118 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
119 }
120
121 sockinfo si (THISNODE, PROT_UDPv4);
122
89 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ())) 123 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
90 { 124 {
91 slog (L_ERR, _("can't bind udpv4 to %s: %s"), (const char *)si, strerror (errno)); 125 slog (L_ERR, _("can't bind udpv4 on %s: %s"), (const char *)si, strerror (errno));
92 exit (1); 126 exit (1);
93 } 127 }
94 128
95#ifdef IP_MTU_DISCOVER 129#ifdef IP_MTU_DISCOVER
96 // this I really consider a linux bug. I am neither connected 130 // this I really consider a linux bug. I am neither connected
100 int oval = IP_PMTUDISC_DONT; 134 int oval = IP_PMTUDISC_DONT;
101 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 135 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
102 } 136 }
103#endif 137#endif
104 138
139 udpv4_ev_watcher.start (udpv4_fd, POLLIN);
140 }
141
142 tcpv4_fd = -1;
143
144#if ENABLE_TCP
145 if (THISNODE->protocols & PROT_TCPv4 && THISNODE->tcp_port)
146 {
147 tcpv4_fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
148
149 if (tcpv4_fd < 0)
150 return -1;
151
105 // standard daemon practise... 152 // standard daemon practise...
106 { 153 {
107 int oval = 1; 154 int oval = 1;
108 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval); 155 setsockopt (tcpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
109 } 156 }
110 157
111 udpv4_ev_watcher.start (udpv4_fd, POLLIN); 158 sockinfo si (THISNODE, PROT_TCPv4);
112 }
113 159
114 ipv4_fd = -1;
115 if (THISNODE->protocols & PROT_IPv4)
116 {
117 ipv4_fd = socket (PF_INET, SOCK_RAW, ::conf.ip_proto);
118
119 if (ipv4_fd < 0)
120 return -1;
121
122 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 160 if (bind (tcpv4_fd, si.sav4 (), si.salenv4 ()))
123 { 161 {
124 slog (L_ERR, _("can't bind ipv4 socket to %s: %s"), (const char *)si, strerror (errno)); 162 slog (L_ERR, _("can't bind tcpv4 on %s: %s"), (const char *)si, strerror (errno));
125 exit (1); 163 exit (1);
126 } 164 }
127 165
128#ifdef IP_MTU_DISCOVER 166 if (listen (tcpv4_fd, 5))
129 // this I really consider a linux bug. I am neither connected
130 // nor do I fragment myself. Linux still sets DF and doesn't
131 // fragment for me sometimes.
132 { 167 {
133 int oval = IP_PMTUDISC_DONT; 168 slog (L_ERR, _("can't listen tcpv4 on %s: %s"), (const char *)si, strerror (errno));
134 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 169 exit (1);
135 } 170 }
171
172 tcpv4_ev_watcher.start (tcpv4_fd, POLLIN);
173 }
136#endif 174#endif
137
138 ipv4_ev_watcher.start (ipv4_fd, POLLIN);
139 }
140 175
141 tap = new tap_device (); 176 tap = new tap_device ();
142 if (!tap) //D this, of course, never catches 177 if (!tap) //D this, of course, never catches
143 { 178 {
144 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname); 179 slog (L_ERR, _("cannot create network interface '%s'"), conf.ifname);
152 reconnect_all (); 187 reconnect_all ();
153 188
154 return 0; 189 return 0;
155} 190}
156 191
157void 192// send a vpn packet out to other hosts
193bool
194vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
195{
196 switch (si.prot)
197 {
198 case PROT_IPv4:
199 return send_ipv4_packet (pkt, si, tos);
200
201 case PROT_UDPv4:
202 return send_udpv4_packet (pkt, si, tos);
203
204#if ENABLE_TCP
205 case PROT_TCPv4:
206 return send_tcpv4_packet (pkt, si, tos);
207#endif
208
209 default:
210 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol"), (const char *)si);
211 return false;
212 }
213}
214
215bool
158vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 216vpn::send_ipv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
159{ 217{
160 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 218 setsockopt (ipv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
161 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 219 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
162}
163 220
164void 221 return true;
222}
223
224bool
165vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos) 225vpn::send_udpv4_packet (vpn_packet *pkt, const sockinfo &si, int tos)
166{ 226{
167 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos); 227 setsockopt (udpv4_fd, SOL_IP, IP_TOS, &tos, sizeof tos);
168 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 228 sendto (udpv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
229
230 return true;
169} 231}
170 232
171void 233void
172vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi) 234vpn::recv_vpn_packet (vpn_packet *pkt, const sockinfo &rsi)
173{ 235{
180 if (src == 0 || src > conns.size () 242 if (src == 0 || src > conns.size ()
181 || dst > conns.size () 243 || dst > conns.size ()
182 || pkt->typ () >= vpn_packet::PT_MAX) 244 || pkt->typ () >= vpn_packet::PT_MAX)
183 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"), 245 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
184 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ()); 246 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
247 else if (dst > conns.size ())
248 slog (L_WARN, _("(%s): received corrupted packet type %d (src %d, dst %d)"),
249 (const char *)rsi, pkt->typ (), pkt->src (), pkt->dst ());
185 else 250 else
186 { 251 {
187 connection *c = conns[src - 1]; 252 connection *c = conns[src - 1];
188 253
189 if (dst == 0 && !THISNODE->routerprio) 254 if (dst == 0 && !THISNODE->routerprio)
190 slog (L_WARN, _("%s(%s): received broadcast, but we are no router"), 255 slog (L_WARN, _("%s(%s): received broadcast, but we are no router"),
191 c->conf->nodename, (const char *)rsi); 256 c->conf->nodename, (const char *)rsi);
192 else if (dst != 0 && dst != THISNODE->id) 257 else if (dst != 0 && dst != THISNODE->id)
193 // FORWARDING NEEDED ;) 258 {
259 if (THISNODE->routerprio)
260 // the tos setting gets lost here. who cares.
261 conns[dst - 1]->inject_vpn_packet (pkt);
262 else
194 slog (L_WARN, 263 slog (L_WARN,
195 _("received frame for node %d ('%s') from %s, but this is node %d ('%s')"), 264 _("%s(%s): forwarding request (=> %s), but we are no router"),
265 c->conf->nodename, (const char *)rsi,
196 dst, conns[dst - 1]->conf->nodename, 266 conns[dst - 1]->conf->nodename);
197 (const char *)rsi, 267 }
198 THISNODE->id, THISNODE->nodename);
199 else 268 else
200 c->recv_vpn_packet (pkt, rsi); 269 c->recv_vpn_packet (pkt, rsi);
201 } 270 }
202} 271}
203 272
204void 273void
205vpn::udpv4_ev (short revents) 274vpn::udpv4_ev (io_watcher &w, short revents)
206{ 275{
207 if (revents & (POLLIN | POLLERR)) 276 if (revents & (POLLIN | POLLERR))
208 { 277 {
209 vpn_packet *pkt = new vpn_packet; 278 vpn_packet *pkt = new vpn_packet;
210 struct sockaddr_in sa; 279 struct sockaddr_in sa;
211 socklen_t sa_len = sizeof (sa); 280 socklen_t sa_len = sizeof (sa);
212 int len; 281 int len;
213 282
214 len = recvfrom (udpv4_fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 283 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
215 284
216 sockinfo si(sa); 285 sockinfo si(sa, PROT_UDPv4);
217 286
218 if (len > 0) 287 if (len > 0)
219 { 288 {
220 pkt->len = len; 289 pkt->len = len;
221 290
222 recv_vpn_packet (pkt, si); 291 recv_vpn_packet (pkt, si);
223 } 292 }
224 else 293 else
225 { 294 {
226 // probably ECONNRESET or somesuch 295 // probably ECONNRESET or somesuch
227 slog (L_DEBUG, _("%s: %s"), (const char *)si, strerror (errno)); 296 slog (L_DEBUG, _("%s: fd %d, %s"), (const char *)si, w.fd, strerror (errno));
228 } 297 }
229 298
230 delete pkt; 299 delete pkt;
231 } 300 }
232 else if (revents & POLLHUP) 301 else if (revents & POLLHUP)
243 exit (1); 312 exit (1);
244 } 313 }
245} 314}
246 315
247void 316void
248vpn::ipv4_ev (short revents) 317vpn::ipv4_ev (io_watcher &w, short revents)
249{ 318{
250 if (revents & (POLLIN | POLLERR)) 319 if (revents & (POLLIN | POLLERR))
251 { 320 {
252 vpn_packet *pkt = new vpn_packet; 321 vpn_packet *pkt = new vpn_packet;
253 struct sockaddr_in sa; 322 struct sockaddr_in sa;
254 socklen_t sa_len = sizeof (sa); 323 socklen_t sa_len = sizeof (sa);
255 int len; 324 int len;
256 325
257 len = recvfrom (ipv4_fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len); 326 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
258 327
259 sockinfo si(sa, PROT_IPv4); 328 sockinfo si(sa, PROT_IPv4);
260 329
261 if (len > 0) 330 if (len > 0)
262 { 331 {
290 exit (1); 359 exit (1);
291 } 360 }
292} 361}
293 362
294void 363void
295vpn::tap_ev (short revents) 364vpn::tap_ev (io_watcher &w, short revents)
296{ 365{
297 if (revents & POLLIN) 366 if (revents & POLLIN)
298 { 367 {
299 /* process data */ 368 /* process data */
300 tap_packet *pkt; 369 tap_packet *pkt;
350 else 419 else
351 abort (); 420 abort ();
352} 421}
353 422
354void 423void
355vpn::event_cb (tstamp &ts) 424vpn::event_cb (time_watcher &w)
356{ 425{
357 if (events) 426 if (events)
358 { 427 {
359 if (events & EVENT_SHUTDOWN) 428 if (events & EVENT_SHUTDOWN)
360 { 429 {
377 } 446 }
378 447
379 events = 0; 448 events = 0;
380 } 449 }
381 450
382 ts = TSTAMP_CANCEL; 451 w.at = TSTAMP_CANCEL;
383} 452}
384 453
385void 454void
386vpn::shutdown_all () 455vpn::shutdown_all ()
387{ 456{
431 } 500 }
432 501
433 return router; 502 return router;
434} 503}
435 504
436void vpn::connect_request (int id) 505void vpn::send_connect_request (int id)
437{ 506{
438 connection *c = find_router (); 507 connection *c = find_router ();
439 508
440 if (c) 509 if (c)
441 c->connect_request (id); 510 c->send_connect_request (id);
442 //else // does not work, because all others must connect to the same router 511 else
443 // // no router found, aggressively connect to all routers 512 // no router found, aggressively connect to all routers
444 // for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i) 513 for (conns_vector::iterator i = conns.begin (); i != conns.end (); ++i)
445 // if ((*i)->conf->routerprio) 514 if ((*i)->conf->routerprio)
446 // (*i)->establish_connection (); 515 (*i)->establish_connection ();
447} 516}
448 517
449void 518void
450connection::dump_status () 519connection::dump_status ()
451{ 520{
468 537
469 slog (L_NOTICE, _("END status dump")); 538 slog (L_NOTICE, _("END status dump"));
470} 539}
471 540
472vpn::vpn (void) 541vpn::vpn (void)
542: event(this, &vpn::event_cb)
473: udpv4_ev_watcher(this, &vpn::udpv4_ev) 543, udpv4_ev_watcher(this, &vpn::udpv4_ev)
474, ipv4_ev_watcher(this, &vpn::ipv4_ev) 544, ipv4_ev_watcher (this, &vpn::ipv4_ev)
475, tap_ev_watcher(this, &vpn::tap_ev) 545, tap_ev_watcher (this, &vpn::tap_ev)
476, event(this, &vpn::event_cb) 546#if ENABLE_TCP
547, tcpv4_ev_watcher(this, &vpn::tcpv4_ev)
548#endif
477{ 549{
478} 550}
479 551
480vpn::~vpn () 552vpn::~vpn ()
481{ 553{

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines