newbie having difficulty with inet_res:nslookup

Jeff Macdonald macfisherman@REDACTED
Sun Sep 13 17:27:46 CEST 2009


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


More information about the erlang-questions mailing list