4
%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
4
%% Copyright Ericsson AB 1997-2010. All Rights Reserved.
6
6
%% The contents of this file are subject to the Erlang Public License,
7
7
%% Version 1.1, (the "License"); you may not use this file except in
8
8
%% compliance with the License. You should have received a copy of the
9
9
%% Erlang Public License along with this software. If not, it can be
10
10
%% retrieved online at http://www.erlang.org/.
12
12
%% Software distributed under the License is distributed on an "AS IS"
13
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
%% the License for the specific language governing rights and limitations
15
15
%% under the License.
88
88
hosts_file_byaddr, %% hosts table from system file
89
89
cache_timer %% timer reference for refresh
91
-type state() :: #state{}.
92
93
-include("inet.hrl").
93
94
-include("inet_int.hrl").
103
104
case gen_server:start({local, inet_db}, inet_db, [], []) of
104
{ok,Pid} -> inet_config:init(), {ok,Pid};
105
{ok, _Pid}=Ok -> inet_config:init(), Ok;
110
111
case gen_server:start_link({local, inet_db}, inet_db, [], []) of
111
{ok,Pid} -> inet_config:init(), {ok,Pid};
112
{ok, _Pid}=Ok -> inet_config:init(), Ok;
425
425
res_optname(edns) -> res_edns;
426
426
res_optname(udp_payload_size) -> res_udp_payload_size;
427
427
res_optname(resolv_conf) -> res_resolv_conf;
428
res_optname(resolv_conf_name) -> res_resolv_conf;
428
429
res_optname(hosts_file) -> res_hosts_file;
430
res_optname(hosts_file_name) -> res_hosts_file;
429
431
res_optname(_) -> undefined.
431
433
res_check_option(nameserver, NSs) -> %% Legacy
458
460
res_check_option(resolv_conf, "") -> true;
459
461
res_check_option(resolv_conf, F) ->
460
462
res_check_option_absfile(F);
463
res_check_option(resolv_conf_name, "") -> true;
464
res_check_option(resolv_conf_name, F) ->
465
res_check_option_absfile(F);
461
466
res_check_option(hosts_file, "") -> true;
462
467
res_check_option(hosts_file, F) ->
463
468
res_check_option_absfile(F);
469
res_check_option(hosts_file_name, "") -> true;
470
res_check_option(hosts_file_name, F) ->
471
res_check_option_absfile(F);
464
472
res_check_option(_, _) -> false.
466
474
res_check_option_absfile(F) ->
474
482
res_check_list([], _Fun) -> true;
475
483
res_check_list([H|T], Fun) ->
477
true -> res_check_list(T, Fun);
484
Fun(H) andalso res_check_list(T, Fun);
480
485
res_check_list(_, _Fun) -> false.
482
487
res_check_ns({{A,B,C,D,E,F,G,H}, Port})
488
493
res_check_search("") -> true;
489
494
res_check_search(Dom) -> inet_parse:visible_string(Dom).
491
socks_option(server) -> db_get(socks5_server);
492
socks_option(port) -> db_get(socks5_port);
493
socks_option(methods) -> db_get(socks5_methods);
494
socks_option(noproxy) -> db_get(socks5_noproxy).
496
socks_option(server) -> db_get(socks5_server);
497
socks_option(port) -> db_get(socks5_port);
498
socks_option(methods) -> db_get(socks5_methods);
499
socks_option(noproxy) -> db_get(socks5_noproxy).
496
gethostname() -> db_get(hostname).
501
gethostname() -> db_get(hostname).
498
503
res_update_conf() ->
499
504
res_update(res_resolv_conf, res_resolv_conf_tm, res_resolv_conf_info,
503
508
res_update(res_hosts_file, res_hosts_file_tm, res_hosts_file_info,
504
509
set_hosts_file_tm, fun set_hosts_file/1).
506
res_update(Tag, TagTm, TagInfo, CallTag, SetFun) ->
511
res_update(Tag, TagTm, TagInfo, TagSetTm, SetFun) ->
507
512
case db_get(TagTm) of
583
588
getbysearch(Name, Dot, [Dom | Ds], Type, _) ->
584
589
case hostent_by_domain(Name ++ Dot ++ Dom, Type) of
585
{ok, HEnt} -> {ok, HEnt};
587
getbysearch(Name, Dot, Ds, Type, Error)
590
{ok, _HEnt}=Ok -> Ok;
591
Error -> getbysearch(Name, Dot, Ds, Type, Error)
589
593
getbysearch(_Name, _Dot, [], _Type, Error) ->
595
598
%% get_searchlist
836
838
%% node_auth Ls - Default authenication
837
839
%% node_crypt Ls - Default encryption
842
-spec init([]) -> {'ok', state()}.
840
845
process_flag(trap_exit, true),
841
846
Db = ets:new(inet_db, [public, named_table]),
889
894
%% {stop, Reason, Reply, State} | (terminate/2 is called)
890
895
%% {stop, Reason, Reply, State} (terminate/2 is called)
891
896
%%----------------------------------------------------------------------
898
-spec handle_call(term(), {pid(), term()}, state()) ->
899
{'reply', term(), state()} | {'stop', 'normal', 'ok', state()}.
892
901
handle_call(Request, From, #state{db=Db}=State) ->
894
903
{load_hosts_file,IPNmAs} when is_list(IPNmAs) ->
974
983
{reply, error, State}
986
{res_set, hosts_file_name=Option, Fname} ->
988
Option, Fname, res_hosts_file_tm, res_hosts_file_info,
989
undefined, From, State);
990
{res_set, resolv_conf_name=Option, Fname} ->
992
Option, Fname, res_resolv_conf_tm, res_resolv_conf_info,
993
undefined, From, State);
977
995
{res_set, hosts_file=Option, Fname} ->
978
handle_set_file(Option, Fname,
979
res_hosts_file_tm, res_hosts_file_info,
981
case inet_parse:hosts(Fname,
984
[{load_hosts_file,Opts}];
997
Option, Fname, res_hosts_file_tm, res_hosts_file_info,
999
case inet_parse:hosts(
1000
Fname, {chars,Bin}) of
1002
[{load_hosts_file,Opts}];
990
1008
{res_set, resolv_conf=Option, Fname} ->
991
handle_set_file(Option, Fname,
992
res_resolv_conf_tm, res_resolv_conf_info,
994
case inet_parse:resolv(Fname,
1002
(T =:= nameserver orelse
1010
Option, Fname, res_resolv_conf_tm, res_resolv_conf_info,
1012
case inet_parse:resolv(
1013
Fname, {chars,Bin}) of
1017
fun ({search,L}, _) ->
1030
|[Opt || {nameserver,_}=Opt <- Opts]];
1009
1036
{res_set, Opt, Value} ->
1010
1037
case res_optname(Opt) of
1112
1139
{reply, error, State}
1116
1142
%%----------------------------------------------------------------------
1117
1143
%% Func: handle_cast/2
1118
1144
%% Returns: {noreply, State} |
1119
1145
%% {noreply, State, Timeout} |
1120
1146
%% {stop, Reason, State} (terminate/2 is called)
1121
1147
%%----------------------------------------------------------------------
1149
-spec handle_cast(term(), state()) -> {'noreply', state()}.
1122
1151
handle_cast(_Msg, State) ->
1123
1152
{noreply, State}.
1128
1157
%% {noreply, State, Timeout} |
1129
1158
%% {stop, Reason, State} (terminate/2 is called)
1130
1159
%%----------------------------------------------------------------------
1161
-spec handle_info(term(), state()) -> {'noreply', state()}.
1131
1163
handle_info(refresh_timeout, State) ->
1132
1164
do_refresh_cache(State#state.cache),
1133
1165
{noreply, State#state{cache_timer = init_timer()}};
1140
1172
%% Purpose: Shutdown the server
1141
1173
%% Returns: any (ignored by gen_server)
1142
1174
%%----------------------------------------------------------------------
1176
-spec terminate(term(), state()) -> 'ok'.
1143
1178
terminate(_Reason, State) ->
1144
1179
stop_timer(State#state.cache_timer),
1156
1191
ets:delete(Db, TagInfo),
1157
1192
ets:delete(Db, TagTm),
1158
1193
handle_set_file(ParseFun, <<>>, From, State);
1194
true when ParseFun =:= undefined ->
1195
File = filename:flatten(Fname),
1196
ets:insert(Db, {res_optname(Option), File}),
1197
ets:insert(Db, {TagInfo, undefined}),
1198
ets:insert(Db, {TagTm, 0}),
1160
1201
File = filename:flatten(Fname),
1161
1202
ets:insert(Db, {res_optname(Option), File}),
1179
1220
handle_set_file(ParseFun, Bin, From, State) ->
1180
1221
case ParseFun(Bin) of
1181
error -> {reply,error,State};
1223
{reply,error,State};
1183
1225
handle_rc_list(Opts, From, State)
1310
1352
case alloc_entry(Db, CacheDb, TM) of
1312
cache_rr(Db, CacheDb, RR#dns_rr { tm = TM,
1354
cache_rr(Db, CacheDb, RR#dns_rr{tm = TM, cnt = TM});
1318
1359
cache_rr(_Db, Cache, RR) ->
1319
1360
%% delete possible old entry
1320
ets:match_delete(Cache, RR#dns_rr { cnt = '_', tm = '_', ttl = '_',
1321
bm = '_', func = '_'}),
1361
ets:match_delete(Cache, RR#dns_rr{cnt = '_', tm = '_', ttl = '_',
1362
bm = '_', func = '_'}),
1322
1363
ets:insert(Cache, RR).
1328
1369
%% lookup and remove old entries
1330
1371
do_lookup_rr(Domain, Class, Type) ->
1331
match_rr(#dns_rr { domain = tolower(Domain), class = Class,type = Type,
1332
cnt = '_', tm = '_', ttl = '_',
1333
bm = '_', func = '_', data = '_'}).
1372
match_rr(#dns_rr{domain = tolower(Domain), class = Class,type = Type,
1373
cnt = '_', tm = '_', ttl = '_',
1374
bm = '_', func = '_', data = '_'}).
1335
1376
match_rr(RR) ->
1336
1377
filter_rr(ets:match_object(inet_cache, RR), times()).
1381
1422
integer_to_list(A) ++ ".in-addr.arpa".
1384
[ hex(X), $., hex(X bsr 4), $., hex(X bsr 8), $., hex(X bsr 12), $.].
1425
[hex(X), $., hex(X bsr 4), $., hex(X bsr 8), $., hex(X bsr 12), $.].
1387
1428
X4 = (X band 16#f),
1477
1518
delete_n_oldest(CacheDb, TM, OldestTM, N) ->
1478
1519
DelTM = trunc((TM - OldestTM) * 0.3) + OldestTM,
1479
case delete_older(CacheDb, DelTM, N) of
1520
delete_older(CacheDb, DelTM, N) =/= 0.
1486
1522
%% Delete entries with latest access time older than TM.
1487
1523
%% Delete max N number of entries.