1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 package com.sun.dhcpmgr.server;
26
27 import java.util.*;
28 import java.net.InetAddress;
29
30 import com.sun.dhcpmgr.bridge.*;
31 import com.sun.dhcpmgr.data.*;
32
33 /**
34 * This class provides methods to manage the contents of the dhcptab.
35 */
36
37 public class DhcptabMgrImpl implements DhcptabMgr {
38 private Bridge bridge;
39
40 /**
41 * Create a new DhcptabMgr using the provided native bridge.
42 * @param bridge the native bridge class which actually does the work.
43 */
44 public DhcptabMgrImpl(Bridge bridge) {
45 this.bridge = bridge;
46 }
47
48 /**
49 * Create an option.
50 * @param name the name of the option.
51 * @param value the value for the option in dhcptab(4) format.
52 * @return the Option.
53 */
54 public Option createOption(String name, String value)
55 throws BridgeException {
56 return bridge.createOption(name, value);
57 }
58
59 /**
60 * Retrieve all options currently defined in the dhcptab.
61 * @return an array of Options
62 */
63 public Option [] getOptions() throws BridgeException {
64 return getOptions(null);
65 }
66
67 /**
68 * Retrieve all options currently defined in the dhcptab.
69 * @param datastore user-supplied datastore attributes
70 * @return an array of Options
71 */
72 public Option [] getOptions(DhcpDatastore datastore)
73 throws BridgeException {
74 return bridge.getOptions(datastore);
75 }
76
77 /**
78 * Retrieve all the macros currently defined in the dhcptab.
79 * @return an array of Macros
80 */
81 public Macro [] getMacros() throws BridgeException {
82 return getMacros(null);
83 }
84
85 /**
86 * Retrieve all the macros currently defined in the dhcptab.
87 * @param datastore user-supplied datastore attributes
88 * @return an array of Macros
89 */
90 public Macro [] getMacros(DhcpDatastore datastore)
91 throws BridgeException {
92 /*
93 * Load the vendor and site options before loading the macros
94 * so we can validate correctly, adding them to the standard options
95 * table.
96 */
97 OptionsTable optionsTable = OptionsTable.getTable();
98 optionsTable.add(bridge.getOptions(datastore));
99 return bridge.getMacros(datastore);
100 }
101
102 /**
103 * Create a given record in the dhcptab, and signal the server to
104 * reload the dhcptab if so requested.
105 * @param rec the record to add to the table
106 * @param signalServer true if the server is to be sent a SIGHUP
107 */
108 public void createRecord(DhcptabRecord rec, boolean signalServer)
109 throws BridgeException {
110 createRecord(rec, signalServer, null);
111 }
112
113 /**
114 * Create a given record in the dhcptab, and signal the server to
115 * reload the dhcptab if so requested.
116 * @param rec the record to add to the table
117 * @param signalServer true if the server is to be sent a SIGHUP
118 * @param datastore user-supplied datastore attributes
119 */
120 public void createRecord(DhcptabRecord rec, boolean signalServer,
121 DhcpDatastore datastore) throws BridgeException {
122 bridge.createDhcptabRecord(rec, datastore);
123 if (signalServer) {
124 bridge.reload();
125 }
126 }
127
128 /**
129 * Modify a given record in the dhcptab, and signal the server to reload
130 * the dhcptab if so requested
131 * @param oldRec the current record to modify
132 * @param newRec the new record to be placed in the table
133 * @param signalServer true if the server is to be sent a SIGHUP
134 */
135 public void modifyRecord(DhcptabRecord oldRec, DhcptabRecord newRec,
136 boolean signalServer) throws BridgeException {
137 modifyRecord(oldRec, newRec, signalServer, null);
138 }
139
140 /**
141 * Modify a given record in the dhcptab, and signal the server to reload
142 * the dhcptab if so requested
143 * @param oldRec the current record to modify
144 * @param newRec the new record to be placed in the table
145 * @param signalServer true if the server is to be sent a SIGHUP
146 * @param datastore user-supplied datastore attributes
147 */
148 public void modifyRecord(DhcptabRecord oldRec, DhcptabRecord newRec,
149 boolean signalServer, DhcpDatastore datastore)
150 throws BridgeException {
151 bridge.modifyDhcptabRecord(oldRec, newRec, datastore);
152 if (signalServer) {
153 bridge.reload();
154 }
155 }
156
157 /**
158 * Delete a given record from the dhcptab, and signal the server to reload
159 * the dhcptab if so requested
160 * @param rec the record to delete
161 * @param signalServer true if the server is to be sent a SIGHUP
162 */
163 public void deleteRecord(DhcptabRecord rec, boolean signalServer)
164 throws BridgeException {
165 deleteRecord(rec, signalServer, null);
166 }
167
168 /**
169 * Delete a given record from the dhcptab, and signal the server to reload
170 * the dhcptab if so requested
171 * @param rec the record to delete
172 * @param signalServer true if the server is to be sent a SIGHUP
173 * @param datastore user-supplied datastore attributes
174 */
175 public void deleteRecord(DhcptabRecord rec, boolean signalServer,
176 DhcpDatastore datastore) throws BridgeException {
177 bridge.deleteDhcptabRecord(rec, datastore);
178 if (signalServer) {
179 bridge.reload();
180 }
181 }
182
183 /**
184 * Delete a record by name and type
185 * @param key The key for the record
186 * @param type The type of record; either MACRO or OPTION
187 */
188 private void deleteRecord(String name, String type) throws BridgeException {
189 DhcptabRecord rec = null;
190 if (type.equals(DhcptabRecord.MACRO)) {
191 rec = getMacro(name);
192 } else {
193 rec = getOption(name);
194 }
195 deleteRecord(rec, false);
196 }
197
198 /**
199 * Delete a set of records.
200 * @return An array of ActionError, one error for each record not deleted
201 */
202 private ActionError [] deleteRecords(DhcptabRecord [] recs) {
203 ArrayList errorList = new ArrayList();
204
205 for (int i = 0; i < recs.length; ++i) {
206 try {
207 deleteRecord(recs[i], false);
208 } catch (BridgeException e) {
209 errorList.add(new ActionError(recs[i].getKey(), e));
210 }
211 }
212
213 return (ActionError[])errorList.toArray(new ActionError[0]);
214 }
215
216 private ActionError [] deleteAllRecords(String type)
217 throws BridgeException {
218 DhcptabRecord [] recs;
219 if (type.equals(DhcptabRecord.MACRO)) {
220 recs = getMacros();
221 } else {
222 recs = getOptions();
223 }
224 return deleteRecords(recs);
225 }
226
227 /**
228 * Delete all macros
229 * @return An array of ActionError, one error for each macro not deleted
230 */
231 public ActionError [] deleteAllMacros() throws BridgeException {
232 return deleteAllRecords(DhcptabRecord.MACRO);
233 }
234
235 /**
236 * Delete all options
237 * @return An array of ActionError, one error for each option not deleted
238 */
239 public ActionError [] deleteAllOptions() throws BridgeException {
240 return deleteAllRecords(DhcptabRecord.OPTION);
241 }
242
243 /**
244 * Delete a list of macros identified by name
245 * @param macroNames Names of the macros to delete
246 * @return An array of ActionError, one element per macro not deleted
247 */
248 public ActionError [] deleteMacros(String [] macroNames) {
249 ArrayList errorList = new ArrayList();
250
251 for (int i = 0; i < macroNames.length; ++i) {
252 try {
253 deleteRecord(macroNames[i], DhcptabRecord.MACRO);
254 } catch (BridgeException e) {
255 errorList.add(new ActionError(macroNames[i], e));
256 }
257 }
258
259 return (ActionError [])errorList.toArray(new ActionError[0]);
260 }
261
262 /**
263 * Delete a list of options identified by name
264 * @param optionNames Names of options to delete
265 * @return An array of ActionError, one element per option not deleted
266 */
267 public ActionError [] deleteOptions(String [] optionNames) {
268 ArrayList errorList = new ArrayList();
269
270 for (int i = 0; i < optionNames.length; ++i) {
271 try {
272 deleteRecord(optionNames[i], DhcptabRecord.OPTION);
273 } catch (BridgeException e) {
274 errorList.add(new ActionError(optionNames[i], e));
275 }
276 }
277
278 return (ActionError [])errorList.toArray(new ActionError[0]);
279 }
280
281 /**
282 * Retrieve a given macro from the dhcptab.
283 * @param key the key of the record to retrieve
284 * @return the Macro for the given key
285 */
286 public Macro getMacro(String key)
287 throws BridgeException {
288 return getMacro(key, null);
289 }
290
291 /**
292 * Retrieve a given macro from the dhcptab.
293 * @param key the key of the record to retrieve
294 * @param datastore user-supplied datastore attributes
295 * @return the Macro for the given key
296 */
297 public Macro getMacro(String key, DhcpDatastore datastore)
298 throws BridgeException {
299 OptionsTable optionsTable = OptionsTable.getTable();
300 optionsTable.add(bridge.getOptions(datastore));
301 return bridge.getMacro(key, datastore);
302 }
303
304 /**
305 * Retrieve a given option from the dhcptab.
306 * @param key the key of the record to retrieve
307 * @return the Option for the given key
308 */
309 public Option getOption(String key)
310 throws BridgeException {
311 return getOption(key, null);
312 }
313
314 /**
315 * Retrieve a given option from the dhcptab.
316 * @param key the key of the record to retrieve
317 * @param datastore user-supplied datastore attributes
318 * @return the Option for the given key
319 */
320 public Option getOption(String key, DhcpDatastore datastore)
321 throws BridgeException {
322 return bridge.getOption(key, datastore);
323 }
324
325 /**
326 * Create a new dhcptab converting the one in the server's data store,
327 * into a new data store.
328 * @param datastore user-supplied datastore attributes
329 */
330 public void cvtDhcptab(DhcpDatastore datastore)
331 throws BridgeException {
332 bridge.cvtDhcptab(datastore);
333 }
334
335 /**
336 * Create a new empty dhcptab in the server's data store, which must
337 * already be configured.
338 */
339 public void createDhcptab() throws BridgeException {
340 createDhcptab(null);
341 }
342
343 /**
344 * Create a new empty dhcptab in the server's data store, which must
345 * already be configured.
346 * @param datastore user-supplied datastore attributes
347 */
348 public void createDhcptab(DhcpDatastore datastore)
349 throws BridgeException {
350 bridge.createDhcptab(datastore);
351 }
352
353 /**
354 * Delete the server's dhcptab in the current data store.
355 */
356 public void deleteDhcptab() throws BridgeException {
357 deleteDhcptab(null);
358 }
359
360 /**
361 * Delete the server's dhcptab in the current data store.
362 * @param datastore user-supplied datastore attributes
363 */
364 public void deleteDhcptab(DhcpDatastore datastore)
365 throws BridgeException {
366 bridge.deleteDhcptab(datastore);
367 }
368
369 public void createLocaleMacro()
370 throws BridgeException, ValidationException {
371 createLocaleMacro(null);
372 }
373
374 public void createLocaleMacro(DhcpDatastore datastore)
375 throws BridgeException, ValidationException {
376
377 Macro macro = new Macro();
378 macro.setKey("Locale");
379 macro.storeOption(StandardOptions.CD_TIMEOFFSET,
380 String.valueOf(TimeZone.getDefault().getRawOffset()/1000));
381
382 createRecord(macro, false);
383 }
384
385 public void createServerMacro(String svrName,
386 InetAddress svrAddress, int leaseLength,
387 boolean leaseNegotiable, String dnsDomain, Vector dnsServs)
388 throws BridgeException, ValidationException {
389
390 createServerMacro(svrName, svrAddress, leaseLength, leaseNegotiable,
391 dnsDomain, dnsServs, null);
392 }
393
394 public void createServerMacro(String svrName,
395 InetAddress svrAddress, int leaseLength,
396 boolean leaseNegotiable, String dnsDomain, Vector dnsServs,
397 DhcpDatastore datastore)
398 throws BridgeException, ValidationException {
399
400 Macro macro = new Macro();
401 macro.setKey(svrName);
402 macro.storeOption("Include", "Locale");
403 macro.storeOption(StandardOptions.CD_TIMESERV, svrAddress);
404 macro.storeOption(StandardOptions.CD_LEASE_TIME,
405 String.valueOf(leaseLength));
406 if (leaseNegotiable) {
407 macro.storeOption(StandardOptions.CD_BOOL_LEASENEG, null);
408 }
409 if (dnsDomain != null && dnsDomain.length() != 0 &&
410 dnsServs != null && dnsServs.size() != 0) {
411 macro.storeOption(StandardOptions.CD_DNSDOMAIN, dnsDomain);
412 macro.storeOption(StandardOptions.CD_DNSSERV, dnsServs);
413 }
414 // First delete it in case it's already there
415 try {
416 deleteRecord(macro, false);
417 } catch (Throwable e) {
418 // Ignore any error
419 }
420
421 createRecord(macro, false);
422 }
423
424 public synchronized void createNetworkMacro(Network network,
425 IPAddress [] routers, boolean isLan, String nisDomain, Vector nisServs)
426 throws BridgeException, ValidationException {
427
428 createNetworkMacro(network, routers, isLan, nisDomain, nisServs,
429 null);
430 }
431
432 public void createNetworkMacro(Network network,
433 IPAddress [] routers, boolean isLan, String nisDomain, Vector nisServs,
434 DhcpDatastore datastore) throws BridgeException, ValidationException {
435
436 Macro macro = new Macro();
437 macro.setKey(network.toString());
438 macro.storeOption(StandardOptions.CD_SUBNETMASK, network.getMask());
439 if (routers == null) {
440 macro.storeOption(StandardOptions.CD_ROUTER_DISCVRY_ON, "1");
441 } else {
442 for (int i = 0; i < routers.length; i++) {
443 macro.storeOption(StandardOptions.CD_ROUTER, routers[i]);
444 }
445 }
446
447 if (isLan) {
448 macro.storeOption(StandardOptions.CD_BROADCASTADDR,
449 network.getBroadcastAddress());
450 }
451
452 // NIS config
453 if (nisDomain != null && nisDomain.length() != 0 &&
454 nisServs != null && nisServs.size() != 0) {
455 macro.storeOption(StandardOptions.CD_NIS_DOMAIN, nisDomain);
456 macro.storeOption(StandardOptions.CD_NIS_SERV, nisServs);
457 }
458
459 createRecord(macro, false);
460 }
461 }