1/* 2 * Wireless network adapter utilities (linux-specific) 3 * 4 * Copyright (C) 2014, Broadcom Corporation. All Rights Reserved. 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * $Id: wl_linux.c 435840 2013-11-12 09:30:26Z $ 19 */ 20 21#include <stdio.h> 22#include <unistd.h> 23#include <string.h> 24#include <errno.h> 25#include <sys/ioctl.h> 26#include <sys/socket.h> 27#include <net/if.h> 28#include <linux/types.h> 29 30typedef u_int64_t u64; 31typedef u_int32_t u32; 32typedef u_int16_t u16; 33typedef u_int8_t u8; 34#include <linux/sockios.h> 35#include <linux/ethtool.h> 36 37#include <typedefs.h> 38#include <wlioctl.h> 39#include <wlutils.h> 40 41 42int 43wl_ioctl(char *name, int cmd, void *buf, int len) 44{ 45 struct ifreq ifr; 46 wl_ioctl_t ioc; 47 int ret = 0; 48 int s; 49 char buffer[100]; 50 51 /* open socket to kernel */ 52 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 53 perror("socket"); 54 return errno; 55 } 56 57 /* do it */ 58 ioc.cmd = cmd; 59 ioc.buf = buf; 60 ioc.len = len; 61 62 /* initializing the remaining fields */ 63 ioc.set = FALSE; 64 ioc.used = 0; 65 ioc.needed = 0; 66 67 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1); 68 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 69 ifr.ifr_data = (caddr_t) &ioc; 70 if ((ret = ioctl(s, SIOCDEVPRIVATE, &ifr)) < 0) 71 if (cmd != WLC_GET_MAGIC && cmd != WLC_GET_BSSID) { 72 if ((cmd == WLC_GET_VAR) || (cmd == WLC_SET_VAR)) { 73 snprintf(buffer, sizeof(buffer), "%s: WLC_%s_VAR(%s)", name, 74 cmd == WLC_GET_VAR ? "GET" : "SET", (char *)buf); 75 } else { 76 snprintf(buffer, sizeof(buffer), "%s: cmd=%d", name, cmd); 77 } 78 perror(buffer); 79 } 80 /* cleanup */ 81 close(s); 82 return ret; 83} 84 85int 86wl_get_dev_type(char *name, void *buf, int len) 87{ 88 int s; 89 int ret; 90 struct ifreq ifr; 91 struct ethtool_drvinfo info; 92 93 /* open socket to kernel */ 94 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 95 perror("socket"); 96 return -1; 97 } 98 99 /* get device type */ 100 memset(&info, 0, sizeof(info)); 101 info.cmd = ETHTOOL_GDRVINFO; 102 ifr.ifr_data = (caddr_t)&info; 103 strncpy(ifr.ifr_name, name, IFNAMSIZ); 104 if ((ret = ioctl(s, SIOCETHTOOL, &ifr)) < 0) { 105 *(char *)buf = '\0'; 106 } else 107 strncpy(buf, info.driver, len); 108 109 close(s); 110 return ret; 111} 112 113int 114wl_hwaddr(char *name, unsigned char *hwaddr) 115{ 116 struct ifreq ifr; 117 int ret = 0; 118 int s; 119 120 /* open socket to kernel */ 121 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 122 perror("socket"); 123 return errno; 124 } 125 126 /* do it */ 127 strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)-1); 128 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0'; 129 if ((ret = ioctl(s, SIOCGIFHWADDR, &ifr)) == 0) 130 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); 131 132 /* cleanup */ 133 close(s); 134 return ret; 135} 136