dhcpcd: update README.DRAGONFLY
[dragonfly.git] / usr.sbin / bthcid / parser.y
blobacb43456d9551f1077da4e7bebd2f02ac8a417d5
1 %{
2 /*
3 * parser.y
5 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $
30 * $FreeBSD: src/usr.sbin/bluetooth/hcsecd/parser.y,v 1.4 2004/09/14 20:04:33 emax Exp $
33 #include <sys/fcntl.h>
34 #include <sys/queue.h>
35 #include <bluetooth.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <syslog.h>
43 #include <unistd.h>
44 #include "bthcid.h"
46 #if YYPATCH < 20180510
47 int yylex (void);
48 #endif
50 static void free_key (link_key_p key);
51 static int hexa2int4(char *a);
52 static int hexa2int8(char *a);
54 extern void yyerror(const char *);
55 extern int yylineno;
56 extern FILE *yyin;
58 static LIST_HEAD(, link_key) link_keys;
60 const char *config_file = "/etc/bluetooth/bthcid.conf";
61 static link_key_p key = NULL;
64 %union {
65 char *string;
68 %token <string> T_BDADDRSTRING T_HEXSTRING T_STRING
69 %token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK
73 config: line
74 | config line
77 line: T_DEVICE
79 key = (link_key_p) malloc(sizeof(*key));
80 if (key == NULL) {
81 syslog(LOG_ERR, "Could not allocate new " \
82 "config entry");
83 exit(1);
86 memset(key, 0, sizeof(*key));
88 '{' options '}'
90 if (get_key(&key->bdaddr, 1) != NULL) {
91 syslog(LOG_ERR, "Ignoring duplicated entry " \
92 "for bdaddr %s",
93 bt_ntoa(&key->bdaddr, NULL));
94 free_key(key);
95 } else
96 LIST_INSERT_HEAD(&link_keys, key, next);
98 key = NULL;
102 options: option ';'
103 | options option ';'
106 option: bdaddr
107 | name
108 | key
109 | pin
112 bdaddr: T_BDADDR T_BDADDRSTRING
114 if (!bt_aton($2, &key->bdaddr)) {
115 syslog(LOG_ERR, "Could not parse BD_ADDR " \
116 "'%s'", $2);
117 exit(1);
122 name: T_NAME T_STRING
124 if (key->name != NULL)
125 free(key->name);
127 key->name = strdup($2);
128 if (key->name == NULL) {
129 syslog(LOG_ERR, "Could not allocate new " \
130 "device name");
131 exit(1);
136 key: T_KEY T_HEXSTRING
138 int i, len;
140 if (key->key != NULL)
141 free(key->key);
143 key->key = (uint8_t *) malloc(HCI_KEY_SIZE);
144 if (key->key == NULL) {
145 syslog(LOG_ERR, "Could not allocate new " \
146 "link key");
147 exit(1);
150 memset(key->key, 0, HCI_KEY_SIZE);
152 len = strlen($2) / 2;
153 if (len > HCI_KEY_SIZE)
154 len = HCI_KEY_SIZE;
156 for (i = 0; i < len; i ++)
157 key->key[i] = hexa2int8((char *)($2) + 2*i);
159 | T_KEY T_NOKEY
161 if (key->key != NULL)
162 free(key->key);
164 key->key = NULL;
168 pin: T_PIN T_STRING
170 if (key->pin != NULL)
171 free(key->pin);
173 key->pin = strdup($2);
174 if (key->pin == NULL) {
175 syslog(LOG_ERR, "Could not allocate new " \
176 "PIN code");
177 exit(1);
180 | T_PIN T_NOPIN
182 if (key->pin != NULL)
183 free(key->pin);
185 key->pin = NULL;
191 /* Display parser error message */
192 void
193 yyerror(char const *message)
195 syslog(LOG_ERR, "%s in line %d", message, yylineno);
198 /* Re-read config file */
199 void
200 read_config_file(void)
202 if (config_file == NULL) {
203 syslog(LOG_ERR, "Unknown config file name!");
204 exit(1);
207 if ((yyin = fopen(config_file, "r")) == NULL) {
208 syslog(LOG_ERR, "Could not open config file '%s'. %s (%d)",
209 config_file, strerror(errno), errno);
210 exit(1);
213 clean_config();
214 if (yyparse() < 0) {
215 syslog(LOG_ERR, "Could not parse config file '%s'",config_file);
216 exit(1);
219 fclose(yyin);
220 yyin = NULL;
222 #ifdef __config_debug__
223 dump_config();
224 #endif
227 /* Clean config */
228 void
229 clean_config(void)
231 link_key_p lkey = NULL;
233 while ((lkey = LIST_FIRST(&link_keys)) != NULL) {
234 LIST_REMOVE(lkey, next);
235 free_key(lkey);
239 /* Find link key entry in the list. Return exact or default match */
240 link_key_p
241 get_key(bdaddr_p bdaddr, int exact_match)
243 link_key_p lkey = NULL, defkey = NULL;
245 LIST_FOREACH(lkey, &link_keys, next) {
246 if (memcmp(bdaddr, &lkey->bdaddr, sizeof(lkey->bdaddr)) == 0)
247 break;
249 if (!exact_match)
250 if (memcmp(BDADDR_ANY, &lkey->bdaddr,
251 sizeof(lkey->bdaddr)) == 0)
252 defkey = lkey;
255 return ((lkey != NULL)? lkey : defkey);
258 #ifdef __config_debug__
259 /* Dump config */
260 void
261 dump_config(void)
263 link_key_p lkey = NULL;
264 char buffer[64];
266 LIST_FOREACH(lkey, &link_keys, next) {
267 if (lkey->key != NULL)
268 snprintf(buffer, sizeof(buffer),
269 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
270 lkey->key[0], lkey->key[1], lkey->key[2],
271 lkey->key[3], lkey->key[4], lkey->key[5],
272 lkey->key[6], lkey->key[7], lkey->key[8],
273 lkey->key[9], lkey->key[10], lkey->key[11],
274 lkey->key[12], lkey->key[13], lkey->key[14],
275 lkey->key[15]);
277 syslog(LOG_DEBUG,
278 "device %s " \
279 "bdaddr %s " \
280 "pin %s " \
281 "key %s",
282 (lkey->name != NULL)? lkey->name : "noname",
283 bt_ntoa(&lkey->bdaddr, NULL),
284 (lkey->pin != NULL)? lkey->pin : "nopin",
285 (lkey->key != NULL)? buffer : "nokey");
288 #endif
290 /* Read keys file */
292 read_keys_file(void)
294 FILE *f = NULL;
295 link_key_t *lkey = NULL;
296 char buf[BTHCID_BUFFER_SIZE], *p = NULL, *cp = NULL;
297 bdaddr_t bdaddr;
298 int i, len;
300 if ((f = fopen(BTHCID_KEYSFILE, "r")) == NULL) {
301 if (errno == ENOENT)
302 return (0);
304 syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n",
305 BTHCID_KEYSFILE, strerror(errno), errno);
307 return (-1);
310 while ((p = fgets(buf, sizeof(buf), f)) != NULL) {
311 if (*p == '#')
312 continue;
313 if ((cp = strpbrk(p, " ")) == NULL)
314 continue;
316 *cp++ = '\0';
318 if (!bt_aton(p, &bdaddr))
319 continue;
321 if ((lkey = get_key(&bdaddr, 1)) == NULL)
322 continue;
324 if (lkey->key == NULL) {
325 lkey->key = (uint8_t *) malloc(HCI_KEY_SIZE);
326 if (lkey->key == NULL) {
327 syslog(LOG_ERR, "Could not allocate link key");
328 exit(1);
332 memset(lkey->key, 0, HCI_KEY_SIZE);
334 len = strlen(cp) / 2;
335 if (len > HCI_KEY_SIZE)
336 len = HCI_KEY_SIZE;
338 for (i = 0; i < len; i ++)
339 lkey->key[i] = hexa2int8(cp + 2*i);
341 syslog(LOG_DEBUG, "Restored link key for the entry, " \
342 "remote bdaddr %s, name '%s'",
343 bt_ntoa(&lkey->bdaddr, NULL),
344 (lkey->name != NULL)? lkey->name : "No name");
347 fclose(f);
349 return (0);
352 /* Dump keys file */
354 dump_keys_file(void)
356 link_key_p lkey = NULL;
357 char tmp[PATH_MAX], buf[BTHCID_BUFFER_SIZE];
358 int f;
360 snprintf(tmp, sizeof(tmp), "%s.tmp", BTHCID_KEYSFILE);
361 if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) {
362 syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n",
363 tmp, strerror(errno), errno);
364 return (-1);
367 LIST_FOREACH(lkey, &link_keys, next) {
368 if (lkey->key == NULL)
369 continue;
371 snprintf(buf, sizeof(buf),
372 "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
373 bt_ntoa(&lkey->bdaddr, NULL),
374 lkey->key[0], lkey->key[1], lkey->key[2], lkey->key[3],
375 lkey->key[4], lkey->key[5], lkey->key[6], lkey->key[7],
376 lkey->key[8], lkey->key[9], lkey->key[10], lkey->key[11],
377 lkey->key[12], lkey->key[13], lkey->key[14], lkey->key[15]);
379 if (write(f, buf, strlen(buf)) < 0) {
380 syslog(LOG_ERR, "Could not write temp keys file. " \
381 "%s (%d)\n", strerror(errno), errno);
382 break;
386 close(f);
388 if (rename(tmp, BTHCID_KEYSFILE) < 0) {
389 syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n",
390 tmp, BTHCID_KEYSFILE, strerror(errno), errno);
391 unlink(tmp);
392 return (-1);
395 return (0);
398 /* Free key entry */
399 static void
400 free_key(link_key_p lkey)
402 if (lkey->name != NULL)
403 free(lkey->name);
404 if (lkey->key != NULL)
405 free(lkey->key);
406 if (lkey->pin != NULL)
407 free(lkey->pin);
409 memset(lkey, 0, sizeof(*lkey));
410 free(lkey);
413 /* Convert hex ASCII to int4 */
414 static int
415 hexa2int4(char *a)
417 if ('0' <= *a && *a <= '9')
418 return (*a - '0');
420 if ('A' <= *a && *a <= 'F')
421 return (*a - 'A' + 0xa);
423 if ('a' <= *a && *a <= 'f')
424 return (*a - 'a' + 0xa);
426 syslog(LOG_ERR, "Invalid hex character: '%c' (%#x)", *a, *a);
427 exit(1);
430 /* Convert hex ASCII to int8 */
431 static int
432 hexa2int8(char *a)
434 return ((hexa2int4(a) << 4) | hexa2int4(a + 1));