%% ``The contents of this file are subject to the Erlang Public License,
%% Version 1.0, (the "License"); you may not use this file except in
%% compliance with the License. You may obtain a copy of the License at
%% http://www.erlang.org/EPL1_0.txt
%% 
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%% 
%% The Original Code is Erlang-4.7.3, December, 1998.
%% 
%% The Initial Developer of the Original Code is Ericsson Telecom
%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson
%% Telecom AB. All Rights Reserved.
%% 
%% Contributor(s): ______________________________________.''
%%
%%% File    : inet_hosts.erl
%%% Author  : Tony Rogvall <tony@erix.ericsson.se>
%%% Purpose : Implement gethostbyname gethostbyaddr for inet_hosts table
%%% Created : 30 Oct 1997 by Tony Rogvall <tony@erix.ericsson.se>

-module(inet_hosts).
-author('tony@erix.ericsson.se').

-export([gethostbyname/1, gethostbyname/2, gethostbyaddr/1]).

-include("inet.hrl").

%% simply scan each entry for a match
gethostbyname(Name) when list(Name) ->
    case find_name(Name, any) of
	false -> {error, nxdomain};
	{true, {IP, Type, [Nm | As]}} ->
	    {ok, make_hostent(Nm,[IP],As,Type)}
    end;
gethostbyname(Name) when atom(Name) ->
    gethostbyname(atom_to_list(Name));
gethostbyname(_) -> {error, formerr}.


gethostbyname(Name, Type) when list(Name), atom(Type) ->
    case find_name(Name, Type) of
	false -> {error, nxdomain};
	{true, {IP, Type, [Nm | As]}} -> {ok,make_hostent(Nm,[IP],As,Type)}
    end;
gethostbyname(Name, Type) when atom(Name), atom(Type) ->
    gethostbyname(atom_to_list(Name), Type);
gethostbyname(_, _) -> {error, formerr}.


gethostbyaddr({A,B,C,D}) when integer(A+B+C+D) ->
    IP = {A,B,C,D},
    case ets:lookup(inet_hosts, IP) of
	[] -> {error, nxdomain};
	[{IP,Type,[Nm | As]}] -> {ok, make_hostent(Nm,[IP],As,Type)}
    end;
%% ipv4  only ipv6 address
gethostbyaddr({0,0,0,0,0,16#ffff,G,H}) when integer(G+H) ->
    gethostbyaddr({G div 256, G rem 256, H div 256, H rem 256});
gethostbyaddr({A,B,C,D,E,F,G,H}) when integer(A+B+C+D+E+F+G+H) ->
    IP = {A,B,C,D,E,F,G,H},
    case ets:lookup(inet_hosts, IP) of
	[] -> {error, nxdomain};
	[{IP,Type,[Nm | As]}] -> {ok, make_hostent(Nm,[IP],As,Type)}
    end;
gethostbyaddr(Addr) when list(Addr) ->
    case inet_parse:address(Addr) of
	{ok, IP} -> gethostbyaddr(IP);
	Error -> {error, formerr}
    end;
gethostbyaddr(Addr) when atom(Addr) ->
    gethostbyaddr(atom_to_list(Addr));
gethostbyaddr(_) -> {error, formerr}.




find_name(Name, Type) ->
    find_name(Name, ets:first(inet_hosts), Type).

find_name(Name, '$end_of_table', Type) -> false;
find_name(Name, Key, Type) ->
    [{IP, T, Ns}] = ets:lookup(inet_hosts, Key),
    LowerName = inet_db:tolower(Name),
    case lists:member(LowerName, Ns) of
	true when Type==any ->
	    Ns2 = lists:map(fun(E)->
				    case E of LowerName -> Name; _ -> E end 
			    end, Ns),
	    {true, {IP,T,Ns2}};
	true when Type==T   ->
	    Ns2 = lists:map(fun(E)->
				    case E of LowerName -> Name; _ -> E end 
			    end, Ns),
	    {true, {IP,T,Ns2}};
	_ -> find_name(Name, ets:next(inet_hosts, Key), Type)
    end.

make_hostent(Name, Addrs, Aliases, inet) ->
    #hostent {
	      h_name = Name,
	      h_addrtype = inet,
	      h_length = 4,
	      h_addr_list = Addrs,
	      h_aliases = Aliases
	     };
make_hostent(Name, Addrs, Aliases, inet6) ->
    #hostent {
	      h_name = Name,
	      h_addrtype = inet6,
	      h_length = 16,
	      h_addr_list = Addrs,
	      h_aliases = Aliases
	     }.


