Home | History | Annotate | Download | only in exe
      1 /*
      2  * Linux port of dhd command line utility, hacked from wl utility.
      3  *
      4  * Copyright (C) 1999-2010, Broadcom Corporation
      5  *
      6  *      Unless you and Broadcom execute a separate written software license
      7  * agreement governing use of this software, this software is licensed to you
      8  * under the terms of the GNU General Public License version 2 (the "GPL"),
      9  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
     10  * following added to such license:
     11  *
     12  *      As a special exception, the copyright holders of this software give you
     13  * permission to link this software with independent modules, and to copy and
     14  * distribute the resulting executable under terms of your choice, provided that
     15  * you also meet, for each linked independent module, the terms and conditions of
     16  * the license of that module.  An independent module is a module which is not
     17  * derived from this software.  The special exception does not apply to any
     18  * modifications of the software.
     19  *
     20  *      Notwithstanding the above, under no circumstances may you combine this
     21  * software in any way with any other Broadcom software provided under a license
     22  * other than the GPL, without Broadcom's express prior written consent.
     23  *
     24  * $Id: dhdu_linux.c,v 1.3.10.2.2.3 2009/01/27 01:02:28 Exp $
     25  */
     26 
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <unistd.h>
     30 #include <ctype.h>
     31 #include <string.h>
     32 #include <errno.h>
     33 #ifndef TARGETENV_android
     34 #include <error.h>
     35 #endif /* TARGETENV_android */
     36 #include <sys/types.h>
     37 #include <sys/socket.h>
     38 #include <sys/ioctl.h>
     39 #include <net/if.h>
     40 
     41 
     42 typedef u_int64_t u64;
     43 typedef u_int32_t u32;
     44 typedef u_int16_t u16;
     45 typedef u_int8_t u8;
     46 #include <linux/sockios.h>
     47 #include <linux/ethtool.h>
     48 
     49 #include <typedefs.h>
     50 #include <dhdioctl.h>
     51 #include "dhdu.h"
     52 
     53 #define DEV_TYPE_LEN 4 /* length for devtype 'dhd' */
     54 
     55 static void
     56 syserr(char *s)
     57 {
     58 	fprintf(stderr, "%s: ", dhdu_av0);
     59 	perror(s);
     60 	exit(errno);
     61 }
     62 
     63 static int
     64 dhd_ioctl(void *dhd, int cmd, void *buf, int len, bool set)
     65 {
     66 	struct ifreq *ifr = (struct ifreq *)dhd;
     67 	dhd_ioctl_t ioc;
     68 	int ret = 0;
     69 	int s;
     70 
     71 	/* open socket to kernel */
     72 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
     73 		syserr("socket");
     74 
     75 	/* do it */
     76 	ioc.cmd = cmd;
     77 	ioc.buf = buf;
     78 	ioc.len = len;
     79 	ioc.set = set;
     80 	ioc.driver = DHD_IOCTL_MAGIC;
     81 	ifr->ifr_data = (caddr_t) &ioc;
     82 	if ((ret = ioctl(s, SIOCDEVPRIVATE, ifr)) < 0) {
     83 		if (cmd != DHD_GET_MAGIC) {
     84 			ret = IOCTL_ERROR;
     85 		}
     86 	}
     87 
     88 	/* cleanup */
     89 	close(s);
     90 	return ret;
     91 }
     92 
     93 static int
     94 dhd_get_dev_type(char *name, void *buf, int len)
     95 {
     96 	int s;
     97 	int ret;
     98 	struct ifreq ifr;
     99 	struct ethtool_drvinfo info;
    100 
    101 	/* open socket to kernel */
    102 	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    103 		syserr("socket");
    104 
    105 	/* get device type */
    106 	memset(&info, 0, sizeof(info));
    107 	info.cmd = ETHTOOL_GDRVINFO;
    108 	strcpy(info.driver, "?dhd");
    109 	ifr.ifr_data = (caddr_t)&info;
    110 	strncpy(ifr.ifr_name, name, IFNAMSIZ);
    111 	if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) {
    112 
    113 		/* print a good diagnostic if not superuser */
    114 		if (errno == EPERM)
    115 			syserr("dhd_get_dev_type");
    116 
    117 		*(char *)buf = '\0';
    118 	}
    119 	else
    120 		strncpy(buf, info.driver, len);
    121 
    122 	close(s);
    123 	return ret;
    124 }
    125 
    126 int
    127 dhd_get(void *dhd, int cmd, void *buf, int len)
    128 {
    129 	return dhd_ioctl(dhd, cmd, buf, len, FALSE);
    130 }
    131 
    132 int
    133 dhd_set(void *dhd, int cmd, void *buf, int len)
    134 {
    135 	return dhd_ioctl(dhd, cmd, buf, len, TRUE);
    136 }
    137 
    138 void
    139 dhd_find(struct ifreq *ifr)
    140 {
    141 	char proc_net_dev[] = "/proc/net/dev";
    142 	FILE *fp;
    143 	char buf[1000], *c, *name;
    144 	char dev_type[DEV_TYPE_LEN];
    145 
    146 	ifr->ifr_name[0] = '\0';
    147 
    148 	/* eat first two lines */
    149 	if (!(fp = fopen(proc_net_dev, "r")) ||
    150 	    !fgets(buf, sizeof(buf), fp) ||
    151 	    !fgets(buf, sizeof(buf), fp))
    152 		return;
    153 
    154 	while (fgets(buf, sizeof(buf), fp)) {
    155 		c = buf;
    156 		while (isspace(*c))
    157 			c++;
    158 		if (!(name = strsep(&c, ":")))
    159 			continue;
    160 		strncpy(ifr->ifr_name, name, IFNAMSIZ);
    161 		if (dhd_get_dev_type(name, dev_type, DEV_TYPE_LEN) >= 0 &&
    162 			!strncmp(dev_type, "dhd", 3))
    163 			if (dhd_check((void *)ifr) == 0)
    164 				break;
    165 		ifr->ifr_name[0] = '\0';
    166 	}
    167 
    168 	fclose(fp);
    169 }
    170 
    171 int
    172 main(int argc, char **argv)
    173 {
    174 	struct ifreq ifr;
    175 	cmd_t *cmd = NULL;
    176 	int err = 0;
    177 	char *ifname = NULL;
    178 	int help = 0;
    179 	int status = CMD_DHD;
    180 
    181 	UNUSED_PARAMETER(argc);
    182 
    183 	dhdu_av0 = argv[0];
    184 
    185 	memset(&ifr, 0, sizeof(ifr));
    186 
    187 	for (++argv; *argv;) {
    188 
    189 		/* command option */
    190 		if ((status = dhd_option(&argv, &ifname, &help)) == CMD_OPT) {
    191 			if (help)
    192 				break;
    193 			if (ifname) {
    194 				if (strlen(ifname) > IFNAMSIZ) {
    195 					fprintf(stderr, "%s: interface name too long\n", dhdu_av0);
    196 					break;
    197 				}
    198 				strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
    199 			}
    200 			continue;
    201 		}
    202 
    203 		/* parse error */
    204 		else if (status == CMD_ERR)
    205 			break;
    206 
    207 		/* use default if no interface specified */
    208 		if (!*ifr.ifr_name)
    209 			dhd_find(&ifr);
    210 		/* validate the interface */
    211 		if (!*ifr.ifr_name || dhd_check((void *)&ifr)) {
    212 			fprintf(stderr, "%s: dhd driver adapter not found\n", dhdu_av0);
    213 			exit(1);
    214 		}
    215 
    216 		/* search for command */
    217 		for (cmd = dhd_cmds; cmd->name && strcmp(cmd->name, *argv); cmd++);
    218 
    219 		/* defaults to using the set_var and get_var commands */
    220 		if (cmd->name == NULL)
    221 			cmd = &dhd_varcmd;
    222 
    223 		/* do command */
    224 		if (cmd->name)
    225 			err = (*cmd->func)((void *)&ifr, cmd, argv);
    226 		break;
    227 	}
    228 
    229 	/* In case of COMMAND_ERROR, command has already printed an error message */
    230 	if (!cmd)
    231 		dhd_usage(NULL);
    232 	else if (err == USAGE_ERROR)
    233 		dhd_cmd_usage(cmd);
    234 	else if (err == IOCTL_ERROR)
    235 		dhd_printlasterror((void *)&ifr);
    236 
    237 	return err;
    238 }
    239