vfs: check userland buffers before reading them.
[haiku.git] / src / bin / network / setwep / setwep.c
blob728b9c2d5d550daf44d2be402dd700b492da1390
1 /*
3 * Copyright 2010 Haiku Inc. All rights reserved.
4 * Distributed under the terms of the MIT License.
6 * Many parts
8 * Copyright 2001 The Aerospace Corporation.
9 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
10 * All rights reserved.
11 * Distributed under the terms of the 2-clause BSD license.
13 * Authors:
14 * Alex Botero-Lowry, alex.boterolowry@gmail.com
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <strings.h>
21 #include <string.h>
23 #include <sys/ioctl.h>
24 #include <sys/kernel.h>
25 #include <sys/sockio.h>
26 #include <sys/types.h>
27 #include <sys/socket.h>
29 #include <net/if.h>
31 #include <net80211/ieee80211_ioctl.h>
32 #include <net80211/ieee80211_haiku.h>
35 extern const char* __progname;
38 static const char*
39 get_string(const char* val, const char* sep, u_int8_t* buf, int* lenp)
41 int len;
42 int hexstr;
43 u_int8_t* p;
45 len = *lenp;
46 p = buf;
47 hexstr = (val[0] == '0' && tolower((u_char) val[1]) == 'x');
48 if (hexstr)
49 val += 2;
50 for (;;) {
51 if (*val == '\0')
52 break;
53 if (sep != NULL && strchr(sep, *val) != NULL) {
54 val++;
55 break;
57 if (hexstr) {
58 if (!isxdigit((u_char) val[0])) {
59 printf("%s: bad hexadecimal digits", __func__);
60 return NULL;
62 if (!isxdigit((u_char) val[1])) {
63 printf("%s: odd count hexadecimal digits", __func__);
64 return NULL;
67 if (p >= buf + len) {
68 if (hexstr)
69 printf("%s: hexadecimal digits too long", __func__);
70 else
71 printf("%s: string too long", __func__);
72 return NULL;
74 if (hexstr) {
75 #define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
76 *p++ = (tohex((u_char) val[0]) << 4)
77 | tohex((u_char) val[1]);
78 #undef tohex
79 val += 2;
80 } else
81 *p++ = *val++;
83 len = p - buf;
84 /* The string "-" is treated as the empty string. */
85 if (!hexstr && len == 1 && buf[0] == '-') {
86 len = 0;
87 memset(buf, 0, *lenp);
88 } else if (len < *lenp)
89 memset(p, 0, *lenp - len);
91 *lenp = len;
92 return val;
96 static void
97 set80211(int s, const char* dev, int type, int val, int len, void* data)
99 struct ieee80211req ireq;
101 (void)memset(&ireq, 0, sizeof(ireq));
102 (void)strncpy(ireq.i_name, dev, sizeof(ireq.i_name));
103 ireq.i_type = type;
104 ireq.i_val = val;
105 ireq.i_len = len;
106 ireq.i_data = data;
107 if (ioctl(s, SIOCS80211, &ireq, sizeof(struct ieee80211req)) < 0) {
108 fprintf(stderr, "%s: error in handling SIOCS80211 (type %d): %s\n",
109 __progname, type, strerror(errno));
114 static void
115 set80211ssid(const char* dev, const char* val, int s)
117 int ssid;
118 int len;
119 u_int8_t data[IEEE80211_NWID_LEN];
121 ssid = 0;
122 len = strlen(val);
123 if (len > 2 && isdigit((int)val[0]) && val[1] == ':') {
124 ssid = atoi(val) - 1;
125 val += 2;
127 bzero(data, sizeof(data));
128 len = sizeof(data);
129 if (get_string(val, NULL, data, &len) == NULL)
130 exit(1);
132 set80211(s, dev, IEEE80211_IOC_SSID, ssid, len, data);
136 static void
137 set80211nwkey(const char* dev, const char* val, int s)
139 int txkey;
140 int i;
141 int len;
142 u_int8_t data[IEEE80211_KEYBUF_SIZE];
144 set80211(s, dev, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
146 if (isdigit((int)val[0]) && val[1] == ':') {
147 txkey = val[0] - '0' - 1;
148 val += 2;
150 for (i = 0; i < 4; i++) {
151 bzero(data, sizeof(data));
152 len = sizeof(data);
153 val = get_string(val, ",", data, &len);
154 if (val == NULL)
155 exit(1);
157 set80211(s, dev, IEEE80211_IOC_WEPKEY, i, len, data);
159 } else {
160 bzero(data, sizeof(data));
161 len = sizeof(data);
162 get_string(val, NULL, data, &len);
163 txkey = 0;
165 set80211(s, dev, IEEE80211_IOC_WEPKEY, 0, len, data);
167 bzero(data, sizeof(data));
168 for (i = 1; i < 4; i++)
169 set80211(s, dev, IEEE80211_IOC_WEPKEY, i, 0, data);
172 set80211(s, dev, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
176 static int
177 get80211val(int s, const char* dev, int type, int* val)
179 struct ieee80211req ireq;
181 (void) memset(&ireq, 0, sizeof(ireq));
182 (void) strncpy(ireq.i_name, dev, sizeof(ireq.i_name));
183 ireq.i_type = type;
184 if (ioctl(s, SIOCG80211, &ireq) < 0)
185 return -1;
186 *val = ireq.i_val;
187 return 0;
191 static int
192 getid(int s, const char* dev, int ix, void* data, size_t len, int* plen,
193 int mesh)
195 struct ieee80211req ireq;
197 (void)memset(&ireq, 0, sizeof(ireq));
198 (void)strncpy(ireq.i_name, dev, sizeof(ireq.i_name));
199 ireq.i_type = (!mesh) ? IEEE80211_IOC_SSID : IEEE80211_IOC_MESH_ID;
200 ireq.i_val = ix;
201 ireq.i_data = data;
202 ireq.i_len = len;
203 if (ioctl(s, SIOCG80211, &ireq) < 0)
204 return -1;
205 *plen = ireq.i_len;
206 return 0;
210 static void
211 print_string(const u_int8_t* buf, int len)
213 int i;
214 int hasspc;
216 i = 0;
217 hasspc = 0;
218 for (; i < len; i++) {
219 if (!isprint(buf[i]) && buf[i] != '\0')
220 break;
221 if (isspace(buf[i]))
222 hasspc++;
224 if (i == len) {
225 if (hasspc || len == 0 || buf[0] == '\0')
226 printf("\"%.*s\"", len, buf);
227 else
228 printf("%.*s", len, buf);
229 } else {
230 printf("0x");
231 for (i = 0; i < len; i++)
232 printf("%02x", buf[i]);
237 static void
238 show_status(const char* dev, int s)
240 int len;
241 int i;
242 int num;
243 uint8_t data[32];
245 if (getid(s, dev, -1, data, sizeof(data), &len, 0) < 0) {
246 fprintf(stderr, "error: not a wifi device\n");
247 exit(1);
250 if (get80211val(s, dev, IEEE80211_IOC_NUMSSIDS, &num) < 0)
251 num = 0;
252 printf("ssid ");
253 if (num > 1) {
254 for (i = 0; i < num; i++) {
255 if (getid(s, dev, i, data, sizeof(data), &len, 0) >= 0
256 && len > 0) {
257 printf(" %d:", i + 1);
258 print_string(data, len);
261 } else
262 print_string(data, len);
264 printf("\n");
268 static void
269 usage()
271 fprintf(stderr, "usage: setwep device_path [ssid] [key]\n");
272 exit(1);
277 main(int argc, char** argv)
279 int s = socket(AF_INET, SOCK_DGRAM, 0);
281 if (argc < 2)
282 usage();
284 if (argc == 2)
285 show_status(argv[1], s);
287 if (argc > 3)
288 set80211ssid(argv[1], argv[2], s);
290 if (argc == 4)
291 set80211nwkey(argv[1], argv[3], s);
293 return 0;