📄 tdi_fw_svc.c
字号:
// $Id: tdi_fw_svc.c,v 1.12 2002/12/05 13:03:27 dev Exp $
#include <stdio.h>
#include <time.h>
#include <windows.h>
#include <winioctl.h>
#include <psapi.h>
#include "flt_rule.h"
#include "ipc.h"
#include "tdi_fw_svc.h"
#include "thread.h"
#include "msg.h"
#define DISP_BUF_SIZE 0x10000
HANDLE g_device = INVALID_HANDLE_VALUE;
static HANDLE g_event = NULL;
static HANDLE g_exit_event = NULL;
static HANDLE g_pipe = INVALID_HANDLE_VALUE;
static HANDLE g_dispatcher = NULL;
static char *g_disp_buf = NULL;
static DWORD WINAPI dispatcher(LPVOID param);
static DWORD WINAPI restart_thread(LPVOID param);
static void dispatch_request(struct flt_request *request);
static FILE *g_logfile = NULL;
static BOOL load_config(const char *config);
static BOOL read_config(const char *config);
static BOOL add_rules_name(const char *main_name, const char *config, int chain);
static void add_rules(char *buf, const char *name, int chain);
static BOOL get_pname_by_pid(u_long pid, char *buf, int buf_size);
static void prepare_addr(char *buf, int size, u_long addr);
static void my_GetLongPathName(LPCSTR lpszShortPath, LPSTR lpszLongPath,
DWORD cchBuffer);
// some config switches
static BOOL g_eventlog_allow = FALSE;
static BOOL g_eventlog_deny = FALSE;
static BOOL g_eventlog_error = FALSE;
// used in flt_rule.c
BOOL g_rules_resolve_addr = FALSE;
static BOOL g_logs_resolve_addr = FALSE;
static void log_msg(const char *msg, int type);
enum {
MSGTYPE_ALLOW,
MSGTYPE_DENY,
MSGTYPE_ERROR
};
int
start(const char *config)
{
static char device_name[] = "\\\\.\\tdi_fw";
int result = FALSE;
WSADATA wsd;
DWORD thread_id;
// startup sockets for names resolution
WSAStartup(MAKEWORD(1, 1), &wsd);
/* connect with driver */
g_device = CreateFile(device_name, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (g_device == INVALID_HANDLE_VALUE) {
winerr(device_name);
goto done;
}
/* open event for driver communication */
g_event = OpenEvent(SYNCHRONIZE, FALSE, "tdi_fw_request");
if (g_event == NULL) {
winerr("start: OpenEvent");
goto done;
}
/* load config & rules */
if (!load_config(config))
goto done;
/* start dispatcher thread */
g_exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_exit_event == NULL) {
winerr("start: CreateEvent");
goto done;
}
g_disp_buf = (char *)malloc(DISP_BUF_SIZE);
if (g_disp_buf == NULL) {
liberr("start: malloc");
goto done;
}
g_dispatcher = lib_CreateThread(NULL, 0, dispatcher, (LPVOID)config, 0, &thread_id);
if (g_dispatcher == NULL) {
winerr("start: lib_CreateThread");
goto done;
}
result = TRUE;
done:
if (!result)
stop();
return result;
}
void
stop(void)
{
// disconnect from driver
if (g_device != INVALID_HANDLE_VALUE) {
HANDLE old_h = g_device;
g_device = INVALID_HANDLE_VALUE;
CancelIo(old_h);
CloseHandle(old_h);
}
// stop dispatcher thread
if (g_exit_event != NULL)
SetEvent(g_exit_event);
if (g_dispatcher != NULL) {
WaitForSingleObject(g_dispatcher, INFINITE);
g_dispatcher = NULL;
}
// close logfile
if (g_logfile != NULL) {
fprintf(g_logfile, "--- end ---\n");
fclose(g_logfile);
g_logfile = NULL;
}
if (g_exit_event != NULL)
CloseHandle(g_exit_event);
if (g_event != NULL)
CloseHandle(g_event);
if (g_disp_buf != NULL) {
free(g_disp_buf);
g_disp_buf = NULL;
}
}
void
wait(void)
{
if (g_exit_event != NULL)
WaitForSingleObject(g_exit_event, INFINITE);
}
/* output functions */
void
error(const char *fmt, ...)
{
va_list ap;
char message[1024];
// prepare message
va_start(ap, fmt);
if (_vsnprintf(message, sizeof(message), fmt, ap) == -1)
message[sizeof(message) - 1] = '\0';
va_end(ap);
// got message
log_msg(message, MSGTYPE_ERROR);
}
void
winerr(const char *fn)
{
char *win_msg = NULL;
DWORD code = GetLastError();
if (code == 0)
error("WINERR\t%s:", fn);
else {
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,NULL,code,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPTSTR)&win_msg,0,NULL);
if (win_msg != NULL) {
// kill \r\n
int len = strlen(win_msg);
if (len >= 1)
win_msg[len-1]=0;
if (len >= 2)
win_msg[len-2]=0;
error("WINERR\t%s: %s", fn, win_msg);
LocalFree(win_msg);
} else
error("WINERR\t%s: %d (0x%x)", fn, code, code);
}
// save error code
SetLastError(code);
}
void
liberr(const char *fn)
{
int code = errno;
if (code != 0)
error("LIBERR\t%s: %s", fn, strerror(code));
else
error("LIBERR\t%s:", fn);
}
/* dispatcher thread */
DWORD WINAPI
dispatcher(LPVOID param)
{
char *config = (char *)param;
HANDLE handles[2];
DWORD i, n;
handles[0] = g_event;
handles[1] = g_exit_event;
for (;;) {
if (!DeviceIoControl(g_device, IOCTL_CMD_GETREQUEST, NULL, 0,
g_disp_buf, DISP_BUF_SIZE, &n, NULL)) {
winerr("dispatcher: DeviceIoControl");
break;
}
if (n == 0) {
// wait for data
DWORD wait = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (wait == WAIT_OBJECT_0 + 1)
break;
else if (wait != WAIT_OBJECT_0) {
winerr("dispatcher: WaitForSingleObject");
break;
}
continue;
}
for (i = 0; i < n;) {
struct flt_request *request;
if (n - i < sizeof(*request))
break;
request = (struct flt_request *)(g_disp_buf + i);
dispatch_request(request);
i += request->struct_size;
}
}
if (g_device != INVALID_HANDLE_VALUE) {
DWORD thread_id;
error("dispatcher: unexpected exit!");
// restart tdi_fw_svc
lib_CreateThread(NULL, 0, restart_thread, config, 0, &thread_id);
}
return 0;
}
DWORD
WINAPI restart_thread(LPVOID param)
{
char *config = (char *)param;
error("restarting...");
stop();
start(config);
return 0;
}
/* log filter request from filter driver */
void
dispatch_request(struct flt_request *request)
{
u_long from_ip, to_ip;
u_short from_port, to_port;
char msg[1024], pname_buf[MAX_PATH], addr_from[100], addr_to[100], *pname;
if (request->pname == NULL) {
// try to resolve pid to pname
if (get_pname_by_pid(request->pid, pname_buf + sizeof(DWORD), sizeof(pname_buf) - sizeof(DWORD))) {
// send message to driver to send process name next time
DWORD n;
pname = pname_buf + sizeof(DWORD);
*(DWORD *)pname_buf = request->pid;
if (!DeviceIoControl(g_device, IOCTL_CMD_SETPNAME, pname_buf,
sizeof(DWORD) + strlen(pname) + 1,
NULL, 0, &n, NULL))
winerr("DeviceIoControl");
} else {
error("PROCESS\tCan't resolve pid %u!\n", request->pid);
sprintf(pname_buf, "pid:%u", request->pid);
pname = pname_buf;
}
} else
pname = (char *)&request[1];
// check is it request type "TYPE_RESOLVE_PID"
if (request->type == TYPE_RESOLVE_PID) {
if (_snprintf(msg, sizeof(msg), "PROCESS\t%u\t%s", request->pid, pname) == -1)
msg[sizeof(msg) - 1] = '\0';
log_msg(msg, request->result == FILTER_ALLOW ? MSGTYPE_ALLOW : MSGTYPE_DENY);
} else {
// prepare message
from_ip = ((struct sockaddr_in *)&request->addr.from)->sin_addr.s_addr;
from_port = ntohs(((struct sockaddr_in *)&request->addr.from)->sin_port);
to_ip = ((struct sockaddr_in *)&request->addr.to)->sin_addr.s_addr;
to_port = ntohs(((struct sockaddr_in *)&request->addr.to)->sin_port);
// prepare address "from" & "to"
prepare_addr(addr_from, sizeof(addr_from), from_ip);
prepare_addr(addr_to, sizeof(addr_to), to_ip);
// log it!
if (_snprintf(msg, sizeof(msg),
"%s\t%s\t%s\t%s:%d\t%s:%d\t%s",
(request->result == FILTER_ALLOW) ? "ALLOW" : "DENY",
(request->proto == IPPROTO_TCP) ? "TCP" :
(request->proto == IPPROTO_UDP ? "UDP" : "RawIP"),
(request->direction == DIRECTION_IN) ? "IN" : "OUT",
addr_from, from_port,
addr_to, to_port, pname) == -1)
msg[sizeof(msg) - 1] = '\0';
log_msg(msg, request->result == FILTER_ALLOW ? MSGTYPE_ALLOW : MSGTYPE_DENY);
}
}
/*
* write message to console, log file or probably to eventlog
*
* don't call any error functions! to cause infinite recurse.
*/
void
log_msg(const char *msg, int type)
{
static int file_day = 0; // for midnight checking
static ULONG event_num = 1; // number of event in log file
// if working in console mode write message to console
if (g_console) {
if (type == MSGTYPE_ERROR)
fprintf(stderr, "%s\n", msg);
else
printf("%s\n", msg);
}
// write to eventlog if filter is set
if ((type == MSGTYPE_ALLOW && g_eventlog_allow) ||
(type == MSGTYPE_DENY && g_eventlog_deny) ||
(type == MSGTYPE_ERROR && g_eventlog_error)) {
HANDLE hEventSource;
const char *strings;
// write message to event log
// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, "tdi_fw_svc");
if (hEventSource != NULL) {
WORD event_type;
strings = msg; // write message without timestamp
event_type = (type == MSGTYPE_ALLOW) ? EVENTLOG_AUDIT_SUCCESS :
(type == MSGTYPE_DENY ? EVENTLOG_AUDIT_FAILURE : EVENTLOG_ERROR_TYPE);
if (!ReportEvent(hEventSource, // handle of event source
event_type,
0, // event category
MSG, // event ID
NULL, // current user's SID
1, // strings in lpszStrings
0, // no bytes of raw data
&strings, // array of error strings
NULL)) { // no raw data
#ifdef _DEBUG
MessageBeep(0);
OutputDebugString("log_msg: ReportEvent\n");
#endif
}
DeregisterEventSource(hEventSource);
}
} else {
// write message to log
time_t tv;
struct tm *tm;
char tm_msg[1024];
time(&tv);
tm = localtime(&tv);
if (tm == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -