1 %{ 2 /* 3 * parser.y 4 * 5 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 6 * All rights reserved. 7 * 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. 16 * 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. 28 * 29 * $Id: parser.y,v 1.1 2002/11/24 20:22:39 max Exp $ 30 * $FreeBSD$ 31 */ 32 33 #include <sys/types.h> 34 #include <sys/queue.h> 35 #include <errno.h> 36 #include <ng_hci.h> 37 #include <stdio.h> 38 #include <stdarg.h> 39 #include <string.h> 40 #include <syslog.h> 41 #include "hcsecd.h" 42 43 int yyparse (void); 44 int yylex (void); 45 46 static void free_key (link_key_p key); 47 static int hexa2int4(char *a); 48 static int hexa2int8(char *a); 49 50 extern int yylineno; 51 static LIST_HEAD(, link_key) link_keys; 52 char *config_file = "/usr/local/etc/hcsecd.conf"; 53 54 static link_key_p key = NULL; 55 %} 56 57 %union { 58 char *string; 59 } 60 61 %token <string> T_BDADDRSTRING T_HEXSTRING T_STRING 62 %token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK 63 64 %% 65 66 config: line 67 | config line 68 ; 69 70 line: T_DEVICE 71 { 72 key = (link_key_p) malloc(sizeof(*key)); 73 if (key == NULL) { 74 syslog(LOG_ERR, "Could not allocate new " \ 75 "config entry"); 76 exit(1); 77 } 78 79 memset(key, 0, sizeof(*key)); 80 } 81 '{' options '}' 82 { 83 if (get_key(&key->bdaddr, 1) != NULL) { 84 syslog(LOG_ERR, "Ignoring duplicated entry " \ 85 "for bdaddr %x:%x:%x:%x:%x:%x", 86 key->bdaddr.b[5], 87 key->bdaddr.b[4], 88 key->bdaddr.b[3], 89 key->bdaddr.b[2], 90 key->bdaddr.b[1], 91 key->bdaddr.b[0]); 92 free_key(key); 93 } else 94 LIST_INSERT_HEAD(&link_keys, key, next); 95 96 key = NULL; 97 } 98 ; 99 100 options: option ';' 101 | options option ';' 102 ; 103 104 option: bdaddr 105 | name 106 | key 107 | pin 108 ; 109 110 bdaddr: T_BDADDR T_BDADDRSTRING 111 { 112 int a0, a1, a2, a3, a4, a5; 113 114 if (sscanf($2, "%x:%x:%x:%x:%x:%x", 115 &a5, &a4, &a3, &a2, &a1, &a0) != 6) { 116 syslog(LOG_ERR, "Cound not parse BDADDR " \ 117 "'%s'", $2); 118 exit(1); 119 } 120 121 key->bdaddr.b[0] = (a0 & 0xff); 122 key->bdaddr.b[1] = (a1 & 0xff); 123 key->bdaddr.b[2] = (a2 & 0xff); 124 key->bdaddr.b[3] = (a3 & 0xff); 125 key->bdaddr.b[4] = (a4 & 0xff); 126 key->bdaddr.b[5] = (a5 & 0xff); 127 } 128 ; 129 130 name: T_NAME T_STRING 131 { 132 if (key->name != NULL) 133 free(key->name); 134 135 key->name = strdup($2); 136 if (key->name == NULL) { 137 syslog(LOG_ERR, "Could not allocate new " \ 138 "device name"); 139 exit(1); 140 } 141 } 142 ; 143 144 key: T_KEY T_HEXSTRING 145 { 146 int i, len; 147 148 if (key->key != NULL) 149 free(key->key); 150 151 key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); 152 if (key->key == NULL) { 153 syslog(LOG_ERR, "Could not allocate new " \ 154 "link key"); 155 exit(1); 156 } 157 158 memset(key->key, 0, NG_HCI_KEY_SIZE); 159 160 len = strlen($2) / 2; 161 if (len > NG_HCI_KEY_SIZE) 162 len = NG_HCI_KEY_SIZE; 163 164 for (i = 0; i < len; i ++) 165 key->key[i] = hexa2int8((char *)($2) + 2*i); 166 } 167 | T_KEY T_NOKEY 168 { 169 if (key->key != NULL) 170 free(key->key); 171 172 key->key = NULL; 173 } 174 ; 175 176 pin: T_PIN T_STRING 177 { 178 if (key->pin != NULL) 179 free(key->pin); 180 181 key->pin = strdup($2); 182 if (key->pin == NULL) { 183 syslog(LOG_ERR, "Could not allocate new " \ 184 "PIN code"); 185 exit(1); 186 } 187 } 188 | T_PIN T_NOPIN 189 { 190 if (key->pin != NULL) 191 free(key->pin); 192 193 key->pin = NULL; 194 } 195 ; 196 197 %% 198 199 /* Display parser error message */ 200 void 201 yyerror(char const *message) 202 { 203 syslog(LOG_ERR, "%s in line %d", message, yylineno); 204 } 205 206 /* Re-read config file */ 207 void 208 read_config_file(int s) 209 { 210 extern FILE *yyin; 211 212 if (config_file == NULL) { 213 syslog(LOG_ERR, "Unknown config file name!"); 214 exit(1); 215 } 216 217 if ((yyin = fopen(config_file, "r")) == NULL) { 218 syslog(LOG_ERR, "Could not open config file '%s'. %s (%d)", 219 config_file, strerror(errno), errno); 220 exit(1); 221 } 222 223 clean_config(); 224 if (yyparse() < 0) { 225 syslog(LOG_ERR, "Could not parse config file '%s'",config_file); 226 exit(1); 227 } 228 229 fclose(yyin); 230 yyin = NULL; 231 232 #if __config_debug__ 233 dump_config(); 234 #endif 235 } 236 237 /* Clean config */ 238 void 239 clean_config(void) 240 { 241 link_key_p key = NULL; 242 243 while ((key = LIST_FIRST(&link_keys)) != NULL) { 244 LIST_REMOVE(key, next); 245 free_key(key); 246 } 247 } 248 249 /* Find link key entry in the list. Return exact or default match */ 250 link_key_p 251 get_key(bdaddr_p bdaddr, int exact_match) 252 { 253 link_key_p key = NULL, defkey = NULL; 254 255 LIST_FOREACH(key, &link_keys, next) { 256 if (memcmp(bdaddr, &key->bdaddr, sizeof(key->bdaddr)) == 0) 257 break; 258 259 if (!exact_match) 260 if (memcmp(NG_HCI_BDADDR_ANY, &key->bdaddr, 261 sizeof(key->bdaddr)) == 0) 262 defkey = key; 263 } 264 265 return ((key != NULL)? key : defkey); 266 } 267 268 #if __config_debug__ 269 /* Dump config */ 270 void 271 dump_config(void) 272 { 273 link_key_p key = NULL; 274 char buffer[64]; 275 276 LIST_FOREACH(key, &link_keys, next) { 277 if (key->key != NULL) 278 snprintf(buffer, sizeof(buffer), 279 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 280 key->key[0], key->key[1], key->key[2], 281 key->key[3], key->key[4], key->key[5], 282 key->key[6], key->key[7], key->key[8], 283 key->key[9], key->key[10], key->key[11], 284 key->key[12], key->key[13], key->key[14], 285 key->key[15]); 286 287 syslog(LOG_DEBUG, 288 "device %s " \ 289 "bdaddr %x:%x:%x:%x:%x:%x " \ 290 "pin %s " \ 291 "key %s", 292 (key->name != NULL)? key->name : "noname", 293 key->bdaddr.b[5], key->bdaddr.b[4], key->bdaddr.b[3], 294 key->bdaddr.b[2], key->bdaddr.b[1], key->bdaddr.b[0], 295 (key->pin != NULL)? key->pin : "nopin", 296 (key->key != NULL)? buffer : "nokey"); 297 } 298 } 299 #endif 300 301 /* Free key entry */ 302 static void 303 free_key(link_key_p key) 304 { 305 if (key->name != NULL) 306 free(key->name); 307 if (key->key != NULL) 308 free(key->key); 309 if (key->pin != NULL) 310 free(key->pin); 311 312 memset(key, 0, sizeof(*key)); 313 free(key); 314 } 315 316 /* Convert hex ASCII to int4 */ 317 static int 318 hexa2int4(char *a) 319 { 320 if ('0' <= *a && *a <= '9') 321 return (*a - '0'); 322 323 if ('A' <= *a && *a <= 'F') 324 return (*a - 'A' + 0xa); 325 326 if ('a' <= *a && *a <= 'f') 327 return (*a - 'a' + 0xa); 328 329 syslog(LOG_ERR, "Invalid hex character: '%c' (%#x)", *a, *a); 330 exit(1); 331 } 332 333 /* Convert hex ASCII to int8 */ 334 static int 335 hexa2int8(char *a) 336 { 337 return ((hexa2int4(a) << 4) | hexa2int4(a + 1)); 338 } 339 340