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