btkey.c revision 1.2 1 1.2 lukem /* $NetBSD: btkey.c,v 1.2 2008/07/21 14:19:21 lukem Exp $ */
2 1.1 plunky
3 1.1 plunky /*-
4 1.1 plunky * Copyright (c) 2007 Iain Hibbert
5 1.1 plunky * All rights reserved.
6 1.1 plunky *
7 1.1 plunky * Redistribution and use in source and binary forms, with or without
8 1.1 plunky * modification, are permitted provided that the following conditions
9 1.1 plunky * are met:
10 1.1 plunky * 1. Redistributions of source code must retain the above copyright
11 1.1 plunky * notice, this list of conditions and the following disclaimer.
12 1.1 plunky * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 plunky * notice, this list of conditions and the following disclaimer in the
14 1.1 plunky * documentation and/or other materials provided with the distribution.
15 1.1 plunky * 3. The name of the author may not be used to endorse or promote products
16 1.1 plunky * derived from this software without specific prior written permission.
17 1.1 plunky *
18 1.1 plunky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 plunky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 plunky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 plunky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 plunky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 plunky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 plunky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 plunky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 plunky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.1 plunky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 plunky */
29 1.1 plunky
30 1.1 plunky #include <sys/cdefs.h>
31 1.2 lukem __COPYRIGHT("@(#) Copyright (c) 2007 Iain Hibbert. All rights reserved.");
32 1.2 lukem __RCSID("$NetBSD: btkey.c,v 1.2 2008/07/21 14:19:21 lukem Exp $");
33 1.1 plunky
34 1.1 plunky #include <bluetooth.h>
35 1.1 plunky #include <err.h>
36 1.1 plunky #include <errno.h>
37 1.1 plunky #include <stdbool.h>
38 1.1 plunky #include <stdlib.h>
39 1.1 plunky #include <string.h>
40 1.1 plunky #include <unistd.h>
41 1.1 plunky
42 1.1 plunky #include "btkey.h"
43 1.1 plunky
44 1.1 plunky static void usage(void);
45 1.1 plunky static bool scan_key(const char *);
46 1.1 plunky
47 1.1 plunky bdaddr_t laddr;
48 1.1 plunky bdaddr_t raddr;
49 1.1 plunky uint8_t key[HCI_KEY_SIZE];
50 1.1 plunky
51 1.1 plunky int
52 1.1 plunky main(int ac, char *av[])
53 1.1 plunky {
54 1.1 plunky struct hostent *he;
55 1.1 plunky int ch;
56 1.1 plunky bool cf, cd, lf, ld, rf, rd, wf, wd, nk;
57 1.1 plunky
58 1.1 plunky memset(&laddr, 0, sizeof(laddr));
59 1.1 plunky memset(&raddr, 0, sizeof(raddr));
60 1.1 plunky memset(key, 0, sizeof(key));
61 1.1 plunky cf = cd = lf = ld = rf = rd = wf = wd = nk = false;
62 1.1 plunky
63 1.1 plunky while ((ch = getopt(ac, av, "a:cCd:k:lLrRwW")) != EOF) {
64 1.1 plunky switch (ch) {
65 1.1 plunky case 'a': /* remote device address */
66 1.1 plunky if (!bt_aton(optarg, &raddr)) {
67 1.1 plunky he = bt_gethostbyname(optarg);
68 1.1 plunky if (he == NULL)
69 1.1 plunky errx(EXIT_FAILURE, "%s: %s",
70 1.1 plunky optarg, hstrerror(h_errno));
71 1.1 plunky
72 1.1 plunky bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
73 1.1 plunky }
74 1.1 plunky break;
75 1.1 plunky
76 1.1 plunky case 'c': /* clear from file */
77 1.1 plunky cf = true;
78 1.1 plunky break;
79 1.1 plunky
80 1.1 plunky case 'C': /* clear from device */
81 1.1 plunky cd = true;
82 1.1 plunky break;
83 1.1 plunky
84 1.1 plunky case 'd': /* local device address */
85 1.1 plunky if (!bt_devaddr(optarg, &laddr)
86 1.1 plunky && !bt_aton(optarg, &laddr)) {
87 1.1 plunky he = bt_gethostbyname(optarg);
88 1.1 plunky if (he == NULL)
89 1.1 plunky errx(EXIT_FAILURE, "%s: %s",
90 1.1 plunky optarg, hstrerror(h_errno));
91 1.1 plunky
92 1.1 plunky bdaddr_copy(&laddr, (bdaddr_t *)he->h_addr);
93 1.1 plunky }
94 1.1 plunky break;
95 1.1 plunky
96 1.1 plunky case 'k': /* new link key */
97 1.1 plunky if (!scan_key(optarg))
98 1.1 plunky errx(EXIT_FAILURE, "invalid key '%s'", optarg);
99 1.1 plunky
100 1.1 plunky nk = true;
101 1.1 plunky break;
102 1.1 plunky
103 1.1 plunky case 'l': /* list from file */
104 1.1 plunky lf = true;
105 1.1 plunky break;
106 1.1 plunky
107 1.1 plunky case 'L': /* list from device */
108 1.1 plunky ld = true;
109 1.1 plunky break;
110 1.1 plunky
111 1.1 plunky case 'r': /* read from file */
112 1.1 plunky rf = true;
113 1.1 plunky break;
114 1.1 plunky
115 1.1 plunky case 'R': /* read from device */
116 1.1 plunky rd = true;
117 1.1 plunky break;
118 1.1 plunky
119 1.1 plunky case 'w': /* write to file */
120 1.1 plunky wf = true;
121 1.1 plunky break;
122 1.1 plunky
123 1.1 plunky case 'W': /* write to device */
124 1.1 plunky wd = true;
125 1.1 plunky break;
126 1.1 plunky
127 1.1 plunky default:
128 1.1 plunky usage();
129 1.1 plunky }
130 1.1 plunky }
131 1.1 plunky
132 1.1 plunky ac -= optind;
133 1.1 plunky av += optind;
134 1.1 plunky
135 1.1 plunky /*
136 1.1 plunky * validate options
137 1.1 plunky */
138 1.1 plunky if ((lf || ld) && (rf || rd || wf || wd || cf || cd || nk))
139 1.1 plunky errx(EXIT_FAILURE, "list is exclusive of other options");
140 1.1 plunky
141 1.1 plunky if (((rf && rd) || (rf && nk) || (rd && nk)) && (wf || wd))
142 1.1 plunky errx(EXIT_FAILURE, "too many key sources");
143 1.1 plunky
144 1.1 plunky if (((bdaddr_any(&laddr) || bdaddr_any(&raddr)) && !(lf || ld))
145 1.1 plunky || ((lf || ld) && (bdaddr_any(&laddr) || !bdaddr_any(&raddr)))
146 1.1 plunky || ac > 0)
147 1.1 plunky usage();
148 1.1 plunky
149 1.1 plunky /*
150 1.1 plunky * do what we gotta do and be done
151 1.1 plunky */
152 1.1 plunky if (!bdaddr_any(&laddr))
153 1.1 plunky print_addr("device", &laddr);
154 1.1 plunky
155 1.1 plunky if (!bdaddr_any(&raddr))
156 1.1 plunky print_addr("bdaddr", &raddr);
157 1.1 plunky
158 1.1 plunky if (lf && !list_file())
159 1.1 plunky err(EXIT_FAILURE, "list file");
160 1.1 plunky
161 1.1 plunky if (ld && !list_device())
162 1.1 plunky err(EXIT_FAILURE, "list device");
163 1.1 plunky
164 1.1 plunky if (nk)
165 1.1 plunky print_key("new key", key);
166 1.1 plunky
167 1.1 plunky if (rf) {
168 1.1 plunky if (!read_file())
169 1.1 plunky err(EXIT_FAILURE, "file key");
170 1.1 plunky
171 1.1 plunky print_key("file key", key);
172 1.1 plunky }
173 1.1 plunky
174 1.1 plunky if (rd) {
175 1.1 plunky if (!read_device())
176 1.1 plunky err(EXIT_FAILURE, "device key");
177 1.1 plunky
178 1.1 plunky print_key("device key", key);
179 1.1 plunky }
180 1.1 plunky
181 1.1 plunky if (wf || wd || cf || cd)
182 1.1 plunky printf("\n");
183 1.1 plunky
184 1.1 plunky if (wf) {
185 1.1 plunky if (!write_file())
186 1.1 plunky err(EXIT_FAILURE, "write to file");
187 1.1 plunky
188 1.1 plunky printf("written to file\n");
189 1.1 plunky }
190 1.1 plunky
191 1.1 plunky if (wd) {
192 1.1 plunky if (!write_device())
193 1.1 plunky err(EXIT_FAILURE, "write to device");
194 1.1 plunky
195 1.1 plunky printf("written to device\n");
196 1.1 plunky }
197 1.1 plunky
198 1.1 plunky if (cf) {
199 1.1 plunky if (!clear_file())
200 1.1 plunky err(EXIT_FAILURE, "clear from file");
201 1.1 plunky
202 1.1 plunky printf("cleared from file\n");
203 1.1 plunky }
204 1.1 plunky
205 1.1 plunky if (cd) {
206 1.1 plunky if (!clear_device())
207 1.1 plunky err(EXIT_FAILURE, "clear from device");
208 1.1 plunky
209 1.1 plunky printf("cleared from device\n");
210 1.1 plunky }
211 1.1 plunky
212 1.1 plunky exit(EXIT_SUCCESS);
213 1.1 plunky }
214 1.1 plunky
215 1.1 plunky static void
216 1.1 plunky usage(void)
217 1.1 plunky {
218 1.1 plunky
219 1.1 plunky fprintf(stderr,
220 1.1 plunky "Usage: %s [-cCrRwW] [-k key] -a address -d device\n"
221 1.1 plunky " %s -lL -d device\n"
222 1.1 plunky "\n", getprogname(), getprogname());
223 1.1 plunky
224 1.1 plunky fprintf(stderr,
225 1.1 plunky "Where:\n"
226 1.1 plunky "\t-a address remote device address\n"
227 1.1 plunky "\t-c clear from file\n"
228 1.1 plunky "\t-C clear from device\n"
229 1.1 plunky "\t-d device local device address\n"
230 1.1 plunky "\t-k key user specified link_key\n"
231 1.1 plunky "\t-l list file keys\n"
232 1.1 plunky "\t-L list device keys\n"
233 1.1 plunky "\t-r read from file\n"
234 1.1 plunky "\t-R read from device\n"
235 1.1 plunky "\t-w write to file\n"
236 1.1 plunky "\t-W write to device\n"
237 1.1 plunky "\n");
238 1.1 plunky
239 1.1 plunky exit(EXIT_FAILURE);
240 1.1 plunky }
241 1.1 plunky
242 1.1 plunky static bool
243 1.1 plunky scan_key(const char *arg)
244 1.1 plunky {
245 1.1 plunky static const char digits[] = "0123456789abcdef";
246 1.1 plunky const char *p;
247 1.1 plunky int i, j;
248 1.1 plunky
249 1.1 plunky memset(key, 0, sizeof(key));
250 1.1 plunky
251 1.1 plunky for (i = 0 ; i < HCI_KEY_SIZE ; i++) {
252 1.1 plunky for (j = 0 ; j < 2 ; j++) {
253 1.1 plunky if (*arg == '\0')
254 1.1 plunky return true;
255 1.1 plunky
256 1.1 plunky for (p = digits ; *p != *arg ; p++)
257 1.1 plunky if (*p == '\0')
258 1.1 plunky return false;
259 1.1 plunky
260 1.1 plunky arg++;
261 1.1 plunky key[i] = (key[i] << 4) + (p - digits);
262 1.1 plunky }
263 1.1 plunky }
264 1.1 plunky
265 1.1 plunky if (*arg != '\0')
266 1.1 plunky return false;
267 1.1 plunky
268 1.1 plunky return true;
269 1.1 plunky }
270 1.1 plunky
271 1.1 plunky void
272 1.1 plunky print_key(const char *type, const uint8_t *src)
273 1.1 plunky {
274 1.1 plunky int i;
275 1.1 plunky
276 1.1 plunky printf("%10s: ", type);
277 1.1 plunky for (i = 0 ; i < HCI_KEY_SIZE ; i++)
278 1.1 plunky printf("%2.2x", src[i]);
279 1.1 plunky
280 1.1 plunky printf("\n");
281 1.1 plunky }
282 1.1 plunky
283 1.1 plunky
284 1.1 plunky void
285 1.1 plunky print_addr(const char *type, const bdaddr_t *addr)
286 1.1 plunky {
287 1.1 plunky char name[HCI_DEVNAME_SIZE];
288 1.1 plunky struct hostent *he;
289 1.1 plunky
290 1.1 plunky printf("%10s: %s", type, bt_ntoa(addr, NULL));
291 1.1 plunky
292 1.1 plunky if (bt_devname(name, addr))
293 1.1 plunky printf(" (%s)", name);
294 1.1 plunky else if ((he = bt_gethostbyaddr((const char *)addr,
295 1.1 plunky sizeof(bdaddr_t), AF_BLUETOOTH)) != NULL)
296 1.1 plunky printf(" (%s)", he->h_name);
297 1.1 plunky
298 1.1 plunky printf("\n");
299 1.1 plunky }
300