1/* 2 * et driver ioctl swiss army knife command. 3 * 4 * Copyright 2007, Broadcom Corporation 5 * All Rights Reserved. 6 * 7 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; 8 * the contents of this file may not be disclosed to third parties, copied 9 * or duplicated in any form, in whole or in part, without the prior 10 * written permission of Broadcom Corporation. 11 * 12 * $Id: et.c,v 1.1.1.1 2008/10/15 03:25:54 james26_jang Exp $ 13 */ 14 15#include <stdio.h> 16 17#include <sys/param.h> 18#include <sys/ioctl.h> 19#include <sys/socket.h> 20#include <sys/sysctl.h> 21#include <sys/time.h> 22#include <net/if.h> 23#include <netinet/in.h> 24#include <typedefs.h> 25#include <string.h> 26#include <ctype.h> 27#include <errno.h> 28#include <stdlib.h> 29#include <etioctl.h> 30#include <proto/ethernet.h> 31 32typedef u_int64_t u64; 33typedef u_int32_t u32; 34typedef u_int16_t u16; 35typedef u_int8_t u8; 36#include <linux/sockios.h> 37#include <linux/ethtool.h> 38 39static void usage(char *av0); 40static void syserr(char *s); 41static void et_find(int s, struct ifreq *ifr); 42static int et_check(int s, struct ifreq *ifr); 43 44 45 46char buf[16 * 1024]; 47 48#define VECLEN 2 49 50static int optind; 51 52int 53main(int ac, char *av[]) 54{ 55 char *interface = NULL; 56 struct ifreq ifr; 57 char *endptr; 58 int arg; 59 int vecarg[VECLEN]; 60 int s; 61 62 if (ac < 2) 63 usage(av[0]); 64 65 optind = 1; 66 67 if (av[1][0] == '-') { 68 if ((av[1][1] != 'a') && (av[1][1] != 'i')) 69 usage(av[0]); 70 if (ac < 4) 71 usage(av[0]); 72 interface = av[2]; 73 optind += 2; 74 } 75 76 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 77 syserr("socket"); 78 79 if (interface) 80 strncpy(ifr.ifr_name, interface, sizeof (ifr.ifr_name)); 81 else 82 et_find(s, &ifr); 83 84 if (!*ifr.ifr_name) { 85 fprintf(stderr, "et interface not found\n"); 86 exit(1); 87 } 88 89 if (strcmp(av[optind], "up") == 0) { 90 if (ioctl(s, SIOCSETCUP, (caddr_t)&ifr) < 0) 91 syserr("etcup"); 92 } else if (strcmp(av[optind], "down") == 0) { 93 if (ioctl(s, SIOCSETCDOWN, (caddr_t)&ifr) < 0) 94 syserr("etcdown"); 95 } else if (strcmp(av[optind], "loop") == 0) { 96 if (optind >= (ac -1)) 97 usage(av[0]); 98 arg = atoi(av[optind + 1]); 99 ifr.ifr_data = (caddr_t) &arg; 100 if (ioctl(s, SIOCSETCLOOP, (caddr_t)&ifr) < 0) 101 syserr("etcloop"); 102 } else if (strcmp(av[optind], "dump") == 0) { 103 ifr.ifr_data = buf; 104 if (ioctl(s, SIOCGETCDUMP, (caddr_t)&ifr) < 0) 105 syserr("etcdump"); 106 printf("%s\n", buf); 107 } else if (strcmp(av[optind], "msglevel") == 0) { 108 if (optind >= (ac -1)) 109 usage(av[0]); 110 arg = strtol(av[optind + 1], &endptr, 0); 111 ifr.ifr_data = (caddr_t) &arg; 112 if (ioctl(s, SIOCSETCSETMSGLEVEL, (caddr_t)&ifr) < 0) 113 syserr("etcsetmsglevel"); 114 } else if (strcmp(av[optind], "promisc") == 0) { 115 if (optind >= (ac -1)) 116 usage(av[0]); 117 arg = atoi(av[optind + 1]); 118 ifr.ifr_data = (caddr_t) &arg; 119 if (ioctl(s, SIOCSETCPROMISC, (caddr_t)&ifr) < 0) 120 syserr("etcpromisc"); 121 } else if (strcmp(av[optind], "qos") == 0) { 122 if (optind >= (ac -1)) 123 usage(av[0]); 124 arg = atoi(av[optind + 1]); 125 ifr.ifr_data = (caddr_t) &arg; 126 if (ioctl(s, SIOCSETCQOS, (caddr_t)&ifr) < 0) 127 syserr("etcqos"); 128 } else if (strcmp(av[optind], "txdown") == 0) { 129 if (ioctl(s, SIOCSETCTXDOWN, (caddr_t)&ifr) < 0) 130 syserr("etctxdown"); 131 } else if (strcmp(av[optind], "speed") == 0) { 132 if (optind >= (ac -1)) 133 usage(av[0]); 134 if (strcmp(av[optind+1], "auto") == 0) 135 arg = -1; 136 else if (strcmp(av[optind+1], "10half") == 0) 137 arg = 0; 138 else if (strcmp(av[optind+1], "10full") == 0) 139 arg = 1; 140 else if (strcmp(av[optind+1], "100half") == 0) 141 arg = 2; 142 else if (strcmp(av[optind+1], "100full") == 0) 143 arg = 3; 144 else 145 usage(av[0]); 146 147 ifr.ifr_data = (caddr_t) &arg; 148 if (ioctl(s, SIOCSETCSPEED, (caddr_t)&ifr) < 0) 149 syserr("etcspeed"); 150 } 151 else if (strcmp(av[optind], "phyrd") == 0) { 152 int cmd = -1; 153 154 if ((ac < (optind + 2)) || (ac > (optind + 3))) { 155 usage(av[0]); 156 } else if (ac == (optind + 3)) { 157 /* PHY address provided */ 158 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;; 159 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff; 160 cmd = SIOCGETCPHYRD2; 161 } else { 162 /* "My" PHY address implied */ 163 vecarg[0] = strtoul(av[optind + 1], NULL, 0); 164 cmd = SIOCGETCPHYRD; 165 } 166 ifr.ifr_data = (caddr_t) vecarg; 167 if (ioctl(s, cmd, (caddr_t)&ifr) < 0) 168 syserr("etcphyrd"); 169 170 printf("0x%04x\n", vecarg[1]); 171 } else if (strcmp(av[optind], "phywr") == 0) { 172 int cmd = -1; 173 174 if ((ac < (optind + 3)) || (ac > (optind + 4))) { 175 usage(av[0]); 176 } else if (ac == (optind + 4)) { 177 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;; 178 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff; 179 vecarg[1] = strtoul(av[optind + 3], NULL, 0); 180 cmd = SIOCSETCPHYWR2; 181 } else { 182 vecarg[0] = strtoul(av[optind + 1], NULL, 0); 183 vecarg[1] = strtoul(av[optind + 2], NULL, 0); 184 cmd = SIOCSETCPHYWR; 185 } 186 ifr.ifr_data = (caddr_t) vecarg; 187 if (ioctl(s, cmd, (caddr_t)&ifr) < 0) 188 syserr("etcphywr"); 189 } else if (strcmp(av[optind], "robord") == 0) { 190 if (ac != (optind + 3)) 191 usage(av[0]); 192 193 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;; 194 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff; 195 196 ifr.ifr_data = (caddr_t) vecarg; 197 if (ioctl(s, SIOCGETCROBORD, (caddr_t)&ifr) < 0) 198 syserr("etcrobord"); 199 200 printf("0x%04x\n", vecarg[1]); 201 } else if (strcmp(av[optind], "robowr") == 0) { 202 if (ac != (optind + 4)) 203 usage(av[0]); 204 205 vecarg[0] = strtoul(av[optind + 1], NULL, 0) << 16;; 206 vecarg[0] |= strtoul(av[optind + 2], NULL, 0) & 0xffff; 207 vecarg[1] = strtoul(av[optind + 3], NULL, 0); 208 209 ifr.ifr_data = (caddr_t) vecarg; 210 if (ioctl(s, SIOCSETCROBOWR, (caddr_t)&ifr) < 0) 211 syserr("etcrobowr"); 212 } else 213 usage(av[0]); 214 215 return (0); 216} 217 218static void 219usage(char *av0) 220{ 221 fprintf(stderr, "usage: %s [ [ -a | -i ] interface ] and one of:\n" 222 "\tup\n" 223 "\tdown\n" 224 "\tloop <0 or 1>\n" 225 "\tdump\n" 226 "\tmsglevel <bitvec> (error=1, trace=2, prhdr=4, prpkt=8)\n" 227 "\tpromisc <0 or 1>\n" 228 "\tqos <0 or 1>\n" 229 "\ttxdown\n" 230 "\tspeed <auto, 10half, 10full, 100half, 100full>\n" 231 "\tphyrd [<phyaddr>] <reg>\n" 232 "\tphywr [<phyaddr>] <reg> <val>\n" 233 "\trobord <page> <reg>\n" 234 "\trobowr <page> <reg> <val>\n" 235 , 236 av0); 237 exit(1); 238} 239 240static void 241et_find(int s, struct ifreq *ifr) 242{ 243 char proc_net_dev[] = "/proc/net/dev"; 244 FILE *fp; 245 char buf[512], *c, *name; 246 247 ifr->ifr_name[0] = '\0'; 248 249 /* eat first two lines */ 250 if (!(fp = fopen(proc_net_dev, "r")) || 251 !fgets(buf, sizeof(buf), fp) || 252 !fgets(buf, sizeof(buf), fp)) 253 return; 254 255 while (fgets(buf, sizeof(buf), fp)) { 256 c = buf; 257 while (isspace(*c)) 258 c++; 259 if (!(name = strsep(&c, ":"))) 260 continue; 261 strncpy(ifr->ifr_name, name, IFNAMSIZ); 262 if (et_check(s, ifr) == 0) 263 break; 264 ifr->ifr_name[0] = '\0'; 265 } 266 267 fclose(fp); 268} 269 270static int 271et_check(int s, struct ifreq *ifr) 272{ 273 struct ethtool_drvinfo info; 274 275 memset(&info, 0, sizeof(info)); 276 info.cmd = ETHTOOL_GDRVINFO; 277 ifr->ifr_data = (caddr_t)&info; 278 if (ioctl(s, SIOCETHTOOL, (caddr_t)ifr) < 0) { 279 /* print a good diagnostic if not superuser */ 280 if (errno == EPERM) 281 syserr("siocethtool"); 282 return (-1); 283 } 284 285 if (!strncmp(info.driver, "et", 2)) 286 return (0); 287 else if (!strncmp(info.driver, "bcm57", 5)) 288 return (0); 289 290 return (-1); 291} 292 293static void 294syserr(char *s) 295{ 296 perror(s); 297 exit(1); 298} 299 300