540 lines
14 KiB
C
540 lines
14 KiB
C
/* src/wlanctl/wlanctl.c
|
|
*
|
|
* user utility for the wlan card
|
|
*
|
|
* Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
|
|
* --------------------------------------------------------------------
|
|
*
|
|
* linux-wlan
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU Public License version 2 (the "GPL"), in which
|
|
* case the provisions of the GPL are applicable instead of the
|
|
* above. If you wish to allow the use of your version of this file
|
|
* only under the terms of the GPL and not to allow others to use
|
|
* your version of this file under the MPL, indicate your decision
|
|
* by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this
|
|
* file under either the MPL or the GPL.
|
|
*
|
|
* --------------------------------------------------------------------
|
|
*
|
|
* Inquiries regarding the linux-wlan Open Source project can be
|
|
* made directly to:
|
|
*
|
|
* AbsoluteValue Systems Inc.
|
|
* info@linux-wlan.com
|
|
* http://www.linux-wlan.com
|
|
*
|
|
* --------------------------------------------------------------------
|
|
*
|
|
* Portions of the development of this software were funded by
|
|
* Intersil Corporation as part of PRISM(R) chipset product development.
|
|
*
|
|
* --------------------------------------------------------------------
|
|
*/
|
|
|
|
/*================================================================*/
|
|
/* System Includes */
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
/* Ugly hack for LinuxPPC R4, don't have time to figure it out right now */
|
|
#if defined(__WLAN_PPC__)
|
|
#undef __GLIBC__
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
|
|
/*================================================================*/
|
|
/* Project Includes */
|
|
|
|
#include <wlan/wlan_compat.h>
|
|
#include <wlan/version.h>
|
|
#include <wlan/p80211types.h>
|
|
#include <wlan/p80211meta.h>
|
|
#include <wlan/p80211metamsg.h>
|
|
#include <wlan/p80211msg.h>
|
|
#include <wlan/p80211ioctl.h>
|
|
#include "wlanctl.h"
|
|
|
|
/*================================================================*/
|
|
/* Local Constants */
|
|
|
|
/*================================================================*/
|
|
/* Local Macros */
|
|
|
|
|
|
/*================================================================*/
|
|
/* Local Types */
|
|
|
|
|
|
/*================================================================*/
|
|
/* Local Static Definitions */
|
|
|
|
char *devname;
|
|
|
|
char *cmdcats[] = {
|
|
"dot11req",
|
|
"lnxreq",
|
|
"p2req"
|
|
};
|
|
|
|
static int debug = 0;
|
|
|
|
/*================================================================*/
|
|
/* Local Function Declarations */
|
|
|
|
INT cmdline2requestmsg( UINT8 *msg, UINT32 msgcode, int argc, char **argv );
|
|
void printmsg( UINT8 *msg, UINT32 msgcode );
|
|
void sim_ioctl( UINT8 *msg, UINT32 msgcode );
|
|
int do_ioctl( UINT8 *msg, UINT32 msgcode );
|
|
void dump_msg(void *msg);
|
|
|
|
/*================================================================*/
|
|
/* Function Definitions */
|
|
|
|
|
|
/*----------------------------------------------------------------
|
|
* main
|
|
*
|
|
* wlanctl-ng entry point.
|
|
*
|
|
* Arguments:
|
|
* argc number of command line arguments
|
|
* argv array of argument strings
|
|
*
|
|
* Returns:
|
|
* 0 - success
|
|
* ~0 - failure
|
|
----------------------------------------------------------------*/
|
|
int main ( int argc, char **argv )
|
|
{
|
|
UINT8 message[MSG_BUFF_LEN];
|
|
UINT32 msgcode = P80211DID_INVALID;
|
|
INT result = 0;
|
|
INT i;
|
|
|
|
if ( argc < 4 && argc >= 2 && strcmp( argv[1], "version") == 0) {
|
|
printf("wlanctl-ng: %s\n", WLAN_RELEASE);
|
|
}
|
|
else if ( argc < 4 && argc >= 2 && strcmp( argv[1], "commands") == 0) {
|
|
print_allrequests();
|
|
}
|
|
else if ( argc < 4 && argc >= 2 && strcmp( argv[1], "mibs") == 0) {
|
|
print_allmibs();
|
|
}
|
|
else if ( argc < 3 ) {
|
|
usage();
|
|
} else {
|
|
/* stuff the device name in a global */
|
|
devname = argv[1];
|
|
|
|
/* returns P80211DID_INVALID no match */
|
|
for ( i = 0; i < sizeof(cmdcats)/sizeof(cmdcats[0]); i++) {
|
|
msgcode = p80211_text2did(msg_catlist,
|
|
cmdcats[i], argv[2], NULL);
|
|
if ( msgcode != P80211DID_INVALID ) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (msgcode != P80211DID_INVALID) { /* msgcode valid */
|
|
result = cmdline2requestmsg( message, msgcode, argc, argv );
|
|
|
|
if ( result == 0 ) {
|
|
if ( (result = do_ioctl( message, msgcode )) == 0 ){
|
|
printmsg( message, msgcode );
|
|
}
|
|
} else {
|
|
printmsg( message, msgcode );
|
|
/*
|
|
printf("Message \"%s\" was unable to be created\n", argv[2]);
|
|
*/
|
|
}
|
|
} else { /* msgcode invalid */
|
|
printf("The cmd \'%s\' is invalid\n", argv[2]);
|
|
result=msgcode;
|
|
}
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------
|
|
* do_ioctl
|
|
*
|
|
* TODO: describe
|
|
*
|
|
* Arguments:
|
|
* argc number of command line arguments
|
|
* argv array of argument strings
|
|
*
|
|
* Returns:
|
|
* 0 - success
|
|
* ~0 - failure
|
|
----------------------------------------------------------------*/
|
|
int do_ioctl( UINT8 *msg, UINT32 msgcode )
|
|
{
|
|
int result = -1;
|
|
int fd;
|
|
p80211ioctl_req_t req;
|
|
|
|
/* set the magic */
|
|
req.magic = P80211_IOCTL_MAGIC;
|
|
|
|
/* get a socket */
|
|
fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
if ( fd == -1 ) {
|
|
perror("wlanctl-ng");
|
|
return result;
|
|
}
|
|
|
|
req.len = MSG_BUFF_LEN; /* TODO: need to fix the length */
|
|
req.data = msg;
|
|
strcpy( req.name, devname);
|
|
req.result = 0;
|
|
|
|
if ( debug ) {
|
|
fprintf(stderr, "raw msg before ioctl:\n");
|
|
dump_msg(msg);
|
|
}
|
|
|
|
result = ioctl( fd, P80211_IFREQ, &req);
|
|
|
|
if ( debug ) {
|
|
fprintf(stderr, "raw msg after ioctl:\n");
|
|
dump_msg(msg);
|
|
}
|
|
|
|
if ( result == -1 ) {
|
|
perror("wlanctl-ng");
|
|
}
|
|
close(fd);
|
|
return result;
|
|
}
|
|
|
|
|
|
void dump_msg(void *msg)
|
|
{
|
|
p80211msgd_t *msgp = msg;
|
|
int i;
|
|
int bodylen;
|
|
|
|
fprintf(stderr, " msgcode=0x%08lx msglen=%lu devname=%s\n",
|
|
msgp->msgcode, msgp->msglen, msgp->devname);
|
|
fprintf(stderr, "body: ");
|
|
bodylen=msgp->msglen -
|
|
(sizeof(msgp->msgcode) +
|
|
sizeof(msgp->msglen) +
|
|
sizeof(msgp->devname));
|
|
for ( i = 0; i < bodylen; i+=4) {
|
|
fprintf(stderr, "%02x%02x%02x%02x ",
|
|
msgp->args[i], msgp->args[i+1],
|
|
msgp->args[i+2], msgp->args[i+3]);
|
|
}
|
|
fprintf(stderr,"\n");
|
|
}
|
|
|
|
/*----------------------------------------------------------------
|
|
* cmdline2requestmsg
|
|
*
|
|
* Default command line to request message converter. Takes the
|
|
* command (request) code and the cmdline arguments, compares them
|
|
* to the metadata for the request arguments for the given request
|
|
* and if all required arguments are present and valid, builds a
|
|
* message structure. This function handles the general case.
|
|
*
|
|
* Arguments:
|
|
* msg buffer to build msg in (assumed to be at least MSG_BUFF_LEN bytes)
|
|
* msgcode partial did containing category and group indices
|
|
* argc number of command line arguments
|
|
* argv array of argument strings
|
|
*
|
|
* Returns:
|
|
* 0 - success
|
|
* ~0 - failure
|
|
----------------------------------------------------------------*/
|
|
INT cmdline2requestmsg( UINT8 *msg, UINT32 msgcode, int argc, char **argv )
|
|
{
|
|
UINT8 *cmdlinelist;
|
|
UINT8 *msgptr;
|
|
UINT8 *start;
|
|
UINT8 tmpitem[MSG_BUFF_LEN];
|
|
p80211meta_t *alist = NULL;
|
|
grplistitem_t *grp = NULL;
|
|
INT found;
|
|
INT i;
|
|
INT j;
|
|
INT32 narg;
|
|
UINT32 tmpdid;
|
|
size_t itemlen;
|
|
size_t offset;
|
|
|
|
/* Create an array of bytes where each byte represents a flag for
|
|
each command line argument. For each argument on the command line
|
|
following the msg code, the repsective byte will contain either
|
|
a 0 (for not found) or 1 (found) after an attempt to match the
|
|
command line argument to one of the metadata arguments for the
|
|
user entered 'valid' msg, such as 'scan' or 'powermgmt'. */
|
|
|
|
if ( (cmdlinelist = (UINT8 *)malloc(argc)) == NULL ) {
|
|
printf("wlanctl-ng: cmdlinelist memory allocation failed\n");
|
|
return 1;
|
|
}
|
|
|
|
/* initialize all the bytes to 0 for not found */
|
|
memset( cmdlinelist, 0, argc);
|
|
memset( msg, 0, MSG_BUFF_LEN);
|
|
memset( tmpitem, 0, MSG_BUFF_LEN);
|
|
|
|
((p80211msg_t *)msg)->msgcode = msgcode;
|
|
strncpy(((p80211msg_t *)msg)->devname, devname,
|
|
WLAN_DEVNAMELEN_MAX - 1 );
|
|
((p80211msg_t *)msg)->msglen = sizeof(p80211msg_t);
|
|
|
|
start = msg + sizeof( p80211msg_t );
|
|
msgptr = start;
|
|
|
|
/* acquire the msg argument metadata list */
|
|
if ( (grp = p80211_did2grp(msg_catlist, msgcode)) != NULL ) {
|
|
alist = grp->itemlist;
|
|
narg = GETMETASIZE(alist);
|
|
} else {
|
|
printf("wlanctl-ng: Invalid msgcode of %u\n", (unsigned int)msgcode);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
printf("The cmd %s is valid with a code of 0x%08lx\n",
|
|
argv[2], msgcode);
|
|
printf(" argc=%d, narg is %lu\n", argc, narg);
|
|
*/
|
|
|
|
/* Loop through the metadata for all the arguments of the message
|
|
and initialize the did, the len and set the status to
|
|
status code of "no value" (i.e. the data isn't set) */
|
|
|
|
for ( i = 1; i < narg; i++) {
|
|
tmpdid = msgcode | P80211DID_MKITEM(i) | alist[i].did;
|
|
|
|
if ( (offset = p80211item_getoffset(msg_catlist, tmpdid)) !=
|
|
0xffffffff ) {
|
|
|
|
msgptr = start + offset;
|
|
|
|
((p80211item_t *)msgptr)->did = tmpdid;
|
|
((p80211item_t *)msgptr)->status =
|
|
(short)P80211ENUM_msgitem_status_no_value;
|
|
if ( (((p80211item_t *)msgptr)->len =
|
|
(short)(p80211item_maxdatalen(msg_catlist,
|
|
tmpdid))) != 0xffffffffUL ) {
|
|
((p80211msg_t *)msg)->msglen +=
|
|
( sizeof(p80211item_t) +
|
|
((p80211item_t *)msgptr)->len );
|
|
} else {
|
|
printf("wlanctl-ng: invalid data length for %s\n",
|
|
alist[i].name);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
} else {
|
|
printf("wlanctl-ng: [1] error creating offset for %s\n",
|
|
alist[i].name);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/* Build message in the same order as the metadata argument list by
|
|
by looping through msg arg metadata, args always start at index 1 */
|
|
|
|
msgptr = start;
|
|
|
|
for ( i = 1; i < narg; i++) {
|
|
found = 0;
|
|
tmpdid = msgcode | P80211DID_MKITEM(i) | alist[i].did;
|
|
|
|
if ( (offset = p80211item_getoffset(msg_catlist, tmpdid)) !=
|
|
0xffffffff ) {
|
|
/*
|
|
printf("cmdline2request: "
|
|
"curr meta data item %s: "
|
|
"offset=%d\n", alist[i].name, offset);
|
|
*/
|
|
msgptr = start + offset;
|
|
} else {
|
|
printf("wlanctl-ng: [2] error creating offset for %s\n",
|
|
alist[i].name);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
|
|
/* loop through msg arguments on cmdline */
|
|
for ( j = 3; (j < argc) && (!found); j++) {
|
|
/* does meta match cmdline arg? */
|
|
if ( strncmp(alist[i].name,argv[j],
|
|
strlen(alist[i].name)) == 0 ) {
|
|
|
|
if ( P80211ITEM_ISREQUEST(alist[i].flags) ) {
|
|
found = 1;
|
|
cmdlinelist[j] = (UINT8)1;
|
|
|
|
if ( alist[i].fromtextptr != NULL ) {
|
|
(*(alist[i].fromtextptr))
|
|
(msg_catlist, tmpdid, tmpitem, argv[j]);
|
|
}
|
|
|
|
itemlen = sizeof(p80211item_t) +
|
|
p80211item_maxdatalen(msg_catlist, tmpdid);
|
|
|
|
memcpy(msgptr, tmpitem, itemlen);
|
|
|
|
} else {
|
|
printf("non-request argument found on cmdline.\n");
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
} /* if cmdline match */
|
|
} /* for each cmdline arg */
|
|
|
|
} /* for each msg argument metadata */
|
|
|
|
/* Loop through the built message and check the status field.
|
|
For required request arguments, the status must be "data ok"
|
|
or it's an error. If the status code is "no value", the
|
|
argument can not be a required request argument; otherwise,
|
|
it's an error. Any other status code is an error. */
|
|
|
|
msgptr = start;
|
|
|
|
for ( i = 1; i < narg; i++) {
|
|
if ( ((p80211item_t *)msgptr)->status >
|
|
(short)P80211ENUM_msgitem_status_no_value ) {
|
|
|
|
p80211_error2text( ((p80211item_t *)msgptr)->status,
|
|
tmpitem );
|
|
printf("%s=\"%s\"\n", alist[i].name, tmpitem);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
} else if ( ((p80211item_t *)msgptr)->status ==
|
|
(short)P80211ENUM_msgitem_status_no_value ) {
|
|
if ( (P80211ITEM_ISREQUIRED(alist[i].flags)) &&
|
|
(P80211ITEM_ISREQUEST(alist[i].flags)) )
|
|
{
|
|
printf("The required argument \'%s\' has no value.\n", alist[i].name);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
msgptr += (sizeof(p80211item_t) + ((p80211item_t *)msgptr)->len);
|
|
}
|
|
|
|
/* check to see that each message argument on the command line was */
|
|
/* matched to an argument metadata for the message */
|
|
for ( j = 3; j < argc; j++) {
|
|
if ( !(cmdlinelist[j]) ) {
|
|
printf("\'%s\' entered on the command line "
|
|
"was either an invalid\n"
|
|
"argument to the cmd \'%s\' or an extra "
|
|
"occurence of a valid argument.\n",
|
|
argv[j], argv[2]);
|
|
free( cmdlinelist );
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
free( cmdlinelist );
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------
|
|
* printmsg
|
|
*
|
|
* Traverse the message items printing each.
|
|
*
|
|
* Arguments:
|
|
* msg buffer containing a complete msg
|
|
* msgcode integer identifying the msg
|
|
*
|
|
* Returns:
|
|
* 0 - success
|
|
* ~0 - failure
|
|
----------------------------------------------------------------*/
|
|
void printmsg( UINT8 *msg, UINT32 msgcode )
|
|
{
|
|
UINT8 tmpitem[MSG_BUFF_LEN];
|
|
UINT8 *msgptr;
|
|
UINT8 *start;
|
|
INT i;
|
|
grplistitem_t *grp;
|
|
UINT32 narg;
|
|
UINT32 offset;
|
|
UINT32 tmpdid;
|
|
p80211meta_t *alist;
|
|
|
|
|
|
msgptr = msg;
|
|
|
|
/* acquire the msg argument metadata list */
|
|
if ( (grp = p80211_did2grp(msg_catlist, msgcode)) != NULL ) {
|
|
alist = grp->itemlist;
|
|
narg = GETMETASIZE(alist);
|
|
} else {
|
|
printf("wlanctl-ng: Invalid msgcode of %u\n", (unsigned int)msgcode);
|
|
return;
|
|
}
|
|
|
|
/* print the message code */
|
|
printf("message=%s\n", grp->name);
|
|
|
|
start = msg + sizeof(p80211msg_t);
|
|
|
|
for ( i = 1; i < narg; i++ ) {
|
|
tmpdid = msgcode | P80211DID_MKITEM(i) | alist[i].did;
|
|
offset = p80211item_getoffset(msg_catlist, tmpdid);
|
|
msgptr = start + offset;
|
|
|
|
/* pass tmpdid since the 'totext' functions */
|
|
/* expect a non-zero did */
|
|
if ( ((p80211item_t *)msgptr)->status ==
|
|
P80211ENUM_msgitem_status_data_ok ) {
|
|
if ( alist[i].totextptr != NULL ) {
|
|
(*(alist[i].totextptr))
|
|
( msg_catlist, tmpdid, msgptr, tmpitem);
|
|
printf(" %s\n", tmpitem);
|
|
} else {
|
|
p80211_error2text(
|
|
P80211ENUM_msgitem_status_missing_print_func,
|
|
tmpitem);
|
|
printf(" %s=%s\n", alist[i].name, tmpitem);
|
|
}
|
|
} else {
|
|
p80211_error2text( ((p80211item_t *)msgptr)->status,
|
|
tmpitem);
|
|
printf(" %s=%s\n", alist[i].name, tmpitem);
|
|
}
|
|
|
|
} /* for each argument in the metadata */
|
|
}
|