Hi,

There is a reduce/reduce conflict during build because in rpki proto
it is possible to specify remote both as IP or text hostname. And both
in place of both tokens there can be a named constant. I added a new
token type that returns a union of IP and string to use in such cases
where we need something like hostname.
commit decd1ac408aef703569e5caa4b5336084a6fd99e
Author: Alexander Zubkov <gr...@qrator.net>
Date:   Mon Jan 3 11:05:36 2022 +0100

    Conf: fix reduce/reduce conflict for rpki remote
    
    Configuration for RPKI remote had conflict because it was not able to
    distinguish between IP and string named constants. Introduce new token
    type for the cases where we need to get either a hostname or an IP.

diff --git a/conf/conf.h b/conf/conf.h
index 3bc37959..ba739d85 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -141,6 +141,14 @@ struct bytestring {
   byte data[];
 };
 
+struct tok_hostname {
+  int class;			/* T_IP or T_STRING */
+  union {
+    ip_addr ip;			/* for T_IP */
+    const char *string;		/* for T_STRING */
+  };
+};
+
 #define SYM_MAX_LEN 64
 
 /* Remember to update cf_symbol_class_name() */
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 6985783b..15fcdbbd 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -58,6 +58,7 @@ CF_DECLS
   ip_addr a;
   ip4_addr ip4;
   ip6_addr ip6;
+  struct tok_hostname host;
   net_addr net;
   net_addr *net_ptr;
   struct symbol *s;
@@ -111,6 +112,7 @@ CF_DECLS
 %type <time> expr_us time
 %type <a> ipa
 %type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
+%type <host> hostname
 %type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
 %type <mls> label_stack_start label_stack
 
@@ -196,6 +198,20 @@ ipa:
    }
  ;
 
+hostname:
+   IP4 { $$.class = T_IP; $$.ip = ipa_from_ip4($1); }
+ | IP6 { $$.class = T_IP; $$.ip = ipa_from_ip6($1); }
+ | TEXT { $$.class = T_STRING; $$.string = $1; }
+ | CF_SYM_KNOWN {
+     if ($1->class == (SYM_CONSTANT | T_IP))
+       { $$.class = T_IP; $$.ip = SYM_VAL($1).ip; }
+     else if ($1->class == (SYM_CONSTANT | T_STRING))
+       { $$.class = T_STRING; $$.string = SYM_VAL($1).s; }
+     else
+       cf_error("IP address or string constant expected");
+   }
+ ;
+
 ipa_scope:
    /* empty */ { $$ = NULL; }
  | '%' symbol { $$ = if_get_by_name($2->name); }
diff --git a/proto/rpki/config.Y b/proto/rpki/config.Y
index d6d326b8..37e534ca 100644
--- a/proto/rpki/config.Y
+++ b/proto/rpki/config.Y
@@ -90,17 +90,20 @@ rpki_keep_interval:
 rpki_proto_item_port: PORT expr { check_u16($2); RPKI_CFG->port = $2; };
 
 rpki_cache_addr:
-   text {
+   hostname {
      rpki_check_unused_hostname();
-     RPKI_CFG->hostname = $1;
-   }
- | ipa {
-     rpki_check_unused_hostname();
-     RPKI_CFG->ip = $1;
-     /* Ensure hostname is filled */
-     char *hostname = cfg_allocz(INET6_ADDRSTRLEN + 1);
-     bsnprintf(hostname, INET6_ADDRSTRLEN+1, "%I", RPKI_CFG->ip);
-     RPKI_CFG->hostname = hostname;
+     switch ($1.class) {
+       case T_STRING:
+         RPKI_CFG->hostname = $1.string;
+         break;
+       case T_IP:
+         RPKI_CFG->ip = $1.ip;
+         /* Ensure hostname is filled */
+         char *hostname = cfg_allocz(INET6_ADDRSTRLEN + 1);
+         bsnprintf(hostname, INET6_ADDRSTRLEN+1, "%I", RPKI_CFG->ip);
+         RPKI_CFG->hostname = hostname;
+         break;
+     }
    }
  ;
 

Reply via email to