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


// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs) 
// 
// $Id: disp_conn.c,v 1.2 2002/10/01 12:54:15 dev Exp $ 
 
/* 
 * This file contains TDI_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_CONNECT handler 
 */ 
 
int 
tdi_connect(PIRP irp, PIO_STACK_LOCATION irps, struct completion *completion) 
{ 
	PTDI_REQUEST_KERNEL_CONNECT param = (PTDI_REQUEST_KERNEL_CONNECT)(&irps->Parameters); 
	TA_ADDRESS *remote_addr = ((TRANSPORT_ADDRESS *)(param->RequestConnectionInformation->RemoteAddress))->Address; 
	PFILE_OBJECT addrobj; 
	NTSTATUS status; 
	TA_ADDRESS *local_addr; 
	int result = FILTER_DENY, ipproto; 
	struct ot_entry *ote_conn = NULL, *ote_addr; 
	KIRQL irql; 
	struct flt_request request; 
	struct flt_rule rule; 
 
	KdPrint(("[tdi_fw] tdi_connect: connobj 0x%x, to address %x:%u\n", 
		irps->FileObject, 
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port))); 
 
	// check device object: TCP or UDP 
	if (irps->DeviceObject != g_tcpfltobj && irps->DeviceObject != g_udpfltobj) { 
		KdPrint(("[tdi_fw] tdi_connect: unknown DeviceObject 0x%x\n", irps->DeviceObject)); 
		goto done; 
	} 
 
	ote_conn = ot_find_fileobj(irps->FileObject, &irql); 
	if (ote_conn == NULL) { 
		KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)\n", irps->FileObject)); 
		goto done; 
	} 
 
	if (get_original_devobj(irps->DeviceObject, &ipproto) == NULL || 
		(ipproto != IPPROTO_TCP && ipproto != IPPROTO_UDP)) { 
		// invalid device object! 
		KdPrint(("[tdi_fw] tdi_connect: invalid device object 0x%x\n", irps->DeviceObject)); 
		goto done; 
	} 
 
	if (ipproto == IPPROTO_TCP) { 
		/* 
		 * For TCP: get addrobj by connobj and get local address by it 
		 */ 
 
		addrobj = ote_conn->associated_fileobj; 
		if (addrobj == NULL) { 
			KdPrint(("[tdi_fw] tdi_connect: empty addrobj!\n")); 
			goto done; 
		} 
 
		ote_addr = ot_find_fileobj(addrobj, NULL); // we're already in spinlock 
		if (ote_conn == NULL) { 
			KdPrint(("[tdi_fw] tdi_connect: ot_find_fileobj(0x%x)\n", addrobj)); 
			goto done; 
		} 
 
	} else { 
		/* 
		 * For UDP: connobj and addrobj are the same 
		 */ 
		KdPrint(("[tdi_fw] tdi_connect: connected UDP socket detected\n")); 
 
		// for connected UDP sockets connobj and addrobj are the same 
		addrobj= irps->FileObject; 
		ote_addr = ote_conn; 
	} 
 
	local_addr = (TA_ADDRESS *)(ote_addr->local_addr); 
 
	// sanity check 
	if (local_addr->AddressLength != remote_addr->AddressLength) { 
		KdPrint(("[tdi_fw] tdi_connect: different addr lengths! (%u != %u)\n", 
			local_addr->AddressLength, remote_addr->AddressLength)); 
		goto done; 
	} 
 
	// set remote address with connobj 
	 
	if (remote_addr->AddressLength > sizeof(ote_conn->remote_addr)) { 
		KdPrint(("[tdi_fw] tdi_connect: address too long! (%u)\n", remote_addr->AddressLength)); 
		goto done; 
	} 
	memcpy(ote_conn->remote_addr, remote_addr, remote_addr->AddressLength); 
 
	// set local address with connobj 
 
	if (local_addr->AddressLength > sizeof(ote_conn->local_addr)) { 
		KdPrint(("[tdi_fw] tdi_connect: address to long! (%u)\n", local_addr->AddressLength)); 
		goto done; 
	} 
	memcpy(ote_conn->local_addr, local_addr, local_addr->AddressLength); 
 
	KdPrint(("[tdi_fw] tdi_connect(pid:%u): %x:%u -> %x:%u (ipproto = %d)\n", 
		ote_conn->pid, 
		ntohl(((TDI_ADDRESS_IP *)(local_addr->Address))->in_addr), 
		ntohs(((TDI_ADDRESS_IP *)(local_addr->Address))->sin_port), 
		ntohl(((TDI_ADDRESS_IP *)(remote_addr->Address))->in_addr), 
		ntohs(((TDI_ADDRESS_IP *)(remote_addr->Address))->sin_port), ipproto)); 
 
	/* 
	 * Call quick_filter 
	 */ 
 
	memset(&request, 0, sizeof(request)); 
	request.struct_size = sizeof(request); 
 
	request.type = TYPE_CONNECT; 
	request.direction = DIRECTION_OUT; 
	request.proto = ipproto; 
	request.pid = ote_conn->pid; 
	 
	memcpy(&request.addr.from, &local_addr->AddressType, sizeof(struct sockaddr)); 
	memcpy(&request.addr.to, &remote_addr->AddressType, sizeof(struct sockaddr)); 
	request.addr.len = sizeof(struct sockaddr_in); 
 
	memset(&rule, 0, sizeof(rule)); 
 
	result = quick_filter(&request, &rule); 
 
	// if logging is needed log request 
	if (rule.log) 
		log_request(&request); 
 
done: 
	// cleanup 
	if (ote_conn != NULL) 
		KeReleaseSpinLock(&g_ot_hash_guard, irql); 
 
	return result; 
}