File 3351-Add-IP-checking-functions.patch of Package erlang
From a6d6a63af979ebafb95a716375e7300af94dd9f9 Mon Sep 17 00:00:00 2001
From: Maria Scott <maria-12648430@hnc-agency.org>
Date: Fri, 11 Feb 2022 14:42:43 +0100
Subject: [PATCH] Add IP checking functions
---
lib/kernel/doc/src/inet.xml | 30 +++++++++++++++++
lib/kernel/src/inet.erl | 22 ++++++++++++-
lib/kernel/test/inet_SUITE.erl | 60 +++++++++++++++++++++++++++++++++-
3 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index e1edf3e657..81b9ca8301 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -782,6 +782,36 @@ get_tcpi_sacked(Sock) ->
</desc>
</func>
+ <func>
+ <name name="is_ip_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv4 or IPv6 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip_address"><c>ip_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="is_ipv4_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv4 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip4_address"><c>ip4_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
+ <func>
+ <name name="is_ipv6_address" arity="1" since="OTP 25.0"/>
+ <fsummary>Tests if <c>IPAddress</c> is an IPv6 address tuple.</fsummary>
+ <desc>
+ <p>Tests if <c>IPAddress</c> is an
+ <seetype marker="#ip6_address"><c>ip6_address()</c></seetype>
+ and returns <c>true</c> if so, otherwise <c>false</c>.</p>
+ </desc>
+ </func>
+
<func>
<name name="ntoa" arity="1" since="OTP R16B02"/>
<fsummary>Convert IPv6/IPV4 address to ASCII.</fsummary>
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 731329bf05..f0d06e3861 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -32,7 +32,8 @@
ifget/3, ifget/2, ifset/3, ifset/2,
getstat/1, getstat/2,
info/1, socket_to_list/1,
- ip/1, stats/0, options/0,
+ ip/1, is_ipv4_address/1, is_ipv6_address/1, is_ip_address/1,
+ stats/0, options/0,
pushf/3, popf/1, close/1, gethostname/0, gethostname/1,
parse_ipv4_address/1, parse_ipv6_address/1, parse_ipv4strict_address/1,
parse_ipv6strict_address/1, parse_address/1, parse_strict_address/1,
@@ -754,6 +755,25 @@ ip(Name) ->
Error -> Error
end.
+-spec is_ipv4_address(IPv4Address) -> boolean() when
+ IPv4Address :: ip4_address() | term().
+is_ipv4_address({A,B,C,D}) when ?ip(A,B,C,D) ->
+ true;
+is_ipv4_address(_) ->
+ false.
+
+-spec is_ipv6_address(IPv6Address) -> boolean() when
+ IPv6Address :: ip6_address() | term().
+is_ipv6_address({A,B,C,D,E,F,G,H}) when ?ip6(A,B,C,D,E,F,G,H) ->
+ true;
+is_ipv6_address(_) ->
+ false.
+
+-spec is_ip_address(IPAddress) -> boolean() when
+ IPAddress :: ip_address() | term().
+is_ip_address(Address) ->
+ is_ipv4_address(Address) orelse is_ipv6_address(Address).
+
%% This function returns the erlang port used (with inet_drv)
-spec getll(Socket :: socket()) -> {'ok', socket()}.
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index 5b92087ebc..ef66f3b257 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -47,6 +47,7 @@
lookup_bad_search_option/1,
getif/1,
getif_ifr_name_overflow/1,getservbyname_overflow/1, getifaddrs/1,
+ is_ip_address/1,
parse_strict_address/1, ipv4_mapped_ipv6_address/1, ntoa/1,
simple_netns/1, simple_netns_open/1,
add_del_host/1, add_del_host_v6/1,
@@ -71,7 +72,7 @@ all() ->
[
t_gethostbyaddr, t_gethostbyname, t_getaddr,
t_gethostbyaddr_v6, t_gethostbyname_v6, t_getaddr_v6,
- ipv4_to_ipv6, host_and_addr, {group, parse},
+ ipv4_to_ipv6, host_and_addr, is_ip_address, {group, parse},
t_gethostnative, gethostnative_parallell, cname_loop,
missing_hosts_reload, hosts_file_quirks,
gethostnative_debug_level, gethostnative_soft_restart,
@@ -816,6 +817,63 @@ parse_strict_address(Config) when is_list(Config) ->
{ok, {3089,3106,23603,50240,0,0,119,136}} =
inet:parse_strict_address("c11:0c22:5c33:c440::077:0088").
+is_ip_address(Config) when is_list(Config) ->
+ IPv4Addresses = [
+ {0, 0, 0, 0},
+ {255, 255, 255, 255}
+ ],
+ IPv6Addresses = [
+ {0, 0, 0, 0, 0, 0, 0, 0},
+ {16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff, 16#ffff}
+ ],
+ NonIPAddresses = [
+ foo,
+ "0.0.0.0",
+ {},
+ {0},
+ {0, 0},
+ {0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, foo},
+ {0, 0, 0, 0, 0, 0, 0, foo},
+ {0, 0, 0, 256},
+ {0, 0, 256, 0},
+ {0, 256, 0, 0},
+ {256, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, 16#10000},
+ {0, 0, 0, 0, 0, 0, 16#10000, 0},
+ {0, 0, 0, 0, 0, 16#10000, 0, 0},
+ {0, 0, 0, 0, 16#10000, 0, 0, 0},
+ {0, 0, 0, 16#10000, 0, 0, 0, 0},
+ {0, 0, 16#10000, 0, 0, 0, 0, 0},
+ {0, 16#10000, 0, 0, 0, 0, 0, 0},
+ {16#10000, 0, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, -1},
+ {0, 0, -1, 0},
+ {0, -1, 0, 0},
+ {-1, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, 0, -1},
+ {0, 0, 0, 0, 0, 0, -1, 0},
+ {0, 0, 0, 0, 0, -1, 0, 0},
+ {0, 0, 0, 0, -1, 0, 0, 0},
+ {0, 0, 0, -1, 0, 0, 0, 0},
+ {0, 0, -1, 0, 0, 0, 0, 0},
+ {0, -1, 0, 0, 0, 0, 0, 0},
+ {-1, 0, 0, 0, 0, 0, 0, 0}
+ ],
+
+ true = lists:all(fun inet:is_ipv4_address/1, IPv4Addresses),
+ false = lists:any(fun inet:is_ipv4_address/1, IPv6Addresses ++ NonIPAddresses),
+
+ true = lists:all(fun inet:is_ipv6_address/1, IPv6Addresses),
+ false = lists:any(fun inet:is_ipv6_address/1, IPv4Addresses ++ NonIPAddresses),
+
+ true = lists:all(fun inet:is_ip_address/1, IPv6Addresses ++ IPv4Addresses),
+ false = lists:any(fun inet:is_ip_address/1, NonIPAddresses).
+
ipv4_mapped_ipv6_address(Config) when is_list(Config) ->
{D1,D2,D3,D4} = IPv4Address =
{rand:uniform(256) - 1,
--
2.34.1