[erlang-questions] Re: newbie having difficulty with inet_res:nslookup

Gleb Peregud gleber.p@REDACTED
Sun Sep 13 17:43:53 CEST 2009


Hello.

Looks like function inet_res:nslookup/3 returns {error, emfile}, so
function lookup_mx/1 returns atom 'emfile', which is passed in
function do_lookups/1 to the lists:map/2 as a second parameter. But
lists:map/2 accepts only lists as second argument.

Error 'emfie' means that there is too many opened file descriptors,
i.e. there are too many opened sockets.

I'd suggest rewriting lookup_mx/1 in "fail fast" way, i.e.:

lookup_mx(Domain)       ->
       {ok, #dns_rec{ anlist = Ans }} = inet_res:nslookup(Domain, 1, mx),
       lists:map(fun parse_mx/1, Ans).

Best,
Gleb Peregud

On Sun, Sep 13, 2009 at 17:29, Jeff Macdonald <macfisherman@REDACTED> wrote:
> I forgot to say Mac OS X (.5), erlang 12B I think (what's the way to
> have the shell give the erlang version?).
>
>
> On Sun, Sep 13, 2009 at 11:27 AM, Jeff Macdonald <macfisherman@REDACTED> wrote:
>> Hi All,
>>
>> I wrote a fairly simple program to look up MX records for domains and
>> then look up the exhanger's A and AAAA records. I'm trying to see how
>> many MX's have IPv6 capable hosts.
>>
>> My program simply reads a file which contains a domain per line and
>> spawns a processes/thread/child for each domain. The spawned process
>> then does the MX, A and AAAA lookups and prints the results to STDOUT
>> as a erlang tupple. This seems to work fine for a small sample set of
>> 10 rows but when trying 100 rows or more I get:
>>
>> =ERROR REPORT==== 12-Sep-2009::23:06:41 ===
>> Error in process <0.11161.0> with exit value:
>> {function_clause,[{lists,map,[#Fun<mx.0.117750125>,emfile]},{mx,do_lookups,1}]}
>>
>> My program is below. Usage is:
>>
>> mx:init({192,168, 1, 1}). (replace that tupple with the IP of your DNS server)
>> mx:process_file("file-with-domains").
>>
>> I currently can't share a list of domains because it is customer data,
>> but I sure there is some lists somewhere.
>>
>> I suspect that I'm overloading the DNS server at home. That is just
>> whatever is running in my linksys router. Any other suggestions about
>> the code welcomed. I know I could probably run the A and AAAA queries
>> in parallel. I also can probably skip queries when the data is present
>> in the MX results. For now, I'm just trying to get the basics.
>>
>> TIA
>>
>>
>>
>> %% Author: jeff
>> %% Created: Sep 10, 2009
>> %% Description: TODO: Add description to mx
>> -module(mx).
>>
>> %%
>> %% Include files
>> %%
>> -include_lib("kernel/src/inet_dns.hrl").
>>
>> %%
>> %% Exported Functions
>> %%
>> -export([init/1, process_file/1, do_lookups/1]).
>>
>> %%
>> %% API Functions
>> %%
>>
>> init(Resolver)  ->
>>        inet_db:add_ns(Resolver).
>>
>> process_file(Filename)  ->
>>        {ok,Fh}=file:open(Filename, [read]),
>>        read_file(Fh).
>>
>> do_lookups(Domain)      ->
>>        MX_list=lookup_mx(Domain),
>>        Address=lists:map(fun lookup_address/1, MX_list),
>>    io:format("~p:~n\t~p~n~n", [Domain, Address]).
>>
>> %%
>> %% Local Functions
>> %%
>>
>> read_file(Fh)   ->
>>        case io:get_line(Fh, "") of
>>                eof                             -> done;
>>                {error, Reason} -> {error, Reason};
>>                Data                    ->
>>                        process_data(string:strip(Data,right,$\n)),
>>                        read_file(Fh)
>>        end.
>>
>> process_data(Data)      ->
>>        spawn(mx, do_lookups, [Data]).
>>
>>
>> lookup_mx(Domain)       ->
>>        case inet_res:nslookup(Domain, 1, mx) of
>>                {error, Reason} -> Reason;
>>                {ok, #dns_rec{ anlist = Ans }} -> lists:map(fun parse_mx/1, Ans)
>>        end.
>>
>> lookup_address(Host)    ->
>>        { Host, {a, lookup_address(Host, a)},
>>                        {aaaa, lookup_address(Host, aaaa)} }.
>>
>> lookup_address(Host, a) ->
>>        case inet_res:nslookup(Host, 1, a) of
>>                {error, Reason} -> Reason;
>>                {ok, #dns_rec{ anlist = Ans }} -> lists:map(fun parse_a/1, Ans)
>>        end;
>>
>> lookup_address(Host, aaaa)      ->
>>        case inet_res:nslookup(Host, 1, aaaa) of
>>                {error, Reason} -> Reason;
>>                {ok, #dns_rec{ anlist = Ans }} -> Host,lists:map(fun parse_aaaa/1, Ans)
>>        end.
>>
>> parse_mx( RR )  ->
>>        #dns_rr{ type=mx, data={ _Pref, Exchange} } = RR,
>>        Exchange.
>>
>> parse_a( RR )   ->
>>        #dns_rr{ type=a, data=Address } = RR,
>>        Address.
>>
>> parse_aaaa( RR )        ->
>>        #dns_rr{ type=aaaa, data=Address } = RR,
>>        Address.
>>
>>
>>
>>
>> --
>> Jeff Macdonald
>> Ayer, MA
>>
>
>
>
> --
> Jeff Macdonald
> Ayer, MA
>
> ________________________________________________________________
> erlang-questions mailing list. See http://www.erlang.org/faq.html
> erlang-questions (at) erlang.org
>
>


More information about the erlang-questions mailing list