Skip to content

Commit cd7742c

Browse files
Tomasz Kazimierz Motylvkatsuba
Tomasz Kazimierz Motyl
authored andcommitted
Fixing IPv6 address parse
IPv6 host name resolution and inet family :inet or :inet6 based on peer's socket address to the client's socket
1 parent 9961af7 commit cd7742c

4 files changed

+44
-25
lines changed

src/eradius_client.erl

+27-9
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@
3636
Req#radius_request.cmd == 'coareq' orelse
3737
Req#radius_request.cmd == 'discreq')).
3838

39-
-type nas_address() :: {string() | binary() | inet:ip_address(),
40-
eradius_server:port_number(),
39+
-type nas_address() :: {string() | binary() | inet:ip_address(),
40+
eradius_server:port_number(),
4141
eradius_lib:secret()}.
4242
-type options() :: [{retries, pos_integer()} |
4343
{timeout, timeout()} |
@@ -63,10 +63,10 @@ send_request(NAS, Request) ->
6363
% If no answer is received within the specified timeout, the request will be sent again.
6464
-spec send_request(nas_address(), #radius_request{}, options()) ->
6565
{ok, binary(), eradius_lib:authenticator()} | {error, 'timeout' | 'socket_down'}.
66-
send_request({Host, Port, Secret}, Request, Options)
66+
send_request({Host, Port, Secret}, Request, Options)
6767
when ?GOOD_CMD(Request) andalso is_binary(Host) ->
6868
send_request({erlang:binary_to_list(Host), Port, Secret}, Request, Options);
69-
send_request({Host, Port, Secret}, Request, Options)
69+
send_request({Host, Port, Secret}, Request, Options)
7070
when ?GOOD_CMD(Request) andalso is_list(Host) ->
7171
IP = get_ip(Host),
7272
send_request({IP, Port, Secret}, Request, Options);
@@ -335,10 +335,19 @@ init([]) ->
335335
Else -> Else
336336
end.
337337

338+
%% @private
339+
inet_family_based_on_peer(_PeerSocket = {{_, _, _, _}, _port}) ->
340+
[inet];
341+
inet_family_based_on_peer(_PeerSocket = {{_, _, _, _, _, _, _, _}, _port}) ->
342+
[inet6];
343+
inet_family_based_on_peer(_PeerSocket) ->
344+
[].
345+
338346
%% @private
339347
handle_call({wanna_send, Peer = {_PeerName, PeerSocket}, _MetricsInfo}, _From, State) ->
340348
{PortIdx, ReqId, NewIdCounters} = next_port_and_req_id(PeerSocket, State#state.no_ports, State#state.idcounters),
341-
{SocketProcess, NewSockets} = find_socket_process(PortIdx, State#state.sockets, State#state.socket_ip, State#state.sup),
349+
InetFamily = inet_family_based_on_peer(PeerSocket),
350+
{SocketProcess, NewSockets} = find_socket_process(PortIdx, State#state.sockets, State#state.socket_ip, InetFamily, State#state.sup),
342351
IsCreated = lists:member(Peer, State#state.clients),
343352
NewState = case IsCreated of
344353
false ->
@@ -512,11 +521,11 @@ next_port_and_req_id(Peer, NumberOfPorts, Counters) ->
512521
NewCounters = Counters#{Peer => {NextPortIdx, NextReqId}},
513522
{NextPortIdx, NextReqId, NewCounters}.
514523

515-
find_socket_process(PortIdx, Sockets, SocketIP, Sup) ->
524+
find_socket_process(PortIdx, Sockets, SocketIP, Options, Sup) ->
516525
case array:get(PortIdx, Sockets) of
517526
undefined ->
518527
Res = supervisor:start_child(Sup, {PortIdx,
519-
{eradius_client_socket, start, [SocketIP, self(), PortIdx]},
528+
{eradius_client_socket, start, [SocketIP, self(), PortIdx, Options]},
520529
transient, brutal_kill, worker, [eradius_client_socket]}),
521530
Pid = case Res of
522531
{ok, P} -> P;
@@ -538,7 +547,7 @@ parse_ip(Address) when is_list(Address) ->
538547
inet_parse:address(Address);
539548
parse_ip(T = {_, _, _, _}) ->
540549
{ok, T};
541-
parse_ip(T = {_, _, _, _, _, _}) ->
550+
parse_ip(T = {_, _, _, _, _, _, _, _}) ->
542551
{ok, T}.
543552

544553
init_server_status_metrics() ->
@@ -689,5 +698,14 @@ get_ip(Host) ->
689698
{ok, #hostent{h_addrtype = inet, h_addr_list = [_ | _] = IPs}} ->
690699
Index = rand:uniform(length(IPs)),
691700
lists:nth(Index, IPs);
692-
_ -> error(badarg)
701+
_ ->
702+
case inet:gethostbyname(Host, inet6) of
703+
{ok, #hostent{h_addrtype = inet6, h_addr_list = [IP]}} ->
704+
IP;
705+
{ok, #hostent{h_addrtype = inet6, h_addr_list = [_ | _] = IPs}} ->
706+
Index = rand:uniform(length(IPs)),
707+
lists:nth(Index, IPs);
708+
_Err ->
709+
error(badarg)
710+
end
693711
end.

src/eradius_client_socket.erl

+11-10
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22

33
-behaviour(gen_server).
44

5-
-export([start/3]).
5+
-export([start/4]).
66
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
77

88
-record(state, {client, socket, pending, mode, counter}).
99

10-
start(SocketIP, Client, PortIdx) ->
11-
gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx], []).
10+
start(SocketIP, Client, PortIdx, Options) ->
11+
gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx, Options], []).
1212

13-
init([SocketIP, Client, PortIdx]) ->
13+
init([SocketIP, Client, PortIdx, Options]) ->
1414
Client ! {PortIdx, self()},
15-
case SocketIP of
16-
undefined ->
17-
ExtraOptions = [];
18-
SocketIP when is_tuple(SocketIP) ->
19-
ExtraOptions = [{ip, SocketIP}]
20-
end,
15+
ExtraOptions =
16+
case SocketIP of
17+
undefined ->
18+
Options;
19+
SocketIP when is_tuple(SocketIP) ->
20+
[{ip, SocketIP} | Options]
21+
end,
2122
RecBuf = application:get_env(eradius, recbuf, 8192),
2223
SndBuf = application:get_env(eradius, sndbuf, 131072),
2324
{ok, Socket} = gen_udp:open(0, [{active, once}, binary , {recbuf, RecBuf}, {sndbuf, SndBuf} | ExtraOptions]),

test/eradius_client_SUITE.erl

+2-2
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ split2(N, List1, [L|List2]) -> split2(N-1, [L|List1], List2).
148148

149149
meckStart() ->
150150
ok = meck:new(eradius_client_socket),
151-
ok = meck:expect(eradius_client_socket, start, fun(X, Y, Z) -> eradius_client_socket_test:start(X, Y, Z) end),
151+
ok = meck:expect(eradius_client_socket, start, fun(X, Y, Z, O) -> eradius_client_socket_test:start(X, Y, Z, O) end),
152152
ok = meck:expect(eradius_client_socket, init, fun(X) -> eradius_client_socket_test:init(X) end),
153153
ok = meck:expect(eradius_client_socket, handle_call, fun(X, Y, Z) -> eradius_client_socket_test:handle_call(X, Y, Z) end),
154154
ok = meck:expect(eradius_client_socket, handle_cast, fun(X, Y) -> eradius_client_socket_test:handle_cast(X, Y) end),
@@ -165,7 +165,7 @@ parse_ip(Address) when is_list(Address) ->
165165
inet_parse:address(Address);
166166
parse_ip(T = {_, _, _, _}) ->
167167
{ok, T};
168-
parse_ip(T = {_, _, _, _, _, _}) ->
168+
parse_ip(T = {_, _, _, _, _, _, _, _}) ->
169169
{ok, T}.
170170

171171
%% CHECK

test/eradius_client_socket_test.erl

+4-4
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222

2323
-behaviour(gen_server).
2424

25-
-export([start/3]).
25+
-export([start/4]).
2626
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
2727

2828
-record(state, {client, socket, pending, mode, counter}).
2929

30-
start(SocketIP, Client, PortIdx) ->
31-
gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx], []).
30+
start(SocketIP, Client, PortIdx, Options) ->
31+
gen_server:start_link(?MODULE, [SocketIP, Client, PortIdx, Options], []).
3232

33-
init([_SocketIP, Client, PortIdx]) ->
33+
init([_SocketIP, Client, PortIdx, Options]) ->
3434
Client ! {PortIdx, self()},
3535
eradius_client_SUITE:addSocket(),
3636
{ok, #state{pending = maps:new(), mode = active, counter = 0}}.

0 commit comments

Comments
 (0)