Merge branch 'tomato-ND-USBmod' into tomato-RT
[tomato.git] / release / src / router / radvd / gram.y
blob77e27b3ba7009179c67944f2a44d3037a65a20df
1 /*
2 * $Id: gram.y,v 1.39.2.1 2011/08/22 12:30:47 reubenhwk Exp $
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Lars Fenneberg <lf@elemental.net>
8 * This software is Copyright 1996-2000 by the above mentioned author(s),
9 * All Rights Reserved.
11 * The license which is distributed with this software in the file COPYRIGHT
12 * applies to this software. If your distribution is missing this file, you
13 * may request it from <pekkas@netcore.fi>.
17 #include "config.h"
18 #include "includes.h"
19 #include "radvd.h"
20 #include "defaults.h"
22 extern struct Interface *IfaceList;
23 struct Interface *iface = NULL;
24 struct AdvPrefix *prefix = NULL;
25 struct AdvRoute *route = NULL;
26 struct AdvRDNSS *rdnss = NULL;
27 struct AdvDNSSL *dnssl = NULL;
29 extern char *conf_file;
30 extern int num_lines;
31 extern char *yytext;
33 static void cleanup(void);
34 static void yyerror(char *msg);
35 static int countbits(int b);
36 static int count_mask(struct sockaddr_in6 *m);
37 static struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask);
39 #if 0 /* no longer necessary? */
40 #ifndef HAVE_IN6_ADDR_S6_ADDR
41 # ifdef __FreeBSD__
42 # define s6_addr32 __u6_addr.__u6_addr32
43 # define s6_addr16 __u6_addr.__u6_addr16
44 # endif
45 #endif
46 #endif
48 #define ABORT do { cleanup(); YYABORT; } while (0);
49 #define ADD_TO_LL(type, list, value) \
50 do { \
51 if (iface->list == NULL) \
52 iface->list = value; \
53 else { \
54 type *current = iface->list; \
55 while (current->next != NULL) \
56 current = current->next; \
57 current->next = value; \
58 } \
59 } while (0)
64 %token T_INTERFACE
65 %token T_PREFIX
66 %token T_ROUTE
67 %token T_RDNSS
68 %token T_DNSSL
69 %token T_CLIENTS
71 %token <str> STRING
72 %token <num> NUMBER
73 %token <snum> SIGNEDNUMBER
74 %token <dec> DECIMAL
75 %token <num> SWITCH
76 %token <addr> IPV6ADDR
77 %token INFINITY
79 %token T_IgnoreIfMissing
80 %token T_AdvSendAdvert
81 %token T_MaxRtrAdvInterval
82 %token T_MinRtrAdvInterval
83 %token T_MinDelayBetweenRAs
84 %token T_AdvManagedFlag
85 %token T_AdvOtherConfigFlag
86 %token T_AdvLinkMTU
87 %token T_AdvReachableTime
88 %token T_AdvRetransTimer
89 %token T_AdvCurHopLimit
90 %token T_AdvDefaultLifetime
91 %token T_AdvDefaultPreference
92 %token T_AdvSourceLLAddress
94 %token T_AdvOnLink
95 %token T_AdvAutonomous
96 %token T_AdvValidLifetime
97 %token T_AdvPreferredLifetime
98 %token T_DeprecatePrefix
99 %token T_DecrementLifetimes
101 %token T_AdvRouterAddr
102 %token T_AdvHomeAgentFlag
103 %token T_AdvIntervalOpt
104 %token T_AdvHomeAgentInfo
106 %token T_Base6Interface
107 %token T_Base6to4Interface
108 %token T_UnicastOnly
110 %token T_HomeAgentPreference
111 %token T_HomeAgentLifetime
113 %token T_AdvRoutePreference
114 %token T_AdvRouteLifetime
115 %token T_RemoveRoute
117 %token T_AdvRDNSSPreference
118 %token T_AdvRDNSSOpenFlag
119 %token T_AdvRDNSSLifetime
120 %token T_FlushRDNSS
122 %token T_AdvDNSSLLifetime
123 %token T_FlushDNSSL
125 %token T_AdvMobRtrSupportFlag
127 %token T_BAD_TOKEN
129 %type <str> name
130 %type <pinfo> prefixdef
131 %type <ainfo> clientslist v6addrlist
132 %type <rinfo> routedef
133 %type <rdnssinfo> rdnssdef
134 %type <dnsslinfo> dnssldef
135 %type <num> number_or_infinity
137 %union {
138 unsigned int num;
139 int snum;
140 double dec;
141 struct in6_addr *addr;
142 char *str;
143 struct AdvPrefix *pinfo;
144 struct AdvRoute *rinfo;
145 struct AdvRDNSS *rdnssinfo;
146 struct AdvDNSSL *dnsslinfo;
147 struct Clients *ainfo;
152 grammar : grammar ifacedef
153 | ifacedef
156 ifacedef : ifacehead '{' ifaceparams '}' ';'
158 struct Interface *iface2;
160 iface2 = IfaceList;
161 while (iface2)
163 if (!strcmp(iface2->Name, iface->Name))
165 flog(LOG_ERR, "duplicate interface "
166 "definition for %s", iface->Name);
167 ABORT;
169 iface2 = iface2->next;
172 if (check_device(iface) < 0) {
173 if (iface->IgnoreIfMissing) {
174 dlog(LOG_DEBUG, 4, "interface %s did not exist, ignoring the interface", iface->Name);
176 else {
177 flog(LOG_ERR, "interface %s does not exist", iface->Name);
178 ABORT;
181 if (setup_deviceinfo(iface) < 0)
182 if (!iface->IgnoreIfMissing)
183 ABORT;
184 if (check_iface(iface) < 0)
185 if (!iface->IgnoreIfMissing)
186 ABORT;
187 if (setup_linklocal_addr(iface) < 0)
188 if (!iface->IgnoreIfMissing)
189 ABORT;
190 if (setup_allrouters_membership(iface) < 0)
191 if (!iface->IgnoreIfMissing)
192 ABORT;
194 dlog(LOG_DEBUG, 4, "interface definition for %s is ok", iface->Name);
196 iface->next = IfaceList;
197 IfaceList = iface;
199 iface = NULL;
202 ifacehead : T_INTERFACE name
204 iface = malloc(sizeof(struct Interface));
206 if (iface == NULL) {
207 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
208 ABORT;
211 iface_init_defaults(iface);
212 strncpy(iface->Name, $2, IFNAMSIZ-1);
213 iface->Name[IFNAMSIZ-1] = '\0';
217 name : STRING
219 /* check vality */
220 $$ = $1;
224 ifaceparams :
225 /* empty */
226 | ifaceparam ifaceparams
229 ifaceparam : ifaceval
230 | prefixdef { ADD_TO_LL(struct AdvPrefix, AdvPrefixList, $1); }
231 | clientslist { ADD_TO_LL(struct Clients, ClientList, $1); }
232 | routedef { ADD_TO_LL(struct AdvRoute, AdvRouteList, $1); }
233 | rdnssdef { ADD_TO_LL(struct AdvRDNSS, AdvRDNSSList, $1); }
234 | dnssldef { ADD_TO_LL(struct AdvDNSSL, AdvDNSSLList, $1); }
237 ifaceval : T_MinRtrAdvInterval NUMBER ';'
239 iface->MinRtrAdvInterval = $2;
241 | T_MaxRtrAdvInterval NUMBER ';'
243 iface->MaxRtrAdvInterval = $2;
245 | T_MinDelayBetweenRAs NUMBER ';'
247 iface->MinDelayBetweenRAs = $2;
249 | T_MinRtrAdvInterval DECIMAL ';'
251 iface->MinRtrAdvInterval = $2;
253 | T_MaxRtrAdvInterval DECIMAL ';'
255 iface->MaxRtrAdvInterval = $2;
257 | T_MinDelayBetweenRAs DECIMAL ';'
259 iface->MinDelayBetweenRAs = $2;
261 | T_IgnoreIfMissing SWITCH ';'
263 iface->IgnoreIfMissing = $2;
265 | T_AdvSendAdvert SWITCH ';'
267 iface->AdvSendAdvert = $2;
269 | T_AdvManagedFlag SWITCH ';'
271 iface->AdvManagedFlag = $2;
273 | T_AdvOtherConfigFlag SWITCH ';'
275 iface->AdvOtherConfigFlag = $2;
277 | T_AdvLinkMTU NUMBER ';'
279 iface->AdvLinkMTU = $2;
281 | T_AdvReachableTime NUMBER ';'
283 iface->AdvReachableTime = $2;
285 | T_AdvRetransTimer NUMBER ';'
287 iface->AdvRetransTimer = $2;
289 | T_AdvDefaultLifetime NUMBER ';'
291 iface->AdvDefaultLifetime = $2;
293 | T_AdvDefaultPreference SIGNEDNUMBER ';'
295 iface->AdvDefaultPreference = $2;
297 | T_AdvCurHopLimit NUMBER ';'
299 iface->AdvCurHopLimit = $2;
301 | T_AdvSourceLLAddress SWITCH ';'
303 iface->AdvSourceLLAddress = $2;
305 | T_AdvIntervalOpt SWITCH ';'
307 iface->AdvIntervalOpt = $2;
309 | T_AdvHomeAgentInfo SWITCH ';'
311 iface->AdvHomeAgentInfo = $2;
313 | T_AdvHomeAgentFlag SWITCH ';'
315 iface->AdvHomeAgentFlag = $2;
317 | T_HomeAgentPreference NUMBER ';'
319 iface->HomeAgentPreference = $2;
321 | T_HomeAgentLifetime NUMBER ';'
323 iface->HomeAgentLifetime = $2;
325 | T_UnicastOnly SWITCH ';'
327 iface->UnicastOnly = $2;
329 | T_AdvMobRtrSupportFlag SWITCH ';'
331 iface->AdvMobRtrSupportFlag = $2;
335 clientslist : T_CLIENTS '{' v6addrlist '}' ';'
337 $$ = $3;
341 v6addrlist : IPV6ADDR ';'
343 struct Clients *new = calloc(1, sizeof(struct Clients));
344 if (new == NULL) {
345 flog(LOG_CRIT, "calloc failed: %s", strerror(errno));
346 ABORT;
349 memcpy(&(new->Address), $1, sizeof(struct in6_addr));
350 $$ = new;
352 | v6addrlist IPV6ADDR ';'
354 struct Clients *new = calloc(1, sizeof(struct Clients));
355 if (new == NULL) {
356 flog(LOG_CRIT, "calloc failed: %s", strerror(errno));
357 ABORT;
360 memcpy(&(new->Address), $2, sizeof(struct in6_addr));
361 new->next = $1;
362 $$ = new;
367 prefixdef : prefixhead optional_prefixplist ';'
369 if (prefix) {
370 unsigned int dst;
372 if (prefix->AdvPreferredLifetime > prefix->AdvValidLifetime)
374 flog(LOG_ERR, "AdvValidLifeTime must be "
375 "greater than AdvPreferredLifetime in %s, line %d",
376 conf_file, num_lines);
377 ABORT;
380 if ( prefix->if6[0] && prefix->if6to4[0]) {
381 flog(LOG_ERR, "Base6Interface and Base6to4Interface are mutually exclusive at this time.");
382 ABORT;
385 if ( prefix->if6to4[0] )
387 if (get_v4addr(prefix->if6to4, &dst) < 0)
389 flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 );
390 prefix->enabled = 0;
392 else
394 *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002);
395 memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) );
399 if ( prefix->if6[0] )
401 #ifndef HAVE_IFADDRS_H
402 flog(LOG_ERR, "Base6Interface not supported in %s, line %d", conf_file, num_lines);
403 ABORT;
404 #else
405 struct ifaddrs *ifap = 0, *ifa = 0;
406 struct AdvPrefix *next = prefix->next;
408 if (prefix->PrefixLen != 64) {
409 flog(LOG_ERR, "Only /64 is allowed with Base6Interface. %s:%d", conf_file, num_lines);
410 ABORT;
413 if (getifaddrs(&ifap) != 0)
414 flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno));
416 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
417 struct sockaddr_in6 *s6 = 0;
418 struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask;
419 struct in6_addr base6prefix;
420 char buf[INET6_ADDRSTRLEN];
421 int i;
423 if (strncmp(ifa->ifa_name, prefix->if6, IFNAMSIZ))
424 continue;
426 if (ifa->ifa_addr->sa_family != AF_INET6)
427 continue;
429 s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
431 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
432 continue;
434 base6prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr);
435 for (i = 0; i < 8; ++i) {
436 prefix->Prefix.s6_addr[i] &= ~mask->sin6_addr.s6_addr[i];
437 prefix->Prefix.s6_addr[i] |= base6prefix.s6_addr[i];
439 memset(&prefix->Prefix.s6_addr[8], 0, 8);
440 prefix->AdvRouterAddr = 1;
441 prefix->AutoSelected = 1;
442 prefix->next = next;
444 if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL)
445 flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, conf_file, num_lines);
446 else
447 dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s from interface %s",
448 buf, prefix->PrefixLen, iface->Name, ifa->ifa_name);
450 /* Taking only one prefix from the Base6Interface. Taking more than one would require allocating new
451 prefixes and building a list. I'm not sure how to do that from here. So for now, break. */
452 break;
455 if (ifap)
456 freeifaddrs(ifap);
457 #endif /* ifndef HAVE_IFADDRS_H */
460 $$ = prefix;
461 prefix = NULL;
465 prefixhead : T_PREFIX IPV6ADDR '/' NUMBER
467 struct in6_addr zeroaddr;
468 memset(&zeroaddr, 0, sizeof(zeroaddr));
470 if (!memcmp($2, &zeroaddr, sizeof(struct in6_addr))) {
471 #ifndef HAVE_IFADDRS_H
472 flog(LOG_ERR, "invalid all-zeros prefix in %s, line %d", conf_file, num_lines);
473 ABORT;
474 #else
475 struct ifaddrs *ifap = 0, *ifa = 0;
476 struct AdvPrefix *next = iface->AdvPrefixList;
478 while (next) {
479 if (next->AutoSelected) {
480 flog(LOG_ERR, "auto selecting prefixes works only once per interface. See %s, line %d", conf_file, num_lines);
481 ABORT;
483 next = next->next;
485 next = 0;
487 dlog(LOG_DEBUG, 5, "all-zeros prefix in %s, line %d, parsing..", conf_file, num_lines);
489 if (getifaddrs(&ifap) != 0)
490 flog(LOG_ERR, "getifaddrs failed: %s", strerror(errno));
492 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
493 struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ifa->ifa_addr;
494 struct sockaddr_in6 *mask = (struct sockaddr_in6 *)ifa->ifa_netmask;
495 char buf[INET6_ADDRSTRLEN];
497 if (strncmp(ifa->ifa_name, iface->Name, IFNAMSIZ))
498 continue;
500 if (ifa->ifa_addr->sa_family != AF_INET6)
501 continue;
503 s6 = (struct sockaddr_in6 *)(ifa->ifa_addr);
505 if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr))
506 continue;
508 prefix = malloc(sizeof(struct AdvPrefix));
510 if (prefix == NULL) {
511 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
512 ABORT;
515 prefix_init_defaults(prefix);
516 prefix->Prefix = get_prefix6(&s6->sin6_addr, &mask->sin6_addr);
517 prefix->AdvRouterAddr = 1;
518 prefix->AutoSelected = 1;
519 prefix->next = next;
520 next = prefix;
522 if (prefix->PrefixLen == 0)
523 prefix->PrefixLen = count_mask(mask);
525 if (inet_ntop(ifa->ifa_addr->sa_family, (void *)&(prefix->Prefix), buf, sizeof(buf)) == NULL)
526 flog(LOG_ERR, "%s: inet_ntop failed in %s, line %d!", ifa->ifa_name, conf_file, num_lines);
527 else
528 dlog(LOG_DEBUG, 3, "auto-selected prefix %s/%d on interface %s", buf, prefix->PrefixLen, ifa->ifa_name);
531 if (!prefix) {
532 flog(LOG_WARNING, "no auto-selected prefix on interface %s, disabling advertisements", iface->Name);
535 if (ifap)
536 freeifaddrs(ifap);
537 #endif /* ifndef HAVE_IFADDRS_H */
539 else {
540 prefix = malloc(sizeof(struct AdvPrefix));
542 if (prefix == NULL) {
543 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
544 ABORT;
547 prefix_init_defaults(prefix);
549 if ($4 > MAX_PrefixLen)
551 flog(LOG_ERR, "invalid prefix length in %s, line %d", conf_file, num_lines);
552 ABORT;
555 prefix->PrefixLen = $4;
557 memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr));
562 optional_prefixplist: /* empty */
563 | '{' /* somewhat empty */ '}'
564 | '{' prefixplist '}'
567 prefixplist : prefixplist prefixparms
568 | prefixparms
571 prefixparms : T_AdvOnLink SWITCH ';'
573 if (prefix) {
574 if (prefix->AutoSelected) {
575 struct AdvPrefix *p = prefix;
576 do {
577 p->AdvOnLinkFlag = $2;
578 p = p->next;
579 } while (p && p->AutoSelected);
581 else
582 prefix->AdvOnLinkFlag = $2;
585 | T_AdvAutonomous SWITCH ';'
587 if (prefix) {
588 if (prefix->AutoSelected) {
589 struct AdvPrefix *p = prefix;
590 do {
591 p->AdvAutonomousFlag = $2;
592 p = p->next;
593 } while (p && p->AutoSelected);
595 else
596 prefix->AdvAutonomousFlag = $2;
599 | T_AdvRouterAddr SWITCH ';'
601 if (prefix) {
602 if (prefix->AutoSelected && $2 == 0)
603 flog(LOG_WARNING, "prefix automatically selected, AdvRouterAddr always enabled, ignoring config line %d", num_lines);
604 else
605 prefix->AdvRouterAddr = $2;
608 | T_AdvValidLifetime number_or_infinity ';'
610 if (prefix) {
611 if (prefix->AutoSelected) {
612 struct AdvPrefix *p = prefix;
613 do {
614 p->AdvValidLifetime = $2;
615 p->curr_validlft = $2;
616 p = p->next;
617 } while (p && p->AutoSelected);
619 else
620 prefix->AdvValidLifetime = $2;
621 prefix->curr_validlft = $2;
624 | T_AdvPreferredLifetime number_or_infinity ';'
626 if (prefix) {
627 if (prefix->AutoSelected) {
628 struct AdvPrefix *p = prefix;
629 do {
630 p->AdvPreferredLifetime = $2;
631 p->curr_preferredlft = $2;
632 p = p->next;
633 } while (p && p->AutoSelected);
635 else
636 prefix->AdvPreferredLifetime = $2;
637 prefix->curr_preferredlft = $2;
640 | T_DeprecatePrefix SWITCH ';'
642 prefix->DeprecatePrefixFlag = $2;
644 | T_DecrementLifetimes SWITCH ';'
646 prefix->DecrementLifetimesFlag = $2;
648 | T_Base6Interface name ';'
650 if (prefix) {
651 if (prefix->AutoSelected) {
652 flog(LOG_ERR, "automatically selecting the prefix and Base6to4Interface are mutually exclusive");
653 ABORT;
654 } /* fallthrough */
655 dlog(LOG_DEBUG, 4, "using prefixes on interface %s for prefixes on interface %s", $2, iface->Name);
656 strncpy(prefix->if6, $2, IFNAMSIZ-1);
657 prefix->if6[IFNAMSIZ-1] = '\0';
661 | T_Base6to4Interface name ';'
663 if (prefix) {
664 if (prefix->AutoSelected) {
665 flog(LOG_ERR, "automatically selecting the prefix and Base6to4Interface are mutually exclusive");
666 ABORT;
667 } /* fallthrough */
668 dlog(LOG_DEBUG, 4, "using interface %s for 6to4 prefixes on interface %s", $2, iface->Name);
669 strncpy(prefix->if6to4, $2, IFNAMSIZ-1);
670 prefix->if6to4[IFNAMSIZ-1] = '\0';
675 routedef : routehead '{' optional_routeplist '}' ';'
677 $$ = route;
678 route = NULL;
683 routehead : T_ROUTE IPV6ADDR '/' NUMBER
685 route = malloc(sizeof(struct AdvRoute));
687 if (route == NULL) {
688 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
689 ABORT;
692 route_init_defaults(route, iface);
694 if ($4 > MAX_PrefixLen)
696 flog(LOG_ERR, "invalid route prefix length in %s, line %d", conf_file, num_lines);
697 ABORT;
700 route->PrefixLen = $4;
702 memcpy(&route->Prefix, $2, sizeof(struct in6_addr));
707 optional_routeplist: /* empty */
708 | routeplist
711 routeplist : routeplist routeparms
712 | routeparms
716 routeparms : T_AdvRoutePreference SIGNEDNUMBER ';'
718 route->AdvRoutePreference = $2;
720 | T_AdvRouteLifetime number_or_infinity ';'
722 route->AdvRouteLifetime = $2;
724 | T_RemoveRoute SWITCH ';'
726 route->RemoveRouteFlag = $2;
730 rdnssdef : rdnsshead '{' optional_rdnssplist '}' ';'
732 $$ = rdnss;
733 rdnss = NULL;
737 rdnssaddrs : rdnssaddrs rdnssaddr
738 | rdnssaddr
741 rdnssaddr : IPV6ADDR
743 if (!rdnss) {
744 /* first IP found */
745 rdnss = malloc(sizeof(struct AdvRDNSS));
747 if (rdnss == NULL) {
748 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
749 ABORT;
752 rdnss_init_defaults(rdnss, iface);
755 switch (rdnss->AdvRDNSSNumber) {
756 case 0:
757 memcpy(&rdnss->AdvRDNSSAddr1, $1, sizeof(struct in6_addr));
758 rdnss->AdvRDNSSNumber++;
759 break;
760 case 1:
761 memcpy(&rdnss->AdvRDNSSAddr2, $1, sizeof(struct in6_addr));
762 rdnss->AdvRDNSSNumber++;
763 break;
764 case 2:
765 memcpy(&rdnss->AdvRDNSSAddr3, $1, sizeof(struct in6_addr));
766 rdnss->AdvRDNSSNumber++;
767 break;
768 default:
769 flog(LOG_CRIT, "Too many addresses in RDNSS section");
770 ABORT;
776 rdnsshead : T_RDNSS rdnssaddrs
778 if (!rdnss) {
779 flog(LOG_CRIT, "No address specified in RDNSS section");
780 ABORT;
785 optional_rdnssplist: /* empty */
786 | rdnssplist
789 rdnssplist : rdnssplist rdnssparms
790 | rdnssparms
794 rdnssparms : T_AdvRDNSSPreference NUMBER ';'
796 flog(LOG_WARNING, "Ignoring deprecated RDNSS preference.");
798 | T_AdvRDNSSOpenFlag SWITCH ';'
800 flog(LOG_WARNING, "Ignoring deprecated RDNSS open flag.");
802 | T_AdvRDNSSLifetime number_or_infinity ';'
804 if ($2 < iface->MaxRtrAdvInterval && $2 != 0) {
805 flog(LOG_ERR, "AdvRDNSSLifetime must be at least MaxRtrAdvInterval");
806 ABORT;
808 if ($2 > 2*(iface->MaxRtrAdvInterval))
809 flog(LOG_WARNING, "Warning: AdvRDNSSLifetime <= 2*MaxRtrAdvInterval would allow stale DNS servers to be deleted faster");
811 rdnss->AdvRDNSSLifetime = $2;
813 | T_FlushRDNSS SWITCH ';'
815 rdnss->FlushRDNSSFlag = $2;
819 dnssldef : dnsslhead '{' optional_dnsslplist '}' ';'
821 $$ = dnssl;
822 dnssl = NULL;
826 dnsslsuffixes : dnsslsuffixes dnsslsuffix
827 | dnsslsuffix
830 dnsslsuffix : STRING
832 char *ch;
833 for (ch = $1;*ch != '\0';ch++) {
834 if (*ch >= 'A' && *ch <= 'Z')
835 continue;
836 if (*ch >= 'a' && *ch <= 'z')
837 continue;
838 if (*ch >= '0' && *ch <= '9')
839 continue;
840 if (*ch == '-' || *ch == '.')
841 continue;
843 flog(LOG_CRIT, "Invalid domain suffix specified");
844 ABORT;
847 if (!dnssl) {
848 /* first domain found */
849 dnssl = malloc(sizeof(struct AdvDNSSL));
851 if (dnssl == NULL) {
852 flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
853 ABORT;
856 dnssl_init_defaults(dnssl, iface);
859 dnssl->AdvDNSSLNumber++;
860 dnssl->AdvDNSSLSuffixes =
861 realloc(dnssl->AdvDNSSLSuffixes,
862 dnssl->AdvDNSSLNumber * sizeof(char*));
863 if (dnssl->AdvDNSSLSuffixes == NULL) {
864 flog(LOG_CRIT, "realloc failed: %s", strerror(errno));
865 ABORT;
868 dnssl->AdvDNSSLSuffixes[dnssl->AdvDNSSLNumber - 1] = strdup($1);
872 dnsslhead : T_DNSSL dnsslsuffixes
874 if (!dnssl) {
875 flog(LOG_CRIT, "No domain specified in DNSSL section");
876 ABORT;
881 optional_dnsslplist: /* empty */
882 | dnsslplist
885 dnsslplist : dnsslplist dnsslparms
886 | dnsslparms
890 dnsslparms : T_AdvDNSSLLifetime number_or_infinity ';'
892 if ($2 < iface->MaxRtrAdvInterval && $2 != 0) {
893 flog(LOG_ERR, "AdvDNSSLLifetime must be at least MaxRtrAdvInterval");
894 ABORT;
896 if ($2 > 2*(iface->MaxRtrAdvInterval))
897 flog(LOG_WARNING, "Warning: AdvDNSSLLifetime <= 2*MaxRtrAdvInterval would allow stale DNS suffixes to be deleted faster");
899 dnssl->AdvDNSSLLifetime = $2;
901 | T_FlushDNSSL SWITCH ';'
903 dnssl->FlushDNSSLFlag = $2;
907 number_or_infinity : NUMBER
909 $$ = $1;
911 | INFINITY
913 $$ = (uint32_t)~0;
919 static
920 int countbits(int b)
922 int count;
924 for (count = 0; b != 0; count++) {
925 b &= b - 1; // this clears the LSB-most set bit
928 return (count);
931 static
932 int count_mask(struct sockaddr_in6 *m)
934 struct in6_addr *in6 = &m->sin6_addr;
935 int i;
936 int count = 0;
938 for (i = 0; i < 16; ++i) {
939 count += countbits(in6->s6_addr[i]);
941 return count;
944 static
945 struct in6_addr get_prefix6(struct in6_addr const *addr, struct in6_addr const *mask)
947 struct in6_addr prefix = *addr;
948 int i = 0;
950 for (; i < 16; ++i) {
951 prefix.s6_addr[i] &= mask->s6_addr[i];
954 return prefix;
957 static
958 void cleanup(void)
960 if (iface)
961 free(iface);
963 if (prefix)
964 free(prefix);
966 if (route)
967 free(route);
969 if (rdnss)
970 free(rdnss);
972 if (dnssl) {
973 int i;
974 for (i = 0;i < dnssl->AdvDNSSLNumber;i++)
975 free(dnssl->AdvDNSSLSuffixes[i]);
976 free(dnssl->AdvDNSSLSuffixes);
977 free(dnssl);
981 static void
982 yyerror(char *msg)
984 cleanup();
985 flog(LOG_ERR, "%s in %s, line %d: %s", msg, conf_file, num_lines, yytext);