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.62 by root, Sat Dec 17 22:05:34 2011 UTC vs.
Revision 1.63 by root, Tue Jan 17 21:38:11 2012 UTC

147int 147int
148vpn::setup () 148vpn::setup ()
149{ 149{
150 int success = 0; 150 int success = 0;
151 151
152#if 1//D2
153 ipv42_tos = -1; 152 ipv4_tos = -1;
154 ipv42_fd = -1; 153 ipv4_fd = -1;
155 154
156 if (THISNODE->protocols & PROT_IPv42 && ::conf.ip_proto) 155 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto)
157 { 156 {
158 ipv42_fd = setup_socket (PROT_IPv42, PF_INET, SOCK_RAW, ::conf.ip2_proto); 157 ipv4_fd = setup_socket (PROT_IPv4, PF_INET, SOCK_RAW, ::conf.ip_proto);
159 158
160 if (ipv42_fd < 0) 159 if (ipv4_fd < 0)
161 return -1; 160 return -1;
162 161
163#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 162#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
164 // this I really consider a linux bug. I am neither connected 163 // this I really consider a linux bug. I am neither connected
165 // 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
166 // fragment for me sometimes. 165 // fragment for me sometimes.
167 { 166 {
168 int oval = IP_PMTUDISC_DONT; 167 int oval = IP_PMTUDISC_DONT;
169 setsockopt (ipv42_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 168 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
170 } 169 }
171#endif 170#endif
172 171
173 sockinfo si (THISNODE, PROT_IPv42); 172 sockinfo si (THISNODE, PROT_IPv4);
174 173
175 if (bind (ipv42_fd, si.sav4 (), si.salenv4 ())) 174 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ()))
176 { 175 {
177 slog (L_ERR, _("can't bind ipv42 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));
178 return -1; 177 return -1;
179 } 178 }
180 179
181 ipv42_ev_watcher.start (ipv42_fd, EV_READ); 180 ipv4_ev_watcher.start (ipv4_fd, EV_READ);
182 ++success; 181 ++success;
183 } 182 }
184 else 183 else
185 THISNODE->protocols &= ~PROT_IPv42; 184 THISNODE->protocols &= ~PROT_IPv4;
186#endif
187 185
188 ipv4_tos = -1; 186 udpv4_tos = -1;
189 ipv4_fd = -1; 187 udpv4_fd = -1;
190 188
191 if (THISNODE->protocols & PROT_IPv4 && ::conf.ip_proto) 189 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port)
192 { 190 {
193 ipv4_fd = setup_socket (PROT_IPv4, PF_INET, SOCK_RAW, ::conf.ip_proto); 191 udpv4_fd = setup_socket (PROT_UDPv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP);
194 192
195 if (ipv4_fd < 0) 193 if (udpv4_fd < 0)
196 return -1; 194 return -1;
195
196 // standard daemon practise...
197 {
198 int oval = 1;
199 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
200 }
197 201
198#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 202#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
199 // this I really consider a linux bug. I am neither connected 203 // this I really consider a linux bug. I am neither connected
200 // nor do I fragment myself. Linux still sets DF and doesn't 204 // nor do I fragment myself. Linux still sets DF and doesn't
201 // fragment for me sometimes. 205 // fragment for me sometimes.
202 { 206 {
203 int oval = IP_PMTUDISC_DONT; 207 int oval = IP_PMTUDISC_DONT;
204 setsockopt (ipv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 208 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
205 } 209 }
206#endif 210#endif
207 211
208 sockinfo si (THISNODE, PROT_IPv4); 212 sockinfo si (THISNODE, PROT_UDPv4);
209 213
210 if (bind (ipv4_fd, si.sav4 (), si.salenv4 ())) 214 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
211 { 215 {
212 slog (L_ERR, _("can't bind ipv4 socket 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));
213 return -1; 217 return -1;
214 } 218 }
215 219
216 ipv4_ev_watcher.start (ipv4_fd, EV_READ); 220 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
217 ++success; 221 ++success;
218 } 222 }
219 else 223 else
220 THISNODE->protocols &= ~PROT_IPv4; 224 THISNODE->protocols &= ~PROT_UDPv4;
221 225
222 udpv4_tos = -1; 226 icmpv4_tos = -1;
223 udpv4_fd = -1; 227 icmpv4_fd = -1;
224 228
225 if (THISNODE->protocols & PROT_UDPv4 && THISNODE->udp_port) 229#if ENABLE_ICMP
230 if (THISNODE->protocols & PROT_ICMPv4)
226 { 231 {
227 udpv4_fd = setup_socket (PROT_UDPv4, PF_INET, SOCK_DGRAM, IPPROTO_UDP); 232 icmpv4_fd = setup_socket (PROT_ICMPv4, PF_INET, SOCK_RAW, IPPROTO_ICMP);
228 233
229 if (udpv4_fd < 0) 234 if (icmpv4_fd < 0)
230 return -1; 235 return -1;
231 236
232 // standard daemon practise... 237#ifdef ICMP_FILTER
233 {
234 int oval = 1;
235 setsockopt (udpv4_fd, SOL_SOCKET, SO_REUSEADDR, &oval, sizeof oval);
236 } 238 {
239 icmp_filter oval;
240 oval.data = 0xffffffff;
241 if (::conf.icmp_type < 32)
242 oval.data &= ~(1 << ::conf.icmp_type);
243
244 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
245 }
246#endif
237 247
238#if defined(SOL_IP) && defined(IP_MTU_DISCOVER) 248#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
239 // this I really consider a linux bug. I am neither connected 249 // this I really consider a linux bug. I am neither connected
240 // nor do I fragment myself. Linux still sets DF and doesn't 250 // nor do I fragment myself. Linux still sets DF and doesn't
241 // fragment for me sometimes. 251 // fragment for me sometimes.
242 { 252 {
243 int oval = IP_PMTUDISC_DONT; 253 int oval = IP_PMTUDISC_DONT;
244 setsockopt (udpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
245 }
246#endif
247
248 sockinfo si (THISNODE, PROT_UDPv4);
249
250 if (bind (udpv4_fd, si.sav4 (), si.salenv4 ()))
251 {
252 slog (L_ERR, _("can't bind udpv4 on %s: %s, exiting."), (const char *)si, strerror (errno));
253 return -1;
254 }
255
256 udpv4_ev_watcher.start (udpv4_fd, EV_READ);
257 ++success;
258 }
259 else
260 THISNODE->protocols &= ~PROT_UDPv4;
261
262 icmpv4_tos = -1;
263 icmpv4_fd = -1;
264
265#if ENABLE_ICMP
266 if (THISNODE->protocols & PROT_ICMPv4)
267 {
268 icmpv4_fd = setup_socket (PROT_ICMPv4, PF_INET, SOCK_RAW, IPPROTO_ICMP);
269
270 if (icmpv4_fd < 0)
271 return -1;
272
273#ifdef ICMP_FILTER
274 {
275 icmp_filter oval;
276 oval.data = 0xffffffff;
277 if (::conf.icmp_type < 32)
278 oval.data &= ~(1 << ::conf.icmp_type);
279
280 setsockopt (icmpv4_fd, SOL_RAW, ICMP_FILTER, &oval, sizeof oval);
281 }
282#endif
283
284#if defined(SOL_IP) && defined(IP_MTU_DISCOVER)
285 // this I really consider a linux bug. I am neither connected
286 // nor do I fragment myself. Linux still sets DF and doesn't
287 // fragment for me sometimes.
288 {
289 int oval = IP_PMTUDISC_DONT;
290 setsockopt (icmpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval); 254 setsockopt (icmpv4_fd, SOL_IP, IP_MTU_DISCOVER, &oval, sizeof oval);
291 } 255 }
292#endif 256#endif
293 257
294 sockinfo si (THISNODE, PROT_ICMPv4); 258 sockinfo si (THISNODE, PROT_ICMPv4);
435 set_tos (ipv4_fd, ipv4_tos, tos); 399 set_tos (ipv4_fd, ipv4_tos, tos);
436 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ()); 400 sendto (ipv4_fd, &((*pkt)[0]), pkt->len, 0, si.sav4 (), si.salenv4 ());
437 401
438 return true; 402 return true;
439} 403}
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
451 404
452static u16 405static u16
453ipv4_checksum (u16 *data, unsigned int len) 406ipv4_checksum (u16 *data, unsigned int len)
454{ 407{
455 // use 32 bit accumulator and fold back carry bits at the end 408 // use 32 bit accumulator and fold back carry bits at the end
559bool 512bool
560vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos) 513vpn::send_vpn_packet (vpn_packet *pkt, const sockinfo &si, int tos)
561{ 514{
562 switch (si.prot) 515 switch (si.prot)
563 { 516 {
564#if 1//D2
565 case PROT_IPv42:
566 return send_ipv42_packet (pkt, si, tos);
567#endif
568
569 case PROT_IPv4: 517 case PROT_IPv4:
570 return send_ipv4_packet (pkt, si, tos); 518 return send_ipv4_packet (pkt, si, tos);
571 519
572 case PROT_UDPv4: 520 case PROT_UDPv4:
573 return send_udpv4_packet (pkt, si, tos); 521 return send_udpv4_packet (pkt, si, tos);
574 522
575#if ENABLE_TCP 523#if ENABLE_TCP
576 case PROT_TCPv4: 524 case PROT_TCPv4:
577 return send_tcpv4_packet (pkt, si, tos); 525 return send_tcpv4_packet (pkt, si, tos);
578#endif 526#endif
579#if ENABLE_ICMP 527#if ENABLE_ICMP
580 case PROT_ICMPv4: 528 case PROT_ICMPv4:
581 return send_icmpv4_packet (pkt, si, tos); 529 return send_icmpv4_packet (pkt, si, tos);
582#endif 530#endif
583#if ENABLE_DNS 531#if ENABLE_DNS
584 case PROT_DNSv4: 532 case PROT_DNSv4:
585 return send_dnsv4_packet (pkt, si, tos); 533 return send_dnsv4_packet (pkt, si, tos);
586#endif 534#endif
587 default: 535 default:
588 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si); 536 slog (L_CRIT, _("%s: FATAL: trying to send packet with unsupported protocol."), (const char *)si);
589 } 537 }
590 538
591 return false; 539 return false;
592} 540}
593
594#if 1//D2
595inline void
596vpn::ipv42_ev (ev::io &w, int revents)
597{
598 if (revents & EV_READ)
599 {
600 vpn_packet *pkt = new vpn_packet;
601 struct sockaddr_in sa;
602 socklen_t sa_len = sizeof (sa);
603 int len;
604
605 len = recvfrom (w.fd, &((*pkt)[0]), MAXSIZE, 0, (sockaddr *)&sa, &sa_len);
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 541
636inline void 542inline void
637vpn::ipv4_ev (ev::io &w, int revents) 543vpn::ipv4_ev (ev::io &w, int revents)
638{ 544{
639 if (revents & EV_READ) 545 if (revents & EV_READ)
972vpn::vpn (void) 878vpn::vpn (void)
973{ 879{
974 event .set<vpn, &vpn::event_cb > (this); 880 event .set<vpn, &vpn::event_cb > (this);
975 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this); 881 udpv4_ev_watcher .set<vpn, &vpn::udpv4_ev > (this);
976 ipv4_ev_watcher .set<vpn, &vpn::ipv4_ev > (this); 882 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
980#if ENABLE_TCP 883#if ENABLE_TCP
981 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this); 884 tcpv4_ev_watcher .set<vpn, &vpn::tcpv4_ev > (this);
982#endif 885#endif
983#if ENABLE_ICMP 886#if ENABLE_ICMP
984 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this); 887 icmpv4_ev_watcher.set<vpn, &vpn::icmpv4_ev> (this);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines