www.pudn.com > tdi_fw.zip > ev_conn.c


// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 
// 
// $Id: ev_conn.c,v 1.3 2002/12/03 12:14:27 dev Exp $ 
 
/* 
 * This file contain TDI_EVENT_CONNECT handler 
 */ 
 
#include  
#include  
#include "sock.h" 
 
#include "dispatch.h" 
#include "events.h" 
#include "memtrack.h" 
#include "obj_tbl.h" 
#include "tdi_fw.h" 
 
//---------------------------------------------------------------------------- 
 
/* 
 * TDI_EVENT_CONNECT handler 
 */ 
 
NTSTATUS 
tdi_event_connect( 
    IN PVOID TdiEventContext, 
    IN LONG RemoteAddressLength, 
    IN PVOID RemoteAddress, 
    IN LONG UserDataLength, 
    IN PVOID UserData, 
    IN LONG OptionsLength, 
    IN PVOID Options, 
    OUT CONNECTION_CONTEXT *ConnectionContext, 
    OUT PIRP *AcceptIrp) 
{ 
	TDI_EVENT_CONTEXT *ctx = (TDI_EVENT_CONTEXT *)TdiEventContext; 
	TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)RemoteAddress)->Address, *local_addr; 
	struct ot_entry *ote_addr = NULL, *ote_conn = NULL; 
	KIRQL irql; 
	struct flt_request request; 
	struct flt_rule rule; 
	int result = FILTER_DENY; 
	NTSTATUS status; 
	PIO_STACK_LOCATION irps = NULL; 
 
	KdPrint(("[tdi_fw] tdi_event_connect: addrobj 0x%x\n", ctx->fileobj)); 
	 
	ote_addr = ot_find_fileobj(ctx->fileobj, &irql); 
	if (ote_addr == NULL) { 
		KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", ctx->fileobj)); 
		goto done; 
	} 
 
	local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 
 
	KdPrint(("[tdi_fw] tdi_event_connect(pid:%u): %x:%u -> %x:%u\n", 
		ote_addr->pid, 
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), 
		ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 
		ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port))); 
 
	/* 
	 * request quick filter 
	 */ 
 
	memset(&request, 0, sizeof(request)); 
	request.struct_size = sizeof(request); 
 
	request.type = TYPE_CONNECT; 
	request.direction = DIRECTION_IN; 
	request.proto = IPPROTO_TCP; 
	request.pid = ote_addr->pid; 
 
	memcpy(&request.addr.from, &remote_addr->AddressType, sizeof(struct sockaddr)); 
	memcpy(&request.addr.to, &local_addr->AddressType, sizeof(struct sockaddr)); 
	request.addr.len = sizeof(struct sockaddr_in); 
 
	result = quick_filter(&request, &rule); 
 
	// if logging is needed log request 
	if (rule.log) 
		log_request(&request); 
 
	if (result == FILTER_DENY) 
		goto done; 
 
	result = FILTER_DENY; 
 
	// leave spinlock before calling original handler 
	KeReleaseSpinLock(&g_ot_hash_guard, irql); 
	ote_addr = NULL; 
 
	/* 
	 * run original handler 
	 */ 
 
	status = ((PTDI_IND_CONNECT)(ctx->old_handler)) 
		(ctx->old_context, RemoteAddressLength, RemoteAddress, 
		UserDataLength, UserData, OptionsLength, Options, ConnectionContext, 
		AcceptIrp); 
 
	if (status != STATUS_MORE_PROCESSING_REQUIRED || !*AcceptIrp) 
		goto done; 
 
	/* 
	 * Create and initialize connobj 
	 */ 
 
	irps = IoGetCurrentIrpStackLocation(*AcceptIrp); 
	KdPrint(("[tdi_fw] tdi_event_connect: connobj 0x%x\n", irps->FileObject)); 
 
	/* 
	 * Don't use irps->DeviceObject because it points to upper device in stack 
	 * I don't know how to get our device. And set exactly TCP. 
	 * (Looks like dirty hack) 
	 */ 
	status = ot_add_fileobj(g_tcpfltobj, irps->FileObject, FILEOBJ_CONNOBJ, 
		*ConnectionContext, 0); 
	if (status != STATUS_SUCCESS) { 
		KdPrint(("[tdi_fw] tdi_event_connect: ot_add_fileobj: 0x%x\n", status)); 
		goto done; 
	} 
 
	ote_conn = ot_find_fileobj(irps->FileObject, &irql); 
	if (ote_conn == NULL) { 
		KdPrint(("[tdi_fw] tdi_event_connect: ot_find_fileobj(0x%x)\n", irps->FileObject)); 
		goto done; 
	} 
 
	// associate connobj with addrobj 
	ote_conn->associated_fileobj = ctx->fileobj; 
 
	// sanity check 
	if (local_addr->AddressLength != remote_addr->AddressLength) { 
		KdPrint(("[tdi_fw] tdi_event_connect: different addr lengths! (%u != %u)\n", 
			local_addr->AddressLength, 
			remote_addr->AddressLength)); 
		goto done; 
	} 
 
	// associate remote address with connobj 
	 
	if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) { 
		KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n", 
			remote_addr->AddressLength)); 
		goto done; 
	} 
	memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength); 
 
	// associate local address with connobj 
 
	if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) { 
		KdPrint(("[tdi_fw] tdi_event_connect: address too long! (%u)\n", 
			local_addr->AddressLength)); 
		goto done; 
	} 
	memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength); 
 
	result = FILTER_ALLOW; 
 
done: 
	if (result != FILTER_ALLOW) { 
		// deny incoming connection 
 
		// destroy accepted IRP 
		if (irps != NULL) 
			IoFreeIrp(*AcceptIrp); 
 
		*AcceptIrp = NULL; 
		status = STATUS_CONNECTION_REFUSED; 
	} else 
		status = STATUS_MORE_PROCESSING_REQUIRED; 
 
	// cleanup 
	if (ote_addr != NULL || ote_conn != NULL) 
		KeReleaseSpinLock(&g_ot_hash_guard, irql); 
 
	return status; 
}