From fdb6f2f9b7a713df79ef0c33342022623c585e36 Mon Sep 17 00:00:00 2001 From: Tomasz Kazimierz Motyl Date: Mon, 4 Oct 2021 00:23:16 -0700 Subject: [PATCH 1/4] Fixing IPv6 address parse + IPv6 host name resolution + inet family :inet or :inet6 based on peer's socket address to the client's socket --- src/eradius_client.erl | 37 ++++++++++++++++++++++++++--------- src/eradius_client_socket.erl | 17 ++++++++-------- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/eradius_client.erl b/src/eradius_client.erl index db621494..f3018d2f 100644 --- a/src/eradius_client.erl +++ b/src/eradius_client.erl @@ -62,19 +62,29 @@ send_request(NAS, Request) -> % If no answer is received within the specified timeout, the request will be sent again. -spec send_request(nas_address(), #radius_request{}, options()) -> {ok, binary(), eradius_lib:authenticator()} | {error, 'timeout' | 'socket_down'}. -send_request({Host, Port, Secret}, Request, Options) +send_request({Host, Port, Secret}, Request, Options) when ?GOOD_CMD(Request) andalso is_binary(Host) -> send_request({erlang:binary_to_list(Host), Port, Secret}, Request, Options); -send_request({Host, Port, Secret}, Request, Options) +send_request({Host, Port, Secret}, Request, Options) when ?GOOD_CMD(Request) andalso is_list(Host) -> case inet:gethostbyname(Host) of - {ok, #hostent{h_addrtype = inet, h_addr_list = [IP]}} -> + {ok, #hostent{h_addrtype = inet, h_addr_list = [IP]}} -> send_request({IP, Port, Secret}, Request, Options); - {ok, #hostent{h_addrtype = inet, h_addr_list = [_ | _] = IPs}} -> + {ok, #hostent{h_addrtype = inet, h_addr_list = [_ | _] = IPs}} -> Index = rand:uniform(length(IPs)), IP = lists:nth(Index, IPs), send_request({IP, Port, Secret}, Request, Options); - _ -> error(badarg) + _Err -> + case inet:gethostbyname(Host, inet6) of + {ok, #hostent{h_addrtype = inet6, h_addr_list = [IP]}} -> + send_request({IP, Port, Secret}, Request, Options); + {ok, #hostent{h_addrtype = inet6, h_addr_list = [_ | _] = IPs}} -> + Index = rand:uniform(length(IPs)), + IP = lists:nth(Index, IPs), + send_request({IP, Port, Secret}, Request, Options); + _Err -> + error(badarg) + end end; send_request({IP, Port, Secret}, Request, Options) when ?GOOD_CMD(Request) andalso is_tuple(IP) -> TS1 = eradius_lib:timestamp(milli_seconds), @@ -315,10 +325,19 @@ init([]) -> Else -> Else end. +%% @private +inet_family_based_on_peer(_PeerSocket = {{_, _, _, _}, _port}) -> + [inet]; +inet_family_based_on_peer(_PeerSocket = {{_, _, _, _, _, _, _, _}, _port}) -> + [inet6]; +inet_family_based_on_peer(_PeerSocket) -> + []. + %% @private handle_call({wanna_send, Peer = {_PeerName, PeerSocket}, _MetricsInfo}, _From, State) -> {PortIdx, ReqId, NewIdCounters} = next_port_and_req_id(PeerSocket, State#state.no_ports, State#state.idcounters), - {SocketProcess, NewSockets} = find_socket_process(PortIdx, State#state.sockets, State#state.socket_ip, State#state.sup), + InetFamily = inet_family_based_on_peer(PeerSocket), + {SocketProcess, NewSockets} = find_socket_process(PortIdx, State#state.sockets, State#state.socket_ip, InetFamily, State#state.sup), IsCreated = lists:member(Peer, State#state.clients), NewState = case IsCreated of false -> @@ -464,11 +483,11 @@ next_port_and_req_id(Peer, NumberOfPorts, Counters) -> NewCounters = Counters#{Peer => {NextPortIdx, NextReqId}}, {NextPortIdx, NextReqId, NewCounters}. -find_socket_process(PortIdx, Sockets, SocketIP, Sup) -> +find_socket_process(PortIdx, Sockets, SocketIP, Options, Sup) -> case array:get(PortIdx, Sockets) of undefined -> Res = supervisor:start_child(Sup, {PortIdx, - {eradius_client_socket, start, [SocketIP, self(), PortIdx]}, + {eradius_client_socket, start, [SocketIP, self(), PortIdx, Options]}, transient, brutal_kill, worker, [eradius_client_socket]}), Pid = case Res of {ok, P} -> P; @@ -490,7 +509,7 @@ parse_ip(Address) when is_list(Address) -> inet_parse:address(Address); parse_ip(T = {_, _, _, _}) -> {ok, T}; -parse_ip(T = {_, _, _, _, _, _}) -> +parse_ip(T = {_, _, _, _, _, _, _, _}) -> {ok, T}. make_metrics_info(Options, {ServerIP, ServerPort}) -> diff --git a/src/eradius_client_socket.erl b/src/eradius_client_socket.erl index c90f1b02..51497379 100644 --- a/src/eradius_client_socket.erl +++ b/src/eradius_client_socket.erl @@ -2,22 +2,23 @@ -behaviour(gen_server). --export([start/3]). +-export([start/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(state, {client, socket, pending, mode, counter}). -start(SocketIP, Client, PortIdx) -> - gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx], []). +start(SocketIP, Client, PortIdx, Options) -> + gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx, Options], []). -init([SocketIP, Client, PortIdx]) -> +init([SocketIP, Client, PortIdx, Options]) -> Client ! {PortIdx, self()}, - case SocketIP of + ExtraOptions = + case SocketIP of undefined -> - ExtraOptions = []; + Options; SocketIP when is_tuple(SocketIP) -> - ExtraOptions = [{ip, SocketIP}] - end, + [{ip, SocketIP} | Options] + end, RecBuf = application:get_env(eradius, recbuf, 8192), {ok, Socket} = gen_udp:open(0, [{active, once}, binary , {recbuf, RecBuf} | ExtraOptions]), {ok, #state{client = Client, socket = Socket, pending = maps:new(), mode = active, counter = 0}}. From 5583b8c0121888279f49ada159ac0f83b7820beb Mon Sep 17 00:00:00 2001 From: Tomasz Kazimierz Motyl Date: Mon, 4 Oct 2021 02:15:10 -0700 Subject: [PATCH 2/4] Unifying indentation --- src/eradius_client.erl | 22 +++++++++++----------- src/eradius_client_socket.erl | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/eradius_client.erl b/src/eradius_client.erl index f3018d2f..ce89567c 100644 --- a/src/eradius_client.erl +++ b/src/eradius_client.erl @@ -76,14 +76,14 @@ send_request({Host, Port, Secret}, Request, Options) send_request({IP, Port, Secret}, Request, Options); _Err -> case inet:gethostbyname(Host, inet6) of - {ok, #hostent{h_addrtype = inet6, h_addr_list = [IP]}} -> - send_request({IP, Port, Secret}, Request, Options); - {ok, #hostent{h_addrtype = inet6, h_addr_list = [_ | _] = IPs}} -> - Index = rand:uniform(length(IPs)), - IP = lists:nth(Index, IPs), - send_request({IP, Port, Secret}, Request, Options); - _Err -> - error(badarg) + {ok, #hostent{h_addrtype = inet6, h_addr_list = [IP]}} -> + send_request({IP, Port, Secret}, Request, Options); + {ok, #hostent{h_addrtype = inet6, h_addr_list = [_ | _] = IPs}} -> + Index = rand:uniform(length(IPs)), + IP = lists:nth(Index, IPs), + send_request({IP, Port, Secret}, Request, Options); + _Err -> + error(badarg) end end; send_request({IP, Port, Secret}, Request, Options) when ?GOOD_CMD(Request) andalso is_tuple(IP) -> @@ -327,11 +327,11 @@ init([]) -> %% @private inet_family_based_on_peer(_PeerSocket = {{_, _, _, _}, _port}) -> - [inet]; + [inet]; inet_family_based_on_peer(_PeerSocket = {{_, _, _, _, _, _, _, _}, _port}) -> - [inet6]; + [inet6]; inet_family_based_on_peer(_PeerSocket) -> - []. + []. %% @private handle_call({wanna_send, Peer = {_PeerName, PeerSocket}, _MetricsInfo}, _From, State) -> diff --git a/src/eradius_client_socket.erl b/src/eradius_client_socket.erl index 51497379..efcf1803 100644 --- a/src/eradius_client_socket.erl +++ b/src/eradius_client_socket.erl @@ -13,12 +13,12 @@ start(SocketIP, Client, PortIdx, Options) -> init([SocketIP, Client, PortIdx, Options]) -> Client ! {PortIdx, self()}, ExtraOptions = - case SocketIP of - undefined -> - Options; - SocketIP when is_tuple(SocketIP) -> - [{ip, SocketIP} | Options] - end, + case SocketIP of + undefined -> + Options; + SocketIP when is_tuple(SocketIP) -> + [{ip, SocketIP} | Options] + end, RecBuf = application:get_env(eradius, recbuf, 8192), {ok, Socket} = gen_udp:open(0, [{active, once}, binary , {recbuf, RecBuf} | ExtraOptions]), {ok, #state{client = Client, socket = Socket, pending = maps:new(), mode = active, counter = 0}}. From ccdded1553691443862921a8618f7da25ea9f85c Mon Sep 17 00:00:00 2001 From: Tomasz Kazimierz Motyl Date: Mon, 4 Oct 2021 03:47:04 -0700 Subject: [PATCH 3/4] Amending the test suite --- test/eradius_client_SUITE.erl | 2 +- test/eradius_client_socket_test.erl | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/eradius_client_SUITE.erl b/test/eradius_client_SUITE.erl index e550df4f..d3e1dab4 100644 --- a/test/eradius_client_SUITE.erl +++ b/test/eradius_client_SUITE.erl @@ -139,7 +139,7 @@ parse_ip(Address) when is_list(Address) -> inet_parse:address(Address); parse_ip(T = {_, _, _, _}) -> {ok, T}; -parse_ip(T = {_, _, _, _, _, _}) -> +parse_ip(T = {_, _, _, _, _, _, _, _}) -> {ok, T}. %% CHECK diff --git a/test/eradius_client_socket_test.erl b/test/eradius_client_socket_test.erl index ee465c59..538c5d3c 100644 --- a/test/eradius_client_socket_test.erl +++ b/test/eradius_client_socket_test.erl @@ -22,15 +22,15 @@ -behaviour(gen_server). --export([start/3]). +-export([start/4]). -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(state, {client, socket, pending, mode, counter}). -start(SocketIP, Client, PortIdx) -> - gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx], []). +start(SocketIP, Client, PortIdx, Options) -> + gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx, Options], []). -init([_SocketIP, Client, PortIdx]) -> +init([_SocketIP, Client, PortIdx, Options]) -> Client ! {PortIdx, self()}, eradius_client_SUITE:addSocket(), {ok, #state{pending = maps:new(), mode = active, counter = 0}}. From c87052b87eff04d0c73946c486ff89d9ca8d6169 Mon Sep 17 00:00:00 2001 From: Tomasz Kazimierz Motyl Date: Mon, 4 Oct 2021 03:52:11 -0700 Subject: [PATCH 4/4] eradius_client_socket start/3 to start/4 --- test/eradius_client_SUITE.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/eradius_client_SUITE.erl b/test/eradius_client_SUITE.erl index d3e1dab4..380e926d 100644 --- a/test/eradius_client_SUITE.erl +++ b/test/eradius_client_SUITE.erl @@ -122,7 +122,7 @@ split2(N, List1, [L|List2]) -> split2(N-1, [L|List1], List2). meckStart() -> ok = meck:new(eradius_client_socket), - ok = meck:expect(eradius_client_socket, start, fun(X, Y, Z) -> eradius_client_socket_test:start(X, Y, Z) end), + ok = meck:expect(eradius_client_socket, start, fun(X, Y, Z, O) -> eradius_client_socket_test:start(X, Y, Z, O) end), ok = meck:expect(eradius_client_socket, init, fun(X) -> eradius_client_socket_test:init(X) end), ok = meck:expect(eradius_client_socket, handle_call, fun(X, Y, Z) -> eradius_client_socket_test:handle_call(X, Y, Z) end), ok = meck:expect(eradius_client_socket, handle_cast, fun(X, Y) -> eradius_client_socket_test:handle_cast(X, Y) end),