⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wrapndis.c

📁 ndiswrapper工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  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 "pnp.h"#include "loader.h"#include "wrapndis.h"extern char *if_name;extern int hangcheck_interval;extern struct iw_handler_def ndis_handler_def;extern NT_SPIN_LOCK timer_lock;static int set_packet_filter(struct wrap_ndis_device *wnd,			     ULONG packet_filter);static void add_stats_timer(struct wrap_ndis_device *wnd);static void del_stats_timer(struct wrap_ndis_device *wnd);static NDIS_STATUS ndis_start_device(struct wrap_ndis_device *wnd);static int ndis_remove_device(struct wrap_ndis_device *wnd);static void set_multicast_list(struct wrap_ndis_device *wnd);static int ndis_net_dev_open(struct net_device *net_dev);static int ndis_net_dev_close(struct net_device *net_dev);static inline int ndis_wait_comm_completion(struct wrap_ndis_device *wnd){	if ((wait_event_interruptible(wnd->ndis_comm_wq,				      (wnd->ndis_comm_done > 0))))		return -1;	else		return 0;}/* MiniportReset */NDIS_STATUS miniport_reset(struct wrap_ndis_device *wnd){	NDIS_STATUS res;	struct miniport_char *miniport;	UINT cur_lookahead, max_lookahead;	BOOLEAN reset_address;	KIRQL irql;	TRACEENTER2("wnd: %p", wnd);	if (down_interruptible(&wnd->tx_ring_mutex))		TRACEEXIT3(return NDIS_STATUS_FAILURE);	if (down_interruptible(&wnd->ndis_comm_mutex)) {		up(&wnd->tx_ring_mutex);		TRACEEXIT3(return NDIS_STATUS_FAILURE);	}			miniport = &wnd->wd->driver->ndis_driver->miniport;	cur_lookahead = wnd->nmb->cur_lookahead;	max_lookahead = wnd->nmb->max_lookahead;	wnd->ndis_comm_done = 0;	WARNING("%s is being reset", wnd->net_dev->name);	irql = serialize_lock_irql(wnd);	res = LIN2WIN2(miniport->reset, &reset_address, wnd->nmb->adapter_ctx);	serialize_unlock_irql(wnd, irql);	DBGTRACE2("%08X, %08X", res, reset_address);	if (res == NDIS_STATUS_PENDING) {		/* wait for NdisMResetComplete */		if (ndis_wait_comm_completion(wnd))			res = NDIS_STATUS_FAILURE;		else {			res = wnd->ndis_comm_status;			reset_address = wnd->ndis_comm_done - 1;		}		DBGTRACE2("%08X, %08X", res, reset_address);	}	up(&wnd->ndis_comm_mutex);	if (res == NDIS_STATUS_SUCCESS && reset_address) {		wnd->nmb->cur_lookahead = cur_lookahead;		wnd->nmb->max_lookahead = max_lookahead;		set_packet_filter(wnd, wnd->packet_filter);		set_multicast_list(wnd);	}	up(&wnd->tx_ring_mutex);	TRACEEXIT3(return res);}/* MiniportQueryInformation */NDIS_STATUS miniport_query_info_needed(struct wrap_ndis_device *wnd,				       ndis_oid oid, void *buf,				       ULONG bufsize, ULONG *needed){	NDIS_STATUS res;	ULONG written;	struct miniport_char *miniport;	KIRQL irql;	DBGTRACE2("oid: %08X", oid);	if (down_interruptible(&wnd->ndis_comm_mutex))		TRACEEXIT3(return NDIS_STATUS_FAILURE);	miniport = &wnd->wd->driver->ndis_driver->miniport;	DBGTRACE2("%p, %08X", miniport->query, oid);	wnd->ndis_comm_done = 0;	irql = serialize_lock_irql(wnd);	res = LIN2WIN6(miniport->query, wnd->nmb->adapter_ctx, oid, buf,		       bufsize, &written, needed);	serialize_unlock_irql(wnd, irql);	DBGTRACE2("%08X, %08X", res, oid);	if (res == NDIS_STATUS_PENDING) {		/* wait for NdisMQueryInformationComplete */		if (ndis_wait_comm_completion(wnd))			res = NDIS_STATUS_FAILURE;		else			res = wnd->ndis_comm_status;		DBGTRACE2("%08X, %08X", res, oid);	}	up(&wnd->ndis_comm_mutex);	DBG_BLOCK(2) {		if (res || needed)			DBGTRACE2("%08X, %d, %d, %d", res, bufsize, written,				  *needed);	}	TRACEEXIT3(return res);}NDIS_STATUS miniport_query_info(struct wrap_ndis_device *wnd, ndis_oid oid,				void *buf, ULONG bufsize){	NDIS_STATUS res;	ULONG needed;	res = miniport_query_info_needed(wnd, oid, buf, bufsize, &needed);	return res;}/* MiniportSetInformation */NDIS_STATUS miniport_set_info(struct wrap_ndis_device *wnd, ndis_oid oid,			      void *buf, ULONG bufsize){	NDIS_STATUS res;	ULONG written, needed;	struct miniport_char *miniport;	KIRQL irql;	DBGTRACE2("oid: %08X", oid);	if (down_interruptible(&wnd->ndis_comm_mutex))		TRACEEXIT3(return NDIS_STATUS_FAILURE);	miniport = &wnd->wd->driver->ndis_driver->miniport;	DBGTRACE2("%p, %08X", miniport->query, oid);	wnd->ndis_comm_done = 0;	irql = serialize_lock_irql(wnd);	res = LIN2WIN6(miniport->setinfo, wnd->nmb->adapter_ctx, oid,		       buf, bufsize, &written, &needed);	serialize_unlock_irql(wnd, irql);	DBGTRACE2("%08X, %08X", res, oid);	if (res == NDIS_STATUS_PENDING) {		/* wait for NdisMQueryInformationComplete */		if (ndis_wait_comm_completion(wnd))			res = NDIS_STATUS_FAILURE;		else			res = wnd->ndis_comm_status;		DBGTRACE2("%08X, %08X", res, oid);	}	up(&wnd->ndis_comm_mutex);	DBG_BLOCK(2) {		if (res && needed)			DBGTRACE2("%08X, %d, %d, %d", res, bufsize, written,				  needed);	}	TRACEEXIT3(return res);}NDIS_STATUS miniport_query_int(struct wrap_ndis_device *wnd, ndis_oid oid,			       ULONG *data){	return miniport_query_info(wnd, oid, data, sizeof(ULONG));}NDIS_STATUS miniport_set_int(struct wrap_ndis_device *wnd, ndis_oid oid,			     ULONG data){	return miniport_set_info(wnd, oid, &data, sizeof(data));}/* MiniportPnPEventNotify */static NDIS_STATUS miniport_pnp_event(struct wrap_ndis_device *wnd,				      enum ndis_device_pnp_event event){	struct miniport_char *miniport;	ULONG power_profile;	TRACEENTER1("%p, %d", wnd, event);	miniport = &wnd->wd->driver->ndis_driver->miniport;	if (!miniport->pnp_event_notify) {		DBGTRACE1("Windows driver %s doesn't support "			  "MiniportPnpEventNotify", wnd->wd->driver->name);		return NDIS_STATUS_FAILURE;	}	/* RNDIS driver doesn't like to be notified if device is	 * already halted */	if (!test_bit(HW_INITIALIZED, &wnd->hw_status))		TRACEEXIT1(return NDIS_STATUS_SUCCESS);	switch (event) {	case NdisDevicePnPEventSurpriseRemoved:		DBGTRACE1("%u, %p",			  (wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK),			  miniport->pnp_event_notify);		if ((wnd->attributes & NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK) &&		    wnd->wd->surprise_removed == TRUE &&		    miniport->pnp_event_notify) {			DBGTRACE1("calling surprise_removed");			LIN2WIN4(miniport->pnp_event_notify,				 wnd->nmb->adapter_ctx,				 NdisDevicePnPEventSurpriseRemoved, NULL, 0);		} else			DBGTRACE1("Windows driver %s doesn't support "				  "MiniportPnpEventNotify for safe unplugging",				  wnd->wd->driver->name);		return NDIS_STATUS_SUCCESS;	case NdisDevicePnPEventPowerProfileChanged:		power_profile = NdisPowerProfileAcOnLine;		LIN2WIN4(miniport->pnp_event_notify, wnd->nmb->adapter_ctx,			 NdisDevicePnPEventPowerProfileChanged,			 &power_profile, (ULONG)sizeof(power_profile));		return NDIS_STATUS_SUCCESS;	default:		WARNING("event %d not yet implemented", event);		return NDIS_STATUS_SUCCESS;	}}/* MiniportInitialize */static NDIS_STATUS miniport_init(struct wrap_ndis_device *wnd){	NDIS_STATUS error_status, status;	UINT medium_index;	UINT medium_array[] = {NdisMedium802_3};	struct miniport_char *miniport;	struct ndis_pnp_capabilities pnp_capa;	TRACEENTER1("irql: %d", current_irql());	if (test_bit(HW_INITIALIZED, &wnd->hw_status)) {		WARNING("device %p already initialized!", wnd);		return NDIS_STATUS_FAILURE;	}	if (!wnd->wd->driver->ndis_driver ||	    !wnd->wd->driver->ndis_driver->miniport.init) {		WARNING("assuming WDM (non-NDIS) driver");		TRACEEXIT1(return NDIS_STATUS_NOT_RECOGNIZED);	}	miniport = &wnd->wd->driver->ndis_driver->miniport;	status = LIN2WIN6(miniport->init, &error_status,			  &medium_index, medium_array,			  sizeof(medium_array) / sizeof(medium_array[0]),			  wnd->nmb, wnd->nmb);	DBGTRACE1("init returns: %08X, irql: %d", status, current_irql());	if (status != NDIS_STATUS_SUCCESS) {		WARNING("couldn't initialize device: %08X", status);		TRACEEXIT1(return NDIS_STATUS_FAILURE);	}	/* Wait a little to let card power up otherwise ifup might	 * fail after boot */	sleep_hz(HZ / 2);	set_bit(HW_INITIALIZED, &wnd->hw_status);	hangcheck_add(wnd);	/* the description about NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND is	 * misleading/confusing; we just ignore it */	status = miniport_query_info(wnd, OID_PNP_CAPABILITIES,				     &pnp_capa, sizeof(pnp_capa));	if (status == NDIS_STATUS_SUCCESS)		wnd->pm_capa = TRUE;	else		wnd->pm_capa = FALSE;	DBGTRACE1("%d", pnp_capa.wakeup_capa.min_magic_packet_wakeup);	TRACEEXIT1(return NDIS_STATUS_SUCCESS);}/* MiniportHalt */static void miniport_halt(struct wrap_ndis_device *wnd){	struct miniport_char *miniport;	TRACEENTER1("%p", wnd);	if (test_and_clear_bit(HW_INITIALIZED, &wnd->hw_status)) {		hangcheck_del(wnd);		del_stats_timer(wnd);		miniport = &wnd->wd->driver->ndis_driver->miniport;		DBGTRACE1("halt: %p", miniport->miniport_halt);		LIN2WIN1(miniport->miniport_halt, wnd->nmb->adapter_ctx);		/* cancel any timers left by bugyy windows driver; also free		 * the memory for timers */		while (1) {			KIRQL irql;			struct nt_list *ent;			struct wrap_timer *wrap_timer;			irql = nt_spin_lock_irql(&timer_lock, DISPATCH_LEVEL);			ent = RemoveHeadList(&wnd->timer_list);			nt_spin_unlock_irql(&timer_lock, irql);			if (!ent)				break;			wrap_timer = container_of(ent, struct wrap_timer, list);			wrap_timer->repeat = 0;			/* ktimer that this wrap_timer is associated to can't			 * be touched, as it may have been freed by the driver			 * already */			if (del_timer_sync(&wrap_timer->timer))				WARNING("Buggy Windows driver left timer %p "					"running", &wrap_timer->timer);			memset(wrap_timer, 0, sizeof(*wrap_timer));			slack_kfree(wrap_timer);		}	} else		WARNING("device %p is not initialized - not halting", wnd);	TRACEEXIT1(return);}static NDIS_STATUS miniport_set_power_state(struct wrap_ndis_device *wnd,					    enum ndis_power_state state){	NDIS_STATUS status;	DBGTRACE1("%d", state);	if (state == NdisDeviceStateD0) {		status = NDIS_STATUS_SUCCESS;		up(&wnd->ndis_comm_mutex);		if (test_and_clear_bit(HW_HALTED, &wnd->hw_status)) {			status = miniport_init(wnd);			if (status == NDIS_STATUS_SUCCESS) {				set_packet_filter(wnd, wnd->packet_filter);				set_multicast_list(wnd);			}		} else if (test_and_clear_bit(HW_SUSPENDED, &wnd->hw_status)) {			status = miniport_set_int(wnd, OID_PNP_SET_POWER,						  state);			if (status != NDIS_STATUS_SUCCESS)				WARNING("%s: setting power to state %d failed? "					"%08X", wnd->net_dev->name, state,					status);			if (wnd->ndis_wolopts &&			    wrap_is_pci_bus(wnd->wd->dev_bus))				pci_enable_wake(wnd->wd->pci.pdev, PCI_D0, 0);		} else			return NDIS_STATUS_FAILURE;		if (status == NDIS_STATUS_SUCCESS) {			up(&wnd->tx_ring_mutex);			netif_device_attach(wnd->net_dev);			hangcheck_add(wnd);			add_stats_timer(wnd);			set_scan(wnd);		} else {			WARNING("%s: couldn't set power to state %d; device not"				" resumed", wnd->net_dev->name, state);		}		TRACEEXIT1(return status);	} else {		if (down_interruptible(&wnd->tx_ring_mutex))			TRACEEXIT1(return NDIS_STATUS_FAILURE);		netif_device_detach(wnd->net_dev);		hangcheck_del(wnd);		del_stats_timer(wnd);		status = NDIS_STATUS_NOT_SUPPORTED;		if (wnd->pm_capa == TRUE) {			enum ndis_power_state pm_state = state;			if (wnd->ndis_wolopts) {				status = miniport_set_int(wnd,							  OID_PNP_ENABLE_WAKE_UP,							  wnd->ndis_wolopts);				if (status == NDIS_STATUS_SUCCESS) {					if (wrap_is_pci_bus(wnd->wd->dev_bus))						pci_enable_wake(wnd->wd->pci.pdev,								PCI_D0, 1);				} else					WARNING("%s: couldn't enable WOL: %08x",						wnd->net_dev->name, status);			}			status = miniport_set_int(wnd, OID_PNP_SET_POWER,						  pm_state);			if (status == NDIS_STATUS_SUCCESS) {				set_bit(HW_SUSPENDED, &wnd->hw_status);			} else				WARNING("suspend failed: %08X", status);		}		if (status != NDIS_STATUS_SUCCESS) {			WARNING("%s does not support power management; "				"halting the device", wnd->net_dev->name);			miniport_halt(wnd);			set_bit(HW_HALTED, &wnd->hw_status);			status = STATUS_SUCCESS;		}		if (down_interruptible(&wnd->ndis_comm_mutex))			WARNING("couldn't lock ndis_comm_mutex");		TRACEEXIT1(return status);	}}static int ndis_set_mac_address(struct net_device *dev, void *p){	struct wrap_ndis_device *wnd = netdev_priv(dev);	struct sockaddr *addr = p;	struct ndis_configuration_parameter param;	struct unicode_string key;	struct ansi_string ansi;	NDIS_STATUS res;	unsigned char mac_string[3 * ETH_ALEN];	mac_address mac;	memcpy(mac, addr->sa_data, sizeof(mac));	memset(mac_string, 0, sizeof(mac_string));	res = snprintf(mac_string, sizeof(mac_string), MACSTR, MAC2STR(mac));	DBGTRACE1("%d", res);	if (res != (2 * sizeof(mac)))		TRACEEXIT1(return -EINVAL);	RtlInitAnsiString(&ansi, mac_string);	if (RtlAnsiStringToUnicodeString(&param.data.string, &ansi, TRUE)) {		RtlFreeUnicodeString(&key);		TRACEEXIT1(return -EINVAL);	}	param.type = NdisParameterString;	RtlInitAnsiString(&ansi, "NetworkAddress");	if (RtlAnsiStringToUnicodeString(&key, &ansi, TRUE))		TRACEEXIT1(return -EINVAL);	NdisWriteConfiguration(&res, wnd->nmb, &key, &param);	RtlFreeUnicodeString(&key);	RtlFreeUnicodeString(&param.data.string);	if (res != NDIS_STATUS_SUCCESS)		TRACEEXIT1(return -EINVAL);	if (ndis_reinit(wnd) == NDIS_STATUS_SUCCESS) {		res = miniport_query_info(wnd, OID_802_3_CURRENT_ADDRESS,					  mac, sizeof(mac));		if (res == NDIS_STATUS_SUCCESS) {			DBGTRACE1("mac:" MACSTRSEP, MAC2STR(mac));			memcpy(dev->dev_addr, mac, sizeof(mac));		} else			ERROR("couldn't get mac address: %08X", res);	}	TRACEEXIT1(return 0);}static struct ndis_packet *alloc_tx_packet(struct wrap_ndis_device *wnd,					   struct sk_buff *skb){	struct ndis_packet *packet;	ndis_buffer *buffer;	struct ndis_packet_oob_data *oob_data;	NDIS_STATUS status;	NdisAllocatePacket(&status, &packet, wnd->tx_packet_pool);	if (status != NDIS_STATUS_SUCCESS)		return NULL;	NdisAllocateBuffer(&status, &buffer, wnd->tx_buffer_pool,			   skb->data, skb->len);	if (status != NDIS_STATUS_SUCCESS) {		NdisFreePacket(packet);		return NULL;	}	packet->private.buffer_head = buffer;	packet->private.buffer_tail = buffer;	oob_data = NDIS_PACKET_OOB_DATA(packet);	oob_data->skb = skb;	if (wnd->use_sg_dma) {		oob_data->ndis_sg_element.address =			PCI_DMA_MAP_SINGLE(wnd->wd->pci.pdev, skb->data,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -