1
%% ``The contents of this file are subject to the Erlang Public License,
4
%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
6
%% The contents of this file are subject to the Erlang Public License,
2
7
%% Version 1.1, (the "License"); you may not use this file except in
3
8
%% compliance with the License. You should have received a copy of the
4
9
%% Erlang Public License along with this software. If not, it can be
5
%% retrieved via the world wide web at http://www.erlang.org/.
10
%% retrieved online at http://www.erlang.org/.
7
12
%% Software distributed under the License is distributed on an "AS IS"
8
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
9
14
%% the License for the specific language governing rights and limitations
10
15
%% under the License.
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
14
%% AB. All Rights Reserved.''
18
19
%% A simple boot_server at a CP.
44
46
priority = 0, %% priority of this server
45
version = "", %% Version handled i.e "4.5.3" etc
47
version = "" :: string(), %% Version handled i.e "4.5.3" etc
46
48
udp_sock, %% listen port for broadcase requests
47
49
udp_port, %% port number must be ?EBOOT_PORT!
48
50
listen_sock, %% listen sock for incoming file requests
49
51
listen_port, %% listen port number
50
52
slaves, %% list of accepted ip addresses
51
bootp, %% boot process
53
bootp :: pid(), %% boot process
52
54
prim_state %% state for efile code loader
55
57
-define(single_addr_mask, {255, 255, 255, 255}).
57
-type(ip4_address() :: {0..255,0..255,0..255,0..255}).
59
-type ip4_address() :: {0..255,0..255,0..255,0..255}.
59
-spec(start/1 :: (Slaves :: [atom()]) ->
60
{'ok', pid()} | {'error', any()}).
61
-spec start(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
63
64
case check_arg(Slaves) of
65
66
gen_server:start({local,boot_server}, erl_boot_server, AL, []);
67
68
{error, {badarg, Slaves}}
70
-spec(start_link/1 :: (Slaves :: [atom()]) ->
71
{'ok', pid()} | {'error', any()}).
71
-spec start_link(Slaves :: [atom()]) -> {'ok', pid()} | {'error', any()}.
73
73
start_link(Slaves) ->
74
74
case check_arg(Slaves) of
76
76
gen_server:start_link({local,boot_server},
77
77
erl_boot_server, AL, []);
94
94
check_arg(_, _Result) ->
97
-spec(add_slave/1 :: (Slave :: atom()) ->
98
'ok' | {'error', any()}).
97
-spec add_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
100
99
add_slave(Slave) ->
101
100
case inet:getaddr(Slave, inet) of
105
104
{error, {badarg, Slave}}
108
-spec(delete_slave/1 :: (Slave :: atom()) ->
109
'ok' | {'error', any()}).
107
-spec delete_slave(Slave :: atom()) -> 'ok' | {'error', any()}.
111
109
delete_slave(Slave) ->
112
110
case inet:getaddr(Slave, inet) of
116
114
{error, {badarg, Slave}}
119
-spec(add_subnet/2 :: (
120
Mask :: ip4_address(),
121
Addr :: ip4_address()) ->
122
{'error', any()} | 'ok').
117
-spec add_subnet(Mask :: ip4_address(), Addr :: ip4_address()) ->
118
'ok' | {'error', any()}.
124
120
add_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
125
121
case member_address(Addr, [{Mask, Addr}]) of
129
125
{error, empty_subnet}
132
-spec(delete_subnet/2 :: (
133
Mask :: ip4_address(),
134
Addr :: ip4_address()) ->
128
-spec delete_subnet(Mask :: ip4_address(), Addr :: ip4_address()) -> 'ok'.
137
130
delete_subnet(Mask, Addr) when is_tuple(Mask), is_tuple(Addr) ->
138
131
gen_server:call(boot_server, {delete, {Mask, Addr}}).
140
-spec(which_slaves/0 :: () ->
133
-spec which_slaves() -> [atom()].
143
135
which_slaves() ->
144
136
gen_server:call(boot_server, which).
177
169
{ok, U} = gen_udp:open(?EBOOT_PORT, []),
178
170
{ok, L} = gen_tcp:listen(0, [binary,{packet,4}]),
179
{ok,Port} = inet:port(L),
180
{ok,UPort} = inet:port(U),
171
{ok, Port} = inet:port(L),
172
{ok, UPort} = inet:port(U),
181
173
Ref = make_ref(),
182
174
Pid = proc_lib:spawn_link(?MODULE, boot_init, [Ref]),
183
175
gen_tcp:controlling_process(L, Pid),
197
189
handle_call({add,Address}, _, S0) ->
198
190
Slaves = ordsets:add_element(Address, S0#state.slaves),
199
191
S0#state.bootp ! {slaves, Slaves},
200
{reply, ok, S0#state { slaves = Slaves}};
192
{reply, ok, S0#state{slaves = Slaves}};
201
193
handle_call({delete,Address}, _, S0) ->
202
194
Slaves = ordsets:del_element(Address, S0#state.slaves),
203
195
S0#state.bootp ! {slaves, Slaves},
204
{reply, ok, S0#state { slaves = Slaves }};
196
{reply, ok, S0#state{slaves = Slaves}};
205
197
handle_call(which, _, S0) ->
206
198
{reply, ordsets:to_list(S0#state.slaves), S0}.
260
252
boot_main(Listen) ->
261
253
Tag = make_ref(),
262
Pid = proc_lib:spawn_link(?MODULE,boot_accept,[self(),Listen,Tag]),
254
Pid = proc_lib:spawn_link(?MODULE, boot_accept, [self(), Listen, Tag]),
263
255
boot_main(Listen, Tag, Pid).
265
257
boot_main(Listen, Tag, Pid) ->
281
273
Server ! {Tag, continue},
284
{ok,{IP,_Port}} = inet:peername(Socket),
276
{ok, {IP, _Port}} = inet:peername(Socket),
285
277
true = member_address(IP, which_slaves()),
286
278
PS = erl_prim_loader:prim_init(),
287
279
boot_loop(Socket, PS)