Esempio n. 1
0
void init_package_head(ap_package_t *pkt, U8 data_type,U8 src_addr, U8 dst_addr, U8 port, U8 ttl, U8 type)
{
	memset(pkt, 0, sizeof(ap_package_t));	
	set_src_addr(pkt, src_addr);
	set_dst_addr(pkt, dst_addr);
	set_port(pkt, port);
    set_ttl(pkt, ttl);//赋值为7
    set_type(pkt, type);//type传入参数为0
    set_CoS(pkt,data_type);
}
Esempio n. 2
0
void write_tcp( tcp_t *tcp, int len )
{
	if(len < sizeof(tcp_t)) {
	  D(bug("<%d> Too small tcp packet(%d) on unknown slot, dropped\r\n", -1, len));
		return;
	}
	uint16 src_port = ntohs(tcp->src_port);
	uint16 dest_port = ntohs(tcp->dest_port);

	BOOL ok = true;
	BOOL handle_data = false;
	BOOL initiate_read = false;

	EnterCriticalSection( &tcp_section );

	int t = find_socket( src_port, dest_port );

	if(t < 0) {
		t = alloc_new_socket( src_port, dest_port, ntohl(tcp->ip.dest) );
		ok = t >= 0;
	}

	if(ok) {
		D(bug("<%d> write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port));
	} else {
		D(bug("<%d> FAILED write_tcp %d bytes from port %d to port %d\r\n", t, len, src_port, dest_port));
	}

	if( ok && ISSET(tcp->flags,RST) ) {
		D(bug("<%d> RST set, resetting socket\r\n", t));
		if( sockets[t].s != INVALID_SOCKET ) {
			D(bug("<%d> doing an extra shutdown (ie4)\r\n", t));
			_shutdown( sockets[t].s, SD_BOTH );
		}
		free_socket( t );
		ok = false;
	}

	if(ok) {
		D(bug("<%d> State machine start = %s\r\n", t, STATENAME(sockets[t].state)));

		// always update receive window
		sockets[t].mac_window = ntohs(tcp->window);

		int header_len = tcp->header_len >> 2;
		int option_bytes = header_len - 20;
		char *data = (char *)tcp + sizeof(tcp_t) + option_bytes;
		int dlen = len - sizeof(tcp_t) - option_bytes;

		if( !ISSET(tcp->flags,ACK) ) {
			D(bug("<%d> ACK not set\r\n", t));
		}
		if( ISSET(tcp->flags,SYN) ) {
			D(bug("<%d> SYN set\r\n", t));

			// Note that some options are valid even if there is no SYN.
			// I don't care about those however.

			uint32 new_mss;
			process_options( t, (uint8 *)data - option_bytes, option_bytes, new_mss );
			if(new_mss) {
				sockets[t].mac_mss = (int)new_mss;
				if( new_mss < sockets[t].buffers_read[0].len ) {
					sockets[t].buffers_read[0].len = new_mss;
				}
				D(bug("<%d> Max segment size set to %d\r\n", t, new_mss));
			}
		}
		if( ISSET(tcp->flags,FIN) ) {
			D(bug("<%d> FIN set\r\n", t));
		}

		// The sequence number Mac expects to see next time.
		sockets[t].mac_ack = ntohl(tcp->ack);

		D(bug("<%d> From Mac: Seq=%d, Ack=%d, window=%d, router Seq=%d\r\n", t, ntohl(tcp->seq), sockets[t].mac_ack, sockets[t].mac_window, sockets[t].seq_out));

		if( sockets[t].stream_to_mac_stalled_until && 
				sockets[t].mac_ack == sockets[t].seq_out &&
				(sockets[t].state == ESTABLISHED || sockets[t].state == CLOSE_WAIT) )
		{
			if( has_mac_read_space(t) ) {
				initiate_read = true;
				sockets[t].stream_to_mac_stalled_until = 0;
				D(bug("<%d> read resumed, mac can accept more data\r\n", t));
			}
		}

		switch( sockets[t].state ) {
			case CLOSED:
				sockets[t].src_port = src_port;
				sockets[t].dest_port = dest_port;
				sockets[t].ip_src = ntohl(tcp->ip.src);
				sockets[t].ip_dest = ntohl(tcp->ip.dest);

				if( ISSET(tcp->flags,SYN) ) {

					sockets[t].seq_out = 0x00000001;
					sockets[t].seq_in = ntohl(tcp->seq) + 1;

					_WSAResetEvent( sockets[t].ev );
					if( SOCKET_ERROR == _WSAEventSelect( sockets[t].s, sockets[t].ev, FD_CONNECT | FD_CLOSE ) ) {
						D(bug("<%d> WSAEventSelect() failed with error code %d\r\n", t, _WSAGetLastError()));
					}

				  D(bug("<%d> connecting local port %d to remote %s:%d\r\n", t, src_port, _inet_ntoa(sockets[t].from.sin_addr), dest_port));

					sockets[t].state = LISTEN;
					if( _WSAConnect(
						sockets[t].s,
						(const struct sockaddr *)&sockets[t].from,
						sockets[t].from_len,
						NULL, NULL,
						NULL, NULL
					) == SOCKET_ERROR )
					{
						int connect_error = _WSAGetLastError();
						if( connect_error == WSAEWOULDBLOCK ) {
							D(bug("<%d> WSAConnect() i/o pending.\r\n", t));
						} else {
							D(bug("<%d> WSAConnect() failed with error %d.\r\n", t, connect_error));
						}
					} else {
						D(bug("<%d> WSAConnect() ok.\r\n", t));
					}
				} else {
					if( ISSET(tcp->flags,FIN) ) {
						D(bug("<%d> No SYN but FIN on a closed socket.\r\n", t));
						free_socket(t);
					} else {
						D(bug("<%d> No SYN on a closed socket. resetting.\r\n", t));
						free_socket(t);
					}
				}
				break;
			case LISTEN:
				// handled in connect callback
				break;
			case SYN_SENT:
				if( ISSET(tcp->flags,SYN) && ISSET(tcp->flags,ACK) ) {
					sockets[t].seq_in = ntohl(tcp->seq) + 1;
					tcp_reply( ACK, t );
					sockets[t].state = ESTABLISHED;
					initiate_read = true;
					sockets[t].accept_more_data_from_mac = true;
					sockets[t].time_wait = 0;
				} else if( ISSET(tcp->flags,SYN) ) {
					sockets[t].seq_in = ntohl(tcp->seq) + 1;
					tcp_reply( ACK|SYN, t );
					sockets[t].seq_out++;
					sockets[t].state = SYN_RCVD;
					sockets[t].time_wait = 0;
				} else if( ISSET(tcp->flags,ACK) ) {
					// What was the bright idea here.
					D(bug("<%d> State is SYN_SENT, but got only ACK from Mac??\r\n", t));
					sockets[t].state = FINWAIT_2;
					sockets[t].time_wait = 0;
				}
				break;
			case SYN_RCVD:
				if( ISSET(tcp->flags,ACK) ) {
					sockets[t].state = ESTABLISHED;
					handle_data = true;
					initiate_read = true;
					sockets[t].accept_more_data_from_mac = true;
				}
				break;
			case ESTABLISHED:
				if( ISSET(tcp->flags,FIN) ) {
					sockets[t].seq_in++;
					tcp_reply( ACK, t );
					_shutdown( sockets[t].s, SD_SEND );
					sockets[t].state = CLOSE_WAIT;
				}
				handle_data = true;
				break;
			case CLOSE_WAIT:
				// handled in tcp_read_completion
				break;
			case LAST_ACK:
				if( ISSET(tcp->flags,ACK) ) {
					D(bug("<%d> LAST_ACK received, socket closed\r\n", t));
					free_socket( t );
				}
				break;
			case FINWAIT_1:
				if( ISSET(tcp->flags,FIN) && ISSET(tcp->flags,ACK) ) {
					sockets[t].seq_in++;
					tcp_reply( ACK, t );
					if(sockets[t].remote_closed) {
						_closesocket(sockets[t].s);
						sockets[t].s = INVALID_SOCKET;
					} else {
						_shutdown( sockets[t].s, SD_SEND );
					}
					sockets[t].state = TIME_WAIT;
					sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl;
				} else if( ISSET(tcp->flags,FIN) ) {
					sockets[t].seq_in++;
					tcp_reply( ACK, t );
					if(sockets[t].remote_closed) {
						_closesocket(sockets[t].s);
						sockets[t].s = INVALID_SOCKET;
					} else {
						_shutdown( sockets[t].s, SD_SEND );
					}
					sockets[t].state = CLOSING;
				} else if( ISSET(tcp->flags,ACK) ) {
					sockets[t].state = FINWAIT_2;
				}
				break;
			case FINWAIT_2:
				if( ISSET(tcp->flags,FIN) ) {
					sockets[t].seq_in++;
					tcp_reply( ACK, t );
					if(sockets[t].remote_closed) {
						_closesocket(sockets[t].s);
						sockets[t].s = INVALID_SOCKET;
					} else {
						_shutdown( sockets[t].s, SD_SEND );
					}
					sockets[t].state = TIME_WAIT;
					sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl;
				}
				break;
			case CLOSING:
				if( ISSET(tcp->flags,ACK) ) {
					sockets[t].state = TIME_WAIT;
					sockets[t].time_wait = GetTickCount() + 2 * sockets[t].msl;
				}
				break;
			case TIME_WAIT:
				// Catching stray packets: wait MSL * 2 seconds, -> CLOSED
				// Timer already set since we might not get here at all.
				// I'm using exceptionally low MSL value (5 secs).
				D(bug("<%d> time wait, datagram discarded\r\n", t));
				break;
		}

		// The "t" descriptor may already be freed. However, it's safe
		// to peek the state value inside the critical section.
		D(bug("<%d> State machine end = %s\r\n", t, STATENAME(sockets[t].state)));

		D(bug("<%d> handle_data=%d, initiate_read=%d\r\n", t, handle_data, initiate_read));

		if( handle_data && dlen && sockets[t].accept_more_data_from_mac ) {
			if( sockets[t].seq_in != ntohl(tcp->seq) ) {
				D(bug("<%d> dropping duplicate datagram seq=%d, expected=%d\r\n", t, ntohl(tcp->seq), sockets[t].seq_in));
			} else {
				set_ttl( t, tcp->ip.ttl );

				struct sockaddr_in to;
				memset( &to, 0, sizeof(to) );
				to.sin_family = AF_INET;
				to.sin_port = tcp->dest_port;
				to.sin_addr.s_addr = tcp->ip.dest;

				D(bug("<%d> sending %d bytes to remote host\r\n", t, dlen));

				sockets[t].accept_more_data_from_mac = false;

				if( dlen > MAX_SEGMENT_SIZE ) {
					D(bug("<%d> IMPOSSIBLE: b_send() dropped %d bytes! \r\n", t, dlen-MAX_SEGMENT_SIZE));
					dlen = MAX_SEGMENT_SIZE;
				}

				memcpy( sockets[t].buffers_write[0].buf, data, dlen );

				sockets[t].buffers_write[0].len = dlen;
				sockets[t].bytes_remaining_to_send = dlen;
				sockets[t].bytes_to_send = dlen;

				bool send_now = false;
				if( ISSET(tcp->flags,PSH) ) {
					send_now = true;
				} else {
					// todo -- delayed send
					send_now = true;
				}
				
				if(send_now) {

					// Patch ftp server or client address if needed.

					int lst = 1;
					bool is_pasv;
					uint16 ftp_data_port = 0;

					if(ftp_is_ftp_port(sockets[t].src_port)) {
						// Local ftp server may be entering to passive mode.
						is_pasv = true;
						ftp_parse_port_command( 
							sockets[t].buffers_write[0].buf,
							dlen,
							ftp_data_port,
							is_pasv
						);
					} else if(ftp_is_ftp_port(sockets[t].dest_port)) {
						// Local ftp client may be using port command.
						is_pasv = false;
						ftp_parse_port_command( 
							sockets[t].buffers_write[0].buf,
							dlen,
							ftp_data_port,
							is_pasv
						);
					}

					if(ftp_data_port) {
						D(bug("<%d> ftp %s command detected, port %d\r\n", t, (is_pasv ? "SERVER PASV REPLY" : "CLIENT PORT"), ftp_data_port ));

						// Note: for security reasons, only allow incoming connection from sockets[t].ip_dest
						lst = alloc_listen_socket( ftp_data_port, sockets[t].ip_dest, 0/*iface*/, true );

						if(lst < 0) {
							D(bug("<%d> no more free slots\r\n", t));
						} else {
							// First start listening (need to know the local name later)
							tcp_start_listen( lst );

							// When t is closed, lst must be closed too.
							sockets[t].child = lst;
							l_sockets[lst].parent = t;

							// Find out the local name
							struct sockaddr_in name;
							int namelen = sizeof(name);
							memset( &name, 0, sizeof(name) );
							if( _getsockname( sockets[t].s, (struct sockaddr *)&name, &namelen ) == SOCKET_ERROR ) {
								D(bug("_getsockname() failed, error=%d\r\n", _WSAGetLastError() ));
							}

							ftp_modify_port_command( 
								sockets[t].buffers_write[0].buf,
								dlen,
								MAX_SEGMENT_SIZE,
								ntohl(name.sin_addr.s_addr),
								ftp_data_port,
								is_pasv
							);

							sockets[t].buffers_write[0].len = dlen;
							sockets[t].bytes_remaining_to_send = dlen;
							// Do not change "bytes_to_send" field as it is used for ack calculation
						}
					} // end of ftp patch

					if(!b_send(t)) {
						// on error, close the ftp data listening socket if one was created
						if(lst >= 0) {
							D(bug("[%d] closing listening port %d after write error\r\n", t, l_sockets[lst].port));
							_closesocket( l_sockets[lst].s );
							l_sockets[lst].s = INVALID_SOCKET;
							l_sockets[lst].port = 0;
							l_sockets[lst].ip = 0;
							l_sockets[lst].parent = -1;
							sockets[t].child = -1;
						}
					}
				}
			}
		}

		if(initiate_read) {
			if(!b_recfrom(t)) {
				// post icmp error message
			}
		}
	}

	LeaveCriticalSection( &tcp_section );
}
Esempio n. 3
0
/* Process TCP packets
 * Return 0 to accept packet, otherwise to drop packet 
 */
int process_tcp_packet(struct mypacket *packet, char inout)
{
    int ret = 0;
    struct myiphdr *iphdr = packet->iphdr;
    struct mytcphdr *tcphdr = packet->tcphdr;
    unsigned char *payload = packet->payload;

    char sip[16], dip[16];
    ip2str(iphdr->saddr, sip);
    ip2str(iphdr->daddr, dip);

    unsigned short sport, dport;
    //unsigned int seq, ack;
    sport = ntohs(tcphdr->th_sport);
    dport = ntohs(tcphdr->th_dport);
    //seq = tcphdr->th_seq;
    //ack = tcphdr->th_ack;
    log_debug("[TCP] This packet goes from %s:%d to %s:%d", sip, sport, dip, dport);
    log_debug("TCP flags: %s", tcp_flags(tcphdr->th_flags));

    struct fourtuple fourtp;
    fourtp.saddr = iphdr->saddr;
    fourtp.daddr = iphdr->daddr;
    fourtp.sport = tcphdr->th_sport;
    fourtp.dport = tcphdr->th_dport;

    // for testing uni-directional packet forwarding to bypass IP blocking 
    //if (dport == 80 && is_blocked_ip(dip)) {
    //    log_debug("Going to forward that packet!!!");
    //    unsigned int newlen = packet->len + 4;
    //    char *newpkt = (char*)malloc(newlen);
    //    memcpy(newpkt, packet->data, packet->len);
    //    *(u_int32_t*)(newpkt + packet->len) = iphdr->daddr;
    //    ip_hdr(newpkt)->daddr = str2ip(PACKET_FORWARDER);
    //    send_raw(newpkt, newlen);
    //    log_debug("sent!!!");
    //    return 0;
    //}

    if (tcphdr->th_flags == TCP_SYN) {
        // Processing outgoing SYN packet. 

        // Uploading diagnostic log is disabled. (2017.9.1) 
        //if (strcmp(dip, FEEDBACK_SERVER_IP) == 0)
        //    return 0;
        

        // choose a strategy for the newly created connection
        int sid = choose_strategy_by_historical_result(iphdr->daddr);
        log_debug("Using strategy %s", g_strats[sid].name);
        set_sid(&fourtp, sid);
        //cache_strategy(&fourtp, sid);

        if (g_strats[sid].process_syn) {
            ret = g_strats[sid].process_syn(packet);
#ifndef EVALUATION
            if (ret) {
                need_evaluation(&fourtp);
            }
#endif
        }
    }
    if (tcphdr->th_flags == (TCP_SYN | TCP_ACK)) {
        // Got a SYN-ACK from server

        // send an ACK with 1 TTL to make home router happy 
        if (opt_inject_ack_with_one_ttl)
            send_ACK_with_one_ttl(dip, dport, sip, sport, tcphdr->th_ack, htonl(ntohl(tcphdr->th_seq)+1));

        struct fourtuple reverse_fourtp;
        reverse_fourtp.saddr = iphdr->daddr;
        reverse_fourtp.daddr = iphdr->saddr;
        reverse_fourtp.sport = tcphdr->th_dport;
        reverse_fourtp.dport = tcphdr->th_sport;

        int sid = get_sid(&reverse_fourtp);
        if (sid >= 0) {
            if (get_ttl(iphdr->saddr) == 0) {
                // if TTL hasn't been initialized 
                // find initial TTL from SYN/ACK packet
                int ttl = choose_appropriate_ttl(iphdr->ttl);
                set_ttl(iphdr->saddr, ttl);
            }
            if  (g_strats[sid].process_synack) {
                ret = g_strats[sid].process_synack(packet);
#ifndef EVALUATION
                if (ret) {
                    need_evaluation(&reverse_fourtp);
                }
#endif
            }
        }
        else if (sid == -1) {
            ret = process_synack_for_ttl_probing(packet);
        }

        //if (opt_inject_syn_and_syn_ack_with_one_ttl)
        //    send_one_ttl_SYN_and_SYN_ACK(dip, dport, sip, sport, tcphdr->th_ack, tcphdr->th_seq);
    } 
    else if ((tcphdr->th_flags & TCP_ACK) && 
        !(tcphdr->th_flags & (TCP_SYN | TCP_RST))) {
        // ignore ACK packets without payload 
        if (packet->payload_len == 0) 
            return 0;

        if (dport == 80) {
            if ((payload[0] == 'G' && payload[1] == 'E' && 
                 payload[2] == 'T' && payload[3] == ' ') ||
                (payload[0] == 'P' && payload[1] == 'O' && 
                 payload[2] == 'S' && payload[3] == 'T' && 
                 payload[4] == ' ')) {
                // Got a outgoing HTTP request 
                log_debug("[TCP] Sent a HTTP request from %s:%d to %s:%d.", sip, sport, dip, dport);
                int i, j, k, l;
                
                //char req_line[1000];
                //for (i = 0; i < 1000; i++) {
                //    if (payload[i] == '\r' || payload[i] == '\n') {
                //        req_line[i] = 0;
                //        break;
                //    }
                //    req_line[i] = payload[i];
                //}
                
                // Generate the HTTP request line. Format: GET/POST domain/url. e.g. GET www.google.com/index.php
                char req_line2[1000];
                // copy GET/POST 
                for (i = 0; payload[i] != ' ' && i < packet->payload_len; i++) {
                    req_line2[i] = payload[i];
                }
                req_line2[i++] = ' ';
                k = i; 
    
                // find Host field
                for (j = i; j < packet->payload_len; j++) {
                    if (payload[j] == 'H' && payload[j+1] == 'o' &&
                            payload[j+2] == 's' && payload[j+3] == 't' &&
                            payload[j+4] == ':' && (payload[j-1] == '\r' || payload[j-1] == '\n')) {
                        j += 5;
                        // copy Host value 
                        while (payload[j] == ' ') j++;
                        for (l = 0; l < 99 && j+l < packet->payload_len; l++) {
                            if (payload[j+l] == '\r' || payload[j+l] == '\n')
                                break;
                            req_line2[k++] = payload[j+l];
                        }
                        break;
                    }
                }

                // copy the rest of request line 
                for (; i < 900 && i < packet->payload_len; i++) {
                    if (payload[i] == '\r' || payload[i] == '\n') {
                        break;
                    }
                    req_line2[k++] = payload[i];
                }
                req_line2[k] = 0;
    
                log_debug("[TCP] %s", req_line2); 

                int sid = get_sid(&fourtp);
                if (sid >= 0 && g_strats[sid].process_request) {
                    ret = g_strats[sid].process_request(packet);
#ifndef EVALUATION
                    if (ret) {
                        need_evaluation(&fourtp);
                    }
#endif
                }
#ifdef EVALUATION
                if (strstr(req_line2, "ultrasurf") || strstr(req_line2, "goodword")) {
                    need_evaluation(&fourtp);
                }
#endif

                cache_http_request(&fourtp, req_line2);
            }
        }
        else if (sport == 80) {
            if (payload[0] == 'H' && payload[1] == 'T' && payload[2] == 'T' && payload[3] == 'P') {
                // Got a incoming HTTP response 
                log_debug("[TCP] Got a HTTP response from %s:%d to %s:%d.", sip, sport, dip, dport);
                process_http_response(&fourtp, tcphdr->th_seq, iphdr->ttl);
            }
        }
        else if (dport == 53) {
            // Got a DNS request over TCP 
            log_debug("[TCP] Sent a DNS request from %s:%d to %s:%d.", sip, sport, dip, dport);

            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
#ifndef EVALUATION
                if (ret) {
                    need_evaluation(&fourtp);
                }
#endif
            }

            cache_dns_tcp_request(&fourtp);
        }
        else if (sport == 53) {
            // Got a DNS response over TCP, maybe triggered by our app, or maybe not 
            log_debug("[TCP] Got a DNS response from %s:%d to %s:%d.", sip, sport, dip, dport);
            // parse the DNS response to get the first qname 
            const unsigned char *dns_payload = packet->payload + 2;
            struct mydnshdr *dnshdr = (struct mydnshdr*)dns_payload;
            unsigned short txn_id = htons(dnshdr->txn_id);
            int qdcount = ntohs(dnshdr->questions);
            char qname[MAX_QNAME_LEN];
            if (qdcount > 0) {
                //log_debug("Questions: %d", qdcount);
                unsigned char *ptr = (unsigned char *)(dnshdr + 1);
                {
                    struct mydnsquery query;
                    int j = 0, l;
                    while (1) {
                        for (l = *ptr++; l != 0; l--) {
                            query.qname[j++] = *ptr++;
                            if (j >= MAX_QNAME_LEN) {
                                while (*ptr != 0) ptr++;
                                break;
                            }
                        }
                        if (*ptr == 0) {
                            query.qname[j] = 0;
                            ptr++;
                            break;
                        }
                        query.qname[j++] = '.';
                    }
                    query.qtype = (ptr[0] << 8) + ptr[1];
                    query.qclass = (ptr[2] << 8) + ptr[3];
                    
                    log_debug("DNS Query: %s %d %d", query.qname, query.qtype, query.qclass);
    
                    // use the first query to calc hash 
                    qname[0] = 0;
                    strncat(qname, query.qname, MAX_QNAME_LEN - 1);
                }

                // Tell the caching thread to process the dns udp response
                // use DNS transaction ID and first query name as unique ID
                // transaction ID alone may cause collision 
                process_dns_tcp_response(txn_id, qname, &fourtp, tcphdr->th_seq, iphdr->ttl, packet->payload, packet->payload_len);

            }
        }
        else if (dport == opt_vpn_port) {
            // outgoing packet
            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
                if (ret) {
                    if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                        send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                    else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                        send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                }
            }
        }
        else if (sport == opt_vpn_port) {
            // incomine packet
        }
        else if (dport == opt_tor_port) {
            // outgoing packet
            int sid = get_sid(&fourtp);
            if (sid >= 0 && g_strats[sid].process_request) {
                ret = g_strats[sid].process_request(packet);
                if (ret) {
                    if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                        send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                    else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                        send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                }
            }
        }
        else if (sport == opt_tor_port) {
            // incomine packet
        }
        else {
            // TODO: for all other protocols. This branch is a piece of temporary code, should be re-write.
            if (inout == 0) {
                // incoming packet
                log_debug("this is an incoming packet.");
            }
            else {
                // outgoing packet
                log_debug("this is an outgoing packet.");
                int sid = get_sid(&fourtp);
                if (sid >= 0 && g_strats[sid].process_request) {
                    ret = g_strats[sid].process_request(packet);
                    if (ret) {
                        if (opt_inject_syn_and_syn_ack_with_one_ttl == 1)
                            send_one_ttl_SYN(sip, sport, dip, dport, tcphdr->th_seq);
                        else if (opt_inject_syn_and_syn_ack_with_one_ttl == 2)
                            send_one_ttl_SYN_and_SYN_ACK(sip, sport, dip, dport, tcphdr->th_seq, tcphdr->th_ack);
                    }
                }
            }
        }
    }
    else if (tcphdr->th_flags & TCP_RST) {
        // Got an incoming RST 
        log_debug("[TCP] Got an incoming RST from %s:%d to %s:%d.", sip, sport, dip, dport);

        process_incoming_RST(packet);
    }

    return ret;
}