05e2375325bcfa5e6ed72cf7c3f2afd833d41521
[dragonfly.git] / usr.sbin / rrenumd / parser.y
1 /*      $KAME: parser.y,v 1.8 2000/11/08 03:03:34 jinmei Exp $  */
2
3 /*
4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: src/usr.sbin/rrenumd/parser.y,v 1.1.2.2 2001/07/03 11:02:10 ume Exp $
32  * $DragonFly: src/usr.sbin/rrenumd/parser.y,v 1.3 2003/11/03 19:31:42 eirikn Exp $
33  */
34
35 %{
36 #include <sys/param.h>
37 #include <sys/ioctl.h>
38 #include <sys/socket.h>
39 #include <sys/uio.h>
40 #include <sys/queue.h>
41
42 #include <net/if.h>
43 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
44 #include <net/if_var.h>
45 #endif /* __FreeBSD__ >= 3 */
46
47 #include <netinet/in.h>
48 #include <netinet/in_var.h>
49 #include <netinet/icmp6.h>
50
51 #include <netdb.h>
52 #include <string.h>
53 #include <stdio.h>
54
55 #include "rrenumd.h"
56
57 struct config_is_set {
58         u_short cis_dest : 1;
59 } cis;
60
61 struct dst_list *dl_head;
62 struct payload_list *pl_head, ple_cur;
63 u_int retry;
64 char errbuf[LINE_MAX];
65
66 extern int lineno;
67 extern void yyerror(const char *s);
68 extern int yylex(void);
69 static struct payload_list * pllist_lookup(int seqnum);
70 static void pllist_enqueue(struct payload_list *pl_entry);
71
72 #define MAX_RETRYNUM 10 /* upper limit of retry in this rrenumd program */
73 #define MAX_SEQNUM 256 /* upper limit of seqnum in this rrenumd program */
74 #define NOSPEC  -1
75
76 %}
77
78 %union {
79         u_long num;
80         struct {
81                 char *cp;
82                 int len;
83         } cs;
84         struct in_addr addr4;
85         struct in6_addr addr6;
86         struct {
87                 struct in6_addr addr;
88                 u_char plen;
89         } prefix;
90         struct dst_list *dl;
91         struct payload_list *pl;
92         struct sockaddr *sa;
93 }
94
95 %token <num> ADD CHANGE SETGLOBAL
96 %token DEBUG_CMD DEST_CMD RETRY_CMD SEQNUM_CMD
97 %token MATCH_PREFIX_CMD MAXLEN_CMD MINLEN_CMD
98 %token USE_PREFIX_CMD KEEPLEN_CMD
99 %token VLTIME_CMD PLTIME_CMD
100 %token RAF_ONLINK_CMD RAF_AUTO_CMD RAF_DECRVALID_CMD RAF_DECRPREFD_CMD
101 %token <num> DAYS HOURS MINUTES SECONDS INFINITY
102 %token <num> ON OFF
103 %token BCL ECL EOS ERROR
104 %token <cs> NAME HOSTNAME QSTRING DECSTRING
105 %token <addr4> IPV4ADDR
106 %token <addr6> IPV6ADDR
107 %token <num> PREFIXLEN
108
109 %type <num> retrynum seqnum rrenum_cmd
110 %type <num> prefixlen maxlen minlen keeplen vltime pltime
111 %type <num> lifetime days hours minutes seconds
112 %type <num> decstring
113 %type <num> raf_onlink raf_auto raf_decrvalid raf_decrprefd flag
114 %type <dl> dest_addrs dest_addr sin sin6
115 %type <pl> rrenum_statement
116 %type <cs> ifname
117 %type <prefix> prefixval
118
119 %%
120 config:
121                 /* empty */
122         |       statements
123         ;
124
125 statements:
126                 statement
127         |       statements statement
128         ;
129
130 statement:
131                 debug_statement
132         |       destination_statement
133         |       rrenum_statement_without_seqnum
134         |       rrenum_statement_with_seqnum
135         |       error EOS
136                 {
137                         yyerrok;
138                 }
139         |       EOS
140         ;
141
142 debug_statement:
143                 DEBUG_CMD flag EOS
144                 {
145 #ifdef YYDEBUG
146                         yydebug = $2;
147 #endif /* YYDEBUG */
148                 }
149         ;
150
151 destination_statement:
152                 DEST_CMD dest_addrs retrynum EOS
153                 {
154                         dl_head = $2;
155                         retry = $3;
156                 }
157         ;
158
159 dest_addrs:
160                 dest_addr
161         |       dest_addrs dest_addr
162                 {
163                         $2->dl_next = $1;
164                         $$ = $2;
165                 }
166         ;
167
168 dest_addr :
169                 sin
170                 {
171                         with_v4dest = 1;
172                 }
173         |       sin6
174                 {
175                         with_v6dest = 1;
176                 }
177         |       sin6 ifname
178                 {
179                         struct sockaddr_in6 *sin6;
180
181                         sin6 = (struct sockaddr_in6 *)$1->dl_dst;
182                         sin6->sin6_scope_id = if_nametoindex($2.cp);
183                         with_v6dest = 1;
184                         $$ = $1;
185                 }
186         |       HOSTNAME
187                 {
188                         struct sockaddr_storage *ss;
189                         struct addrinfo hints, *res;
190                         int error;
191
192                         memset(&hints, 0, sizeof(hints));
193                         hints.ai_flags = AI_CANONNAME;
194                         hints.ai_family = AF_UNSPEC;
195                         hints.ai_socktype = SOCK_RAW;
196                         hints.ai_protocol = 0;
197                         error = getaddrinfo($1.cp, 0, &hints, &res);
198                         if (error) {
199                                 snprintf(errbuf, sizeof(errbuf),
200                                     "name resolution failed for %s:%s",
201                                     $1.cp, gai_strerror(error));
202                                 yyerror(errbuf);
203                         }
204                         ss = (struct sockaddr_storage *)malloc(sizeof(*ss));
205                         memset(ss, 0, sizeof(*ss));
206                         memcpy(ss, res->ai_addr, res->ai_addr->sa_len);
207                         freeaddrinfo(res);
208
209                         $$ = (struct dst_list *)
210                              malloc(sizeof(struct dst_list));
211                         memset($$, 0, sizeof(struct dst_list));
212                         $$->dl_dst = (struct sockaddr *)ss;
213                 }
214         ;
215
216 sin:
217                 IPV4ADDR
218                 {
219                         struct sockaddr_in *sin;
220
221                         sin = (struct sockaddr_in *)malloc(sizeof(*sin));
222                         memset(sin, 0, sizeof(*sin));
223                         sin->sin_len = sizeof(*sin);
224                         sin->sin_family = AF_INET;
225                         sin->sin_addr = $1;
226
227                         $$ = (struct dst_list *)
228                              malloc(sizeof(struct dst_list));
229                         memset($$, 0, sizeof(struct dst_list));
230                         $$->dl_dst = (struct sockaddr *)sin;
231                 }
232         ;
233
234 sin6:
235                 IPV6ADDR
236                 {
237                         struct sockaddr_in6 *sin6;
238
239                         sin6 = (struct sockaddr_in6 *)malloc(sizeof(*sin6));
240                         memset(sin6, 0, sizeof(*sin6));
241                         sin6->sin6_len = sizeof(*sin6);
242                         sin6->sin6_family = AF_INET6;
243                         sin6->sin6_addr = $1;
244
245                         $$ = (struct dst_list *)
246                              malloc(sizeof(struct dst_list));
247                         memset($$, 0, sizeof(struct dst_list));
248                         $$->dl_dst = (struct sockaddr *)sin6;
249                 }
250
251 ifname:
252                 NAME
253                 {
254                         $$.cp = strdup($1.cp);
255                         $$.len = $1.len;
256                 }
257         |       QSTRING
258                 {
259                         $1.cp[$1.len - 1] = 0;
260                         $$.cp = strdup(&$1.cp[1]);
261                         $$.len = $1.len - 2;
262                 }
263         ;
264
265 retrynum:
266                 /* empty */
267                 {
268                         $$ = 2;
269                 }
270         |       RETRY_CMD decstring
271                 {
272                         if ($2 > MAX_RETRYNUM)
273                                 $2 = MAX_RETRYNUM;
274                         $$ = $2;
275                 }
276         ;
277
278 rrenum_statement_with_seqnum:
279                 SEQNUM_CMD seqnum
280                 {
281                         if (pllist_lookup($2)) {
282                                 snprintf(errbuf, sizeof(errbuf),
283                                     "duplicate seqnum %ld specified at %d",
284                                     $2, lineno);
285                                 yyerror(errbuf);
286                         }
287                 }
288                 BCL rrenum_statement EOS ECL EOS
289                 {
290                         $5->pl_irr.rr_seqnum = $2;
291                         pllist_enqueue($5);
292                 }
293         ;
294
295 seqnum:
296                 /* empty */
297                 {
298                         $$ = 0;
299                 }
300         |       decstring
301                 {
302                         if ($1 > MAX_SEQNUM) {
303                                 snprintf(errbuf, sizeof(errbuf),
304                                     "seqnum %ld is illegal for this  program. "
305                                     "should be between 0 and %d",
306                                     $1, MAX_SEQNUM);
307                                 yyerror(errbuf);
308                         }
309                         $$ = $1;
310                 }
311         ;
312
313 rrenum_statement_without_seqnum:
314                 rrenum_statement EOS
315                 {
316                         if (pllist_lookup(0)) {
317                                 snprintf(errbuf, sizeof(errbuf),
318                                     "duplicate seqnum %d specified  at %d",
319                                     0, lineno);
320                                 yyerror(errbuf);
321                         }
322                         $1->pl_irr.rr_seqnum = 0;
323                         pllist_enqueue($1);
324                 }
325         ;
326
327 rrenum_statement:
328                 match_prefix_definition use_prefix_definition
329                 {
330                         $$ = (struct payload_list *)
331                              malloc(sizeof(struct payload_list));
332                         memcpy($$, &ple_cur, sizeof(ple_cur));
333                 }
334         ;
335
336 match_prefix_definition:
337                 rrenum_cmd MATCH_PREFIX_CMD prefixval maxlen minlen
338                 {
339                         struct icmp6_router_renum *irr;
340                         struct rr_pco_match *rpm;
341
342                         irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
343                         rpm = (struct rr_pco_match *)(irr + 1);
344                         memset(rpm, 0, sizeof(*rpm));
345
346                         rpm->rpm_code = $1;
347                         rpm->rpm_prefix = $3.addr;
348                         rpm->rpm_matchlen = $3.plen;
349                         rpm->rpm_maxlen = $4;
350                         rpm->rpm_minlen = $5;
351                 }
352         ;
353
354 rrenum_cmd:
355                 /* empty */
356                 {
357                         $$ = RPM_PCO_ADD;
358                 }
359         |       ADD
360         |       CHANGE
361         |       SETGLOBAL
362         ;
363
364 prefixval:
365                 IPV6ADDR prefixlen
366                 {
367                         $$.addr = $1;
368                         $$.plen = $2;
369                 }
370         ;
371
372 prefixlen:
373                 /* empty */
374                 {
375                         $$ = 64;
376                 }
377         |       PREFIXLEN
378         ;
379
380 maxlen:
381                 /* empty */
382                 {
383                         $$ = 128;
384                 }
385         |       MAXLEN_CMD decstring
386                 {
387                         if ($2 > 128)
388                                 $2 = 128;
389                         $$ = $2;
390                 }
391         ;
392
393 minlen:
394                 /* empty */
395                 {
396                         $$ = 0;
397                 }
398         |       MINLEN_CMD decstring
399                 {
400                         if ($2 > 128)
401                                 $2 = 128;
402                         $$ = $2;
403                 }
404         ;
405
406 use_prefix_definition:
407                 /* empty */
408                 {
409                         struct icmp6_router_renum *irr;
410                         struct rr_pco_match *rpm;
411                         struct rr_pco_use *rpu;
412
413                         irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
414                         rpm = (struct rr_pco_match *)(irr + 1);
415                         rpu = (struct rr_pco_use *)(rpm + 1);
416                         memset(rpu, 0, sizeof(*rpu));
417                 }
418         |       USE_PREFIX_CMD prefixval keeplen use_prefix_values
419                 {
420                         struct icmp6_router_renum *irr;
421                         struct rr_pco_match *rpm;
422                         struct rr_pco_use *rpu;
423
424                         irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
425                         rpm = (struct rr_pco_match *)(irr + 1);
426                         rpu = (struct rr_pco_use *)(rpm + 1);
427
428                         rpu->rpu_prefix = $2.addr;
429                         rpu->rpu_uselen = $2.plen;
430                         rpu->rpu_keeplen = $3;
431                 }
432         ;
433
434 use_prefix_values:
435                 /* empty */
436                 {
437                         struct icmp6_router_renum *irr;
438                         struct rr_pco_match *rpm;
439                         struct rr_pco_use *rpu;
440
441                         irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
442                         rpm = (struct rr_pco_match *)(irr + 1);
443                         rpu = (struct rr_pco_use *)(rpm + 1);
444                         memset(rpu, 0, sizeof(*rpu));
445
446                         rpu->rpu_vltime = htonl(DEF_VLTIME);
447                         rpu->rpu_pltime = htonl(DEF_PLTIME);
448                         rpu->rpu_ramask = 0;
449                         rpu->rpu_flags = 0;
450                 }
451         |       BCL vltime pltime raf_onlink raf_auto raf_decrvalid raf_decrprefd ECL
452                 {
453                         struct icmp6_router_renum *irr;
454                         struct rr_pco_match *rpm;
455                         struct rr_pco_use *rpu;
456
457                         irr = (struct icmp6_router_renum *)&ple_cur.pl_irr;
458                         rpm = (struct rr_pco_match *)(irr + 1);
459                         rpu = (struct rr_pco_use *)(rpm + 1);
460                         memset(rpu, 0, sizeof(*rpu));
461
462                         rpu->rpu_vltime = $2;
463                         rpu->rpu_pltime = $3;
464                         if ($4 == NOSPEC) {
465                                 rpu->rpu_ramask &=
466                                     ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
467                         } else {
468                                 rpu->rpu_ramask |=
469                                     ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
470                                 if ($4 == ON) {
471                                         rpu->rpu_raflags |=
472                                             ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
473                                 } else {
474                                         rpu->rpu_raflags &=
475                                             ~ICMP6_RR_PCOUSE_RAFLAGS_ONLINK;
476                                 }
477                         }
478                         if ($5 == NOSPEC) {
479                                 rpu->rpu_ramask &=
480                                     ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
481                         } else {
482                                 rpu->rpu_ramask |=
483                                     ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
484                                 if ($5 == ON) {
485                                         rpu->rpu_raflags |=
486                                             ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
487                                 } else {
488                                         rpu->rpu_raflags &=
489                                             ~ICMP6_RR_PCOUSE_RAFLAGS_AUTO;
490                                 }
491                         }
492                         rpu->rpu_flags = 0;
493                         if ($6 == ON) {
494                                 rpu->rpu_flags |=
495                                     ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME;
496                         }
497                         if ($7 == ON) {
498                                 rpu->rpu_flags |=
499                                     ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME;
500                         }
501                 }
502         ;
503
504 keeplen:
505                 /* empty */
506                 {
507                         $$ = 0;
508                 }
509         |       KEEPLEN_CMD decstring
510                 {
511                         if ($2 > 128)
512                                 $2 = 128;
513                         $$ = $2;
514                 }
515         ;
516
517
518 vltime:
519                 /* empty */
520                 {
521                         $$ = htonl(DEF_VLTIME);
522                 }
523         |       VLTIME_CMD lifetime
524                 {
525                         $$ = htonl($2);
526                 }
527         ;
528
529 pltime:
530                 /* empty */
531                 {
532                         $$ = htonl(DEF_PLTIME);
533                 }
534         |       PLTIME_CMD lifetime
535                 {
536                         $$ = htonl($2);
537                 }
538
539 raf_onlink:
540                 /* empty */
541                 {
542                         $$ = NOSPEC;
543                 }
544         |       RAF_ONLINK_CMD flag
545                 {
546                         $$ = $2;
547                 }
548         ;
549
550 raf_auto:
551                 /* empty */
552                 {
553                         $$ = NOSPEC;
554                 }
555         |       RAF_AUTO_CMD flag
556                 {
557                         $$ = $2;
558                 }
559         ;
560
561 raf_decrvalid:
562                 /* empty */
563                 {
564                         $$ = NOSPEC;
565                 }
566         |       RAF_DECRVALID_CMD flag
567                 {
568                         $$ = $2;
569                 }
570         ;
571
572 raf_decrprefd:
573                 /* empty */
574                 {
575                         $$ = NOSPEC;
576                 }
577         |       RAF_DECRPREFD_CMD flag
578                 {
579                         $$ = $2;
580                 }
581         ;
582
583 flag:
584                 ON { $$ = ON; }
585         |       OFF { $$ = OFF; }
586         ;
587
588 lifetime:
589                 decstring
590         |       INFINITY
591                 {
592                         $$ = 0xffffffff;
593                 }
594         |       days hours minutes seconds
595                 {
596                         int d, h, m, s;
597
598                         d = $1 * 24 * 60 * 60;
599                         h = $2 * 60 * 60;
600                         m = $3 * 60;
601                         s = $4;
602                         $$ = d + h + m + s;
603                 }
604         ;
605
606 days:
607                 /* empty */
608                 {
609                         $$ = 0;
610                 }
611         |       DAYS
612         ;
613
614 hours:
615                 /* empty */
616                 {
617                         $$ = 0;
618                 }
619         |       HOURS
620         ;
621
622 minutes:
623                 /* empty */
624                 {
625                         $$ = 0;
626                 }
627         |       MINUTES
628         ;
629
630 seconds:
631                 /* empty */
632                 {
633                         $$ = 0;
634                 }
635         |       SECONDS
636         ;
637
638 decstring:
639                 DECSTRING
640                 {
641                         int dval;
642
643                         dval = atoi($1.cp);
644                         $$ = dval;
645                 }
646         ;
647
648 %%
649
650 static struct payload_list *
651 pllist_lookup(int seqnum)
652 {
653         struct payload_list *pl;
654         for (pl = pl_head; pl && pl->pl_irr.rr_seqnum != seqnum;
655              pl = pl->pl_next)
656                 continue;
657         return (pl);
658 }
659
660 static void
661 pllist_enqueue(struct payload_list *pl_entry)
662 {
663         struct payload_list *pl, *pl_last;
664
665         pl_last = NULL;
666         for (pl = pl_head;
667              pl && pl->pl_irr.rr_seqnum < pl_entry->pl_irr.rr_seqnum;
668              pl_last = pl, pl = pl->pl_next)
669                 continue;
670         if (pl_last)
671                 pl_last->pl_next = pl_entry;
672         else
673                 pl_head = pl_entry;
674
675         return;
676 }