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