Fix compatibility with procfs API changes in Linux 3.10
[madwifi/.git] / tools / athchans.c
1 /*-
2  * Copyright (c) 2002-2005 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  * 3. Neither the names of the above-listed copyright holders nor the names
16  *    of any contributors may be used to endorse or promote products derived
17  *    from this software without specific prior written permission.
18  *
19  * Alternatively, this software may be distributed under the terms of the
20  * GNU General Public License ("GPL") version 2 as published by the Free
21  * Software Foundation.
22  *
23  * NO WARRANTY
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
27  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
28  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
29  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
32  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34  * THE POSSIBILITY OF SUCH DAMAGES.
35  *
36  * $Id$
37  */
38
39 /*
40  * athchans [-i interface] chan ...
41  * (default interface is wifi0).
42  */
43 #include <sys/types.h>
44 #include <sys/file.h>
45 #include <sys/ioctl.h>
46 #include <sys/socket.h>
47
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <ctype.h>
52 #include <getopt.h>
53 #include <err.h>
54
55 #include <include/compat.h>
56
57 #include "wireless_copy.h"
58 #include "net80211/ieee80211.h"
59 #include "net80211/ieee80211_crypto.h"
60 #include "net80211/ieee80211_ioctl.h"
61
62 static  int s = -1;
63 static const char *progname;
64
65 static void
66 checksocket(void)
67 {
68         if (s < 0 ? (s = socket(AF_INET, SOCK_DGRAM, 0)) == -1 : 0)
69                 perror("socket(SOCK_DGRAM)");
70 }
71
72 #define IOCTL_ERR(x) [x - SIOCIWFIRSTPRIV] = "ioctl[" #x "]"
73 static int
74 set80211priv(const char *dev, int op, void *data, int len, int show_err)
75 {
76         struct iwreq iwr;
77
78         checksocket();
79
80         memset(&iwr, 0, sizeof(iwr));
81         strncpy(iwr.ifr_name, dev, IFNAMSIZ);
82         if (len < IFNAMSIZ) {
83                 /*
84                  * Argument data fits inline; put it there.
85                  */
86                 memcpy(iwr.u.name, data, len);
87         } else {
88                 /*
89                  * Argument data too big for inline transfer; setup a
90                  * parameter block instead; the kernel will transfer
91                  * the data for the driver.
92                  */
93                 iwr.u.data.pointer = data;
94                 iwr.u.data.length = len;
95         }
96
97         if (ioctl(s, op, &iwr) < 0) {
98                 if (show_err) {
99                         static const char *opnames[] = {
100                                 IOCTL_ERR(IEEE80211_IOCTL_SETPARAM),
101                                 IOCTL_ERR(IEEE80211_IOCTL_GETPARAM),
102                                 IOCTL_ERR(IEEE80211_IOCTL_SETMODE),
103                                 IOCTL_ERR(IEEE80211_IOCTL_GETMODE),
104                                 IOCTL_ERR(IEEE80211_IOCTL_SETWMMPARAMS),
105                                 IOCTL_ERR(IEEE80211_IOCTL_GETWMMPARAMS),
106                                 IOCTL_ERR(IEEE80211_IOCTL_SETCHANLIST),
107                                 IOCTL_ERR(IEEE80211_IOCTL_GETCHANLIST),
108                                 IOCTL_ERR(IEEE80211_IOCTL_CHANSWITCH),
109                                 IOCTL_ERR(IEEE80211_IOCTL_GETCHANINFO),
110                                 IOCTL_ERR(IEEE80211_IOCTL_SETOPTIE),
111                                 IOCTL_ERR(IEEE80211_IOCTL_GETOPTIE),
112                                 IOCTL_ERR(IEEE80211_IOCTL_SETMLME),
113                                 IOCTL_ERR(IEEE80211_IOCTL_RADAR),
114                                 IOCTL_ERR(IEEE80211_IOCTL_SETKEY),
115                                 IOCTL_ERR(IEEE80211_IOCTL_DELKEY),
116                                 IOCTL_ERR(IEEE80211_IOCTL_HALMAP),
117                                 IOCTL_ERR(IEEE80211_IOCTL_ADDMAC),
118                                 IOCTL_ERR(IEEE80211_IOCTL_DELMAC),
119                                 IOCTL_ERR(IEEE80211_IOCTL_WDSADDMAC),
120                                 IOCTL_ERR(IEEE80211_IOCTL_WDSDELMAC),
121                         };
122                         if (IEEE80211_IOCTL_SETPARAM <= op &&
123                             op <= IEEE80211_IOCTL_SETCHANLIST)
124                                 perror(opnames[op - SIOCIWFIRSTPRIV]);
125                         else
126                                 perror("ioctl[unknown???]");
127                 }
128                 return -1;
129         }
130         return 0;
131 }
132
133 static void
134 usage(void)
135 {
136         fprintf(stderr, "usage: %s [-i device] channels...\n", progname);
137         exit(-1);
138 }
139
140 #define MAXCHAN ((int)(sizeof(struct ieee80211req_chanlist) * NBBY))
141 int
142 main(int argc, char *argv[])
143 {
144         const char *ifname = "wifi0";
145         struct ieee80211req_chanlist chanlist;
146         int c;
147
148         progname = argv[0];
149         while ((c = getopt(argc, argv, "i:")) != -1)
150                 switch (c) {
151                 case 'i':
152                         ifname = optarg;
153                         break;
154                 default:
155                         usage();
156                         /*NOTREACHED*/
157                 }
158         argc -= optind;
159         argv += optind;
160         if (argc < 1)
161                 usage();
162
163         memset(&chanlist, 0, sizeof(chanlist));
164         for (; argc > 0; argc--, argv++) {
165                 int first, last, f;
166
167                 switch (sscanf(argv[0], "%u-%u", &first, &last)) {
168                 case 1:
169                         if (first > MAXCHAN)
170                                 errx(-1, "%s: channel %u out of range, max %u",
171                                         progname, first, MAXCHAN);
172                         setbit(chanlist.ic_channels, first);
173                         break;
174                 case 2:
175                         if (first > MAXCHAN)
176                                 errx(-1, "%s: channel %u out of range, max %u",
177                                         progname, first, MAXCHAN);
178                         if (last > MAXCHAN)
179                                 errx(-1, "%s: channel %u out of range, max %u",
180                                         progname, last, MAXCHAN);
181                         if (first > last)
182                                 errx(-1, "%s: void channel range, %u > %u",
183                                         progname, first, last);
184                         for (f = first; f <= last; f++)
185                                 setbit(chanlist.ic_channels, f);
186                         break;
187                 }
188         }
189         return set80211priv(ifname, IEEE80211_IOCTL_SETCHANLIST,
190                 &chanlist, sizeof(chanlist), 1);
191 }