📄 ndis.c
字号:
/* * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */#include "ndis.h"#include "iw_ndis.h"#include "wrapndis.h"#include "pnp.h"#include "loader.h"#include <linux/kernel_stat.h>#define MAX_ALLOCATED_NDIS_PACKETS 20#define MAX_ALLOCATED_NDIS_BUFFERS 20static workqueue_struct_t *ndis_wq;static void ndis_worker(worker_param_t dummy);static work_struct_t ndis_work;static struct nt_list ndis_work_list;static NT_SPIN_LOCK ndis_work_list_lock;extern struct semaphore loader_mutex;wstdcall void WIN_FUNC(NdisInitializeWrapper,4) (void **driver_handle, struct driver_object *driver, struct unicode_string *reg_path, void *unused){ ENTER1("handle: %p, driver: %p", driver_handle, driver); *driver_handle = driver; EXIT1(return);}wstdcall void WIN_FUNC(NdisTerminateWrapper,2) (struct device_object *dev_obj, void *system_specific){ EXIT1(return);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterMiniport,3) (struct driver_object *drv_obj, struct miniport_char *miniport_char, UINT length){ int min_length; struct wrap_driver *wrap_driver; struct wrap_ndis_driver *ndis_driver; min_length = ((char *)&miniport_char->co_create_vc) - ((char *)miniport_char); ENTER1("%p %p %d", drv_obj, miniport_char, length); if (miniport_char->major_version < 4) { ERROR("Driver is using ndis version %d which is too old.", miniport_char->major_version); EXIT1(return NDIS_STATUS_BAD_VERSION); } if (length < min_length) { ERROR("Characteristics length %d is too small", length); EXIT1(return NDIS_STATUS_BAD_CHARACTERISTICS); } TRACE1("%d.%d, %d, %u", miniport_char->major_version, miniport_char->minor_version, length, (u32)sizeof(struct miniport_char)); wrap_driver = IoGetDriverObjectExtension(drv_obj, (void *)WRAP_DRIVER_CLIENT_ID); if (!wrap_driver) { ERROR("couldn't get wrap_driver"); EXIT1(return NDIS_STATUS_RESOURCES); } if (IoAllocateDriverObjectExtension( drv_obj, (void *)NDIS_DRIVER_CLIENT_ID, sizeof(*ndis_driver), (void **)&ndis_driver) != STATUS_SUCCESS) EXIT1(return NDIS_STATUS_RESOURCES); wrap_driver->ndis_driver = ndis_driver; TRACE1("driver: %p", ndis_driver); memcpy(&ndis_driver->miniport, miniport_char, length > sizeof(*miniport_char) ? sizeof(*miniport_char) : length); DBG_BLOCK(2) { int i; void **func; char *miniport_funcs[] = { "query", "reconfig", "reset", "send", "setinfo", "tx_data", "return_packet", "send_packets", "alloc_complete", "co_create_vc", "co_delete_vc", "co_activate_vc", "co_deactivate_vc", "co_send_packets", "co_request", "cancel_send_packets", "pnp_event_notify", "shutdown", }; func = (void **)&ndis_driver->miniport.query; for (i = 0; i < (sizeof(miniport_funcs) / sizeof(miniport_funcs[0])); i++) TRACE2("function '%s' is at %p", miniport_funcs[i], func[i]); } EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall NDIS_STATUS WIN_FUNC(NdisMRegisterDevice,6) (struct driver_object *drv_obj, struct unicode_string *dev_name, struct unicode_string *link, void **funcs, struct device_object **dev_obj, void **dev_obj_handle){ NTSTATUS status; struct device_object *tmp; int i; ENTER1("%p, %p, %p", drv_obj, dev_name, link); status = IoCreateDevice(drv_obj, 0, dev_name, FILE_DEVICE_NETWORK, 0, FALSE, &tmp); if (status != STATUS_SUCCESS) EXIT1(return NDIS_STATUS_RESOURCES); if (link) status = IoCreateSymbolicLink(link, dev_name); if (status != STATUS_SUCCESS) { IoDeleteDevice(tmp); EXIT1(return NDIS_STATUS_RESOURCES); } *dev_obj = tmp; *dev_obj_handle = *dev_obj; for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) if (funcs[i] && i != IRP_MJ_PNP && i != IRP_MJ_POWER) { drv_obj->major_func[i] = funcs[i]; TRACE1("mj_fn for 0x%x is at %p", i, funcs[i]); } EXIT1(return NDIS_STATUS_SUCCESS);}wstdcall NDIS_STATUS WIN_FUNC(NdisMDeregisterDevice,1) (struct device_object *dev_obj){ ENTER2("%p", dev_obj); IoDeleteDevice(dev_obj); return NDIS_STATUS_SUCCESS;}wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemoryWithTag,3) (void **dest, UINT length, ULONG tag){ void *addr; addr = ExAllocatePoolWithTag(NonPagedPool, length, tag); TRACE4("%p", addr); if (addr) { *dest = addr; EXIT4(return NDIS_STATUS_SUCCESS); } else EXIT4(return NDIS_STATUS_FAILURE);}wstdcall NDIS_STATUS WIN_FUNC(NdisAllocateMemory,4) (void **dest, UINT length, UINT flags, NDIS_PHY_ADDRESS highest_address){ return NdisAllocateMemoryWithTag(dest, length, 0);}/* length_tag is either length or tag, depending on if * NdisAllocateMemory or NdisAllocateMemoryTag is used to allocate * memory */wstdcall void WIN_FUNC(NdisFreeMemory,3) (void *addr, UINT length_tag, UINT flags){ TRACE4("%p", addr); ExFreePool(addr);}noregparm void WIN_FUNC(NdisWriteErrorLogEntry,12) (struct driver_object *drv_obj, ULONG error, ULONG count, ...){ va_list args; int i; ULONG code; va_start(args, count); ERROR("log: %08X, count: %d, return_address: %p", error, count, __builtin_return_address(0)); for (i = 0; i < count; i++) { code = va_arg(args, ULONG); ERROR("code: 0x%x", code); } va_end(args); EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfiguration,3) (NDIS_STATUS *status, struct ndis_miniport_block **conf_handle, struct ndis_miniport_block *handle){ ENTER2("%p", conf_handle); *conf_handle = handle; *status = NDIS_STATUS_SUCCESS; EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenProtocolConfiguration,3) (NDIS_STATUS *status, void **confhandle, struct unicode_string *section){ ENTER2("%p", confhandle); *status = NDIS_STATUS_SUCCESS; EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByName,4) (NDIS_STATUS *status, void *handle, struct unicode_string *key, void **subkeyhandle){ struct ansi_string ansi; ENTER2(""); if (RtlUnicodeStringToAnsiString(&ansi, key, TRUE) == STATUS_SUCCESS) { TRACE2("%s", ansi.buf); RtlFreeAnsiString(&ansi); } *subkeyhandle = handle; *status = NDIS_STATUS_SUCCESS; EXIT2(return);}wstdcall void WIN_FUNC(NdisOpenConfigurationKeyByIndex,5) (NDIS_STATUS *status, void *handle, ULONG index, struct unicode_string *key, void **subkeyhandle){ ENTER2("%u", index);// *subkeyhandle = handle; *status = NDIS_STATUS_FAILURE; EXIT2(return);}wstdcall void WIN_FUNC(NdisCloseConfiguration,1) (void *handle){ /* instead of freeing all configuration parameters as we are * supposed to do here, we free them when the device is * removed */ ENTER2("%p", handle); return;}wstdcall void WIN_FUNC(NdisOpenFile,5) (NDIS_STATUS *status, struct wrap_bin_file **file, UINT *filelength, struct unicode_string *filename, NDIS_PHY_ADDRESS highest_address){ struct ansi_string ansi; struct wrap_bin_file *bin_file; ENTER2("%p, %d, %llx, %p", status, *filelength, highest_address, *file); if (RtlUnicodeStringToAnsiString(&ansi, filename, TRUE) != STATUS_SUCCESS) { *status = NDIS_STATUS_RESOURCES; EXIT2(return); } TRACE2("%s", ansi.buf); bin_file = get_bin_file(ansi.buf); if (bin_file) { *file = bin_file; *filelength = bin_file->size; *status = NDIS_STATUS_SUCCESS; } else *status = NDIS_STATUS_FILE_NOT_FOUND; RtlFreeAnsiString(&ansi); EXIT2(return);}wstdcall void WIN_FUNC(NdisMapFile,3) (NDIS_STATUS *status, void **mappedbuffer, struct wrap_bin_file *file){ ENTER2("%p", file); if (!file) { *status = NDIS_STATUS_ALREADY_MAPPED; EXIT2(return); } *status = NDIS_STATUS_SUCCESS; *mappedbuffer = file->data; EXIT2(return);}wstdcall void WIN_FUNC(NdisUnmapFile,1) (struct wrap_bin_file *file){ ENTER2("%p", file); EXIT2(return);}wstdcall void WIN_FUNC(NdisCloseFile,1) (struct wrap_bin_file *file){ ENTER2("%p", file); free_bin_file(file); EXIT2(return);}wstdcall void WIN_FUNC(NdisGetSystemUpTime,1) (ULONG *ms){ *ms = 1000 * jiffies / HZ; EXIT5(return);}wstdcall ULONG WIN_FUNC(NDIS_BUFFER_TO_SPAN_PAGES,1) (ndis_buffer *buffer){ ULONG n, length; if (buffer == NULL) EXIT2(return 0); if (MmGetMdlByteCount(buffer) == 0) EXIT2(return 1); length = MmGetMdlByteCount(buffer); n = SPAN_PAGES(MmGetMdlVirtualAddress(buffer), length); TRACE4("%p, %p, %d, %d", buffer->startva, buffer->mappedsystemva, length, n); EXIT3(return n);}wstdcall void WIN_FUNC(NdisGetBufferPhysicalArraySize,2) (ndis_buffer *buffer, UINT *arraysize){ ENTER3("%p", buffer); *arraysize = NDIS_BUFFER_TO_SPAN_PAGES(buffer); EXIT3(return);}static struct ndis_configuration_parameter *ndis_encode_setting(struct wrap_device_setting *setting, enum ndis_parameter_type type){ struct ansi_string ansi; struct ndis_configuration_parameter *param; param = setting->encoded; if (param) { if (param->type == type) EXIT2(return param); if (param->type == NdisParameterString) RtlFreeUnicodeString(¶m->data.string); setting->encoded = NULL; } else param = ExAllocatePoolWithTag(NonPagedPool, sizeof(*param), 0); if (!param) { ERROR("couldn't allocate memory"); return NULL; } switch(type) { case NdisParameterInteger: param->data.integer = simple_strtol(setting->value, NULL, 0); TRACE2("%u", (ULONG)param->data.integer); break; case NdisParameterHexInteger: param->data.integer = simple_strtol(setting->value, NULL, 16); TRACE2("%u", (ULONG)param->data.integer); break; case NdisParameterString: RtlInitAnsiString(&ansi, setting->value); TRACE2("'%s'", ansi.buf); if (RtlAnsiStringToUnicodeString(¶m->data.string, &ansi, TRUE)) { ExFreePool(param); EXIT2(return NULL); } break; default: ERROR("unknown type: %d", type); ExFreePool(param); return NULL; } param->type = type; setting->encoded = param; EXIT2(return param);}static int ndis_decode_setting(struct wrap_device_setting *setting, struct ndis_configuration_parameter *param){ struct ansi_string ansi; struct ndis_configuration_parameter *prev; ENTER2("%p, %p", setting, param); prev = setting->encoded; if (prev && prev->type == NdisParameterString) { RtlFreeUnicodeString(&prev->data.string); setting->encoded = NULL; } switch(param->type) { case NdisParameterInteger: snprintf(setting->value, sizeof(u32), "%u", param->data.integer); setting->value[sizeof(ULONG)] = 0; break; case NdisParameterHexInteger: snprintf(setting->value, sizeof(u32), "%x", param->data.integer); setting->value[sizeof(ULONG)] = 0; break; case NdisParameterString: ansi.buf = setting->value; ansi.max_length = MAX_SETTING_VALUE_LEN; if ((RtlUnicodeStringToAnsiString(&ansi, ¶m->data.string, FALSE) != STATUS_SUCCESS) || ansi.length >= MAX_SETTING_VALUE_LEN) { EXIT1(return -1); } if (ansi.length == ansi.max_length) ansi.length--; setting->value[ansi.length] = 0; break; default: TRACE2("unknown setting type: %d", param->type); return -1; } TRACE2("setting changed %s='%s', %d", setting->name, setting->value, ansi.length); return 0;}static int read_setting(struct nt_list *setting_list, char *keyname, int length, struct ndis_configuration_parameter **param, enum ndis_parameter_type type){ struct wrap_device_setting *setting; if (down_interruptible(&loader_mutex)) WARNING("couldn't obtain loader_mutex"); nt_list_for_each_entry(setting, setting_list, list) { if (strnicmp(keyname, setting->name, length) == 0) { TRACE2("setting %s='%s'", keyname, setting->value); up(&loader_mutex); *param = ndis_encode_setting(setting, type); if (*param) EXIT2(return 0); else EXIT2(return -1); } } up(&loader_mutex); EXIT2(return -1);}wstdcall void WIN_FUNC(NdisReadConfiguration,5) (NDIS_STATUS *status, struct ndis_configuration_parameter **param, struct ndis_miniport_block *nmb, struct unicode_string *key, enum ndis_parameter_type type){ struct ansi_string ansi; char *keyname; int ret; ENTER2("nmb: %p", nmb); ret = RtlUnicodeStringToAnsiString(&ansi, key, TRUE); if (ret != STATUS_SUCCESS || ansi.buf == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -