]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSShared/dnsextd_parser.y
mDNSResponder-878.270.2.tar.gz
[apple/mdnsresponder.git] / mDNSShared / dnsextd_parser.y
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2006-2010 Apple Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 %{
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "mDNSEmbeddedAPI.h"
23 #include "DebugServices.h"
24 #include "dnsextd.h"
25
26 void yyerror( const char* error );
27 int yylex(void);
28
29
30 typedef struct StringListElem
31 {
32 char * string;
33 struct StringListElem * next;
34 } StringListElem;
35
36
37 typedef struct OptionsInfo
38 {
39 char server_address[ 256 ];
40 int server_port;
41 char source_address[ 256 ];
42 int source_port;
43 int private_port;
44 int llq_port;
45 } OptionsInfo;
46
47
48 typedef struct ZoneInfo
49 {
50 char name[ 256 ];
51 char certificate_name[ 256 ];
52 char allow_clients_file[ 256 ];
53 char allow_clients[ 256 ];
54 char key[ 256 ];
55 } ZoneInfo;
56
57
58 typedef struct KeySpec
59 {
60 char name[ 256 ];
61 char algorithm[ 256 ];
62 char secret[ 256 ];
63 struct KeySpec * next;
64 } KeySpec;
65
66
67 typedef struct ZoneSpec
68 {
69 char name[ 256 ];
70 DNSZoneSpecType type;
71 StringListElem * allowUpdate;
72 StringListElem * allowQuery;
73 char key[ 256 ];
74 struct ZoneSpec * next;
75 } ZoneSpec;
76
77
78 static StringListElem * g_stringList = NULL;
79 static StringListElem * g_addrList = NULL;
80 static KeySpec * g_keys;
81 static ZoneSpec * g_zones;
82 static ZoneSpec g_zoneSpec;
83 static const char * g_filename;
84
85 #define YYPARSE_PARAM context
86
87 void
88 SetupOptions
89 (
90 OptionsInfo * info,
91 void * context
92 );
93
94 %}
95
96 %union
97 {
98 int number;
99 char * string;
100 }
101
102 %token OPTIONS
103 %token LISTEN_ON
104 %token NAMESERVER
105 %token PORT
106 %token ADDRESS
107 %token LLQ
108 %token PUBLIC
109 %token PRIVATE
110 %token ALLOWUPDATE
111 %token ALLOWQUERY
112 %token KEY
113 %token ALGORITHM
114 %token SECRET
115 %token ISSUER
116 %token SERIAL
117 %token ZONE
118 %token TYPE
119 %token ALLOW
120 %token OBRACE
121 %token EBRACE
122 %token SEMICOLON
123 %token IN
124 %token <string> DOTTED_DECIMAL_ADDRESS
125 %token <string> WILDCARD
126 %token <string> DOMAINNAME
127 %token <string> HOSTNAME
128 %token <string> QUOTEDSTRING
129 %token <number> NUMBER
130
131 %type <string> addressstatement
132 %type <string> networkaddress
133
134 %%
135
136 commands:
137 |
138 commands command SEMICOLON
139 ;
140
141
142 command:
143 options_set
144 |
145 zone_set
146 |
147 key_set
148 ;
149
150
151 options_set:
152 OPTIONS optionscontent
153 {
154 // SetupOptions( &g_optionsInfo, context );
155 }
156 ;
157
158 optionscontent:
159 OBRACE optionsstatements EBRACE
160 ;
161
162 optionsstatements:
163 |
164 optionsstatements optionsstatement SEMICOLON
165 ;
166
167
168 optionsstatement:
169 statements
170 |
171 LISTEN_ON addresscontent
172 {
173 }
174 |
175 LISTEN_ON PORT NUMBER addresscontent
176 {
177 mDNSIPPort listen_port = mDNSOpaque16fromIntVal( $3 );
178 DaemonInfo* d = ( DaemonInfo* ) context;
179 d->addr.sin_port = ( listen_port.NotAnInteger) ? listen_port.NotAnInteger : UnicastDNSPort.NotAnInteger;
180 StringListElem* addr = g_addrList;
181 while (addr != NULL)
182 {
183 StringListElem* next;
184 // The first ipv4 address in {,} is used; the rest are ignored.
185 if (inet_pton( AF_INET, addr->string, &d->addr.sin_addr ) == 0) {
186 inet_pton( AF_INET, "127.0.0.1", &d->ns_addr.sin_addr );
187 LogMsg("LISTEN_ON: An invalid ipv4 address, %s, detected.", addr->string);
188 }
189 next = addr->next;
190 free(addr);
191 addr = next;
192 }
193 }
194 |
195 NAMESERVER ADDRESS networkaddress
196 {
197 }
198 |
199 NAMESERVER ADDRESS networkaddress PORT NUMBER
200 {
201 }
202 |
203 PRIVATE PORT NUMBER
204 {
205 ( ( DaemonInfo* ) context )->private_port = mDNSOpaque16fromIntVal( $3 );
206 }
207 |
208 LLQ PORT NUMBER
209 {
210 ( ( DaemonInfo* ) context )->llq_port = mDNSOpaque16fromIntVal( $3 );
211 }
212 ;
213
214 key_set:
215 KEY QUOTEDSTRING OBRACE SECRET QUOTEDSTRING SEMICOLON EBRACE
216 {
217 KeySpec * keySpec;
218
219 keySpec = ( KeySpec* ) malloc( sizeof( KeySpec ) );
220
221 if ( !keySpec )
222 {
223 LogMsg("ERROR: memory allocation failure");
224 YYABORT;
225 }
226
227 strncpy( keySpec->name, $2, sizeof( keySpec->name ) );
228 strncpy( keySpec->secret, $5, sizeof( keySpec->secret ) );
229
230 keySpec->next = g_keys;
231 g_keys = keySpec;
232 }
233 ;
234
235 zone_set:
236 ZONE QUOTEDSTRING zonecontent
237 {
238 ZoneSpec * zoneSpec;
239
240 zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
241
242 if ( !zoneSpec )
243 {
244 LogMsg("ERROR: memory allocation failure");
245 YYABORT;
246 }
247
248 strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
249 zoneSpec->type = g_zoneSpec.type;
250 strcpy( zoneSpec->key, g_zoneSpec.key );
251 zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
252 zoneSpec->allowQuery = g_zoneSpec.allowQuery;
253
254 zoneSpec->next = g_zones;
255 g_zones = zoneSpec;
256 }
257 |
258 ZONE QUOTEDSTRING IN zonecontent
259 {
260 ZoneSpec * zoneSpec;
261
262 zoneSpec = ( ZoneSpec* ) malloc( sizeof( ZoneSpec ) );
263
264 if ( !zoneSpec )
265 {
266 LogMsg("ERROR: memory allocation failure");
267 YYABORT;
268 }
269
270 strncpy( zoneSpec->name, $2, sizeof( zoneSpec->name ) );
271 zoneSpec->type = g_zoneSpec.type;
272 strcpy( zoneSpec->key, g_zoneSpec.key );
273 zoneSpec->allowUpdate = g_zoneSpec.allowUpdate;
274 zoneSpec->allowQuery = g_zoneSpec.allowQuery;
275
276 zoneSpec->next = g_zones;
277 g_zones = zoneSpec;
278 }
279 ;
280
281 zonecontent:
282 OBRACE zonestatements EBRACE
283
284 zonestatements:
285 |
286 zonestatements zonestatement SEMICOLON
287 ;
288
289 zonestatement:
290 TYPE PUBLIC
291 {
292 g_zoneSpec.type = kDNSZonePublic;
293 }
294 |
295 TYPE PRIVATE
296 {
297 g_zoneSpec.type = kDNSZonePrivate;
298 }
299 |
300 ALLOWUPDATE keycontent
301 {
302 g_zoneSpec.allowUpdate = g_stringList;
303 g_stringList = NULL;
304 }
305 |
306 ALLOWQUERY keycontent
307 {
308 g_zoneSpec.allowQuery = g_stringList;
309 g_stringList = NULL;
310 }
311 ;
312
313 addresscontent:
314 OBRACE addressstatements EBRACE
315 {
316 }
317
318 addressstatements:
319 |
320 addressstatements addressstatement SEMICOLON
321 {
322 }
323 ;
324
325 addressstatement:
326 DOTTED_DECIMAL_ADDRESS
327 {
328 StringListElem * elem;
329
330 elem = ( StringListElem* ) malloc( sizeof( StringListElem ) );
331
332 if ( !elem )
333 {
334 LogMsg("ERROR: memory allocation failure");
335 YYABORT;
336 }
337
338 elem->string = $1;
339
340 elem->next = g_addrList;
341 g_addrList = elem;
342 }
343 ;
344
345
346 keycontent:
347 OBRACE keystatements EBRACE
348 {
349 }
350
351 keystatements:
352 |
353 keystatements keystatement SEMICOLON
354 {
355 }
356 ;
357
358 keystatement:
359 KEY DOMAINNAME
360 {
361 StringListElem * elem;
362
363 elem = ( StringListElem* ) malloc( sizeof( StringListElem ) );
364
365 if ( !elem )
366 {
367 LogMsg("ERROR: memory allocation failure");
368 YYABORT;
369 }
370
371 elem->string = $2;
372
373 elem->next = g_stringList;
374 g_stringList = elem;
375 }
376 ;
377
378
379 networkaddress:
380 DOTTED_DECIMAL_ADDRESS
381 |
382 HOSTNAME
383 |
384 WILDCARD
385 ;
386
387 block:
388 OBRACE zonestatements EBRACE SEMICOLON
389 ;
390
391 statements:
392 |
393 statements statement
394 ;
395
396 statement:
397 block
398 {
399 $<string>$ = NULL;
400 }
401 |
402 QUOTEDSTRING
403 {
404 $<string>$ = $1;
405 }
406 %%
407
408 int yywrap(void);
409
410 extern int yylineno;
411
412 void yyerror( const char *str )
413 {
414 fprintf( stderr,"%s:%d: error: %s\n", g_filename, yylineno, str );
415 }
416
417 int yywrap()
418 {
419 return 1;
420 }
421
422
423 int
424 ParseConfig
425 (
426 DaemonInfo * d,
427 const char * file
428 )
429 {
430 extern FILE * yyin;
431 DNSZone * zone;
432 DomainAuthInfo * key;
433 KeySpec * keySpec;
434 ZoneSpec * zoneSpec;
435 int err = 0;
436
437 g_filename = file;
438
439 // Tear down the current zone specifiers
440
441 zone = d->zones;
442
443 while ( zone )
444 {
445 DNSZone * next = zone->next;
446
447 key = zone->updateKeys;
448
449 while ( key )
450 {
451 DomainAuthInfo * nextKey = key->next;
452
453 free( key );
454
455 key = nextKey;
456 }
457
458 key = zone->queryKeys;
459
460 while ( key )
461 {
462 DomainAuthInfo * nextKey = key->next;
463
464 free( key );
465
466 key = nextKey;
467 }
468
469 free( zone );
470
471 zone = next;
472 }
473
474 d->zones = NULL;
475
476 yyin = fopen( file, "r" );
477 require_action( yyin, exit, err = 0 );
478
479 err = yyparse( ( void* ) d );
480 require_action( !err, exit, err = 1 );
481
482 for ( zoneSpec = g_zones; zoneSpec; zoneSpec = zoneSpec->next )
483 {
484 StringListElem * elem;
485 mDNSu8 * ok;
486
487 zone = ( DNSZone* ) malloc( sizeof( DNSZone ) );
488 require_action( zone, exit, err = 1 );
489 memset( zone, 0, sizeof( DNSZone ) );
490
491 zone->next = d->zones;
492 d->zones = zone;
493
494 // Fill in the domainname
495
496 ok = MakeDomainNameFromDNSNameString( &zone->name, zoneSpec->name );
497 require_action( ok, exit, err = 1 );
498
499 // Fill in the type
500
501 zone->type = zoneSpec->type;
502
503 // Fill in the allow-update keys
504
505 for ( elem = zoneSpec->allowUpdate; elem; elem = elem->next )
506 {
507 mDNSBool found = mDNSfalse;
508
509 for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
510 {
511 if ( strcmp( elem->string, keySpec->name ) == 0 )
512 {
513 DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
514 mDNSs32 keylen;
515 require_action( authInfo, exit, err = 1 );
516 memset( authInfo, 0, sizeof( DomainAuthInfo ) );
517
518 ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
519 if (!ok) { free(authInfo); err = 1; goto exit; }
520
521 keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
522 if (keylen < 0) { free(authInfo); err = 1; goto exit; }
523
524 authInfo->next = zone->updateKeys;
525 zone->updateKeys = authInfo;
526
527 found = mDNStrue;
528
529 break;
530 }
531 }
532
533 // Log this
534 require_action( found, exit, err = 1 );
535 }
536
537 // Fill in the allow-query keys
538
539 for ( elem = zoneSpec->allowQuery; elem; elem = elem->next )
540 {
541 mDNSBool found = mDNSfalse;
542
543 for ( keySpec = g_keys; keySpec; keySpec = keySpec->next )
544 {
545 if ( strcmp( elem->string, keySpec->name ) == 0 )
546 {
547 DomainAuthInfo * authInfo = malloc( sizeof( DomainAuthInfo ) );
548 mDNSs32 keylen;
549 require_action( authInfo, exit, err = 1 );
550 memset( authInfo, 0, sizeof( DomainAuthInfo ) );
551
552 ok = MakeDomainNameFromDNSNameString( &authInfo->keyname, keySpec->name );
553 if (!ok) { free(authInfo); err = 1; goto exit; }
554
555 keylen = DNSDigest_ConstructHMACKeyfromBase64( authInfo, keySpec->secret );
556 if (keylen < 0) { free(authInfo); err = 1; goto exit; }
557
558 authInfo->next = zone->queryKeys;
559 zone->queryKeys = authInfo;
560
561 found = mDNStrue;
562
563 break;
564 }
565 }
566
567 // Log this
568 require_action( found, exit, err = 1 );
569 }
570 }
571
572 exit:
573
574 return err;
575 }
576
577
578 void
579 SetupOptions
580 (
581 OptionsInfo * info,
582 void * context
583 )
584 {
585 DaemonInfo * d = ( DaemonInfo* ) context;
586
587 if ( strlen( info->source_address ) )
588 {
589 inet_pton( AF_INET, info->source_address, &d->addr.sin_addr );
590 }
591
592 if ( info->source_port )
593 {
594 d->addr.sin_port = htons( ( mDNSu16 ) info->source_port );
595 }
596
597 if ( strlen( info->server_address ) )
598 {
599 inet_pton( AF_INET, info->server_address, &d->ns_addr.sin_addr );
600 }
601
602 if ( info->server_port )
603 {
604 d->ns_addr.sin_port = htons( ( mDNSu16 ) info->server_port );
605 }
606
607 if ( info->private_port )
608 {
609 d->private_port = mDNSOpaque16fromIntVal( info->private_port );
610 }
611
612 if ( info->llq_port )
613 {
614 d->llq_port = mDNSOpaque16fromIntVal( info->llq_port );
615 }
616 }