1 /*-
2 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer,
10 * without modification.
11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13 * redistribution must be conditioned upon including a substantially
14 * similar Disclaimer requirement for further binary redistribution.
15 *
16 * NO WARRANTY
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGES.
28 */
29
30 /*
31 * athdebug [-i interface] flags
32 * (default interface is wlan0).
33 */
34
35 #include <sys/param.h>
36 #include <sys/file.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <sys/sysctl.h>
40
41 #include <ctype.h>
42 #include <err.h>
43 #include <getopt.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <strings.h>
48
49 const char *progname;
50
51 /* XXX TODO: include if_ath_debug.h */
52 enum {
53 ATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
54 ATH_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */
55 ATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
56 ATH_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */
57 ATH_DEBUG_RATE = 0x00000010, /* rate control */
58 ATH_DEBUG_RESET = 0x00000020, /* reset processing */
59 ATH_DEBUG_MODE = 0x00000040, /* mode init/setup */
60 ATH_DEBUG_BEACON = 0x00000080, /* beacon handling */
61 ATH_DEBUG_WATCHDOG = 0x00000100, /* watchdog timeout */
62 ATH_DEBUG_INTR = 0x00001000, /* ISR */
63 ATH_DEBUG_TX_PROC = 0x00002000, /* tx ISR proc */
64 ATH_DEBUG_RX_PROC = 0x00004000, /* rx ISR proc */
65 ATH_DEBUG_BEACON_PROC = 0x00008000, /* beacon ISR proc */
66 ATH_DEBUG_CALIBRATE = 0x00010000, /* periodic calibration */
67 ATH_DEBUG_KEYCACHE = 0x00020000, /* key cache management */
68 ATH_DEBUG_STATE = 0x00040000, /* 802.11 state transitions */
69 ATH_DEBUG_NODE = 0x00080000, /* node management */
70 ATH_DEBUG_LED = 0x00100000, /* led management */
71 ATH_DEBUG_FF = 0x00200000, /* fast frames */
72 ATH_DEBUG_DFS = 0x00400000, /* DFS processing */
73 ATH_DEBUG_TDMA = 0x00800000, /* TDMA processing */
74 ATH_DEBUG_TDMA_TIMER = 0x01000000, /* TDMA timer processing */
75 ATH_DEBUG_REGDOMAIN = 0x02000000, /* regulatory processing */
76 ATH_DEBUG_FATAL = 0x80000000, /* fatal errors */
77 ATH_DEBUG_ANY = 0xffffffff
78 };
79
80 static struct {
81 const char *name;
82 uint64_t bit;
83 } flags[] = {
84 { "xmit", ATH_DEBUG_XMIT },
85 { "xmit_desc", ATH_DEBUG_XMIT_DESC },
86 { "recv", ATH_DEBUG_RECV },
87 { "recv_desc", ATH_DEBUG_RECV_DESC },
88 { "rate", ATH_DEBUG_RATE },
89 { "reset", ATH_DEBUG_RESET },
90 { "mode", ATH_DEBUG_MODE },
91 { "beacon", ATH_DEBUG_BEACON },
92 { "watchdog", ATH_DEBUG_WATCHDOG },
93 { "intr", ATH_DEBUG_INTR },
94 { "xmit_proc", ATH_DEBUG_TX_PROC },
95 { "recv_proc", ATH_DEBUG_RX_PROC },
96 { "beacon_proc",ATH_DEBUG_BEACON_PROC },
97 { "calibrate", ATH_DEBUG_CALIBRATE },
98 { "keycache", ATH_DEBUG_KEYCACHE },
99 { "state", ATH_DEBUG_STATE },
100 { "node", ATH_DEBUG_NODE },
101 { "led", ATH_DEBUG_LED },
102 { "ff", ATH_DEBUG_FF },
103 { "dfs", ATH_DEBUG_DFS },
104 { "tdma", ATH_DEBUG_TDMA },
105 { "tdma_timer", ATH_DEBUG_TDMA_TIMER },
106 { "regdomain", ATH_DEBUG_REGDOMAIN },
107 { "fatal", ATH_DEBUG_FATAL },
108 };
109
110 static uint64_t
getflag(const char * name,int len)111 getflag(const char *name, int len)
112 {
113 unsigned int i;
114
115 for (i = 0; i < nitems(flags); i++)
116 if (strncasecmp(flags[i].name, name, len) == 0)
117 return flags[i].bit;
118 return 0;
119 }
120
121 #if 0
122 static const char *
123 getflagname(u_int flag)
124 {
125 int i;
126
127 for (i = 0; i < nitems(flags); i++)
128 if (flags[i].bit == flag)
129 return flags[i].name;
130 return "???";
131 }
132 #endif
133
134 static void
usage(void)135 usage(void)
136 {
137 unsigned int i;
138
139 fprintf(stderr, "usage: %s [-i device] [flags]\n", progname);
140 fprintf(stderr, "where flags are:\n");
141 for (i = 0; i < nitems(flags); i++)
142 printf("%s\n", flags[i].name);
143 exit(-1);
144 }
145
146 int
main(int argc,char * argv[])147 main(int argc, char *argv[])
148 {
149 const char *ifname;
150 const char *cp, *tp;
151 const char *sep;
152 int op;
153 unsigned int i;
154 uint64_t debug, ndebug;
155 size_t debuglen;
156 char oid[256];
157
158 ifname = getenv("ATH");
159 if (ifname == NULL)
160 ifname = ATH_DEFAULT;
161 progname = argv[0];
162 if (argc > 1) {
163 if (strcmp(argv[1], "-i") == 0) {
164 if (argc < 2)
165 errx(1, "missing interface name for -i option");
166 ifname = argv[2];
167 if (strncmp(ifname, "ath", 3) != 0)
168 errx(2, "huh, this is for ath devices?");
169 argc -= 2, argv += 2;
170 } else if (strcmp(argv[1], "-?") == 0)
171 usage();
172 }
173
174 #ifdef __linux__
175 snprintf(oid, sizeof(oid), "dev.%s.debug", ifname);
176 #else
177 snprintf(oid, sizeof(oid), "dev.ath.%s.debug", ifname+3);
178 #endif
179 debuglen = sizeof(debug);
180 if (sysctlbyname(oid, &debug, &debuglen, NULL, 0) < 0)
181 err(1, "sysctl-get(%s)", oid);
182 ndebug = debug;
183 for (; argc > 1; argc--, argv++) {
184 cp = argv[1];
185 do {
186 u_int bit;
187
188 if (*cp == '-') {
189 cp++;
190 op = -1;
191 } else if (*cp == '+') {
192 cp++;
193 op = 1;
194 } else
195 op = 0;
196 for (tp = cp; *tp != '\0' && *tp != '+' && *tp != '-';)
197 tp++;
198 bit = getflag(cp, tp-cp);
199 if (op < 0)
200 ndebug &= ~bit;
201 else if (op > 0)
202 ndebug |= bit;
203 else {
204 if (bit == 0) {
205 if (isdigit(*cp))
206 bit = strtoul(cp, NULL, 0);
207 else
208 errx(1, "unknown flag %.*s",
209 (int) (tp-cp), cp);
210 }
211 ndebug = bit;
212 }
213 } while (*(cp = tp) != '\0');
214 }
215 if (debug != ndebug) {
216 printf("%s: 0x%llx => ", oid, (long long) debug);
217 if (sysctlbyname(oid, NULL, NULL, &ndebug, sizeof(ndebug)) < 0)
218 err(1, "sysctl-set(%s)", oid);
219 printf("0x%llx", (long long) ndebug);
220 debug = ndebug;
221 } else
222 printf("%s: 0x%llx", oid, (long long) debug);
223 sep = "<";
224 for (i = 0; i < nitems(flags); i++)
225 if (debug & flags[i].bit) {
226 printf("%s%s", sep, flags[i].name);
227 sep = ",";
228 }
229 printf("%s\n", *sep != '<' ? ">" : "");
230 return 0;
231 }
232