diff --git a/doc/bird.sgml b/doc/bird.sgml
index 761c5396..b10b1a21 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -1186,7 +1186,8 @@ foot).
This type can hold a single IP address. Depending on the compile-time
configuration of BIRD you are using, it is either an IPv4 or IPv6
- address. IP addresses are written in the standard notation
+ address; this may be checked by .is_ip4 which returns .mask(num) on values of type ip. It masks out all but
first num bits from the IP address. So
diff --git a/filter/config.Y b/filter/config.Y
index f84360ff..2864d290 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -400,6 +400,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, DEST, IFNAME, IFINDEX,
PREFERENCE,
ROA_CHECK, ASN,
+ IS_V4, IS_V6,
LEN, MAXLEN,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
@@ -890,7 +891,8 @@ term:
| rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); }
- | term '.' TYPE { $$ = f_new_inst(); $$->code = 'T'; $$->a1.p = $1; }
+ | term '.' IS_V4 { $$ = f_new_inst(); $$->code = P('I','i'); $$->a1.p = $1; }
+ | term '.' TYPE { $$ = f_new_inst(); $$->code = 'T'; $$->a1.p = $1; }
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
| term '.' RD { $$ = f_new_inst(); $$->code = P('R','D'); $$->a1.p = $1; $$->aux = T_RD; }
| term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
diff --git a/filter/filter.c b/filter/filter.c
index 616f9e2a..9f6c2cdd 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -829,6 +829,13 @@ interpret(struct f_inst *what)
runtime( "Can't determine type of this item" );
}
break;
+ case P('I','i'):
+ ONEARG;
+ if (v1.type != T_IP)
+ runtime( "IP version check needs an IP address" );
+ res.type = T_BOOL;
+ res.val.i = ipa_is_ip4(v1.val.ip);
+ break;
/* Set to indirect value, a1 = variable, a2 = value */
case 's':
diff --git a/filter/test.conf b/filter/test.conf
index 89c882ae..dedad1d8 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -312,15 +312,18 @@ function t_ip()
ip p;
{
p = 127.1.2.3;
+ bt_assert(p.is_v4);
bt_assert(p.mask(8) = 127.0.0.0);
bt_assert(1.2.3.4 = 1.2.3.4);
bt_assert(1.2.3.4 = onetwo);
bt_assert(format(p) = "127.1.2.3");
p = ::fffe:6:c0c:936d:88c7:35d3;
+ bt_assert(!p.is_v4);
bt_assert(format(p) = "::fffe:6:c0c:936d:88c7:35d3");
p = 1234:5678::;
+ bt_assert(!p.is_v4);
bt_assert(p.mask(24) = 1234:5600::);
}