]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - support/sdk/c/blip/driver/radvd-1.0/gram.y
Merge TinyOS 2.1.1 into master.
[tinyos-2.x.git] / support / sdk / c / blip / driver / radvd-1.0 / gram.y
diff --git a/support/sdk/c/blip/driver/radvd-1.0/gram.y b/support/sdk/c/blip/driver/radvd-1.0/gram.y
new file mode 100644 (file)
index 0000000..06b7acf
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ *   $Id$
+ *
+ *   Authors:
+ *    Pedro Roque              <roque@di.fc.ul.pt>
+ *    Lars Fenneberg           <lf@elemental.net>       
+ *
+ *   This software is Copyright 1996-2000 by the above mentioned author(s), 
+ *   All Rights Reserved.
+ *
+ *   The license which is distributed with this software in the file COPYRIGHT
+ *   applies to this software. If your distribution is missing this file, you
+ *   may request it from <pekkas@netcore.fi>.
+ *
+ */
+%{
+#include <config.h>
+#include <includes.h>
+#include <radvd.h>
+#include <defaults.h>
+
+extern struct Interface *IfaceList;
+struct Interface *iface = NULL;
+struct AdvPrefix *prefix = NULL;
+struct AdvRoute *route = NULL;
+struct AdvRDNSS *rdnss = NULL;
+
+extern char *conf_file;
+extern int num_lines;
+extern char *yytext;
+extern int sock;
+
+static void cleanup(void);
+static void yyerror(char *msg);
+
+#if 0 /* no longer necessary? */
+#ifndef HAVE_IN6_ADDR_S6_ADDR
+# ifdef __FreeBSD__
+#  define s6_addr32 __u6_addr.__u6_addr32
+#  define s6_addr16 __u6_addr.__u6_addr16
+# endif
+#endif
+#endif
+
+#define ABORT  do { cleanup(); YYABORT; } while (0);
+
+%}
+
+%token         T_INTERFACE
+%token         T_PREFIX
+%token         T_ROUTE
+%token         T_RDNSS
+
+%token <str>   STRING
+%token <num>   NUMBER
+%token <snum>  SIGNEDNUMBER
+%token <dec>   DECIMAL
+%token <bool>  SWITCH
+%token <addr>  IPV6ADDR
+%token                 INFINITY
+
+%token         T_IgnoreIfMissing
+%token         T_AdvSendAdvert
+%token         T_MaxRtrAdvInterval
+%token         T_MinRtrAdvInterval
+%token         T_MinDelayBetweenRAs
+%token         T_AdvManagedFlag
+%token         T_AdvOtherConfigFlag
+%token         T_AdvLinkMTU
+%token         T_AdvReachableTime
+%token         T_AdvRetransTimer
+%token         T_AdvCurHopLimit
+%token         T_AdvDefaultLifetime
+%token         T_AdvDefaultPreference
+%token         T_AdvSourceLLAddress
+
+%token         T_AdvOnLink
+%token         T_AdvAutonomous
+%token         T_AdvValidLifetime
+%token         T_AdvPreferredLifetime
+
+%token         T_AdvRouterAddr
+%token         T_AdvHomeAgentFlag
+%token         T_AdvIntervalOpt
+%token         T_AdvHomeAgentInfo
+
+%token         T_Base6to4Interface
+%token         T_UnicastOnly
+
+%token         T_HomeAgentPreference
+%token         T_HomeAgentLifetime
+
+%token         T_AdvRoutePreference
+%token         T_AdvRouteLifetime
+
+%token         T_AdvRDNSSPreference
+%token         T_AdvRDNSSOpenFlag
+%token         T_AdvRDNSSLifetime
+
+%token         T_AdvMobRtrSupportFlag
+
+%token         T_BAD_TOKEN
+
+%type  <str>   name
+%type  <pinfo> optional_prefixlist prefixdef prefixlist
+%type  <rinfo> optional_routelist routedef routelist
+%type  <rdnssinfo> optional_rdnsslist rdnssdef rdnsslist
+%type   <num>  number_or_infinity
+
+%union {
+       unsigned int            num;
+       int                     snum;
+       double                  dec;
+       int                     bool;
+       struct in6_addr         *addr;
+       char                    *str;
+       struct AdvPrefix        *pinfo;
+       struct AdvRoute         *rinfo;
+       struct AdvRDNSS         *rdnssinfo;
+};
+
+%%
+
+grammar                : grammar ifacedef
+               | ifacedef
+               ;
+
+ifacedef       : ifacehead '{' ifaceparams  '}' ';'
+               {
+                       struct Interface *iface2;
+
+                       iface2 = IfaceList;
+                       while (iface2)
+                       {
+                               if (!strcmp(iface2->Name, iface->Name))
+                               {
+                                       flog(LOG_ERR, "duplicate interface "
+                                               "definition for %s", iface->Name);
+                                       ABORT;
+                               }
+                               iface2 = iface2->next;
+                       }                       
+
+                       if (check_device(sock, iface) < 0) {
+                               if (iface->IgnoreIfMissing) {
+                                       dlog(LOG_DEBUG, 4, "interface %s did not exist, ignoring the interface", iface->Name);
+                                       goto skip_interface;
+                               }
+                               else {
+                                       flog(LOG_ERR, "interface %s does not exist", iface->Name);
+                                       ABORT;
+                               }
+                       }
+                       if (setup_deviceinfo(sock, iface) < 0)
+                               ABORT;
+                       if (check_iface(iface) < 0)
+                               ABORT;
+                       if (setup_linklocal_addr(sock, iface) < 0)
+                               ABORT;
+                       if (setup_allrouters_membership(sock, iface) < 0)
+                               ABORT;
+
+                       iface->next = IfaceList;
+                       IfaceList = iface;
+
+                       dlog(LOG_DEBUG, 4, "interface definition for %s is ok", iface->Name);
+
+skip_interface:
+                       iface = NULL;
+               };
+
+ifacehead      : T_INTERFACE name
+               {
+                       iface = malloc(sizeof(struct Interface));
+
+                       if (iface == NULL) {
+                               flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+                               ABORT;
+                       }
+
+                       iface_init_defaults(iface);
+                       strncpy(iface->Name, $2, IFNAMSIZ-1);
+                       iface->Name[IFNAMSIZ-1] = '\0';
+               }
+               ;
+       
+name           : STRING
+               {
+                       /* check vality */
+                       $$ = $1;
+               }
+               ;
+
+ifaceparams    : optional_ifacevlist optional_prefixlist optional_routelist optional_rdnsslist
+               {
+                       iface->AdvPrefixList = $2;
+                       iface->AdvRouteList = $3;
+                       iface->AdvRDNSSList = $4;
+               }
+               ;
+
+optional_ifacevlist: /* empty */
+                  | ifacevlist
+                  ;
+
+optional_prefixlist: /* empty */
+               {
+                       $$ = NULL;
+               }
+               | prefixlist
+               ;
+
+optional_routelist: /* empty */
+               {
+                       $$ = NULL;
+               }
+               | routelist
+               ;
+               
+optional_rdnsslist: /* empty */
+               {
+                       $$ = NULL;
+               }
+               | rdnsslist
+               ;
+
+ifacevlist     : ifacevlist ifaceval
+               | ifaceval
+               ;
+
+ifaceval       : T_MinRtrAdvInterval NUMBER ';'
+               {
+                       iface->MinRtrAdvInterval = $2;
+               }
+               | T_MaxRtrAdvInterval NUMBER ';'
+               {
+                       iface->MaxRtrAdvInterval = $2;
+               }
+               | T_MinDelayBetweenRAs NUMBER ';'
+               {
+                       iface->MinDelayBetweenRAs = $2;
+               }
+               | T_MinRtrAdvInterval DECIMAL ';'
+               {
+                       iface->MinRtrAdvInterval = $2;
+               }
+               | T_MaxRtrAdvInterval DECIMAL ';'
+               {
+                       iface->MaxRtrAdvInterval = $2;
+               }
+               | T_MinDelayBetweenRAs DECIMAL ';'
+               {
+                       iface->MinDelayBetweenRAs = $2;
+               }
+               | T_IgnoreIfMissing SWITCH ';'
+               {
+                       iface->IgnoreIfMissing = $2;
+               }
+               | T_AdvSendAdvert SWITCH ';'
+               {
+                       iface->AdvSendAdvert = $2;
+               }
+               | T_AdvManagedFlag SWITCH ';'
+               {
+                       iface->AdvManagedFlag = $2;
+               }
+               | T_AdvOtherConfigFlag SWITCH ';'
+               {
+                       iface->AdvOtherConfigFlag = $2;
+               }
+               | T_AdvLinkMTU NUMBER ';'
+               {
+                       iface->AdvLinkMTU = $2;
+               }
+               | T_AdvReachableTime NUMBER ';'
+               {
+                       iface->AdvReachableTime = $2;
+               }
+               | T_AdvRetransTimer NUMBER ';'
+               {
+                       iface->AdvRetransTimer = $2;
+               }
+               | T_AdvDefaultLifetime NUMBER ';'
+               {
+                       iface->AdvDefaultLifetime = $2;
+               }
+               | T_AdvDefaultPreference SIGNEDNUMBER ';'
+               {
+                       iface->AdvDefaultPreference = $2;
+               }
+               | T_AdvCurHopLimit NUMBER ';'
+               {
+                       iface->AdvCurHopLimit = $2;
+               }
+               | T_AdvSourceLLAddress SWITCH ';'
+               {
+                       iface->AdvSourceLLAddress = $2;
+               }
+               | T_AdvIntervalOpt SWITCH ';'
+               {
+                       iface->AdvIntervalOpt = $2;
+               }
+               | T_AdvHomeAgentInfo SWITCH ';'
+               {
+                       iface->AdvHomeAgentInfo = $2;
+               }
+               | T_AdvHomeAgentFlag SWITCH ';'
+               {
+                       iface->AdvHomeAgentFlag = $2;
+               }
+               | T_HomeAgentPreference NUMBER ';'
+               {
+                       iface->HomeAgentPreference = $2;
+               }
+               | T_HomeAgentLifetime NUMBER ';'
+               {
+                       iface->HomeAgentLifetime = $2;
+               }
+               | T_UnicastOnly SWITCH ';'
+               {
+                       iface->UnicastOnly = $2;
+               }
+               | T_AdvMobRtrSupportFlag SWITCH ';'
+               {
+                       iface->AdvMobRtrSupportFlag = $2;
+               }
+               ;
+               
+prefixlist     : prefixdef
+               {
+                       $$ = $1;
+               }
+               | prefixlist prefixdef
+               {
+                       $2->next = $1;
+                       $$ = $2;
+               }
+               ;
+
+prefixdef      : prefixhead '{' optional_prefixplist '}' ';'
+               {
+                       unsigned int dst;
+
+                       if (prefix->AdvPreferredLifetime >
+                           prefix->AdvValidLifetime)
+                       {
+                               flog(LOG_ERR, "AdvValidLifeTime must be "
+                                       "greater than AdvPreferredLifetime in %s, line %d", 
+                                       conf_file, num_lines);
+                               ABORT;
+                       }
+
+                       if( prefix->if6to4[0] )
+                       {
+                               if (get_v4addr(prefix->if6to4, &dst) < 0)
+                               {
+                                       flog(LOG_ERR, "interface %s has no IPv4 addresses, disabling 6to4 prefix", prefix->if6to4 );
+                                       prefix->enabled = 0;
+                               } else
+                               {
+                                       *((uint16_t *)(prefix->Prefix.s6_addr)) = htons(0x2002);
+                                       memcpy( prefix->Prefix.s6_addr + 2, &dst, sizeof( dst ) );
+                               }
+                       }
+
+                       $$ = prefix;
+                       prefix = NULL;
+               }
+               ;
+
+prefixhead     : T_PREFIX IPV6ADDR '/' NUMBER
+               {
+                       prefix = malloc(sizeof(struct AdvPrefix));
+                       
+                       if (prefix == NULL) {
+                               flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+                               ABORT;
+                       }
+
+                       prefix_init_defaults(prefix);
+
+                       if ($4 > MAX_PrefixLen)
+                       {
+                               flog(LOG_ERR, "invalid prefix length in %s, line %d", conf_file, num_lines);
+                               ABORT;
+                       }
+
+                       prefix->PrefixLen = $4;
+
+                       memcpy(&prefix->Prefix, $2, sizeof(struct in6_addr));
+               }
+               ;
+
+optional_prefixplist: /* empty */
+               | prefixplist 
+               ;
+
+prefixplist    : prefixplist prefixparms
+               | prefixparms
+               ;
+
+prefixparms    : T_AdvOnLink SWITCH ';'
+               {
+                       prefix->AdvOnLinkFlag = $2;
+               }
+               | T_AdvAutonomous SWITCH ';'
+               {
+                       prefix->AdvAutonomousFlag = $2;
+               }
+               | T_AdvRouterAddr SWITCH ';'
+               {
+                       prefix->AdvRouterAddr = $2;
+               }
+               | T_AdvValidLifetime number_or_infinity ';'
+               {
+                       prefix->AdvValidLifetime = $2;
+               }
+               | T_AdvPreferredLifetime number_or_infinity ';'
+               {
+                       prefix->AdvPreferredLifetime = $2;
+               }
+               | T_Base6to4Interface name ';'
+               {
+                       dlog(LOG_DEBUG, 4, "using interface %s for 6to4", $2);
+                       strncpy(prefix->if6to4, $2, IFNAMSIZ-1);
+                       prefix->if6to4[IFNAMSIZ-1] = '\0';
+               }
+               ;
+
+routelist      : routedef
+               {
+                       $$ = $1;
+               }
+               | routelist routedef
+               {
+                       $2->next = $1;
+                       $$ = $2;
+               }
+               ;
+
+routedef       : routehead '{' optional_routeplist '}' ';'
+               {
+                       $$ = route;
+                       route = NULL;
+               }
+               ;
+
+
+routehead      : T_ROUTE IPV6ADDR '/' NUMBER
+               {
+                       route = malloc(sizeof(struct AdvRoute));
+                       
+                       if (route == NULL) {
+                               flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+                               ABORT;
+                       }
+
+                       route_init_defaults(route, iface);
+
+                       if ($4 > MAX_PrefixLen)
+                       {
+                               flog(LOG_ERR, "invalid route prefix length in %s, line %d", conf_file, num_lines);
+                               ABORT;
+                       }
+
+                       route->PrefixLen = $4;
+
+                       memcpy(&route->Prefix, $2, sizeof(struct in6_addr));
+               }
+               ;
+
+
+optional_routeplist: /* empty */
+               | routeplist 
+               ;
+
+routeplist     : routeplist routeparms
+               | routeparms
+               ;
+
+
+routeparms     : T_AdvRoutePreference SIGNEDNUMBER ';'
+               {
+                       route->AdvRoutePreference = $2;
+               }
+               | T_AdvRouteLifetime number_or_infinity ';'
+               {
+                       route->AdvRouteLifetime = $2;
+               }
+               ;
+               
+rdnsslist      : rdnssdef
+               {
+                       $$ = $1;
+               }
+               | rdnsslist rdnssdef
+               {
+                       $2->next = $1;
+                       $$ = $2;
+               }
+               ;
+               
+rdnssdef       : rdnsshead '{' optional_rdnssplist '}' ';'
+               {
+                       $$ = rdnss;
+                       rdnss = NULL;
+               }
+               ;
+
+rdnssaddrs     : rdnssaddrs rdnssaddr
+               | rdnssaddr
+               ;
+
+rdnssaddr      : IPV6ADDR
+               {
+                       if (!rdnss) {
+                               /* first IP found */
+                               rdnss = malloc(sizeof(struct AdvRDNSS));
+                               
+                               if (rdnss == NULL) {
+                                       flog(LOG_CRIT, "malloc failed: %s", strerror(errno));
+                                       ABORT;
+                               }
+
+                               rdnss_init_defaults(rdnss, iface);
+                       }
+                       
+                       switch (rdnss->AdvRDNSSNumber) {
+                               case 0:
+                                       memcpy(&rdnss->AdvRDNSSAddr1, $1, sizeof(struct in6_addr));
+                                       rdnss->AdvRDNSSNumber++;
+                                       break;
+                               case 1:
+                                       memcpy(&rdnss->AdvRDNSSAddr2, $1, sizeof(struct in6_addr));
+                                       rdnss->AdvRDNSSNumber++;
+                                       break;
+                               case 2:
+                                       memcpy(&rdnss->AdvRDNSSAddr3, $1, sizeof(struct in6_addr));
+                                       rdnss->AdvRDNSSNumber++;
+                                       break;
+                               default:
+                                       flog(LOG_CRIT, "Too many addresses in RDNSS section");
+                                       ABORT;
+                       }
+                       
+               }
+               ;
+               
+rdnsshead      : T_RDNSS rdnssaddrs
+               {
+                       if (!rdnss) {
+                               flog(LOG_CRIT, "No address specified in RDNSS section");
+                               ABORT;
+                       }
+               }
+               ;
+               
+optional_rdnssplist: /* empty */
+               | rdnssplist 
+               ;
+               
+rdnssplist     : rdnssplist rdnssparms
+               | rdnssparms
+               ;
+
+
+rdnssparms     : T_AdvRDNSSPreference NUMBER ';'
+               {
+                       rdnss->AdvRDNSSPreference = $2;
+               }
+               | T_AdvRDNSSOpenFlag SWITCH ';'
+               {
+                       rdnss->AdvRDNSSOpenFlag = $2;
+               }
+               | T_AdvRDNSSLifetime number_or_infinity ';'
+               {
+                       if ($2 < iface->MaxRtrAdvInterval && $2 != 0) {
+                               flog(LOG_ERR, "AdvRDNSSLifetime must be at least MaxRtrAdvInterval");
+                               ABORT;
+                       }
+                       if ($2 > 2*(iface->MaxRtrAdvInterval))
+                               flog(LOG_WARNING, "Warning: AdvRDNSSLifetime <= 2*MaxRtrAdvInterval would allow stale DNS servers to be deleted faster");
+
+                       rdnss->AdvRDNSSLifetime = $2;
+               }
+               ;
+
+number_or_infinity      : NUMBER
+                        {
+                                $$ = $1; 
+                        }
+                        | INFINITY
+                        {
+                                $$ = (uint32_t)~0;
+                        }
+                        ;
+
+%%
+
+static
+void cleanup(void)
+{
+       if (iface)
+               free(iface);
+       
+       if (prefix)
+               free(prefix);
+
+       if (route)
+               free(route);
+
+       if (rdnss)
+               free(rdnss);
+}
+
+static void
+yyerror(char *msg)
+{
+       cleanup();
+       flog(LOG_ERR, "%s in %s, line %d: %s", msg, conf_file, num_lines, yytext);
+}