📄 rndis.c
字号:
/*if ( buf_len && rndis_debug > 1 )
{
printf( "set 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] )));
}
}*/
params = & rndis_per_dev_params [configNr];
switch ( OID ) {
case OID_GEN_CURRENT_PACKET_FILTER:
* params->filter = ( u16 ) le32_to_cpu( get_unaligned(( le32 *)buf ));
//if ( rndis_debug > 1 )
// printf( "%s: OID_GEN_CURRENT_PACKET_FILTER %08x\n", __FUNCTION__, * params->filter );
#ifdef RNDIS_PM
update_linkstate:
#endif
retval = 0;
if (* params->filter )
params->state = RNDIS_DATA_INITIALIZED;
else
params->state = RNDIS_INITIALIZED;
break;
case OID_802_3_MULTICAST_LIST:
/* I think we can ignore this */
//if ( rndis_debug > 1 )
// printf( "%s: OID_802_3_MULTICAST_LIST\n", __FUNCTION__ );
retval = 0;
break;
#ifdef RNDIS_PM
case OID_PNP_SET_POWER:
i = le32_to_cpu( get_unaligned(( le32 *)buf ));
//if ( rndis_debug > 1 )
// printf( "%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;
#endif /* RNDIS_PM */
default:
printf( "%s: set unknown OID 0x%08X, size %d\n", __FUNCTION__, OID, buf_len );
break;
}
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 - ERR_NOTSUPP;
r = rndis_add_response ( configNr, sizeof ( rndis_init_cmplt_type ));
if (! r ) return - ERR_NOMEM;
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)*/ETH_HLEN
+ 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;
//if ( rndis_debug > 1 )
// printf( "%s: OID = %08X\n", __FUNCTION__, cpu_to_le32( buf->OID ));
if (! rndis_per_dev_params [configNr].dev ) return - ERR_NOTSUPP;
r = rndis_add_response ( configNr,
sizeof ( oid_supported_list ) + sizeof( rndis_query_cmplt_type ));
if (! r ) return - ERR_NOMEM;
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->MessageLength = constant_cpu_to_le32 ( sizeof ( rndis_query_cmplt_type ) ); /////////////
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 - ERR_NOMEM;
resp = ( rndis_set_cmplt_type *) r->buf;
BufLength = le32_to_cpu ( buf->InformationBufferLength );
BufOffset = le32_to_cpu ( buf->InformationBufferOffset );
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 - ERR_NOMEM;
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 - ERR_NOMEM;
resp = ( rndis_keepalive_cmplt_type *) r->buf;
resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_KEEPALIVE_CMPLT );
resp->MessageLength = constant_cpu_to_le32 ( 16 );
resp->RequestID = buf->RequestID; /* Still LE in msg buffer */
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;
}
/*
* Device to Host Comunication
*/
/*static int rndis_indicate_status_msg ( int configNr, u32 status )
{
rndis_indicate_status_msg_type * resp;
rndis_resp_t * r;
if ( rndis_per_dev_params [configNr].state == RNDIS_UNINITIALIZED )
return - ERR_NOTSUPP;
r = rndis_add_response ( configNr, sizeof ( rndis_indicate_status_msg_type ));
if (! r ) return - ERR_NOMEM;
resp = ( rndis_indicate_status_msg_type *) r->buf;
resp->MessageType = constant_cpu_to_le32 ( REMOTE_NDIS_INDICATE_STATUS_MSG );
resp->MessageLength = constant_cpu_to_le32 ( 20 );
resp->Status = cpu_to_le32 ( status );
resp->StatusBufferLength = constant_cpu_to_le32 ( 0 );
resp->StatusBufferOffset = 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;
}*/
void rndis_set_host_mac ( int configNr, const u8 * addr )
{
rndis_per_dev_params [configNr].host_mac = addr;
}
/*
* Message Parser
*/
int rndis_msg_parser ( u8 configNr, u8 * buf )
{
u32 MsgType, MsgLength;
le32 * tmp;
struct rndis_params * params;
if (! buf ) return - ERR_NOMEM;
tmp = ( le32 *) buf;
MsgType = le32_to_cpu( get_unaligned( tmp ++));
MsgLength = le32_to_cpu( get_unaligned( tmp ++));
if ( configNr >= RNDIS_MAX_CONFIGS )
return - ERR_NOTSUPP;
params = & rndis_per_dev_params [configNr];
/* For USB: responses may take up to 10 seconds */
switch ( MsgType )
{
case REMOTE_NDIS_INITIALIZE_MSG:
//if ( rndis_debug > 1 )
// printf( "%s: REMOTE_NDIS_INITIALIZE_MSG\n", __FUNCTION__ );
params->state = RNDIS_INITIALIZED;
return rndis_init_response ( configNr, ( rndis_init_msg_type *) buf );
case REMOTE_NDIS_HALT_MSG:
//if ( rndis_debug > 1 )
// printf( "%s: REMOTE_NDIS_HALT_MSG\n", __FUNCTION__ );
params->state = RNDIS_UNINITIALIZED;
return 0;
case REMOTE_NDIS_QUERY_MSG:
return rndis_query_response ( configNr, ( rndis_query_msg_type *) buf );
case REMOTE_NDIS_SET_MSG:
return rndis_set_response ( configNr, ( rndis_set_msg_type *) buf );
case REMOTE_NDIS_RESET_MSG:
//if ( rndis_debug > 1 )
// printf( "%s: REMOTE_NDIS_RESET_MSG\n", __FUNCTION__ );
return rndis_reset_response ( configNr, ( rndis_reset_msg_type *) buf );
case REMOTE_NDIS_KEEPALIVE_MSG:
/* For USB: host does this every 5 seconds */
//if ( rndis_debug > 1 )
// printf( "%s: REMOTE_NDIS_KEEPALIVE_MSG\n", __FUNCTION__ );
return rndis_keepalive_response ( configNr,( rndis_keepalive_msg_type *)buf );
default:
printf( "%s: unknown RNDIS message 0x%08X len %d\n",
__FUNCTION__ , MsgType, MsgLength );
{
unsigned i;
for ( i = 0; i < MsgLength; i += 16 )
{
printf( "%03d: "
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
" %02x %02x %02x %02x"
"\n",
i,
buf[i], buf [i + 1],
buf[i + 2], buf[i + 3],
buf[i + 4], buf [i + 5],
buf[i + 6], buf[i + 7],
buf[i + 8], buf [i + 9],
buf[i + 10], buf[i + 11],
buf[i + 12], buf [i + 13],
buf[i + 14], buf[i + 15] );
}
}
break;
}
return - ERR_NOTSUPP;
}
int rndis_register ( int (* rndis_control_ack ) ( struct rndis_dev *))
{
u8 i;
for ( i = 0; i < RNDIS_MAX_CONFIGS; i ++)
{
if (! rndis_per_dev_params [i].used )
{
rndis_per_dev_params [i].used = 1;
rndis_per_dev_params [i].ack = rndis_control_ack;
//printf( "%s: configNr = %d\n", __FUNCTION__, i );
return i;
}
}
printf( "failed\n" );
return - 1;
}
int rndis_set_param_dev ( u8 configNr, struct rndis_dev * dev,
struct net_device_stats1 * stats,
u16 * cdc_filter )
{
//printf( "%s:\n", __FUNCTION__ );
if (! dev || ! stats ) return - 1;
if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;
rndis_per_dev_params [configNr].dev = dev;
rndis_per_dev_params [configNr].stats = stats;
rndis_per_dev_params [configNr].filter = cdc_filter;
return 0;
}
int rndis_set_param_vendor ( u8 configNr, u32 vendorID, const char * vendorDescr )
{
//printf( "%s:\n", __FUNCTION__ );
if (! vendorDescr ) return - 1;
if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;
rndis_per_dev_params [configNr].vendorID = vendorID;
rndis_per_dev_params [configNr].vendorDescr = vendorDescr;
return 0;
}
int rndis_set_param_medium ( u8 configNr, u32 medium, u32 speed )
{
//printf( "%s: %u %u\n", __FUNCTION__, medium, speed );
if ( configNr >= RNDIS_MAX_CONFIGS ) return - 1;
rndis_per_dev_params [configNr].medium = medium;
rndis_per_dev_params [configNr].speed = speed;
return 0;
}
void rndis_free_response ( int configNr, u8 * buf )
{
int i;
rndis_resp_t * r;
for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
{
r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
if(( u8 *)r->buf == buf )
{
memset( r, 0, sizeof( rndis_resp_t ));
break;
}
}
}
u8 * rndis_get_next_response ( int configNr, u32 * length )
{
int i;
rndis_resp_t * r;
for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
{
r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
if( r->inUse && ( r->send == 0 ) )
{
r->send = 1;
* length = r->length;
return ( u8 *)r->buf;
}
}
return NULL;
}
static rndis_resp_t * rndis_add_response ( int configNr, u32 length )
{
int i;
rndis_resp_t * r = 0;
assert( length < ( RNDSI_MAX_MSGS * 4 ) );
for( i = 0; i < RNDIS_MSG_QUEUE_SIZE; i ++)
{
r = & ( rndis_per_dev_params[configNr].resp_queue[i] );
if( r->inUse == 0 )
{
r->inUse = 1;
r->length = length;
r->send = 0;
break;
}
}
return r;
}
int rndis_init ( void )
{
u8 i;
for ( i = 0; i < RNDIS_MAX_CONFIGS; i ++)
{
memset(& rndis_per_dev_params[i], 0, sizeof( rndis_params ));
rndis_per_dev_params [i].confignr = i;
rndis_per_dev_params [i].used = 0;
rndis_per_dev_params [i].state = RNDIS_UNINITIALIZED;
rndis_per_dev_params [i].media_state = NDIS_MEDIA_STATE_CONNECTED;
//NDIS_MEDIA_STATE_DISCONNECTED;
}
return 0;
}
void rndis_setstate( int configNr, enum rndis_state state )
{
rndis_per_dev_params[configNr].state = state;
}
enum rndis_state rndis_getstate( int configNr )
{
return rndis_per_dev_params[configNr].state;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -