1- % % @doc This module contains a RADIUS client that can be used to send authentication and accounting requests.
1+ % % @doc This module contains a RADIUS client that can be used to send authentication and accounting requests.
22% % A counter is kept for every NAS in order to determine the next request id and sender port
33% % for each outgoing request. The implementation naively assumes that you won't send requests to a
44% % distinct number of NASs over the lifetime of the VM, which is why the counters are not garbage-collected.
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
339347handle_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 );
539548parse_ip (T = {_ , _ , _ , _ }) ->
540549 {ok , T };
541- parse_ip (T = {_ , _ , _ , _ , _ , _ }) ->
550+ parse_ip (T = {_ , _ , _ , _ , _ , _ , _ , _ }) ->
542551 {ok , T }.
543552
544553init_server_status_metrics () ->
@@ -689,5 +698,15 @@ 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+ send_request ({IP , Port , Secret }, Request , Options );
705+ {ok , # hostent {h_addrtype = inet6 , h_addr_list = [_ | _ ] = IPs }} ->
706+ Index = rand :uniform (length (IPs )),
707+ IP = lists :nth (Index , IPs ),
708+ send_request ({IP , Port , Secret }, Request , Options );
709+ _Err ->
710+ error (badarg )
711+ end
693712 end .
0 commit comments