📄 rndis.c
字号:
#undef RNDIS_PM
#undef RNDIS_WAKEUP
#undef VERBOSE
#include "rndis.h"
#include "errno.h"
#include "stdio.h"
#include <assert.h>
//static int rndis_debug = 0;
#define RNDIS_MAX_CONFIGS 1
static rndis_params rndis_per_dev_params [RNDIS_MAX_CONFIGS];
static const le32 rndis_driver_version = constant_cpu_to_le32 ( 1 );
static rndis_resp_t * rndis_add_response ( int configNr, u32 length );
/* supported OIDs */
static const u32 oid_supported_list [] =
{
/* the general stuff */
OID_GEN_SUPPORTED_LIST,
OID_GEN_HARDWARE_STATUS,
OID_GEN_MEDIA_SUPPORTED,
OID_GEN_MEDIA_IN_USE,
OID_GEN_MAXIMUM_FRAME_SIZE,
OID_GEN_LINK_SPEED,
OID_GEN_TRANSMIT_BLOCK_SIZE,
OID_GEN_RECEIVE_BLOCK_SIZE,
OID_GEN_VENDOR_ID,
OID_GEN_VENDOR_DESCRIPTION,
OID_GEN_VENDOR_DRIVER_VERSION,
OID_GEN_CURRENT_PACKET_FILTER,
OID_GEN_MAXIMUM_TOTAL_SIZE,
OID_GEN_MEDIA_CONNECT_STATUS,
OID_GEN_PHYSICAL_MEDIUM,
/* the statistical stuff */
OID_GEN_XMIT_OK,
OID_GEN_RCV_OK,
OID_GEN_XMIT_ERROR,
OID_GEN_RCV_ERROR,
OID_GEN_RCV_NO_BUFFER,
/* mandatory 802.3 */
/* the general stuff */
OID_802_3_PERMANENT_ADDRESS,
OID_802_3_CURRENT_ADDRESS,
OID_802_3_MULTICAST_LIST,
OID_802_3_MAC_OPTIONS,
OID_802_3_MAXIMUM_LIST_SIZE,
/* the statistical stuff */
OID_802_3_RCV_ERROR_ALIGNMENT,
OID_802_3_XMIT_ONE_COLLISION,
OID_802_3_XMIT_MORE_COLLISIONS,
#ifdef RNDIS_PM
/* PM and wakeup are mandatory for USB: */
/* power management */
OID_PNP_CAPABILITIES,
OID_PNP_QUERY_POWER,
OID_PNP_SET_POWER,
#ifdef RNDIS_WAKEUP
/* wake up host */
OID_PNP_ENABLE_WAKE_UP,
OID_PNP_ADD_WAKE_UP_PATTERN,
OID_PNP_REMOVE_WAKE_UP_PATTERN,
#endif /* RNDIS_WAKEUP */
#endif /* RNDIS_PM */
};
static u32 get_unaligned( void * data )
{
le32 val;
u8 * buf = data;
val = * buf +
((* ( buf + 1 )) << 8 ) +
((* ( buf + 2 )) << 16 ) +
((* ( buf + 3 )) << 24 );
return le32_to_cpu( val );
}
/* NDIS Functions */
static int gen_ndis_query_resp ( int configNr, u32 OID, u8 * buf,
unsigned buf_len, rndis_resp_t * r )
{
int retval = - ERR_NOMEM;
u32 length = 4; /* usually */
le32 * outbuf;
int i, count;
rndis_query_cmplt_type * resp;
if (! r ) return - ERR_NOMEM;
resp = ( rndis_query_cmplt_type *) r->buf;
if (! resp ) return - ERR_NOMEM;
/* if ( buf_len && rndis_debug > 1 )
{
printf( "query OID %08x value, len %d:\n", OID, buf_len );
for ( i = 0; i < buf_len; i += 16 )
{
printf( "%03d: %08x %08x %08x %08x\n", i,
le32_to_cpu( get_unaligned(( le32 *)& buf[i] )),
le32_to_cpu( get_unaligned(( le32 *)& buf[i + 4] )),
le32_to_cpu( get_unaligned(( le32 *)& buf[i + 8] )),
le32_to_cpu( get_unaligned(( le32 *)& buf[i + 12] )));
}
}*/
/* response goes here, right after the header */
outbuf = ( le32 *) & resp[1];
resp->InformationBufferOffset = constant_cpu_to_le32 ( 16 );
switch ( OID ) {
/* general oids (table 4-1) */
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_SUPPORTED_LIST\n", __FUNCTION__ );*/
length = sizeof ( oid_supported_list );
count = length / sizeof ( u32 );
for ( i = 0; i < count; i ++)
outbuf[i] = cpu_to_le32 ( oid_supported_list[i] );
retval = 0;
break;
/* mandatory */
case OID_GEN_HARDWARE_STATUS:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_HARDWARE_STATUS\n", __FUNCTION__ ); */
* outbuf = constant_cpu_to_le32 ( 0 );
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_SUPPORTED:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_MEDIA_SUPPORTED\n", __FUNCTION__ );*/
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].medium );
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_IN_USE:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_MEDIA_IN_USE\n", __FUNCTION__ ); */
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].medium );
retval = 0;
break;
/* mandatory */
case OID_GEN_MAXIMUM_FRAME_SIZE:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_MAXIMUM_FRAME_SIZE\n", __FUNCTION__ );*/
if ( rndis_per_dev_params [configNr].dev )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_LINK_SPEED:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_LINK_SPEED\n", __FUNCTION__ );*/
if ( rndis_per_dev_params [configNr].media_state == NDIS_MEDIA_STATE_DISCONNECTED )
* outbuf = constant_cpu_to_le32 ( 0 );
else
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].speed );
retval = 0;
break;
/* mandatory */
case OID_GEN_TRANSMIT_BLOCK_SIZE:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_TRANSMIT_BLOCK_SIZE\n", __FUNCTION__ );*/
if ( rndis_per_dev_params [configNr].dev )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_RECEIVE_BLOCK_SIZE:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_RECEIVE_BLOCK_SIZE\n", __FUNCTION__ );*/
if ( rndis_per_dev_params [configNr].dev )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].dev->mtu );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_VENDOR_ID:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_VENDOR_ID\n", __FUNCTION__ );*/
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].vendorID );
retval = 0;
break;
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_VENDOR_DESCRIPTION\n", __FUNCTION__ );*/
length = strlen ( rndis_per_dev_params [configNr].vendorDescr );
memcpy ( outbuf, rndis_per_dev_params [configNr].vendorDescr, length );
retval = 0;
break;
case OID_GEN_VENDOR_DRIVER_VERSION:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_VENDOR_DRIVER_VERSION\n", __FUNCTION__ );*/
/* Created as LE */
* outbuf = rndis_driver_version;
retval = 0;
break;
/* mandatory */
case OID_GEN_CURRENT_PACKET_FILTER:
/*if ( rndis_debug > 1 )
printf( "%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__ );*/
* outbuf = cpu_to_le32 (* rndis_per_dev_params[configNr].filter );
retval = 0;
break;
/* mandatory */
case OID_GEN_MAXIMUM_TOTAL_SIZE:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_MAXIMUM_TOTAL_SIZE\n", __FUNCTION__ );
* outbuf = constant_cpu_to_le32( RNDIS_MAX_TOTAL_SIZE );
retval = 0;
break;
/* mandatory */
case OID_GEN_MEDIA_CONNECT_STATUS:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_MEDIA_CONNECT_STATUS\n", __FUNCTION__ );
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].media_state );
retval = 0;
break;
case OID_GEN_PHYSICAL_MEDIUM:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_PHYSICAL_MEDIUM\n", __FUNCTION__ );
* outbuf = constant_cpu_to_le32 ( 0 );
retval = 0;
break;
/* The RNDIS specification is incomplete/wrong. Some versions
* of MS-Windows expect OIDs that aren't specified there. Other
* versions emit undefined RNDIS messages. DOCUMENT ALL THESE!
*/
case OID_GEN_MAC_OPTIONS: /* from WinME */
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_MAC_OPTIONS\n", __FUNCTION__ );
* outbuf = constant_cpu_to_le32(
NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
NDIS_MAC_OPTION_FULL_DUPLEX );
retval = 0;
break;
/* statistics OIDs (table 4-2) */
/* mandatory */
case OID_GEN_XMIT_OK:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_XMIT_OK\n", __FUNCTION__ );
if ( rndis_per_dev_params [configNr].stats )
{
* outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->tx_packets -
rndis_per_dev_params [configNr].stats->tx_errors -
rndis_per_dev_params [configNr].stats->tx_dropped );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_RCV_OK:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_RCV_OK\n", __FUNCTION__ );
if ( rndis_per_dev_params [configNr].stats )
{
* outbuf = cpu_to_le32 (
rndis_per_dev_params [configNr].stats->rx_packets -
rndis_per_dev_params [configNr].stats->rx_errors -
rndis_per_dev_params [configNr].stats->rx_dropped );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_XMIT_ERROR:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_XMIT_ERROR\n", __FUNCTION__ );
if ( rndis_per_dev_params [configNr].stats )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->tx_errors );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_RCV_ERROR:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_RCV_ERROR\n", __FUNCTION__ );
if ( rndis_per_dev_params [configNr].stats )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_errors );
retval = 0;
}
break;
/* mandatory */
case OID_GEN_RCV_NO_BUFFER:
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_RCV_NO_BUFFER\n", __FUNCTION__ );
if ( rndis_per_dev_params [configNr].stats )
{
* outbuf = cpu_to_le32 ( rndis_per_dev_params [configNr].stats->rx_dropped );
retval = 0;
}
break;
/* ieee802.3 OIDs (table 4-3) */
/* mandatory */
case OID_802_3_PERMANENT_ADDRESS:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%s: OID_802_3_MAC_OPTIONS\n", __FUNCTION__ );
break;
/* ieee802.3 statistics OIDs (table 4-4) */
/* mandatory */
case OID_802_3_RCV_ERROR_ALIGNMENT:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%s: OID_802_3_XMIT_MORE_COLLISIONS\n", __FUNCTION__ );
* outbuf = constant_cpu_to_le32 ( 0 );
retval = 0;
break;
#ifdef RNDIS_PM
/* power management OIDs (table 4-5) */
case OID_PNP_CAPABILITIES:
//if ( rndis_debug > 1 )
// printf( "%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:
//if ( rndis_debug > 1 )
// printf( "%s: OID_PNP_QUERY_POWER D%d\n", __FUNCTION__,
// le32_to_cpu( get_unaligned(( 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:
printf( "%s: query unknown OID 0x%08X\n", __FUNCTION__, OID );
break;
}
if ( retval < 0 )
length = 0;
resp->InformationBufferLength = cpu_to_le32 ( length );
//r->length = length + sizeof * resp;
r->length = length + sizeof ( rndis_query_cmplt_type ); //////////////////
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 = - ERR_NOTSUPP;
struct rndis_params * params;
if (! r )
return - ERR_NOMEM;
resp = ( rndis_set_cmplt_type *) r->buf;
if (! resp )
return - ERR_NOMEM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -