1358 lines
25 KiB
Plaintext
1358 lines
25 KiB
Plaintext
/* $KAME: cfparse.y,v 1.36 2005/05/03 06:46:00 jinmei Exp $ */
|
|
|
|
/*
|
|
* Copyright (C) 2002 WIDE Project.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the project nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
%{
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/queue.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "dhcp6.h"
|
|
#include "config.h"
|
|
#include "common.h"
|
|
|
|
extern int lineno;
|
|
extern int cfdebug;
|
|
|
|
extern void yywarn __P((char *, ...))
|
|
__attribute__((__format__(__printf__, 1, 2)));
|
|
extern void yyerror __P((char *, ...))
|
|
__attribute__((__format__(__printf__, 1, 2)));
|
|
|
|
#define MAKE_NAMELIST(l, n, p) do { \
|
|
(l) = (struct cf_namelist *)malloc(sizeof(*(l))); \
|
|
if ((l) == NULL) { \
|
|
yywarn("can't allocate memory"); \
|
|
if (p) cleanup_cflist(p); \
|
|
return (-1); \
|
|
} \
|
|
memset((l), 0, sizeof(*(l))); \
|
|
l->line = lineno; \
|
|
l->name = (n); \
|
|
l->params = (p); \
|
|
} while (0)
|
|
|
|
#define MAKE_CFLIST(l, t, pp, pl) do { \
|
|
(l) = (struct cf_list *)malloc(sizeof(*(l))); \
|
|
if ((l) == NULL) { \
|
|
yywarn("can't allocate memory"); \
|
|
if (pp) free(pp); \
|
|
if (pl) cleanup_cflist(pl); \
|
|
return (-1); \
|
|
} \
|
|
memset((l), 0, sizeof(*(l))); \
|
|
l->line = lineno; \
|
|
l->type = (t); \
|
|
l->ptr = (pp); \
|
|
l->list = (pl); \
|
|
l->tail = (l); \
|
|
} while (0)
|
|
|
|
static struct cf_namelist *iflist_head, *hostlist_head, *iapdlist_head;
|
|
static struct cf_namelist *addrpoollist_head;
|
|
static struct cf_namelist *authinfolist_head, *keylist_head;
|
|
static struct cf_namelist *ianalist_head;
|
|
struct cf_list *cf_dns_list, *cf_dns_name_list, *cf_ntp_list;
|
|
struct cf_list *cf_sip_list, *cf_sip_name_list;
|
|
struct cf_list *cf_nis_list, *cf_nis_name_list;
|
|
struct cf_list *cf_nisp_list, *cf_nisp_name_list;
|
|
struct cf_list *cf_bcmcs_list, *cf_bcmcs_name_list;
|
|
long long cf_refreshtime = -1;
|
|
|
|
extern int yylex __P((void));
|
|
extern int cfswitch_buffer __P((char *));
|
|
static int add_namelist __P((struct cf_namelist *, struct cf_namelist **));
|
|
static void cleanup __P((void));
|
|
static void cleanup_namelist __P((struct cf_namelist *));
|
|
static void cleanup_cflist __P((struct cf_list *));
|
|
%}
|
|
|
|
%token INTERFACE IFNAME
|
|
%token PREFIX_INTERFACE SLA_ID SLA_LEN DUID_ID
|
|
%token ID_ASSOC IA_PD IAID IA_NA
|
|
%token ADDRESS
|
|
%token REQUEST SEND ALLOW PREFERENCE
|
|
%token HOST HOSTNAME DUID
|
|
%token OPTION RAPID_COMMIT DNS_SERVERS DNS_NAME DSLITE_NAME DSLITE_ADDRESS NTP_SERVERS REFRESHTIME
|
|
%token SIP_SERVERS SIP_NAME
|
|
%token NIS_SERVERS NIS_NAME
|
|
%token NISP_SERVERS NISP_NAME
|
|
%token BCMCS_SERVERS BCMCS_NAME
|
|
%token INFO_ONLY
|
|
%token SCRIPT DELAYEDKEY
|
|
%token AUTHENTICATION PROTOCOL ALGORITHM DELAYED RECONFIG HMACMD5 MONOCOUNTER
|
|
%token AUTHNAME RDM KEY
|
|
%token KEYINFO REALM KEYID SECRET KEYNAME EXPIRE
|
|
%token ADDRPOOL POOLNAME RANGE TO ADDRESS_POOL
|
|
%token INCLUDE
|
|
|
|
%token NUMBER SLASH EOS BCL ECL STRING QSTRING PREFIX INFINITY
|
|
%token COMMA
|
|
|
|
%union {
|
|
long long num;
|
|
char* str;
|
|
struct cf_list *list;
|
|
struct dhcp6_prefix *prefix;
|
|
struct dhcp6_range *range;
|
|
struct dhcp6_poolspec *pool;
|
|
}
|
|
|
|
%type <str> IFNAME HOSTNAME AUTHNAME KEYNAME DUID_ID STRING QSTRING IAID
|
|
%type <str> POOLNAME
|
|
%type <num> NUMBER duration authproto authalg authrdm
|
|
%type <list> declaration declarations dhcpoption ifparam ifparams
|
|
%type <list> address_list address_list_ent dhcpoption_list
|
|
%type <list> iapdconf_list iapdconf prefix_interface
|
|
%type <list> ianaconf_list ianaconf
|
|
%type <list> authparam_list authparam
|
|
%type <list> keyparam_list keyparam
|
|
%type <prefix> addressparam prefixparam
|
|
%type <range> rangeparam
|
|
%type <pool> poolparam
|
|
|
|
%%
|
|
statements:
|
|
/* empty */
|
|
| statements statement
|
|
;
|
|
|
|
statement:
|
|
interface_statement
|
|
| host_statement
|
|
| option_statement
|
|
| ia_statement
|
|
| authentication_statement
|
|
| key_statement
|
|
| addrpool_statement
|
|
| include_statement
|
|
;
|
|
|
|
interface_statement:
|
|
INTERFACE IFNAME BCL declarations ECL EOS
|
|
{
|
|
struct cf_namelist *ifl;
|
|
|
|
MAKE_NAMELIST(ifl, $2, $4);
|
|
|
|
if (add_namelist(ifl, &iflist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
host_statement:
|
|
HOST HOSTNAME BCL declarations ECL EOS
|
|
{
|
|
struct cf_namelist *host;
|
|
|
|
MAKE_NAMELIST(host, $2, $4);
|
|
|
|
if (add_namelist(host, &hostlist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
option_statement:
|
|
OPTION DNS_SERVERS address_list EOS
|
|
{
|
|
if (cf_dns_list == NULL)
|
|
cf_dns_list = $3;
|
|
else {
|
|
cf_dns_list->tail->next = $3;
|
|
cf_dns_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION DNS_NAME QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, $3, NULL);
|
|
|
|
if (cf_dns_name_list == NULL) {
|
|
cf_dns_name_list = l;
|
|
cf_dns_name_list->tail = l;
|
|
cf_dns_name_list->next = NULL;
|
|
} else {
|
|
cf_dns_name_list->tail->next = l;
|
|
cf_dns_name_list->tail = l->tail;
|
|
}
|
|
}
|
|
| OPTION NTP_SERVERS address_list EOS
|
|
{
|
|
if (cf_ntp_list == NULL)
|
|
cf_ntp_list = $3;
|
|
else {
|
|
cf_ntp_list->tail->next = $3;
|
|
cf_ntp_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION SIP_SERVERS address_list EOS
|
|
{
|
|
if (cf_sip_list == NULL)
|
|
cf_sip_list = $3;
|
|
else {
|
|
cf_sip_list->tail->next = $3;
|
|
cf_sip_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION SIP_NAME QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, $3, NULL);
|
|
|
|
if (cf_sip_name_list == NULL) {
|
|
cf_sip_name_list = l;
|
|
cf_sip_name_list->tail = l;
|
|
cf_sip_name_list->next = NULL;
|
|
} else {
|
|
cf_sip_name_list->tail->next = l;
|
|
cf_sip_name_list->tail = l->tail;
|
|
}
|
|
}
|
|
| OPTION NIS_SERVERS address_list EOS
|
|
{
|
|
if (cf_nis_list == NULL)
|
|
cf_nis_list = $3;
|
|
else {
|
|
cf_nis_list->tail->next = $3;
|
|
cf_nis_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION NIS_NAME QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, $3, NULL);
|
|
|
|
if (cf_nis_name_list == NULL) {
|
|
cf_nis_name_list = l;
|
|
cf_nis_name_list->tail = l;
|
|
cf_nis_name_list->next = NULL;
|
|
} else {
|
|
cf_nis_name_list->tail->next = l;
|
|
cf_nis_name_list->tail = l->tail;
|
|
}
|
|
}
|
|
| OPTION NISP_SERVERS address_list EOS
|
|
{
|
|
if (cf_nisp_list == NULL)
|
|
cf_nisp_list = $3;
|
|
else {
|
|
cf_nisp_list->tail->next = $3;
|
|
cf_nisp_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION NISP_NAME QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, $3, NULL);
|
|
|
|
if (cf_nisp_name_list == NULL) {
|
|
cf_nisp_name_list = l;
|
|
cf_nisp_name_list->tail = l;
|
|
cf_nisp_name_list->next = NULL;
|
|
} else {
|
|
cf_nisp_name_list->tail->next = l;
|
|
cf_nisp_name_list->tail = l->tail;
|
|
}
|
|
}
|
|
| OPTION BCMCS_SERVERS address_list EOS
|
|
{
|
|
if (cf_bcmcs_list == NULL)
|
|
cf_bcmcs_list = $3;
|
|
else {
|
|
cf_bcmcs_list->tail->next = $3;
|
|
cf_bcmcs_list->tail = $3->tail;
|
|
}
|
|
}
|
|
| OPTION BCMCS_NAME QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, $3, NULL);
|
|
|
|
if (cf_bcmcs_name_list == NULL) {
|
|
cf_bcmcs_name_list = l;
|
|
cf_bcmcs_name_list->tail = l;
|
|
cf_bcmcs_name_list->next = NULL;
|
|
} else {
|
|
cf_bcmcs_name_list->tail->next = l;
|
|
cf_bcmcs_name_list->tail = l->tail;
|
|
}
|
|
}
|
|
| OPTION REFRESHTIME NUMBER EOS
|
|
{
|
|
if (cf_refreshtime == -1) {
|
|
cf_refreshtime = $3;
|
|
if (cf_refreshtime < -1 ||
|
|
cf_refreshtime > 0xffffffff) {
|
|
/*
|
|
* refresh time should not be negative
|
|
* according to the lex definition,
|
|
* but check it for safety.
|
|
*/
|
|
yyerror("refresh time is out of range");
|
|
}
|
|
if (cf_refreshtime < DHCP6_IRT_MINIMUM) {
|
|
/*
|
|
* the value MUST NOT be smaller than
|
|
* IRT_MINIMUM.
|
|
*/
|
|
yyerror("refresh time is too small "
|
|
"(must not be smaller than %d)",
|
|
DHCP6_IRT_MINIMUM);
|
|
}
|
|
} else {
|
|
yywarn("multiple refresh times (ignored)");
|
|
}
|
|
}
|
|
;
|
|
|
|
ia_statement:
|
|
ID_ASSOC IA_PD IAID BCL iapdconf_list ECL EOS
|
|
{
|
|
struct cf_namelist *iapd;
|
|
|
|
MAKE_NAMELIST(iapd, $3, $5);
|
|
|
|
if (add_namelist(iapd, &iapdlist_head))
|
|
return (-1);
|
|
}
|
|
| ID_ASSOC IA_PD BCL iapdconf_list ECL EOS
|
|
{
|
|
struct cf_namelist *iapd;
|
|
char *zero;
|
|
|
|
if ((zero = strdup("0")) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
MAKE_NAMELIST(iapd, zero, $4);
|
|
|
|
if (add_namelist(iapd, &iapdlist_head))
|
|
return (-1);
|
|
}
|
|
| ID_ASSOC IA_NA IAID BCL ianaconf_list ECL EOS
|
|
{
|
|
struct cf_namelist *iana;
|
|
|
|
MAKE_NAMELIST(iana, $3, $5);
|
|
|
|
if (add_namelist(iana, &ianalist_head))
|
|
return (-1);
|
|
}
|
|
| ID_ASSOC IA_NA BCL ianaconf_list ECL EOS
|
|
{
|
|
struct cf_namelist *iana;
|
|
char *zero;
|
|
|
|
if ((zero = strdup("0")) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
MAKE_NAMELIST(iana, zero, $4);
|
|
|
|
if (add_namelist(iana, &ianalist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
authentication_statement:
|
|
AUTHENTICATION AUTHNAME BCL authparam_list ECL EOS
|
|
{
|
|
struct cf_namelist *authinfo;
|
|
|
|
MAKE_NAMELIST(authinfo, $2, $4);
|
|
|
|
if (add_namelist(authinfo, &authinfolist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
key_statement:
|
|
KEYINFO KEYNAME BCL keyparam_list ECL EOS
|
|
{
|
|
struct cf_namelist *key;
|
|
|
|
MAKE_NAMELIST(key, $2, $4);
|
|
|
|
if (add_namelist(key, &keylist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
include_statement:
|
|
INCLUDE QSTRING EOS
|
|
{
|
|
if (cfswitch_buffer($2)) {
|
|
free($2);
|
|
return (-1);
|
|
}
|
|
free($2);
|
|
}
|
|
;
|
|
|
|
addrpool_statement:
|
|
ADDRPOOL POOLNAME BCL declarations ECL EOS
|
|
{
|
|
struct cf_namelist *pool;
|
|
|
|
MAKE_NAMELIST(pool, $2, $4);
|
|
|
|
if (add_namelist(pool, &addrpoollist_head))
|
|
return (-1);
|
|
}
|
|
;
|
|
|
|
address_list:
|
|
{ $$ = NULL; }
|
|
| address_list address_list_ent
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
address_list_ent:
|
|
STRING
|
|
{
|
|
struct cf_list *l;
|
|
struct in6_addr a0, *a;
|
|
|
|
if (inet_pton(AF_INET6, $1, &a0) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
if ((a = malloc(sizeof(*a))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*a = a0;
|
|
|
|
MAKE_CFLIST(l, CFLISTENT_GENERIC, a, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
declarations:
|
|
{ $$ = NULL; }
|
|
| declarations declaration
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
declaration:
|
|
SEND dhcpoption_list EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_SEND, NULL, $2);
|
|
|
|
$$ = l;
|
|
}
|
|
| REQUEST dhcpoption_list EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_REQUEST, NULL, $2);
|
|
|
|
$$ = l;
|
|
}
|
|
| INFO_ONLY EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_INFO_ONLY, NULL, NULL);
|
|
/* no value */
|
|
$$ = l;
|
|
}
|
|
| ALLOW dhcpoption EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_ALLOW, NULL, $2);
|
|
|
|
$$ = l;
|
|
}
|
|
| DUID DUID_ID EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_DUID, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| ADDRESS addressparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_ADDRESS, $2,NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| PREFIX prefixparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_PREFIX, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| PREFERENCE NUMBER EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_PREFERENCE, NULL, NULL);
|
|
l->num = $2;
|
|
|
|
$$ = l;
|
|
}
|
|
| SCRIPT QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_SCRIPT, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| DELAYEDKEY STRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_DELAYEDKEY, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| RANGE rangeparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_RANGE, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
| ADDRESS_POOL poolparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DECL_ADDRESSPOOL, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
dhcpoption_list:
|
|
dhcpoption
|
|
{
|
|
$$ = $1;
|
|
}
|
|
| dhcpoption COMMA dhcpoption_list
|
|
{
|
|
$1->next = $3;
|
|
$1->tail = $3->tail;
|
|
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
dhcpoption:
|
|
RAPID_COMMIT
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_RAPID_COMMIT, NULL, NULL);
|
|
/* no value */
|
|
$$ = l;
|
|
}
|
|
| AUTHENTICATION AUTHNAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_AUTHINFO, NULL, NULL);
|
|
l->ptr = $2;
|
|
$$ = l;
|
|
}
|
|
| IA_PD NUMBER
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_IA_PD, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| IA_NA NUMBER
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_IA_NA, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| SIP_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_SIP, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| SIP_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_SIPNAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| DNS_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_DNS, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| DNS_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_DNSNAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| DSLITE_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_DSLITENAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| DSLITE_ADDRESS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_DSLITEADDRESS, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
|
|
| NTP_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_NTP, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| REFRESHTIME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_REFRESHTIME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| NIS_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_NIS, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| NIS_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_NISNAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| NISP_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_NISP, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| NISP_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_NISPNAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| BCMCS_SERVERS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_BCMCS, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
| BCMCS_NAME
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, DHCPOPT_BCMCSNAME, NULL, NULL);
|
|
/* currently no value */
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
rangeparam:
|
|
STRING TO STRING
|
|
{
|
|
struct dhcp6_range range0, *range;
|
|
|
|
memset(&range0, 0, sizeof(range0));
|
|
if (inet_pton(AF_INET6, $1, &range0.min) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
free($3);
|
|
return (-1);
|
|
}
|
|
if (inet_pton(AF_INET6, $3, &range0.max) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $3);
|
|
free($1);
|
|
free($3);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
free($3);
|
|
|
|
if ((range = malloc(sizeof(*range))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*range = range0;
|
|
|
|
$$ = range;
|
|
}
|
|
;
|
|
|
|
addressparam:
|
|
STRING duration
|
|
{
|
|
struct dhcp6_prefix pconf0, *pconf;
|
|
|
|
memset(&pconf0, 0, sizeof(pconf0));
|
|
if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
/* validate other parameters later */
|
|
pconf0.plen = 128; /* XXX this field is ignored */
|
|
if ($2 < 0)
|
|
pconf0.pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.pltime = (u_int32_t)$2;
|
|
pconf0.vltime = pconf0.pltime;
|
|
|
|
if ((pconf = malloc(sizeof(*pconf))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*pconf = pconf0;
|
|
|
|
$$ = pconf;
|
|
}
|
|
| STRING duration duration
|
|
{
|
|
struct dhcp6_prefix pconf0, *pconf;
|
|
|
|
memset(&pconf0, 0, sizeof(pconf0));
|
|
if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
/* validate other parameters later */
|
|
pconf0.plen = 128; /* XXX */
|
|
if ($2 < 0)
|
|
pconf0.pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.pltime = (u_int32_t)$2;
|
|
if ($3 < 0)
|
|
pconf0.vltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.vltime = (u_int32_t)$3;
|
|
|
|
if ((pconf = malloc(sizeof(*pconf))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*pconf = pconf0;
|
|
|
|
$$ = pconf;
|
|
}
|
|
;
|
|
|
|
prefixparam:
|
|
STRING SLASH NUMBER duration
|
|
{
|
|
struct dhcp6_prefix pconf0, *pconf;
|
|
|
|
memset(&pconf0, 0, sizeof(pconf0));
|
|
if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
/* validate other parameters later */
|
|
pconf0.plen = $3;
|
|
if ($4 < 0)
|
|
pconf0.pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.pltime = (u_int32_t)$4;
|
|
pconf0.vltime = pconf0.pltime;
|
|
|
|
if ((pconf = malloc(sizeof(*pconf))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*pconf = pconf0;
|
|
|
|
$$ = pconf;
|
|
}
|
|
| STRING SLASH NUMBER duration duration
|
|
{
|
|
struct dhcp6_prefix pconf0, *pconf;
|
|
|
|
memset(&pconf0, 0, sizeof(pconf0));
|
|
if (inet_pton(AF_INET6, $1, &pconf0.addr) != 1) {
|
|
yywarn("invalid IPv6 address: %s", $1);
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
/* validate other parameters later */
|
|
pconf0.plen = $3;
|
|
if ($4 < 0)
|
|
pconf0.pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.pltime = (u_int32_t)$4;
|
|
if ($5 < 0)
|
|
pconf0.vltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pconf0.vltime = (u_int32_t)$5;
|
|
|
|
if ((pconf = malloc(sizeof(*pconf))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
return (-1);
|
|
}
|
|
*pconf = pconf0;
|
|
|
|
$$ = pconf;
|
|
}
|
|
;
|
|
|
|
poolparam:
|
|
STRING duration
|
|
{
|
|
struct dhcp6_poolspec* pool;
|
|
|
|
if ((pool = malloc(sizeof(*pool))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
if ((pool->name = strdup($1)) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
|
|
/* validate other parameters later */
|
|
if ($2 < 0)
|
|
pool->pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pool->pltime = (u_int32_t)$2;
|
|
pool->vltime = pool->pltime;
|
|
|
|
$$ = pool;
|
|
}
|
|
| STRING duration duration
|
|
{
|
|
struct dhcp6_poolspec* pool;
|
|
|
|
if ((pool = malloc(sizeof(*pool))) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
if ((pool->name = strdup($1)) == NULL) {
|
|
yywarn("can't allocate memory");
|
|
free($1);
|
|
return (-1);
|
|
}
|
|
free($1);
|
|
|
|
/* validate other parameters later */
|
|
if ($2 < 0)
|
|
pool->pltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pool->pltime = (u_int32_t)$2;
|
|
if ($3 < 0)
|
|
pool->vltime = DHCP6_DURATION_INFINITE;
|
|
else
|
|
pool->vltime = (u_int32_t)$3;
|
|
|
|
$$ = pool;
|
|
}
|
|
;
|
|
|
|
duration:
|
|
INFINITY
|
|
{
|
|
$$ = -1;
|
|
}
|
|
| NUMBER
|
|
{
|
|
$$ = $1;
|
|
}
|
|
;
|
|
|
|
iapdconf_list:
|
|
{ $$ = NULL; }
|
|
| iapdconf_list iapdconf
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
iapdconf:
|
|
prefix_interface { $$ = $1; }
|
|
| PREFIX prefixparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, IACONF_PREFIX, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
prefix_interface:
|
|
PREFIX_INTERFACE IFNAME BCL ifparams ECL EOS
|
|
{
|
|
struct cf_list *ifl;
|
|
|
|
MAKE_CFLIST(ifl, IACONF_PIF, $2, $4);
|
|
$$ = ifl;
|
|
}
|
|
;
|
|
|
|
ifparams:
|
|
{ $$ = NULL; }
|
|
| ifparams ifparam
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
ifparam:
|
|
SLA_ID NUMBER EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, IFPARAM_SLA_ID, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| SLA_LEN NUMBER EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, IFPARAM_SLA_LEN, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
ianaconf_list:
|
|
{ $$ = NULL; }
|
|
| ianaconf_list ianaconf
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
ianaconf:
|
|
ADDRESS addressparam EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, IACONF_ADDR, $2, NULL);
|
|
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
authparam_list:
|
|
{ $$ = NULL; }
|
|
| authparam_list authparam
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
authparam:
|
|
PROTOCOL authproto EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, AUTHPARAM_PROTO, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| ALGORITHM authalg EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, AUTHPARAM_ALG, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| RDM authrdm EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, AUTHPARAM_RDM, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| KEY STRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, AUTHPARAM_KEY, NULL, NULL);
|
|
l->ptr = $2;
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
authproto:
|
|
DELAYED { $$ = DHCP6_AUTHPROTO_DELAYED; }
|
|
| RECONFIG { $$ = DHCP6_AUTHPROTO_RECONFIG; }
|
|
;
|
|
|
|
authalg:
|
|
HMACMD5 { $$ = DHCP6_AUTHALG_HMACMD5; }
|
|
;
|
|
|
|
authrdm:
|
|
MONOCOUNTER { $$ = DHCP6_AUTHRDM_MONOCOUNTER; }
|
|
;
|
|
|
|
keyparam_list:
|
|
{ $$ = NULL; }
|
|
| keyparam_list keyparam
|
|
{
|
|
struct cf_list *head;
|
|
|
|
if ((head = $1) == NULL) {
|
|
$2->next = NULL;
|
|
$2->tail = $2;
|
|
head = $2;
|
|
} else {
|
|
head->tail->next = $2;
|
|
head->tail = $2->tail;
|
|
}
|
|
|
|
$$ = head;
|
|
}
|
|
;
|
|
|
|
keyparam:
|
|
REALM QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, KEYPARAM_REALM, NULL, NULL);
|
|
l->ptr = $2;
|
|
$$ = l;
|
|
}
|
|
| KEYID NUMBER EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, KEYPARAM_KEYID, NULL, NULL);
|
|
l->num = $2;
|
|
$$ = l;
|
|
}
|
|
| SECRET QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, KEYPARAM_SECRET, NULL, NULL);
|
|
l->ptr = $2;
|
|
$$ = l;
|
|
}
|
|
| EXPIRE QSTRING EOS
|
|
{
|
|
struct cf_list *l;
|
|
|
|
MAKE_CFLIST(l, KEYPARAM_EXPIRE, NULL, NULL);
|
|
l->ptr = $2;
|
|
$$ = l;
|
|
}
|
|
;
|
|
|
|
%%
|
|
/* supplement routines for configuration */
|
|
static int
|
|
add_namelist(new, headp)
|
|
struct cf_namelist *new, **headp;
|
|
{
|
|
struct cf_namelist *n;
|
|
|
|
/* check for duplicated configuration */
|
|
for (n = *headp; n; n = n->next) {
|
|
if (strcmp(n->name, new->name) == 0) {
|
|
yywarn("duplicated name: %s (ignored)",
|
|
new->name);
|
|
cleanup_namelist(new);
|
|
return (0);
|
|
}
|
|
}
|
|
|
|
new->next = *headp;
|
|
*headp = new;
|
|
|
|
return (0);
|
|
}
|
|
|
|
/* free temporary resources */
|
|
static void
|
|
cleanup()
|
|
{
|
|
cleanup_namelist(iflist_head);
|
|
iflist_head = NULL;
|
|
cleanup_namelist(hostlist_head);
|
|
hostlist_head = NULL;
|
|
cleanup_namelist(iapdlist_head);
|
|
iapdlist_head = NULL;
|
|
cleanup_namelist(ianalist_head);
|
|
ianalist_head = NULL;
|
|
cleanup_namelist(authinfolist_head);
|
|
authinfolist_head = NULL;
|
|
cleanup_namelist(keylist_head);
|
|
keylist_head = NULL;
|
|
cleanup_namelist(addrpoollist_head);
|
|
addrpoollist_head = NULL;
|
|
|
|
cleanup_cflist(cf_sip_list);
|
|
cf_sip_list = NULL;
|
|
cleanup_cflist(cf_sip_name_list);
|
|
cf_sip_name_list = NULL;
|
|
cleanup_cflist(cf_dns_list);
|
|
cf_dns_list = NULL;
|
|
cleanup_cflist(cf_dns_name_list);
|
|
cf_dns_name_list = NULL;
|
|
cleanup_cflist(cf_ntp_list);
|
|
cf_ntp_list = NULL;
|
|
cleanup_cflist(cf_nis_list);
|
|
cf_nis_list = NULL;
|
|
cleanup_cflist(cf_nis_name_list);
|
|
cf_nis_name_list = NULL;
|
|
cleanup_cflist(cf_nisp_list);
|
|
cf_nisp_list = NULL;
|
|
cleanup_cflist(cf_nisp_name_list);
|
|
cf_nisp_name_list = NULL;
|
|
cleanup_cflist(cf_bcmcs_list);
|
|
cf_bcmcs_list = NULL;
|
|
cleanup_cflist(cf_bcmcs_name_list);
|
|
cf_bcmcs_name_list = NULL;
|
|
}
|
|
|
|
static void
|
|
cleanup_namelist(head)
|
|
struct cf_namelist *head;
|
|
{
|
|
struct cf_namelist *ifp, *ifp_next;
|
|
|
|
for (ifp = head; ifp; ifp = ifp_next) {
|
|
ifp_next = ifp->next;
|
|
cleanup_cflist(ifp->params);
|
|
free(ifp->name);
|
|
free(ifp);
|
|
}
|
|
}
|
|
|
|
static void
|
|
cleanup_cflist(p)
|
|
struct cf_list *p;
|
|
{
|
|
struct cf_list *n;
|
|
|
|
if (p == NULL)
|
|
return;
|
|
|
|
n = p->next;
|
|
if (p->type == DECL_ADDRESSPOOL) {
|
|
free(((struct dhcp6_poolspec *)p->ptr)->name);
|
|
}
|
|
if (p->ptr)
|
|
free(p->ptr);
|
|
if (p->list)
|
|
cleanup_cflist(p->list);
|
|
free(p);
|
|
|
|
cleanup_cflist(n);
|
|
}
|
|
|
|
#define config_fail() \
|
|
do { cleanup(); configure_cleanup(); return (-1); } while(0)
|
|
|
|
int
|
|
cf_post_config()
|
|
{
|
|
if (configure_keys(keylist_head))
|
|
config_fail();
|
|
|
|
if (configure_authinfo(authinfolist_head))
|
|
config_fail();
|
|
|
|
if (configure_ia(iapdlist_head, IATYPE_PD))
|
|
config_fail();
|
|
|
|
if (configure_ia(ianalist_head, IATYPE_NA))
|
|
config_fail();
|
|
|
|
if (configure_pool(addrpoollist_head))
|
|
config_fail();
|
|
|
|
if (configure_interface(iflist_head))
|
|
config_fail();
|
|
|
|
if (configure_host(hostlist_head))
|
|
config_fail();
|
|
|
|
if (configure_global_option())
|
|
config_fail();
|
|
|
|
configure_commit();
|
|
cleanup();
|
|
return (0);
|
|
}
|
|
#undef config_fail
|
|
|
|
void
|
|
cf_init()
|
|
{
|
|
iflist_head = NULL;
|
|
}
|