File 0982-snmp-test-Finding-local-address.patch of Package erlang

From edf3cfa243d20e47f4e37281f64102685e63ffed Mon Sep 17 00:00:00 2001
From: Micael Karlberg <bmk@erlang.org>
Date: Wed, 16 Jul 2025 09:14:42 +0200
Subject: [PATCH 1/2] [snmp|test] Finding local address

Improved finding local address. Also made it more verbose
so we can see which interfaces are rejected and why.
---
 lib/snmp/test/snmp_test_lib.erl | 117 ++++++++++++++++++++++++++++----
 1 file changed, 102 insertions(+), 15 deletions(-)

diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl
index e41da876b0..10503d63be 100644
--- a/lib/snmp/test/snmp_test_lib.erl
+++ b/lib/snmp/test/snmp_test_lib.erl
@@ -449,32 +449,119 @@ localhost(Family) ->
 
 which_addr(_Family, []) ->
     fail(no_valid_addr, ?MODULE, ?LINE);
-which_addr(Family, [{"lo", _} | IfList]) ->
+which_addr(Family, [{"lo" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
     which_addr(Family, IfList);
-which_addr(Family, [{"tun" ++ _, _} | IfList]) ->
+which_addr(Family, [{"tun" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
     which_addr(Family, IfList);
-which_addr(Family, [{"docker" ++ _, _} | IfList]) ->
+which_addr(Family, [{"docker" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
     which_addr(Family, IfList);
-which_addr(Family, [{"br-" ++ _, _} | IfList]) ->
+which_addr(Family, [{"br-" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
     which_addr(Family, IfList);
-which_addr(Family, [{_Name, IfOpts} | IfList]) ->
+which_addr(Family, [{"ap" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"anpi" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"vmenet" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"vtun" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"bridge" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"llw" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"awdl" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"p2p" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"stf" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{"XHCZ" ++ _ = Name, _} | IfList]) ->
+    iprint("reject interface ~s", [Name]),
+    which_addr(Family, IfList);
+which_addr(Family, [{Name, IfOpts} | IfList]) ->
     case which_addr2(Family, IfOpts) of
         {ok, Addr} ->
+            iprint("interface ~s accepted: "
+                   "~n   ~p", [Name, Addr]),
             Addr;
-        {error, _} ->
+        {error, no_address} ->
+            iprint("reject interface ~s:"
+                   "~n   No valid address", [Name]),
+            which_addr(Family, IfList);
+        {error, not_running_or_loopback} ->
+            iprint("reject interface ~s:"
+                   "~n   Not running or loopback", [Name]),
             which_addr(Family, IfList)
     end.
 
-which_addr2(_Family, []) ->
-    {error, not_found};
-which_addr2(Family, [{addr, Addr}|_]) 
-  when (Family =:= inet) andalso (tuple_size(Addr) =:= 4) ->
-    {ok, Addr};
-which_addr2(Family, [{addr, Addr}|_]) 
-  when (Family =:= inet6) andalso (tuple_size(Addr) =:= 8) ->
+which_addr2(Fam, IfOpts) ->
+    case if_is_running_and_not_loopback(IfOpts) of
+        true ->
+            try which_addr3(Fam, IfOpts)
+            catch
+                throw:E ->
+                    E
+            end;
+        false ->
+            {error, not_running_or_loopback}
+    end.
+
+if_is_running_and_not_loopback(If) ->
+    lists:keymember(flags, 1, If) andalso
+        begin
+            {value, {flags, Flags}} = lists:keysearch(flags, 1, If),
+            (not lists:member(loopback, Flags)) andalso
+                lists:member(running, Flags)
+        end.
+
+which_addr3(inet = _Fam, IfOpts) ->
+    Addr = which_addr4(
+             addr,  IfOpts,
+             fun({A, _, _, _}) when (A =:= 127) -> false;
+                ({A, B, _, _}) when (A =:= 169) andalso 
+                                    (B =:= 254) -> false;
+                ({_, _, _, _}) -> true;
+                (_) -> false
+             end),
     {ok, Addr};
-which_addr2(Family, [_|IfOpts]) ->
-    which_addr2(Family, IfOpts).
+which_addr3(inet6 = _Fam, IfOpts) ->
+    Addr = which_addr4(
+             addr,  IfOpts,
+             fun({A, _, _, _, _, _, _, _}) 
+                   when (A =:= 0) -> false;
+                ({A, _, _, _, _, _, _, _})
+                   when (A =:= 16#fe80) -> false;
+                ({_, _, _, _, _, _, _, _}) -> true;
+                (_) -> false
+             end),
+    {ok, Addr}.
+
+which_addr4(_Key, [], _) ->
+    throw({error, no_address});
+which_addr4(Key, [{Key, Val}|IfOpts], Check) ->
+    case Check(Val) of
+        true ->
+            %% iprint("~w -> address validated: "
+            %%.       "~n   ~p", [?FUNCTION_NAME, Val]),    
+            Val;
+        false ->
+            which_addr4(Key, IfOpts, Check)
+    end;
+which_addr4(Key, [_|IFO], Check) ->
+    which_addr4(Key, IFO, Check).
 
 
 sz(L) when is_list(L) ->
-- 
2.43.0

openSUSE Build Service is sponsored by