1/* $Id: client6_parse.y,v 1.1.1.1 2006/12/04 00:45:21 Exp $ */ 2/* ported from KAME: cfparse.y,v 1.16 2002/09/24 14:20:49 itojun Exp */ 3 4/* 5 * Copyright (C) 2002 WIDE Project. 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 * 3. Neither the name of the project nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32%{ 33#include <string.h> 34 35#include <stdlib.h> 36#include <sys/types.h> 37#include <sys/socket.h> 38#include <netinet/in.h> 39 40#include <arpa/inet.h> 41 42#include <malloc.h> 43#include "queue.h" 44#include "dhcp6.h" 45#include "config.h" 46#include "common.h" 47 48extern int lineno; 49extern int cfdebug; 50 51extern void cpyywarn __P((char *, ...)) 52 __attribute__((__format__(__printf__, 1, 2))); 53extern void cpyyerror __P((char *, ...)) 54 __attribute__((__format__(__printf__, 1, 2))); 55 56#define MAKE_NAMELIST(l, n, p) do { \ 57 (l) = (struct cf_namelist *)malloc(sizeof(*(l))); \ 58 if ((l) == NULL) { \ 59 cpyywarn("can't allocate memory"); \ 60 if (p) cleanup_cflist(p); \ 61 return (-1); \ 62 } \ 63 memset((l), 0, sizeof(*(l))); \ 64 l->line = lineno; \ 65 l->name = (n); \ 66 l->params = (p); \ 67 } while (0) 68 69#define MAKE_CFLIST(l, t, pp, pl) do { \ 70 (l) = (struct cf_list *)malloc(sizeof(*(l))); \ 71 if ((l) == NULL) { \ 72 cpyywarn("can't allocate memory"); \ 73 if (pp) free(pp); \ 74 if (pl) cleanup_cflist(pl); \ 75 return (-1); \ 76 } \ 77 memset((l), 0, sizeof(*(l))); \ 78 l->line = lineno; \ 79 l->type = (t); \ 80 l->ptr = (pp); \ 81 l->list = (pl); \ 82 } while (0) 83 84static struct cf_namelist *iflist_head; 85struct cf_list *cf_dns_list; 86 87extern int cpyylex __P((void)); 88static void cleanup __P((void)); 89static int add_namelist __P((struct cf_namelist *, struct cf_namelist **)); 90static void cleanup_namelist __P((struct cf_namelist *)); 91static void cleanup_cflist __P((struct cf_list *)); 92%} 93 94%token INTERFACE IFNAME IPV6ADDR 95%token REQUEST SEND 96%token RAPID_COMMIT PREFIX_DELEGATION DNS_SERVERS SIP_SERVERS NTP_SERVERS 97%token INFO_ONLY TEMP_ADDR SOLICIT_ONLY 98%token IANA_ONLY IAPD_ONLY DOMAIN_LIST 99%token ADDRESS PREFIX IAID RENEW_TIME REBIND_TIME V_TIME P_TIME PREFIX_DELEGATION_INTERFACE USER_CLASS 100%token XID_SOL XID_REQ DUID_TIME 101%token NUMBER SLASH EOS BCL ECL STRING INFINITY 102%token COMMA OPTION 103 104%union { 105 long long num; 106 char* str; 107 struct cf_list *list; 108 struct in6_addr addr; 109 struct dhcp6_addr *v6addr; 110} 111 112%type <str> IFNAME STRING 113%type <num> NUMBER duration addrvtime addrptime 114%type <list> declaration declarations dhcpoption 115%type <v6addr> addrparam addrdecl 116%type <addr> IPV6ADDR 117 118%% 119statements: 120 /* empty */ 121 | statements statement 122 ; 123 124statement: 125 interface_statement 126 ; 127 128interface_statement: 129 INTERFACE IFNAME BCL declarations ECL EOS 130 { 131 struct cf_namelist *ifl; 132 133 MAKE_NAMELIST(ifl, $2, $4); 134 135 if (add_namelist(ifl, &iflist_head)) 136 return (-1); 137 } 138 ; 139 140declarations: 141 { $$ = NULL; } 142 | declarations declaration 143 { 144 struct cf_list *head; 145 146 if ((head = $1) == NULL) { 147 $2->next = NULL; 148 $2->tail = $2; 149 head = $2; 150 } else { 151 head->tail->next = $2; 152 head->tail = $2; 153 } 154 155 $$ = head; 156 } 157 ; 158 159declaration: 160 SEND dhcpoption EOS 161 { 162 struct cf_list *l; 163 164 MAKE_CFLIST(l, DECL_SEND, NULL, $2); 165 166 $$ = l; 167 } 168 | REQUEST dhcpoption EOS 169 { 170 struct cf_list *l; 171 172 MAKE_CFLIST(l, DECL_REQUEST, NULL, $2); 173 174 $$ = l; 175 } 176 | INFO_ONLY EOS 177 { 178 struct cf_list *l; 179 180 MAKE_CFLIST(l, DECL_INFO_ONLY, NULL, NULL); 181 /* no value */ 182 $$ = l; 183 } 184 | SOLICIT_ONLY EOS 185 { 186 struct cf_list *l; 187 188 MAKE_CFLIST(l, DECL_SOLICIT_ONLY, NULL, NULL); 189 /* no value */ 190 $$ = l; 191 } 192 | IANA_ONLY EOS 193 { 194 struct cf_list *l; 195 196 MAKE_CFLIST(l, DECL_IANA_ONLY, NULL, NULL); 197 /* no value */ 198 $$ = l; 199 } 200 | IAPD_ONLY EOS 201 { 202 struct cf_list *l; 203 204 MAKE_CFLIST(l, DECL_IAPD_ONLY, NULL, NULL); 205 /* no value */ 206 $$ = l; 207 } 208 209 | REQUEST TEMP_ADDR EOS 210 { 211 struct cf_list *l; 212 213 MAKE_CFLIST(l, DECL_TEMP_ADDR, NULL, NULL); 214 /* no value */ 215 $$ = l; 216 } 217 | ADDRESS BCL addrdecl ECL EOS 218 { 219 struct cf_list *l; 220 221 MAKE_CFLIST(l, DECL_ADDRESS, $3, NULL); 222 223 $$ = l; 224 225 } 226 227 | PREFIX BCL addrdecl ECL EOS 228 { 229 struct cf_list *l; 230 231 MAKE_CFLIST(l, DECL_PREFIX, $3, NULL); 232 233 $$ = l; 234 235 } 236 237 | RENEW_TIME duration EOS 238 { 239 struct cf_list *l; 240 241 MAKE_CFLIST(l, DECL_RENEWTIME, NULL, NULL); 242 l->num = $2; 243 244 $$ = l; 245 246 } 247 | REBIND_TIME duration EOS 248 { 249 struct cf_list *l; 250 251 MAKE_CFLIST(l, DECL_REBINDTIME, NULL, NULL); 252 l->num = $2; 253 254 $$ = l; 255 256 } 257 | IAID NUMBER EOS 258 { 259 struct cf_list *l; 260 261 MAKE_CFLIST(l, DECL_IAID, NULL, NULL); 262 l->num = $2; 263 264 $$ = l; 265 } 266 | PREFIX_DELEGATION_INTERFACE STRING EOS 267 { 268 struct cf_list *l; 269 char *pp = (char*)malloc(strlen($2)+1); 270 strcpy(pp,$2); 271 MAKE_CFLIST(l, DECL_PREFIX_DELEGATION_INTERFACE, pp, NULL ); 272 273 $$ = l; 274 } 275 | USER_CLASS STRING EOS 276 { 277 struct cf_list *l; 278 char *pp = (char*)malloc(strlen($2)+1); 279 strcpy(pp,$2); 280 MAKE_CFLIST(l, DECL_USER_CLASS, pp, NULL ); 281 282 $$ = l; 283 } 284 | XID_SOL NUMBER EOS 285 { 286 struct cf_list *l; 287 288 MAKE_CFLIST(l, DECL_XID_SOL, NULL, NULL); 289 l->num = $2; 290 291 $$ = l; 292 } 293 | XID_REQ NUMBER EOS 294 { 295 struct cf_list *l; 296 297 MAKE_CFLIST(l, DECL_XID_REQ, NULL, NULL); 298 l->num = $2; 299 300 $$ = l; 301 } 302 | DUID_TIME NUMBER EOS 303 { 304 struct cf_list *l; 305 306 MAKE_CFLIST(l, DECL_DUID_TIME, NULL, NULL); 307 l->num = $2; 308 309 $$ = l; 310 } 311 ; 312 313dhcpoption: 314 RAPID_COMMIT 315 { 316 struct cf_list *l; 317 318 MAKE_CFLIST(l, DHCPOPT_RAPID_COMMIT, NULL, NULL); 319 /* no value */ 320 $$ = l; 321 } 322 | PREFIX_DELEGATION 323 { 324 struct cf_list *l; 325 326 MAKE_CFLIST(l, DHCPOPT_PREFIX_DELEGATION, NULL, NULL); 327 /* currently no value */ 328 $$ = l; 329 } 330 | DNS_SERVERS 331 { 332 struct cf_list *l; 333 334 MAKE_CFLIST(l, DHCPOPT_DNS, NULL, NULL); 335 /* currently no value */ 336 $$ = l; 337 } 338 | DOMAIN_LIST 339 { 340 struct cf_list *l; 341 342 MAKE_CFLIST(l, DHCPOPT_DOMAIN_LIST, NULL, NULL); 343 /* currently no value */ 344 $$ = l; 345 } 346 | SIP_SERVERS 347 { 348 struct cf_list *l; 349 350 MAKE_CFLIST(l, DHCPOPT_SIP, NULL, NULL); 351 /* currently no value */ 352 $$ = l; 353 } 354 | NTP_SERVERS 355 { 356 struct cf_list *l; 357 358 MAKE_CFLIST(l, DHCPOPT_NTP, NULL, NULL); 359 /* currently no value */ 360 $$ = l; 361 } 362 ; 363 364addrdecl: 365 366 addrparam addrvtime 367 { 368 struct dhcp6_addr *addr=(struct dhcp6_addr *)$1; 369 370 addr->validlifetime = (u_int32_t)$2; 371 $$ = $1; 372 } 373 | addrparam addrptime 374 { 375 struct dhcp6_addr *addr=(struct dhcp6_addr *)$1; 376 addr->preferlifetime = (u_int32_t)$2; 377 $$ = $1; 378 } 379 | addrparam addrvtime addrptime 380 { 381 struct dhcp6_addr *addr=(struct dhcp6_addr *)$1; 382 addr->validlifetime = (u_int32_t)$2; 383 addr->preferlifetime = (u_int32_t)$3; 384 $$ = $1; 385 } 386 | addrparam addrptime addrvtime 387 { 388 struct dhcp6_addr *addr=(struct dhcp6_addr *)$1; 389 addr->validlifetime = (u_int32_t)$3; 390 addr->preferlifetime = (u_int32_t)$2; 391 $$ = $1; 392 } 393 | addrparam 394 { 395 $$ = $1; 396 } 397 ; 398addrparam: 399 IPV6ADDR SLASH NUMBER EOS 400 { 401 struct dhcp6_addr *v6addr; 402 /* validate other parameters later */ 403 if ($3 < 0 || $3 > 128) 404 return (-1); 405 if ((v6addr = malloc(sizeof(*v6addr))) == NULL) { 406 cpyywarn("can't allocate memory"); 407 return (-1); 408 } 409 memset(v6addr, 0, sizeof(*v6addr)); 410 memcpy(&v6addr->addr, &$1, sizeof(v6addr->addr)); 411 v6addr->plen = $3; 412 $$ = v6addr; 413 } 414 ; 415 416addrvtime: 417 V_TIME duration EOS 418 { 419 $$ = $2; 420 } 421 ; 422 423addrptime: 424 P_TIME duration EOS 425 { 426 $$ = $2; 427 } 428 ; 429 430duration: 431 INFINITY 432 { 433 $$ = -1; 434 } 435 | NUMBER 436 { 437 $$ = $1; 438 } 439 ; 440 441%% 442/* supplement routines for configuration */ 443static int 444add_namelist(new, headp) 445 struct cf_namelist *new, **headp; 446{ 447 struct cf_namelist *ifp; 448 449 /* check for duplicated configuration */ 450 for (ifp = *headp; ifp; ifp = ifp->next) { 451 if (strcmp(ifp->name, new->name) == 0) { 452 cpyywarn("duplicated interface: %s (ignored)", 453 new->name); 454 cleanup_namelist(new); 455 return (0); 456 } 457 } 458 459 new->next = *headp; 460 *headp = new; 461 462 return (0); 463} 464 465/* free temporary resources */ 466static void 467cleanup() 468{ 469 cleanup_namelist(iflist_head); 470 471} 472 473static void 474cleanup_namelist(head) 475 struct cf_namelist *head; 476{ 477 struct cf_namelist *ifp, *ifp_next; 478 479 for (ifp = head; ifp; ifp = ifp_next) { 480 ifp_next = ifp->next; 481 cleanup_cflist(ifp->params); 482 free(ifp->name); 483 free(ifp); 484 } 485} 486 487static void 488cleanup_cflist(p) 489 struct cf_list *p; 490{ 491 struct cf_list *n; 492 493 if (p == NULL) 494 return; 495 496 n = p->next; 497 if (p->ptr) 498 free(p->ptr); 499 if (p->list) 500 cleanup_cflist(p->list); 501 free(p); 502 503 cleanup_cflist(n); 504} 505 506#define config_fail() \ 507 do { cleanup(); configure_cleanup(); return (-1); } while(0) 508 509int 510cf_post_config() 511{ 512 if (configure_interface(iflist_head)) 513 config_fail(); 514 515 if (configure_global_option()) 516 config_fail(); 517 518 configure_commit(); 519 cleanup(); 520 return (0); 521} 522#undef config_fail 523 524void 525cf_init() 526{ 527 iflist_head = NULL; 528} 529