📄 rndis.c
字号:
case OID_GEN_DIRECTED_BYTES_RCV: DEBUG("%s: OID_GEN_DIRECTED_BYTES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_DIRECTED_FRAMES_RCV: DEBUG("%s: OID_GEN_DIRECTED_FRAMES_RCV\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; case OID_GEN_MULTICAST_BYTES_RCV: DEBUG("%s: OID_GEN_MULTICAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->multicast * 1111); retval = 0; } break; case OID_GEN_MULTICAST_FRAMES_RCV: DEBUG("%s: OID_GEN_MULTICAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->multicast); retval = 0; } break; case OID_GEN_BROADCAST_BYTES_RCV: DEBUG("%s: OID_GEN_BROADCAST_BYTES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->rx_packets/42*255); retval = 0; } break; case OID_GEN_BROADCAST_FRAMES_RCV: DEBUG("%s: OID_GEN_BROADCAST_FRAMES_RCV\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->rx_packets/42); retval = 0; } break; case OID_GEN_RCV_CRC_ERROR: DEBUG("%s: OID_GEN_RCV_CRC_ERROR\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->rx_crc_errors); retval = 0; } break; case OID_GEN_TRANSMIT_QUEUE_LENGTH: DEBUG("%s: OID_GEN_TRANSMIT_QUEUE_LENGTH\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break;#endif /* RNDIS_OPTIONAL_STATS */ /* ieee802.3 OIDs (table 4-3) */ /* mandatory */ case OID_802_3_PERMANENT_ADDRESS: DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = ETH_ALEN; memcpy (outbuf, rndis_per_dev_params [configNr].host_mac, length); retval = 0; } break; /* mandatory */ case OID_802_3_CURRENT_ADDRESS: DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__); if (rndis_per_dev_params [configNr].dev) { length = ETH_ALEN; memcpy (outbuf, rndis_per_dev_params [configNr].host_mac, length); retval = 0; } break; /* mandatory */ case OID_802_3_MULTICAST_LIST: DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); /* Multicast base address only */ *outbuf = __constant_cpu_to_le32 (0xE0000000); retval = 0; break; /* mandatory */ case OID_802_3_MAXIMUM_LIST_SIZE: DEBUG("%s: OID_802_3_MAXIMUM_LIST_SIZE\n", __FUNCTION__); /* Multicast base address only */ *outbuf = __constant_cpu_to_le32 (1); retval = 0; break; case OID_802_3_MAC_OPTIONS: DEBUG("%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__); break; /* ieee802.3 statistics OIDs (table 4-4) */ /* mandatory */ case OID_802_3_RCV_ERROR_ALIGNMENT: DEBUG("%s: OID_802_3_RCV_ERROR_ALIGNMENT\n", __FUNCTION__); if (rndis_per_dev_params [configNr].stats) { *outbuf = cpu_to_le32 (rndis_per_dev_params [configNr] .stats->rx_frame_errors); retval = 0; } break; /* mandatory */ case OID_802_3_XMIT_ONE_COLLISION: DEBUG("%s: OID_802_3_XMIT_ONE_COLLISION\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; /* mandatory */ case OID_802_3_XMIT_MORE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__); *outbuf = __constant_cpu_to_le32 (0); retval = 0; break; #ifdef RNDIS_OPTIONAL_STATS case OID_802_3_XMIT_DEFERRED: DEBUG("%s: OID_802_3_XMIT_DEFERRED\n", __FUNCTION__); /* TODO */ break; case OID_802_3_XMIT_MAX_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_MAX_COLLISIONS\n", __FUNCTION__); /* TODO */ break; case OID_802_3_RCV_OVERRUN: DEBUG("%s: OID_802_3_RCV_OVERRUN\n", __FUNCTION__); /* TODO */ break; case OID_802_3_XMIT_UNDERRUN: DEBUG("%s: OID_802_3_XMIT_UNDERRUN\n", __FUNCTION__); /* TODO */ break; case OID_802_3_XMIT_HEARTBEAT_FAILURE: DEBUG("%s: OID_802_3_XMIT_HEARTBEAT_FAILURE\n", __FUNCTION__); /* TODO */ break; case OID_802_3_XMIT_TIMES_CRS_LOST: DEBUG("%s: OID_802_3_XMIT_TIMES_CRS_LOST\n", __FUNCTION__); /* TODO */ break; case OID_802_3_XMIT_LATE_COLLISIONS: DEBUG("%s: OID_802_3_XMIT_LATE_COLLISIONS\n", __FUNCTION__); /* TODO */ break; #endif /* RNDIS_OPTIONAL_STATS */#ifdef RNDIS_PM /* power management OIDs (table 4-5) */ case OID_PNP_CAPABILITIES: DEBUG("%s: OID_PNP_CAPABILITIES\n", __FUNCTION__); /* for now, no wakeup capabilities */ length = sizeof (struct NDIS_PNP_CAPABILITIES); memset(outbuf, 0, length); retval = 0; break; case OID_PNP_QUERY_POWER: DEBUG("%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__, le32_to_cpup((__le32 *) buf) - 1); /* only suspend is a real power state, and * it can't be entered by OID_PNP_SET_POWER... */ length = 0; retval = 0; break;#endif default: printk (KERN_WARNING "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID); } if (retval < 0) length = 0; resp->InformationBufferLength = cpu_to_le32 (length); r->length = length + sizeof *resp; resp->MessageLength = cpu_to_le32 (r->length); return retval;}static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len, rndis_resp_t *r){ rndis_set_cmplt_type *resp; int i, retval = -ENOTSUPP; struct rndis_params *params; if (!r) return -ENOMEM; resp = (rndis_set_cmplt_type *) r->buf; if (!resp) return -ENOMEM; if (buf_len && rndis_debug > 1) { DEBUG("set OID %08x value, len %d:\n", OID, buf_len); for (i = 0; i < buf_len; i += 16) { DEBUG ("%03d: %08x %08x %08x %08x\n", i, le32_to_cpup((__le32 *)&buf[i]), le32_to_cpup((__le32 *)&buf[i + 4]), le32_to_cpup((__le32 *)&buf[i + 8]), le32_to_cpup((__le32 *)&buf[i + 12])); } } params = &rndis_per_dev_params [configNr]; switch (OID) { case OID_GEN_CURRENT_PACKET_FILTER: /* these NDIS_PACKET_TYPE_* bitflags are shared with * cdc_filter; it's not RNDIS-specific * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: * PROMISCUOUS, DIRECTED, * MULTICAST, ALL_MULTICAST, BROADCAST */ *params->filter = (u16) le32_to_cpup((__le32 *)buf); DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, *params->filter); /* this call has a significant side effect: it's * what makes the packet flow start and stop, like * activating the CDC Ethernet altsetting. */#ifdef RNDIS_PMupdate_linkstate:#endif retval = 0; if (*params->filter) { params->state = RNDIS_DATA_INITIALIZED; netif_carrier_on(params->dev); if (netif_running(params->dev)) netif_wake_queue (params->dev); } else { params->state = RNDIS_INITIALIZED; netif_carrier_off (params->dev); netif_stop_queue (params->dev); } break; case OID_802_3_MULTICAST_LIST: /* I think we can ignore this */ DEBUG("%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__); retval = 0; break;#if 0 case OID_GEN_RNDIS_CONFIG_PARAMETER: { struct rndis_config_parameter *param; param = (struct rndis_config_parameter *) buf; DEBUG("%s: OID_GEN_RNDIS_CONFIG_PARAMETER '%*s'\n", __FUNCTION__, min(cpu_to_le32(param->ParameterNameLength),80), buf + param->ParameterNameOffset); retval = 0; } break;#endif#ifdef RNDIS_PM case OID_PNP_SET_POWER: /* The only real power state is USB suspend, and RNDIS requests * can't enter it; this one isn't really about power. After * resuming, Windows forces a reset, and then SET_POWER D0. * FIXME ... then things go batty; Windows wedges itself. */ i = le32_to_cpup((__force __le32 *)buf); DEBUG("%s: OID_PNP_SET_POWER D%d\n", __FUNCTION__, i - 1); switch (i) { case NdisDeviceStateD0: *params->filter = params->saved_filter; goto update_linkstate; case NdisDeviceStateD3: case NdisDeviceStateD2: case NdisDeviceStateD1: params->saved_filter = *params->filter; retval = 0; break; } break;#ifdef RNDIS_WAKEUP // no wakeup support advertised, so wakeup OIDs always fail: // - OID_PNP_ENABLE_WAKE_UP // - OID_PNP_{ADD,REMOVE}_WAKE_UP_PATTERN#endif#endif /* RNDIS_PM */ default: printk (KERN_WARNING "%s: set unknown OID 0x%08X, size %d\n", __FUNCTION__, OID, buf_len); } return retval;}/* * Response Functions */static int rndis_init_response (int configNr, rndis_init_msg_type *buf){ rndis_init_cmplt_type *resp; rndis_resp_t *r; if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; r = rndis_add_response (configNr, sizeof (rndis_init_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_init_cmplt_type *) r->buf; resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_INITIALIZE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (52); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); resp->MajorVersion = __constant_cpu_to_le32 (RNDIS_MAJOR_VERSION); resp->MinorVersion = __constant_cpu_to_le32 (RNDIS_MINOR_VERSION); resp->DeviceFlags = __constant_cpu_to_le32 (RNDIS_DF_CONNECTIONLESS); resp->Medium = __constant_cpu_to_le32 (RNDIS_MEDIUM_802_3); resp->MaxPacketsPerTransfer = __constant_cpu_to_le32 (1); resp->MaxTransferSize = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu + sizeof (struct ethhdr) + sizeof (struct rndis_packet_msg_type) + 22); resp->PacketAlignmentFactor = __constant_cpu_to_le32 (0); resp->AFListOffset = __constant_cpu_to_le32 (0); resp->AFListSize = __constant_cpu_to_le32 (0); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev); return 0;}static int rndis_query_response (int configNr, rndis_query_msg_type *buf){ rndis_query_cmplt_type *resp; rndis_resp_t *r; // DEBUG("%s: OID = %08X\n", __FUNCTION__, cpu_to_le32(buf->OID)); if (!rndis_per_dev_params [configNr].dev) return -ENOTSUPP; /* * we need more memory: * oid_supported_list is the largest answer */ r = rndis_add_response (configNr, sizeof (oid_supported_list)); if (!r) return -ENOMEM; resp = (rndis_query_cmplt_type *) r->buf; resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_QUERY_CMPLT); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ if (gen_ndis_query_resp (configNr, le32_to_cpu (buf->OID), le32_to_cpu(buf->InformationBufferOffset) + 8 + (u8 *) buf, le32_to_cpu(buf->InformationBufferLength), r)) { /* OID not supported */ resp->Status = __constant_cpu_to_le32 ( RNDIS_STATUS_NOT_SUPPORTED); resp->MessageLength = __constant_cpu_to_le32 (sizeof *resp); resp->InformationBufferLength = __constant_cpu_to_le32 (0); resp->InformationBufferOffset = __constant_cpu_to_le32 (0); } else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev); return 0;}static int rndis_set_response (int configNr, rndis_set_msg_type *buf){ u32 BufLength, BufOffset; rndis_set_cmplt_type *resp; rndis_resp_t *r; r = rndis_add_response (configNr, sizeof (rndis_set_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_set_cmplt_type *) r->buf; BufLength = le32_to_cpu (buf->InformationBufferLength); BufOffset = le32_to_cpu (buf->InformationBufferOffset);#ifdef VERBOSE DEBUG("%s: Length: %d\n", __FUNCTION__, BufLength); DEBUG("%s: Offset: %d\n", __FUNCTION__, BufOffset); DEBUG("%s: InfoBuffer: ", __FUNCTION__); for (i = 0; i < BufLength; i++) { DEBUG ("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); } DEBUG ("\n");#endif resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_SET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ if (gen_ndis_set_resp (configNr, le32_to_cpu (buf->OID), ((u8 *) buf) + 8 + BufOffset, BufLength, r)) resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_NOT_SUPPORTED); else resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev); return 0;}static int rndis_reset_response (int configNr, rndis_reset_msg_type *buf){ rndis_reset_cmplt_type *resp; rndis_resp_t *r; r = rndis_add_response (configNr, sizeof (rndis_reset_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_reset_cmplt_type *) r->buf; resp->MessageType = __constant_cpu_to_le32 (REMOTE_NDIS_RESET_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16); resp->Status = __constant_cpu_to_le32 (RNDIS_STATUS_SUCCESS); /* resent information */ resp->AddressingReset = __constant_cpu_to_le32 (1); if (rndis_per_dev_params [configNr].ack) rndis_per_dev_params [configNr].ack ( rndis_per_dev_params [configNr].dev); return 0;}static int rndis_keepalive_response (int configNr, rndis_keepalive_msg_type *buf){ rndis_keepalive_cmplt_type *resp; rndis_resp_t *r; /* host "should" check only in RNDIS_DATA_INITIALIZED state */ r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type)); if (!r) return -ENOMEM; resp = (rndis_keepalive_cmplt_type *) r->buf; resp->MessageType = __constant_cpu_to_le32 ( REMOTE_NDIS_KEEPALIVE_CMPLT); resp->MessageLength = __constant_cpu_to_le32 (16);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -