📄 forward.c
字号:
/* reset packet received timer if TLS packet */ if (c->options.ping_rec_timeout) event_timeout_reset (&c->c2.ping_rec_interval); } }#endif /* USE_SSL */ /* authenticate and decrypt the incoming packet */ decrypt_status = openvpn_decrypt (&c->c2.buf, c->c2.buffers->decrypt_buf, &c->c2.crypto_options, &c->c2.frame);#ifdef USE_SSL if (c->c2.tls_multi) { //tls_mutex_unlock (c->c2.tls_multi); }#endif if (!decrypt_status && link_socket_connection_oriented (c->c2.link_socket)) { /* decryption errors are fatal in TCP mode */ c->sig->signal_received = SIGUSR1; msg (D_STREAM_ERRORS, "Fatal decryption error, restarting"); c->sig->signal_text = "decryption-error"; goto done; }#endif /* USE_CRYPTO */ if (c->c2.fragment) fragment_incoming (c->c2.fragment, &c->c2.buf, &c->c2.frame_fragment);#ifdef USE_LZO /* decompress the incoming packet */ if (c->options.comp_lzo) lzo_decompress (&c->c2.buf, c->c2.buffers->lzo_decompress_buf, &c->c2.lzo_compwork, &c->c2.frame);#endif /* * Set our "official" outgoing address, since * if buf.len is non-zero, we know the packet * authenticated. In TLS mode we do nothing * because TLS mode takes care of source address * authentication. * * Also, update the persisted version of our packet-id. */ if (!TLS_MODE) link_socket_set_outgoing_addr (&c->c2.buf, lsi, &c->c2.from, NULL); /* reset packet received timer */ if (c->options.ping_rec_timeout && c->c2.buf.len > 0) event_timeout_reset (&c->c2.ping_rec_interval); /* increment authenticated receive byte count */ if (c->c2.buf.len > 0) { c->c2.link_read_bytes_auth += c->c2.buf.len; c->c2.max_recv_size_local = max_int (c->c2.original_recv_size, c->c2.max_recv_size_local); } /* Did we just receive an openvpn ping packet? */ if (is_ping_msg (&c->c2.buf)) { msg (D_PACKET_CONTENT, "RECEIVED PING PACKET"); c->c2.buf.len = 0; /* drop packet */ } /* Did we just receive an OCC packet? */ if (is_occ_msg (&c->c2.buf)) process_received_occ_msg (c); c->c2.to_tun = c->c2.buf; /* to_tun defined + unopened tuntap can cause deadlock */ if (!tuntap_defined (c->c1.tuntap)) c->c2.to_tun.len = 0; } else { buf_reset (&c->c2.to_tun); } done: gc_free (&gc);}voidread_incoming_tun (struct context *c){ /* * Setup for read() call on TUN/TAP device. */ ASSERT (!c->c2.to_link.len); c->c2.buf = c->c2.buffers->read_tun_buf;#ifdef TUN_PASS_BUFFER read_tun_buffered (c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame));#else ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); c->c2.buf.len = read_tun (c->c1.tuntap, BPTR (&c->c2.buf), MAX_RW_SIZE_TUN (&c->c2.frame));#endif /* Was TUN/TAP interface stopped? */ if (tuntap_stop (c->c2.buf.len)) { c->sig->signal_received = SIGTERM; c->sig->signal_text = "tun-stop"; msg (M_INFO, "TUN/TAP interface has been stopped, exiting"); return; } /* Check the status return from read() */ check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap);}voidprocess_incoming_tun (struct context *c){ struct gc_arena gc = gc_new (); if (c->c2.buf.len > 0) c->c2.tun_read_bytes += c->c2.buf.len;#ifdef LOG_RW if (c->c2.log_rw) fprintf (stderr, "r");#endif /* Show packet content */ msg (D_TUN_RW, "TUN READ [%d]: %s md5=%s", BLEN (&c->c2.buf), format_hex (BPTR (&c->c2.buf), BLEN (&c->c2.buf), 80, &gc), MD5SUM (BPTR (&c->c2.buf), BLEN (&c->c2.buf), &gc)); if (c->c2.buf.len > 0) { /* * The --passtos and --mssfix options require * us to examine the IPv4 header. */ if (c->options.mssfix#if PASSTOS_CAPABILITY || c->options.passtos#endif ) { struct buffer ipbuf = c->c2.buf; if (is_ipv4 (TUNNEL_TYPE (c->c1.tuntap), &ipbuf)) {#if PASSTOS_CAPABILITY /* extract TOS from IP header */ if (c->options.passtos) { struct openvpn_iphdr *iph = (struct openvpn_iphdr *) BPTR (&ipbuf); c->c2.ptos = iph->tos; c->c2.ptos_defined = true; }#endif /* possibly alter the TCP MSS */ if (c->options.mssfix) mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); } } encrypt_sign (c, true); } else { buf_reset (&c->c2.to_link); } gc_free (&gc);}voidprocess_outgoing_link (struct context *c){ struct gc_arena gc = gc_new (); if (c->c2.to_link.len > 0 && c->c2.to_link.len <= EXPANDED_SIZE (&c->c2.frame)) { /* * Setup for call to send/sendto which will send * packet to remote over the TCP/UDP port. */ int size; ASSERT (addr_defined (&c->c2.to_link_addr)); /* In gremlin-test mode, we may choose to drop this packet */ if (!c->options.gremlin || ask_gremlin()) { /* * Let the traffic shaper know how many bytes * we wrote. */#ifdef HAVE_GETTIMEOFDAY if (c->options.shaper) shaper_wrote_bytes (&c->c2.shaper, BLEN (&c->c2.to_link) + datagram_overhead (c->options.proto));#endif /* * Let the pinger know that we sent a packet. */ if (c->options.ping_send_timeout) event_timeout_reset (&c->c2.ping_send_interval);#if PASSTOS_CAPABILITY /* Set TOS */ if (c->c2.ptos_defined) setsockopt (c->c2.link_socket->sd, IPPROTO_IP, IP_TOS, &c->c2.ptos, sizeof (c->c2.ptos));#endif /* Log packet send */#ifdef LOG_RW if (c->c2.log_rw) fprintf (stderr, "W");#endif msg (D_LINK_RW, "%s WRITE [%d] to %s: %s", proto2ascii (c->c2.link_socket->info.proto, true), BLEN (&c->c2.to_link), print_sockaddr (&c->c2.to_link_addr, &gc), PROTO_DUMP (&c->c2.to_link, &gc)); /* Packet send complexified by possible Socks5 usage */ { struct sockaddr_in *to_addr = &c->c2.to_link_addr; int size_delta = 0; /* If Socks5 over UDP, prepend header */ socks_preprocess_outgoing_link (c, &to_addr, &size_delta); /* Send packet */ size = link_socket_write (c->c2.link_socket, &c->c2.to_link, to_addr); /* Undo effect of prepend */ link_socket_write_post_size_adjust (&size, size_delta, &c->c2.to_link); } if (size > 0) { c->c2.max_send_size_local = max_int (size, c->c2.max_send_size_local); c->c2.link_write_bytes += size; } } else size = 0; /* Check return status */ check_status (size, "write", c->c2.link_socket, NULL); if (size > 0) { /* Did we write a different size packet than we intended? */ if (size != BLEN (&c->c2.to_link)) msg (D_LINK_ERRORS, "TCP/UDP packet was truncated/expanded on write to %s (tried=%d,actual=%d)", print_sockaddr (&c->c2.to_link_addr, &gc), BLEN (&c->c2.to_link), size); } } else { if (c->c2.to_link.len > 0) msg (D_LINK_ERRORS, "TCP/UDP packet too large on write to %s (tried=%d,max=%d)", print_sockaddr (&c->c2.to_link_addr, &gc), c->c2.to_link.len, EXPANDED_SIZE (&c->c2.frame)); } buf_reset (&c->c2.to_link); gc_free (&gc);}voidprocess_outgoing_tun (struct context *c){ struct gc_arena gc = gc_new (); /* * Set up for write() call to TUN/TAP * device. */ ASSERT (c->c2.to_tun.len > 0); /* * The --mssfix option requires * us to examine the IPv4 header. */ if (c->options.mssfix) { struct buffer ipbuf = c->c2.to_tun; if (is_ipv4 (c->c1.tuntap->type, &ipbuf)) { /* possibly alter the TCP MSS */ if (c->options.mssfix) mss_fixup (&ipbuf, MTU_TO_MSS (TUN_MTU_SIZE_DYNAMIC (&c->c2.frame))); } } if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame)) { /* * Write to TUN/TAP device. */ int size;#ifdef LOG_RW if (c->c2.log_rw) fprintf (stderr, "w");#endif msg (D_TUN_RW, "TUN WRITE [%d]: %s md5=%s", BLEN (&c->c2.to_tun), format_hex (BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun), 80, &gc), MD5SUM (BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun), &gc));#ifdef TUN_PASS_BUFFER size = write_tun_buffered (c->c1.tuntap, &c->c2.to_tun);#else size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun));#endif if (size > 0) c->c2.tun_write_bytes += size; check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap); /* check written packet size */ if (size > 0) { /* Did we write a different size packet than we intended? */ if (size != BLEN (&c->c2.to_tun)) msg (D_LINK_ERRORS, "TUN/TAP packet was destructively fragmented on write to %s (tried=%d,actual=%d)", c->c1.tuntap->actual_name, BLEN (&c->c2.to_tun), size); } } else { /* * This should never happen, probably indicates some kind * of MTU mismatch. */ msg (D_LINK_ERRORS, "tun packet too large on write (tried=%d,max=%d)", c->c2.to_tun.len, MAX_RW_SIZE_TUN (&c->c2.frame)); } /* * Putting the --inactive timeout reset here, ensures that we will timeout * if the remote goes away, even if we are trying to send data to the * remote and failing. */ register_activity (c); buf_reset (&c->c2.to_tun); gc_free (&gc);}voidpre_select (struct context *c){ /* make sure current time (now) is updated on function entry */ /* * Start with an effectively infinite timeout, then let it * reduce to a timeout that reflects the component which * needs the earliest service. */ c->c2.timeval.tv_sec = BIG_TIMEOUT; c->c2.timeval.tv_usec = 0;#if defined(WIN32) && defined(TAP_WIN32_DEBUG) c->c2.timeval.tv_sec = 1; if (tuntap_defined (c->c1.tuntap) && check_debug_level (D_TAP_WIN32_DEBUG)) tun_show_debug (c->c1.tuntap);#endif /* check coarse timers? */ check_coarse_timers (c); if (c->sig->signal_received) return; /* Does TLS need service? */ check_tls (c); /* In certain cases, TLS errors will require a restart */ check_tls_errors (c); if (c->sig->signal_received) return; /* check for incoming configuration info on the control channel */ check_incoming_control_channel (c); /* Should we send an OCC message? */ check_send_occ_msg (c); /* Should we deliver a datagram fragment to remote? */ check_fragment (c); /* Update random component of timeout */ check_timeout_random_component (c);}/* * Wait for I/O events. Used for both TCP & UDP sockets * in point-to-point mode and for UDP sockets in * point-to-multipoint mode. */voidio_wait (struct context *c, unsigned int flags){ unsigned int socket = 0; unsigned int tuntap = 0; struct event_set_return esr[3]; /* These shifts all depend on EVENT_READ and EVENT_WRITE */ static const int socket_shift = 0; /* depends on SOCKET_READ and SOCKET_WRITE */ static const int tun_shift = 2; /* depends on TUN_READ and TUN_WRITE */ static const int err_shift = 4; /* depends on ES_ERROR */ /* * Decide what kind of events we want to wait for. */ event_reset (c->c2.event_set); /* * On win32 we use the keyboard or an event object as a source * of asynchronous signals. */ wait_signal (c->c2.event_set, (void*)&err_shift); /* * If outgoing data (for TCP/UDP port) pending, wait for ready-to-send * status from TCP/UDP port. Otherwise, wait for incoming data on * TUN/TAP device. */ if (flags & IOW_TO_LINK) { if (flags & IOW_SHAPER) { /* * If sending this packet would put us over our traffic shaping * quota, don't send -- instead compute the delay we must wait * until it will be OK to send the packet. */#ifdef HAVE_GETTIMEOFDAY int delay = 0; /* set traffic shaping delay in microseconds */ if (c->options.shaper) delay = max_int (delay, shaper_delay (&c->c2.shaper)); if (delay < 1000) { socket |= EVENT_WRITE; } else { shaper_soonest_event (&c->c2.timeval, delay); }#else /* HAVE_GETTIMEOFDAY */ socket |= EVENT_WRITE;#endif /* HAVE_GETTIMEOFDAY */ } else { socket |= EVENT_WRITE; } } else if (!((flags & IOW_FRAG) && TO_LINK_FRAG (c))) { if (flags & IOW_READ) tuntap |= EVENT_READ; } /* * outgoing bcast buffer waiting to be sent? */ if (flags & IOW_MBUF) socket |= EVENT_WRITE; /* * If outgoing data (for TUN/TAP device) pending, wait for ready-to-send status * from device. Otherwise, wait for incoming data on TCP/UDP port. */ if (flags & IOW_TO_TUN) { tuntap |= EVENT_WRITE; } else { if (flags & IOW_READ) socket |= EVENT_READ; } /* * Configure event wait based on socket, tuntap flags. */ socket_set (c->c2.link_socket, c->c2.event_set, socket, (void*)&socket_shift); tun_set (c->c1.tuntap, c->c2.event_set, tuntap, (void*)&tun_shift); /* * Possible scenarios: * (1) tcp/udp port has data available to read * (2) tcp/udp port is ready to accept more data to write * (3) tun dev has data available to read * (4) tun dev is ready to accept more data to write * (5) we received a signal (handler sets signal_received) * (6) timeout (tv) expired */ c->c2.event_set_status = ES_ERROR; if (!c->sig->signal_received) { if (!(flags & IOW_CHECK_RESIDUAL) || !socket_read_residual (c->c2.link_socket)) { int status; if (check_debug_level (D_EVENT_WAIT)) show_wait_status (c); /* * Wait for something to happen. */ status = event_wait (c->c2.event_set, &c->c2.timeval, esr, SIZE(esr)); check_status (status, "event_wait", NULL, NULL); if (status > 0) { int i; c->c2.event_set_status = 0; for (i = 0; i < status; ++i) { const struct event_set_return *e = &esr[i]; c->c2.event_set_status |= ((e->rwflags & 3) << *((int*)e->arg)); } } else if (status == 0) { c->c2.event_set_status = ES_TIMEOUT; } } else { c->c2.event_set_status = SOCKET_READ; } } /* 'now' should always be a reasonably up-to-date timestamp */ update_time (); /* set signal_received if a signal was received */ if (c->c2.event_set_status & ES_ERROR) get_signal (&c->sig->signal_received); msg (D_EVENT_WAIT, "I/O WAIT status=0x%04x", c->c2.event_set_status);}voidprocess_io (struct context *c){ const unsigned int status = c->c2.event_set_status; /* TCP/UDP port ready to accept write */ if (status & SOCKET_WRITE) { process_outgoing_link (c); } /* TUN device ready to accept write */ else if (status & TUN_WRITE) { process_outgoing_tun (c); } /* Incoming data on TCP/UDP port */ else if (status & SOCKET_READ) { read_incoming_link (c); if (!IS_SIG (c)) process_incoming_link (c); } /* Incoming data on TUN device */ else if (status & TUN_READ) { read_incoming_tun (c); if (!IS_SIG (c)) process_incoming_tun (c); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -