📄 wrapndis.c
字号:
i++; } res = miniport_set_info(wnd, OID_802_3_MULTICAST_LIST, buf, i * ETH_ALEN); if (res == NDIS_STATUS_SUCCESS && i > 0) packet_filter |= NDIS_PACKET_TYPE_MULTICAST; else packet_filter |= NDIS_PACKET_TYPE_ALL_MULTICAST; kfree(buf); } DBGTRACE2("0x%08x", packet_filter); res = set_packet_filter(wnd, packet_filter); if (res) DBGTRACE1("couldn't set packet filter (%08X)", res); TRACEEXIT2(return);}static void link_status_handler(struct wrap_ndis_device *wnd){ struct ndis_assoc_info *ndis_assoc_info; union iwreq_data wrqu; NDIS_STATUS res; const int assoc_size = sizeof(*ndis_assoc_info) + IW_CUSTOM_MAX + 32;#if WIRELESS_EXT <= 17 unsigned char *wpa_assoc_info, *ies; unsigned char *p; int i;#endif TRACEENTER2("link: %d", netif_carrier_ok(wnd->net_dev)); if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) TRACEEXIT2(return);#ifndef CONFIG_NET_RADIO TRACEEXIT2(return);#endif if (!netif_carrier_ok(wnd->net_dev)) { memset(&wrqu, 0, sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); TRACEEXIT2(return); } ndis_assoc_info = kmalloc(assoc_size, GFP_KERNEL); if (!ndis_assoc_info) { ERROR("couldn't allocate memory"); TRACEEXIT2(return); } memset(ndis_assoc_info, 0, assoc_size); res = miniport_query_info(wnd, OID_802_11_ASSOCIATION_INFORMATION, ndis_assoc_info, assoc_size); if (res) { DBGTRACE2("query assoc_info failed (%08X)", res); kfree(ndis_assoc_info); TRACEEXIT2(return); }#if WIRELESS_EXT > 17 memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = ndis_assoc_info->req_ie_length; wireless_send_event(wnd->net_dev, IWEVASSOCREQIE, &wrqu, ((char *)ndis_assoc_info) + ndis_assoc_info->offset_req_ies); wrqu.data.length = ndis_assoc_info->resp_ie_length; wireless_send_event(wnd->net_dev, IWEVASSOCRESPIE, &wrqu, ((char *)ndis_assoc_info) + ndis_assoc_info->offset_resp_ies);#else /* we need 28 extra bytes for the format strings */ if ((ndis_assoc_info->req_ie_length + ndis_assoc_info->resp_ie_length + 28) > IW_CUSTOM_MAX) { WARNING("information element is too long! (%u,%u)," "association information dropped", ndis_assoc_info->req_ie_length, ndis_assoc_info->resp_ie_length); kfree(ndis_assoc_info); TRACEEXIT2(return); } wpa_assoc_info = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); if (!wpa_assoc_info) { ERROR("couldn't allocate memory"); kfree(ndis_assoc_info); TRACEEXIT2(return); } p = wpa_assoc_info; p += sprintf(p, "ASSOCINFO(ReqIEs="); ies = ((char *)ndis_assoc_info) + ndis_assoc_info->offset_req_ies; for (i = 0; i < ndis_assoc_info->req_ie_length; i++) p += sprintf(p, "%02x", ies[i]); p += sprintf(p, " RespIEs="); ies = ((char *)ndis_assoc_info) + ndis_assoc_info->offset_resp_ies; for (i = 0; i < ndis_assoc_info->resp_ie_length; i++) p += sprintf(p, "%02x", ies[i]); p += sprintf(p, ")"); memset(&wrqu, 0, sizeof(wrqu)); wrqu.data.length = p - wpa_assoc_info; wireless_send_event(wnd->net_dev, IWEVCUSTOM, &wrqu, wpa_assoc_info); kfree(wpa_assoc_info);#endif kfree(ndis_assoc_info); get_ap_address(wnd, (char *)&wrqu.ap_addr.sa_data); wrqu.ap_addr.sa_family = ARPHRD_ETHER; wireless_send_event(wnd->net_dev, SIOCGIWAP, &wrqu, NULL); DBGTRACE2(MACSTRSEP, MAC2STR(wrqu.ap_addr.sa_data)); TRACEEXIT2(return);}static void stats_timer_proc(unsigned long data){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)data; TRACEENTER2(""); if (wnd->stats_interval <= 0) TRACEEXIT2(return); set_bit(COLLECT_STATS, &wnd->wrap_ndis_pending_work); schedule_wrap_work(&wnd->wrap_ndis_work); wnd->stats_timer.expires += wnd->stats_interval; add_timer(&wnd->stats_timer);}static void add_stats_timer(struct wrap_ndis_device *wnd){ if (wnd->physical_medium != NdisPhysicalMediumWirelessLan) return; if (wnd->stats_interval < 0) wnd->stats_interval *= -1; wnd->stats_timer.data = (unsigned long)wnd; wnd->stats_timer.function = stats_timer_proc; wnd->stats_timer.expires = jiffies + wnd->stats_interval; add_timer(&wnd->stats_timer);}static void del_stats_timer(struct wrap_ndis_device *wnd){ TRACEENTER2(""); wnd->stats_interval *= -1; del_timer_sync(&wnd->stats_timer); TRACEEXIT2(return);}static void hangcheck_proc(unsigned long data){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)data; BOOLEAN reset; struct miniport_char *miniport; TRACEENTER2(""); if (wnd->hangcheck_interval <= 0) TRACEEXIT2(return); miniport = &wnd->wd->driver->ndis_driver->miniport; if_serialize_lock(wnd); reset = LIN2WIN1(miniport->hangcheck, wnd->nmb->adapter_ctx); if_serialize_unlock(wnd); if (reset) { set_bit(MINIPORT_RESET, &wnd->wrap_ndis_pending_work); schedule_wrap_work(&wnd->wrap_ndis_work); } wnd->hangcheck_timer.expires += wnd->hangcheck_interval; add_timer(&wnd->hangcheck_timer); TRACEEXIT3(return);}void hangcheck_add(struct wrap_ndis_device *wnd){ if (!wnd->wd->driver->ndis_driver->miniport.hangcheck || hangcheck_interval < 0) return; if (hangcheck_interval > 0) wnd->hangcheck_interval = hangcheck_interval * HZ; if (wnd->hangcheck_interval < 0) wnd->hangcheck_interval *= -1; wnd->hangcheck_timer.data = (unsigned long)wnd; wnd->hangcheck_timer.function = hangcheck_proc; wnd->hangcheck_timer.expires = jiffies + wnd->hangcheck_interval; add_timer(&wnd->hangcheck_timer); return;}void hangcheck_del(struct wrap_ndis_device *wnd){ TRACEENTER2(""); if (wnd->hangcheck_interval > 0) wnd->hangcheck_interval *= -1; del_timer_sync(&wnd->hangcheck_timer); TRACEEXIT2(return);}/* worker procedure to take care of setting/checking various states */static void wrap_ndis_worker(void *param){ struct wrap_ndis_device *wnd = (struct wrap_ndis_device *)param; DBGTRACE2("%lu", wnd->wrap_ndis_pending_work); if (test_bit(SHUTDOWN, &wnd->wrap_ndis_pending_work)) TRACEEXIT3(return); if (test_and_clear_bit(SET_MULTICAST_LIST, &wnd->wrap_ndis_pending_work)) set_multicast_list(wnd); if (test_and_clear_bit(COLLECT_STATS, &wnd->wrap_ndis_pending_work)) update_wireless_stats(wnd); if (test_and_clear_bit(LINK_STATUS_CHANGED, &wnd->wrap_ndis_pending_work)) link_status_handler(wnd); if (test_and_clear_bit(MINIPORT_RESET, &wnd->wrap_ndis_pending_work)) miniport_reset(wnd); TRACEEXIT3(return);}NDIS_STATUS ndis_reinit(struct wrap_ndis_device *wnd){ NDIS_STATUS status; wnd->pm_capa = FALSE; status = miniport_set_power_state(wnd, NdisDeviceStateD3); if (status != NDIS_STATUS_SUCCESS) { ERROR("halting device %s failed: %08X", wnd->net_dev->name, status); return status; } status = miniport_set_power_state(wnd, NdisDeviceStateD0); if (status != NDIS_STATUS_SUCCESS) ERROR("starting device %s failed: %08X", wnd->net_dev->name, status); return status;}void get_encryption_capa(struct wrap_ndis_device *wnd){ int i, mode; NDIS_STATUS res; struct ndis_assoc_info ndis_assoc_info; struct ndis_add_key ndis_key; struct ndis_capability *c; char *buf; const int buf_len = 512; TRACEENTER1("%p", wnd); /* check if WEP is supported */ if (set_encr_mode(wnd, Ndis802_11Encryption1Enabled) == 0 && get_encr_mode(wnd) == Ndis802_11Encryption1KeyAbsent) set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); /* check if WPA is supported */ if (set_auth_mode(wnd, Ndis802_11AuthModeWPA) == 0 && get_auth_mode(wnd) == Ndis802_11AuthModeWPA) set_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth); else TRACEEXIT1(return); if (set_auth_mode(wnd, Ndis802_11AuthModeWPAPSK) == 0 && get_auth_mode(wnd) == Ndis802_11AuthModeWPAPSK) set_bit(Ndis802_11AuthModeWPAPSK, &wnd->capa.auth); /* check for highest encryption */ mode = 0; if (set_encr_mode(wnd, Ndis802_11Encryption3Enabled) == 0 && (i = get_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption3KeyAbsent || i == Ndis802_11Encryption3Enabled)) mode = Ndis802_11Encryption3Enabled; else if (set_encr_mode(wnd, Ndis802_11Encryption2Enabled) == 0 && (i = get_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption2KeyAbsent || i == Ndis802_11Encryption2Enabled)) mode = Ndis802_11Encryption2Enabled; else if (set_encr_mode(wnd, Ndis802_11Encryption1Enabled) == 0 && (i = get_encr_mode(wnd)) > 0 && (i == Ndis802_11Encryption1KeyAbsent || i == Ndis802_11Encryption1Enabled)) mode = Ndis802_11Encryption1Enabled; DBGTRACE1("mode: %d", mode); if (mode == 0) TRACEEXIT1(return); set_bit(Ndis802_11Encryption1Enabled, &wnd->capa.encr); if (mode == Ndis802_11Encryption1Enabled) TRACEEXIT1(return); ndis_key.length = 32; ndis_key.index = 0xC0000001; ndis_key.struct_size = sizeof(ndis_key); res = miniport_set_info(wnd, OID_802_11_ADD_KEY, &ndis_key, ndis_key.struct_size); DBGTRACE2("%08X, %lu", res, (unsigned long)sizeof(ndis_key)); if (res && res != NDIS_STATUS_INVALID_DATA) TRACEEXIT1(return); res = miniport_query_info(wnd, OID_802_11_ASSOCIATION_INFORMATION, &ndis_assoc_info, sizeof(ndis_assoc_info)); DBGTRACE1("%08X", res); if (res == NDIS_STATUS_NOT_SUPPORTED) TRACEEXIT1(return); set_bit(Ndis802_11Encryption2Enabled, &wnd->capa.encr); if (mode == Ndis802_11Encryption3Enabled) set_bit(Ndis802_11Encryption3Enabled, &wnd->capa.encr); /* not all drivers support OID_802_11_CAPABILITY, so we don't * know for sure if driver support WPA or WPAPSK; assume * WPA */ set_bit(Ndis802_11AuthModeWPA, &wnd->capa.auth); /* check for wpa2 */ buf = kmalloc(buf_len, GFP_KERNEL); if (!buf) { ERROR("couldn't allocate memory"); TRACEEXIT1(return); } memset(buf, 0, buf_len); c = (struct ndis_capability *)buf; res = miniport_query_info(wnd, OID_802_11_CAPABILITY, buf, buf_len); if (!(res == NDIS_STATUS_SUCCESS && c->version == 2)) { kfree(buf); TRACEEXIT1(return); } wnd->num_pmkids = c->num_PMKIDs; for (i = 0; i < c->num_auth_encr_pair; i++) { struct ndis_auth_encr_pair *ae; ae = &c->auth_encr_pair[i]; if ((char *)(ae + 1) > buf + buf_len) break; switch (ae->auth_mode) { case Ndis802_11AuthModeOpen: case Ndis802_11AuthModeShared: case Ndis802_11AuthModeWPA: case Ndis802_11AuthModeWPAPSK: case Ndis802_11AuthModeWPANone: case Ndis802_11AuthModeWPA2: case Ndis802_11AuthModeWPA2PSK: set_bit(ae->auth_mode, &wnd->capa.auth); break; default: WARNING("unknown auth_mode: %d", ae->auth_mode); break; } switch (ae->encr_mode) { case Ndis802_11EncryptionDisabled: case Ndis802_11Encryption1Enabled: case Ndis802_11Encryption2Enabled: case Ndis802_11Encryption3Enabled: set_bit(ae->encr_mode, &wnd->capa.encr); break; default: WARNING("unknown encr_mode: %d", ae->encr_mode); break; } } kfree(buf); TRACEEXIT1(return);}wstdcall NTSTATUS NdisDispatchDeviceControl(struct device_object *fdo, struct irp *irp){ struct wrap_ndis_device *wnd; DBGTRACE3("fdo: %p", fdo); /* for now, we don't have anything intresting here, so pass it * down to bus driver */ wnd = fdo->reserved; return IoPassIrpDown(wnd->nmb->pdo, irp);}WIN_FUNC_DECL(NdisDispatchDeviceControl,2)wstdcall NTSTATUS NdisDispatchPower(struct device_object *fdo, struct irp *irp){ struct io_stack_location *irp_sl; struct wrap_ndis_device *wnd; enum ndis_power_state state; NTSTATUS status; NDIS_STATUS ndis_status; irp_sl = IoGetCurrentIrpStackLocation(irp); wnd = fdo->reserved; IOTRACE("fdo: %p, fn: %d:%d, wnd: %p", fdo, irp_sl->major_fn, irp_sl->minor_fn, wnd); if ((irp_sl->params.power.type == SystemPowerState && irp_sl->params.power.state.system_state > PowerSystemWorking) || (irp_sl->params.power.type == DevicePowerState && irp_sl->params.power.state.device_state > PowerDeviceD0)) state = NdisDeviceStateD3; else state = NdisDeviceStateD0; switch (irp_sl->minor_fn) { case IRP_MN_SET_POWER: if (state == NdisDeviceStateD0) { status = IoSyncForwardIrp(wnd->nmb->pdo, irp); if (status != STATUS_SUCCESS) break; ndis_status = miniport_set_power_state(wnd, state); if (ndis_status != NDIS_STATUS_SUCCESS) WARNING("couldn't set power to %d: %08X", state, ndis_status); DBGTRACE2("%s: device resumed", wnd->net_dev->name); irp->io_status.status = status = STATUS_SUCCESS; IoCompleteRequest(irp, IO_NO_INCREMENT); break; } else { ndis_status = miniport_set_power_state(wnd, state); /* TODO: handle error case */ if (ndis_status != NDIS_STATUS_SUCCESS) WARNING("setting power to %d failed: %08X", state, ndis_status); status = IoAsyncForwardIrp(wnd->nmb->pdo, irp); } break; case IRP_MN_QUERY_POWER: if (wnd->pm_capa) { ndis_status = miniport_query_info(wnd, OID_PNP_QUERY_POWER, &state, sizeof(state)); DBGTRACE2("%d, %08X", state, ndis_status); /* this OID must always succeed */ if (ndis_status != NDIS_STATUS_SUCCESS) DBGTRACE1("query power returns %08X", ndis_status); irp->io_status.status = STATUS_SUCCESS; } else irp->io_status.status = STATUS_SUCCESS; status = IoPassIrpDown(wnd->nmb->pdo, irp); break; case IRP_MN_WAIT_WAKE: case IRP_MN_POWER_SEQUENCE: /* TODO: implement WAIT_WAKE */ status = IoPassIrpDown(wnd->nmb->pdo, irp); break; default: status = IoPassIrpDown(wnd->nmb->pdo, irp); break; } IOEXIT(return status);}WIN_FUNC_DECL(NdisDispatchPower,2)wstdcall NTSTATUS NdisDispatchPnp(struct device_object *fdo, struct irp *irp){ struct io_stack_location *irp_sl; struct wrap_ndis_device *wnd; struct device_object *pdo; NTSTATUS status; IOTRACE("fdo: %p, irp: %p", fdo, irp); irp_sl = IoGetCurrentIrpStackLocation(irp); wnd = fdo->reserved; pdo = wnd->nmb->pdo; switch (irp_sl->minor_fn) { case IRP_MN_START_DEVICE: status = IoSyncForwardIrp(pdo, irp); if (status != STATUS_SUCCESS) break; if (ndis_start_device(wnd) == NDIS_STATUS_SUCCESS) status = STATUS_SUCCESS; else status = STATUS_FAILURE; irp->io_status.status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); break; case IRP_MN_QUERY_STOP_DEVICE: /* TODO: implement in NDIS */ status = IoPassIrpDown(wnd->nmb->pdo, irp); break; case IRP_MN_STOP_DEVICE: miniport_halt(wnd); irp->io_status.status = STATUS_SUCCESS; status = IoAsyncForwardIrp(pdo, irp); break; case IRP_MN_REMOVE_DEVICE: DBGTRACE1("%s", wnd->net_dev->name); miniport_pnp_event(wnd, NdisDevicePnPEventSurpriseRemoved); if (ndis_remove_device(wnd)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -