blob: 18c5990fba16dd5025773efe0c7eb6e3147c4cf2 [file] [log] [blame]
/* -*- Mode: C; tab-width: 4 -*-
*
* Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mDNSEmbeddedAPI.h"
#include "DebugServices.h"
#include "dnsextd.h"
void yyerror( const char* error );
int yylex(void);
typedef struct StringListElem
{
char * string;
struct StringListElem * next;
} StringListElem;
typedef struct OptionsInfo
{
char server_address[ 256 ];
int server_port;
char source_address[ 256 ];
int source_port;
int private_port;
int llq_port;
} OptionsInfo;
typedef struct ZoneInfo
{
char name[ 256 ];
char certificate_name[ 256 ];
char allow_clients_file[ 256 ];
char allow_clients[ 256 ];
char key[ 256 ];
} ZoneInfo;
typedef struct KeySpec
{
char name[ 256 ];
char algorithm[ 256 ];
char secret[ 256 ];
struct KeySpec * next;
} KeySpec;
typedef struct ZoneSpec
{
char name[ 256 ];
DNSZoneSpecType type;
StringListElem * allowUpdate;
StringListElem * allowQuery;
char key[ 256 ];
struct ZoneSpec * next;
} ZoneSpec;
static StringListElem * g_stringList = NULL;
static KeySpec * g_keys;
static ZoneSpec * g_zones;
static ZoneSpec g_zoneSpec;
static const char * g_filename;
#define YYPARSE_PARAM context
void
SetupOptions
(
OptionsInfo * info,
void * context
);
%}
%union
{
int number;
char * string;
}
%token OPTIONS
%token LISTEN_ON
%token NAMESERVER
%token PORT
%token ADDRESS
%token LLQ
%token PUBLIC
%token PRIVATE
%token ALLOWUPDATE
%token ALLOWQUERY
%token KEY
%token ALGORITHM
%token SECRET
%token ISSUER
%token SERIAL
%token ZONE
%token TYPE
%token ALLOW
%token OBRACE
%token EBRACE
%token SEMICOLON
%token IN
%token <string> DOTTED_DECIMAL_ADDRESS
%token <string> WILDCARD
%token <string> DOMAINNAME
%token <string> HOSTNAME
%token <string> QUOTEDSTRING
%token <number> NUMBER
%type <string> addressstatement
%type <string> networkaddress
%%
commands:
|
commands command SEMICOLON
;
command:
options_set
|
zone_set
|
key_set
;
options_set:
OPTIONS optionscontent
{
// SetupOptions( &g_optionsInfo, context );
}
;
optionscontent:
OBRACE optionsstatements EBRACE
;
optionsstatements:
|
optionsstatements optionsstatement SEMICOLON
;
optionsstatement:
statements
|
LISTEN_ON addresscontent
{
}
|
LISTEN_ON PORT NUMBER addresscontent
{
}
|
NAMESERVER ADDRESS networkaddress
{
}
|
NAMESERVER ADDRESS networkaddress PORT NUMBER
{
}
|
PRIVATE PORT NUMBER
{
( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( $3 );
}
|
LLQ PORT NUMBER
{
( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( $3 );
}
;
key_set:
KEY QUOTEDSTRING OBRACE SECRET QUOTEDSTRING SEMICOLON EBRACE
{
KeySpec * keySpec;
keySpec = ( KeySpec* ) malloc( sizeof( KeySpec ) );
if ( !keySpec )
{
LogMsg("ERROR: memory allocation failure");
YYABORT;
}
strncpy( keySpec->name, $2, sizeof( keySpec->name ) );
strncpy( keySpec->secret, $5, sizeof( keySpec->secret ) );
keySpec->next = g_keys;
g_keys = keySpec;
}
;
zone_set:
ZONE QUOTEDSTRING zonecontent
{
ZoneSpec * zoneSpec;
zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
if ( !zoneSpec )
{
LogMsg("ERROR: memory allocation failure");
YYABORT;
}
strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
zoneSpec->type = g_zoneSpec.type;
strcpy( zoneSpec->key, g_zoneSpec.key );
zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
zoneSpec->allowQuery = g_zoneSpec.allowQuery;
zoneSpec->next = g_zones;
g_zones = zoneSpec;
}
|
ZONE QUOTEDSTRING IN zonecontent
{
ZoneSpec * zoneSpec;
zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
if ( !zoneSpec )
{
LogMsg("ERROR: memory allocation failure");
YYABORT;
}
strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
zoneSpec->type = g_zoneSpec.type;
strcpy( zoneSpec->key, g_zoneSpec.key );
zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
zoneSpec->allowQuery = g_zoneSpec.allowQuery;
zoneSpec->next = g_zones;
g_zones = zoneSpec;
}
;
zonecontent:
OBRACE zonestatements EBRACE
zonestatements:
|
zonestatements zonestatement SEMICOLON
;
zonestatement:
TYPE PUBLIC
{
g_zoneSpec.type = kDNSZonePublic;
}
|
TYPE PRIVATE
{
g_zoneSpec.type = kDNSZonePrivate;
}
|
ALLOWUPDATE keycontent
{
g_zoneSpec.allowUpdate = g_stringList;
g_stringList = NULL;
}
|
ALLOWQUERY keycontent
{
g_zoneSpec.allowQuery = g_stringList;
g_stringList = NULL;
}
;
addresscontent:
OBRACE addressstatements EBRACE
{
}
addressstatements:
|
addressstatements addressstatement SEMICOLON
{
}
;
addressstatement:
DOTTED_DECIMAL_ADDRESS
{
}
;
keycontent:
OBRACE keystatements EBRACE
{
}
keystatements:
|
keystatements keystatement SEMICOLON
{
}
;
keystatement:
KEY DOMAINNAME
{
StringListElem * elem;
elem = ( StringListElem* ) malloc( sizeof( StringListElem ) );
if ( !elem )
{
LogMsg("ERROR: memory allocation failure");
YYABORT;
}
elem->string = $2;
elem->next = g_stringList;
g_stringList = elem;
}
;
networkaddress:
DOTTED_DECIMAL_ADDRESS
|
HOSTNAME
|
WILDCARD
;
block:
OBRACE zonestatements EBRACE SEMICOLON
;
statements:
|
statements statement
;
statement:
block
{
$<string>$ = NULL;
}
|
QUOTEDSTRING
{
$<string>$ = $1;
}
%%
int yywrap(void);
extern int yylineno;
void yyerror( const char *str )
{
fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
}
int yywrap()
{
return 1;
}
int
ParseConfig
(
DaemonInfo * d,
const char * file
)
{
extern FILE * yyin;
DNSZone * zone;
DomainAuthInfo * key;
KeySpec * keySpec;
ZoneSpec * zoneSpec;
int err = 0;
g_filename = file;
// Tear down the current zone specifiers
zone = d->zones;
while ( zone )
{
DNSZone * next = zone->next;
key = zone->updateKeys;
while ( key )
{
DomainAuthInfo * nextKey = key->next;
free( key );
key = nextKey;
}
key = zone->queryKeys;
while ( key )
{
DomainAuthInfo * nextKey = key->next;
free( key );
key = nextKey;
}
free( zone );
zone = next;
}
d->zones = NULL;
yyin = fopen( file, "r" );
require_action( yyin, exit, err = 0 );
err = yyparse( ( void* ) d );
require_action( !err, exit, err = 1 );
for ( zoneSpec = g_zones; zoneSpec; zoneSpec = zoneSpec->next )
{
StringListElem * elem;
mDNSu8 * ok;
zone = ( DNSZone* ) malloc( sizeof( DNSZone ) );
require_action( zone, exit, err = 1 );
memset( zone, 0, sizeof( DNSZone ) );
zone->next = d->zones;
d->zones = zone;
// Fill in the domainname
ok = MakeDomainNameFromDNSNameString( &zone->name, zoneSpec->name );
require_action( ok, exit, err = 1 );
// Fill in the type
zone->type = zoneSpec->type;
// Fill in the allow-update keys
for ( elem = zoneSpec->allowUpdate; elem; elem = elem->next )
{
mDNSBool found = mDNSfalse;
for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
{
if ( strcmp( elem->string, keySpec->name ) == 0 )
{
DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
mDNSs32 keylen;
require_action( authInfo, exit, err = 1 );
memset( authInfo, 0, sizeof( DomainAuthInfo ) );
ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
if (!ok) { free(authInfo); err = 1; goto exit; }
keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
if (keylen < 0) { free(authInfo); err = 1; goto exit; }
authInfo->next = zone->updateKeys;
zone->updateKeys = authInfo;
found = mDNStrue;
break;
}
}
// Log this
require_action( found, exit, err = 1 );
}
// Fill in the allow-query keys
for ( elem = zoneSpec->allowQuery; elem; elem = elem->next )
{
mDNSBool found = mDNSfalse;
for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
{
if ( strcmp( elem->string, keySpec->name ) == 0 )
{
DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
mDNSs32 keylen;
require_action( authInfo, exit, err = 1 );
memset( authInfo, 0, sizeof( DomainAuthInfo ) );
ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
if (!ok) { free(authInfo); err = 1; goto exit; }
keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
if (keylen < 0) { free(authInfo); err = 1; goto exit; }
authInfo->next = zone->queryKeys;
zone->queryKeys = authInfo;
found = mDNStrue;
break;
}
}
// Log this
require_action( found, exit, err = 1 );
}
}
exit:
return err;
}
void
SetupOptions
(
OptionsInfo * info,
void * context
)
{
DaemonInfo * d = ( DaemonInfo* ) context;
if ( strlen( info->source_address ) )
{
inet_pton( AF_INET, info->source_address, &d->addr.sin_addr );
}
if ( info->source_port )
{
d->addr.sin_port = htons( ( mDNSu16 ) info->source_port );
}
if ( strlen( info->server_address ) )
{
inet_pton( AF_INET, info->server_address, &d->ns_addr.sin_addr );
}
if ( info->server_port )
{
d->ns_addr.sin_port = htons( ( mDNSu16 ) info->server_port );
}
if ( info->private_port )
{
d->private_port = mDNSOpaque16fromIntVal( info->private_port );
}
if ( info->llq_port )
{
d->llq_port = mDNSOpaque16fromIntVal( info->llq_port );
}
}