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