btkey.c revision 1.1 1 1.1 plunky /* $NetBSD: btkey.c,v 1.1 2007/11/09 21:18:25 plunky 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.1 plunky __COPYRIGHT("@(#) Copyright (c) 2007 Iain Hibbert\n"
32 1.1 plunky "All rights reserved.\n");
33 1.1 plunky __RCSID("$NetBSD: btkey.c,v 1.1 2007/11/09 21:18:25 plunky Exp $");
34 1.1 plunky
35 1.1 plunky #include <bluetooth.h>
36 1.1 plunky #include <err.h>
37 1.1 plunky #include <errno.h>
38 1.1 plunky #include <stdbool.h>
39 1.1 plunky #include <stdlib.h>
40 1.1 plunky #include <string.h>
41 1.1 plunky #include <unistd.h>
42 1.1 plunky
43 1.1 plunky #include "btkey.h"
44 1.1 plunky
45 1.1 plunky static void usage(void);
46 1.1 plunky static bool scan_key(const char *);
47 1.1 plunky
48 1.1 plunky bdaddr_t laddr;
49 1.1 plunky bdaddr_t raddr;
50 1.1 plunky uint8_t key[HCI_KEY_SIZE];
51 1.1 plunky
52 1.1 plunky int
53 1.1 plunky main(int ac, char *av[])
54 1.1 plunky {
55 1.1 plunky struct hostent *he;
56 1.1 plunky int ch;
57 1.1 plunky bool cf, cd, lf, ld, rf, rd, wf, wd, nk;
58 1.1 plunky
59 1.1 plunky memset(&laddr, 0, sizeof(laddr));
60 1.1 plunky memset(&raddr, 0, sizeof(raddr));
61 1.1 plunky memset(key, 0, sizeof(key));
62 1.1 plunky cf = cd = lf = ld = rf = rd = wf = wd = nk = false;
63 1.1 plunky
64 1.1 plunky while ((ch = getopt(ac, av, "a:cCd:k:lLrRwW")) != EOF) {
65 1.1 plunky switch (ch) {
66 1.1 plunky case 'a': /* remote device address */
67 1.1 plunky if (!bt_aton(optarg, &raddr)) {
68 1.1 plunky he = bt_gethostbyname(optarg);
69 1.1 plunky if (he == NULL)
70 1.1 plunky errx(EXIT_FAILURE, "%s: %s",
71 1.1 plunky optarg, hstrerror(h_errno));
72 1.1 plunky
73 1.1 plunky bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
74 1.1 plunky }
75 1.1 plunky break;
76 1.1 plunky
77 1.1 plunky case 'c': /* clear from file */
78 1.1 plunky cf = true;
79 1.1 plunky break;
80 1.1 plunky
81 1.1 plunky case 'C': /* clear from device */
82 1.1 plunky cd = true;
83 1.1 plunky break;
84 1.1 plunky
85 1.1 plunky case 'd': /* local device address */
86 1.1 plunky if (!bt_devaddr(optarg, &laddr)
87 1.1 plunky && !bt_aton(optarg, &laddr)) {
88 1.1 plunky he = bt_gethostbyname(optarg);
89 1.1 plunky if (he == NULL)
90 1.1 plunky errx(EXIT_FAILURE, "%s: %s",
91 1.1 plunky optarg, hstrerror(h_errno));
92 1.1 plunky
93 1.1 plunky bdaddr_copy(&laddr, (bdaddr_t *)he->h_addr);
94 1.1 plunky }
95 1.1 plunky break;
96 1.1 plunky
97 1.1 plunky case 'k': /* new link key */
98 1.1 plunky if (!scan_key(optarg))
99 1.1 plunky errx(EXIT_FAILURE, "invalid key '%s'", optarg);
100 1.1 plunky
101 1.1 plunky nk = true;
102 1.1 plunky break;
103 1.1 plunky
104 1.1 plunky case 'l': /* list from file */
105 1.1 plunky lf = true;
106 1.1 plunky break;
107 1.1 plunky
108 1.1 plunky case 'L': /* list from device */
109 1.1 plunky ld = true;
110 1.1 plunky break;
111 1.1 plunky
112 1.1 plunky case 'r': /* read from file */
113 1.1 plunky rf = true;
114 1.1 plunky break;
115 1.1 plunky
116 1.1 plunky case 'R': /* read from device */
117 1.1 plunky rd = true;
118 1.1 plunky break;
119 1.1 plunky
120 1.1 plunky case 'w': /* write to file */
121 1.1 plunky wf = true;
122 1.1 plunky break;
123 1.1 plunky
124 1.1 plunky case 'W': /* write to device */
125 1.1 plunky wd = true;
126 1.1 plunky break;
127 1.1 plunky
128 1.1 plunky default:
129 1.1 plunky usage();
130 1.1 plunky }
131 1.1 plunky }
132 1.1 plunky
133 1.1 plunky ac -= optind;
134 1.1 plunky av += optind;
135 1.1 plunky
136 1.1 plunky /*
137 1.1 plunky * validate options
138 1.1 plunky */
139 1.1 plunky if ((lf || ld) && (rf || rd || wf || wd || cf || cd || nk))
140 1.1 plunky errx(EXIT_FAILURE, "list is exclusive of other options");
141 1.1 plunky
142 1.1 plunky if (((rf && rd) || (rf && nk) || (rd && nk)) && (wf || wd))
143 1.1 plunky errx(EXIT_FAILURE, "too many key sources");
144 1.1 plunky
145 1.1 plunky if (((bdaddr_any(&laddr) || bdaddr_any(&raddr)) && !(lf || ld))
146 1.1 plunky || ((lf || ld) && (bdaddr_any(&laddr) || !bdaddr_any(&raddr)))
147 1.1 plunky || ac > 0)
148 1.1 plunky usage();
149 1.1 plunky
150 1.1 plunky /*
151 1.1 plunky * do what we gotta do and be done
152 1.1 plunky */
153 1.1 plunky if (!bdaddr_any(&laddr))
154 1.1 plunky print_addr("device", &laddr);
155 1.1 plunky
156 1.1 plunky if (!bdaddr_any(&raddr))
157 1.1 plunky print_addr("bdaddr", &raddr);
158 1.1 plunky
159 1.1 plunky if (lf && !list_file())
160 1.1 plunky err(EXIT_FAILURE, "list file");
161 1.1 plunky
162 1.1 plunky if (ld && !list_device())
163 1.1 plunky err(EXIT_FAILURE, "list device");
164 1.1 plunky
165 1.1 plunky if (nk)
166 1.1 plunky print_key("new key", key);
167 1.1 plunky
168 1.1 plunky if (rf) {
169 1.1 plunky if (!read_file())
170 1.1 plunky err(EXIT_FAILURE, "file key");
171 1.1 plunky
172 1.1 plunky print_key("file key", key);
173 1.1 plunky }
174 1.1 plunky
175 1.1 plunky if (rd) {
176 1.1 plunky if (!read_device())
177 1.1 plunky err(EXIT_FAILURE, "device key");
178 1.1 plunky
179 1.1 plunky print_key("device key", key);
180 1.1 plunky }
181 1.1 plunky
182 1.1 plunky if (wf || wd || cf || cd)
183 1.1 plunky printf("\n");
184 1.1 plunky
185 1.1 plunky if (wf) {
186 1.1 plunky if (!write_file())
187 1.1 plunky err(EXIT_FAILURE, "write to file");
188 1.1 plunky
189 1.1 plunky printf("written to file\n");
190 1.1 plunky }
191 1.1 plunky
192 1.1 plunky if (wd) {
193 1.1 plunky if (!write_device())
194 1.1 plunky err(EXIT_FAILURE, "write to device");
195 1.1 plunky
196 1.1 plunky printf("written to device\n");
197 1.1 plunky }
198 1.1 plunky
199 1.1 plunky if (cf) {
200 1.1 plunky if (!clear_file())
201 1.1 plunky err(EXIT_FAILURE, "clear from file");
202 1.1 plunky
203 1.1 plunky printf("cleared from file\n");
204 1.1 plunky }
205 1.1 plunky
206 1.1 plunky if (cd) {
207 1.1 plunky if (!clear_device())
208 1.1 plunky err(EXIT_FAILURE, "clear from device");
209 1.1 plunky
210 1.1 plunky printf("cleared from device\n");
211 1.1 plunky }
212 1.1 plunky
213 1.1 plunky exit(EXIT_SUCCESS);
214 1.1 plunky }
215 1.1 plunky
216 1.1 plunky static void
217 1.1 plunky usage(void)
218 1.1 plunky {
219 1.1 plunky
220 1.1 plunky fprintf(stderr,
221 1.1 plunky "Usage: %s [-cCrRwW] [-k key] -a address -d device\n"
222 1.1 plunky " %s -lL -d device\n"
223 1.1 plunky "\n", getprogname(), getprogname());
224 1.1 plunky
225 1.1 plunky fprintf(stderr,
226 1.1 plunky "Where:\n"
227 1.1 plunky "\t-a address remote device address\n"
228 1.1 plunky "\t-c clear from file\n"
229 1.1 plunky "\t-C clear from device\n"
230 1.1 plunky "\t-d device local device address\n"
231 1.1 plunky "\t-k key user specified link_key\n"
232 1.1 plunky "\t-l list file keys\n"
233 1.1 plunky "\t-L list device keys\n"
234 1.1 plunky "\t-r read from file\n"
235 1.1 plunky "\t-R read from device\n"
236 1.1 plunky "\t-w write to file\n"
237 1.1 plunky "\t-W write to device\n"
238 1.1 plunky "\n");
239 1.1 plunky
240 1.1 plunky exit(EXIT_FAILURE);
241 1.1 plunky }
242 1.1 plunky
243 1.1 plunky static bool
244 1.1 plunky scan_key(const char *arg)
245 1.1 plunky {
246 1.1 plunky static const char digits[] = "0123456789abcdef";
247 1.1 plunky const char *p;
248 1.1 plunky int i, j;
249 1.1 plunky
250 1.1 plunky memset(key, 0, sizeof(key));
251 1.1 plunky
252 1.1 plunky for (i = 0 ; i < HCI_KEY_SIZE ; i++) {
253 1.1 plunky for (j = 0 ; j < 2 ; j++) {
254 1.1 plunky if (*arg == '\0')
255 1.1 plunky return true;
256 1.1 plunky
257 1.1 plunky for (p = digits ; *p != *arg ; p++)
258 1.1 plunky if (*p == '\0')
259 1.1 plunky return false;
260 1.1 plunky
261 1.1 plunky arg++;
262 1.1 plunky key[i] = (key[i] << 4) + (p - digits);
263 1.1 plunky }
264 1.1 plunky }
265 1.1 plunky
266 1.1 plunky if (*arg != '\0')
267 1.1 plunky return false;
268 1.1 plunky
269 1.1 plunky return true;
270 1.1 plunky }
271 1.1 plunky
272 1.1 plunky void
273 1.1 plunky print_key(const char *type, const uint8_t *src)
274 1.1 plunky {
275 1.1 plunky int i;
276 1.1 plunky
277 1.1 plunky printf("%10s: ", type);
278 1.1 plunky for (i = 0 ; i < HCI_KEY_SIZE ; i++)
279 1.1 plunky printf("%2.2x", src[i]);
280 1.1 plunky
281 1.1 plunky printf("\n");
282 1.1 plunky }
283 1.1 plunky
284 1.1 plunky
285 1.1 plunky void
286 1.1 plunky print_addr(const char *type, const bdaddr_t *addr)
287 1.1 plunky {
288 1.1 plunky char name[HCI_DEVNAME_SIZE];
289 1.1 plunky struct hostent *he;
290 1.1 plunky
291 1.1 plunky printf("%10s: %s", type, bt_ntoa(addr, NULL));
292 1.1 plunky
293 1.1 plunky if (bt_devname(name, addr))
294 1.1 plunky printf(" (%s)", name);
295 1.1 plunky else if ((he = bt_gethostbyaddr((const char *)addr,
296 1.1 plunky sizeof(bdaddr_t), AF_BLUETOOTH)) != NULL)
297 1.1 plunky printf(" (%s)", he->h_name);
298 1.1 plunky
299 1.1 plunky printf("\n");
300 1.1 plunky }
301