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.data;
26 
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.io.Serializable;
30 import com.sun.dhcpmgr.data.qualifier.*;
31 
32 /**
33  * DhcpdOptions models the option settings for the in.dhcpd daemon.  We read
34  * and write the option settings in the daemon's defaults file.
35  * Getter and setter methods are provided for each individual option.
36  */
37 
38 public class DhcpdOptions implements DhcpConfigOpts, Serializable {
39     /* The list of facility choices the user may select from for logging */
40     private static final Integer [] loggingFacilities = {
41         new Integer(0), new Integer(1), new Integer(2), new Integer(3),
42 	new Integer(4), new Integer(5), new Integer(6), new Integer(7)
43     };
44 
45     // Store the option settings here
46     private ArrayList options;
47 
48     /**
49      *  Dirty flag. Set after a clear or a set on an option.
50      */
51     private boolean dirty = false;
52 
DhcpdOptions()53     public DhcpdOptions() {
54     	options = new ArrayList();
55     }
56 
DhcpdOptions(DhcpResource [] opts)57     public DhcpdOptions(DhcpResource [] opts) {
58     	options = new ArrayList(Arrays.asList(opts));
59     }
60 
clone()61     public Object clone() {
62 	DhcpdOptions o = new DhcpdOptions();
63 	o.options = (ArrayList)options.clone();
64 	return o;
65     }
66 
67     /**
68      * Test whether a particular option is set.
69      * @param key
70      *   The name of the option to set.
71      * @return
72      *   True if the option is set, otherwise false.
73      */
isSet(String key)74     public boolean isSet(String key) {
75 	return internalIsSet(key);
76     }
77 
78     /**
79      * Set an option to a supplied value.
80      * @param key
81      *   The name of the option to set.
82      * @param value
83      *   The value of the option.
84      */
set(String key, String value)85     public void set(String key, String value) {
86 	set(key, value, false);
87     }
88 
89     /**
90      * Set an option to a supplied value, or add a comment line to the
91      * table.
92      * @param key
93      *   The name of the option to set.
94      * @param value
95      *   The value of the option.
96      * @param comment
97      *   true if this is a comment, in which case value is ignored
98      * and the comment text is contained entirely in key.
99      */
set(String key, String value, boolean comment)100     public void set(String key, String value, boolean comment) {
101 	internalSet(key, value, comment);
102 
103 	/*
104 	 * Ensure that the run mode is kept consistent with the
105 	 * configuration parameters.  Mgt. tools rely on this!
106 	 */
107 	if (key.equals(DSVC_CK_PATH)) {
108 	    internalSet(DSVC_CK_RUN_MODE, DSVC_CV_SERVER);
109 	} else if (key.equals(DSVC_CK_RELAY_DESTINATIONS)) {
110 	    internalSet(DSVC_CK_RUN_MODE, DSVC_CV_RELAY);
111 	} else if (key.equals(DSVC_CK_RESOURCE)) {
112 	    internalSet(DSVC_CK_RUN_MODE, DSVC_CV_SERVER);
113 	}
114     }
115 
116     /**
117      * Clear an option.
118      * @param key
119      *   The name of the option to clear.
120      */
clear(String key)121     public void clear(String key) {
122 	internalClear(key);
123 
124 	if (key.equals(DSVC_CK_RELAY_DESTINATIONS)) {
125 	    internalSet(DSVC_CK_RUN_MODE, DSVC_CV_SERVER);
126 	}
127     }
128 
129     /**
130      * Return the value of an option setting; null if it's not set.
131      * @param key
132      *   The option whose value is to be retrieved.
133      * @return
134      *   The value of an option setting; null if it's not set.
135      */
valueOf(String key)136     public String valueOf(String key) {
137 	return internalValueOf(key);
138     }
139 
140     // Test whether a particular option is set
internalIsSet(String key)141     private boolean internalIsSet(String key) {
142 	DhcpResource res = new DhcpResource();
143 	res.setKey(key);
144 	return options.contains(res);
145     }
146 
147     // Set an option to a supplied value
internalSet(String key, String value)148     private void internalSet(String key, String value) {
149 	internalSet(key, value, false);
150     }
151 
152     /**
153      * Set an option to a supplied value, or add a comment line to the
154      * table.
155      * @param key The name of the option to set
156      * @param value The value of the option
157      * @param comment true if this is a comment, in which case value is ignored
158      * and the comment text is contained entirely in key.
159      */
internalSet(String key, String value, boolean comment)160     private void internalSet(String key, String value, boolean comment) {
161 	DhcpResource res = new DhcpResource(key, value, comment);
162 	int i = options.indexOf(res);
163 	if (i != -1) {
164 	    DhcpResource existing = (DhcpResource)options.get(i);
165 
166 	    if (!existing.getValue().equals(res.getValue())) {
167 		options.set(i, res);
168 		dirty = true;
169 	    }
170 	} else {
171 	    options.add(res);
172 	    dirty = true;
173 	}
174     }
175 
176     // Clear an option
internalClear(String key)177     private void internalClear(String key) {
178 	DhcpResource res = new DhcpResource();
179 	res.setKey(key);
180 	int i = options.indexOf(res);
181 	if (i != -1) {
182 	    options.remove(i);
183 	    dirty = true;
184 	}
185     }
186 
187     /**
188      * Return the value of an option setting; null if it's not set
189      * @param key The option whose value is to be retrieved
190      * @return The value of an option setting; null if it's not set
191      */
internalValueOf(String key)192     private String internalValueOf(String key) {
193 	DhcpResource res = new DhcpResource();
194 	res.setKey(key);
195 	int i = options.indexOf(res);
196 	if (i != -1) {
197 	    return ((DhcpResource)options.get(i)).getValue();
198 	} else {
199 	    return null;
200 	}
201     }
202 
203     /**
204      * Return all of the option settings as an array
205      * @return An array of Objects which will all be DhcpResources
206      */
getAll()207     public Object [] getAll() {
208     	return options.toArray();
209     }
210 
211     /**
212      * Test to see whether or not the daemon is enabled.
213      * @return true if daemon is enabled, false if not.
214      */
isDaemonEnabled()215     public boolean isDaemonEnabled() {
216 	return DSVC_CV_TRUE.equals(valueOf(DSVC_CK_DAEMON_ENABLED));
217     }
218 
219     /**
220      * Set daemon enabled or disabled
221      * @param state true for enabled, false for disabled
222      */
setDaemonEnabled(boolean state)223     public void setDaemonEnabled(boolean state) {
224 	set(DSVC_CK_DAEMON_ENABLED, state ? DSVC_CV_TRUE : DSVC_CV_FALSE);
225     }
226 
227     /**
228      * Set the DhcpDatastore attributes.
229      * @param resource the data store resource attribute
230      * @param location the data store location attribute
231      * @param config the data store config attribute
232      * @param version the data store version attribute
233      */
setDhcpDatastore(String resource, String location, String config, int version)234     public void setDhcpDatastore(String resource, String location,
235 	String config, int version) {
236 	setResource(resource);
237 	setPath(location);
238 	setConfig(config);
239 	setResourceVersion(version);
240     } // setDhcpDatastore
241 
242     /**
243      * Set the DhcpDatastore attributes.
244      * @param datastore a datastore object whose attributes
245      * are the desired attributes.
246      */
setDhcpDatastore(DhcpDatastore datastore)247     public void setDhcpDatastore(DhcpDatastore datastore) {
248 	setResource(datastore.getResource());
249 	setPath(datastore.getLocation());
250 	setConfig(datastore.getConfig());
251 	setResourceVersion(datastore.getVersion());
252     } // setDhcpDatastore
253 
254     /**
255      * Set the DhcpDatastore attributes.
256      * @param resource the data store resource attribute
257      * @param location the data store location attribute
258      * @param config the data store config attribute
259      * @param version the data store version attribute
260      */
getDhcpDatastore()261     public DhcpDatastore getDhcpDatastore() {
262 	return (new DhcpDatastore(getResource(), getPath(),
263 	    getConfig(), getResourceVersion()));
264     } // getDhcpDatastore
265 
266     /**
267      * Set the resource (aka data store) in which DHCP data is stored.
268      * This automatically also sets the run mode to server.
269      * @param s Unique name of resource
270      */
setResource(String s)271     public void setResource(String s) {
272     	set(DSVC_CK_RESOURCE, s);
273     }
274 
275     /**
276      * Retrieve the name of the resource/data store used for DHCP.
277      * @return The unique name of the resource; null if not set
278      */
getResource()279     public String getResource() {
280     	return valueOf(DSVC_CK_RESOURCE);
281     }
282 
283     /**
284      * Set the version of the resource in which DHCP data is stored.
285      * @param i version number
286      */
setResourceVersion(int i)287     public void setResourceVersion(int i) {
288     	set(DSVC_CK_CONVER, Integer.toString(i));
289     }
290 
291     /**
292      * Retrieve the version of the resource/data store used for DHCP.
293      * @return The version number or -1 if not valid.
294      */
getResourceVersion()295     public int getResourceVersion() {
296 	try {
297 	    return Integer.parseInt(valueOf(DSVC_CK_CONVER));
298 	} catch (NumberFormatException e) {
299 	    return -1;
300 	}
301     }
302 
303     /**
304      * Set the path within the resource in which to place the tables.
305      * For files, this is a Unix pathname; for NIS+, the directory name.
306      * @param s The path
307      */
setPath(String s)308     public void setPath(String s) {
309     	set(DSVC_CK_PATH, s);
310     }
311 
312     /**
313      * Get the path used for data storage.
314      * @return The path within the resource; null if not set
315      */
getPath()316     public String getPath() {
317     	return valueOf(DSVC_CK_PATH);
318     }
319 
320     /**
321      * Set the config for the resource.
322      * @param s The config
323      */
setConfig(String s)324     public void setConfig(String s) {
325 	if (s != null) {
326 	    set(DSVC_CK_RESOURCE_CONFIG, s);
327 	} else {
328 	    clear(DSVC_CK_RESOURCE_CONFIG);
329 	}
330     }
331 
332     /**
333      * Get the config for data store.
334      * @return The config; null if not set
335      */
getConfig()336     public String getConfig() {
337     	return valueOf(DSVC_CK_RESOURCE_CONFIG);
338     }
339 
340     /**
341      * Set the hosts resource (aka data store) in which host data is stored.
342      * @param s Unique name of resource
343      */
setHostsResource(String s)344     public void setHostsResource(String s) {
345     	set(DSVC_CK_HOSTS_RESOURCE, s);
346     }
347 
348     /**
349      * Retrieve the name of the resource/data store used for hosts.
350      * @return The unique name of the resource; null if not set
351      */
getHostsResource()352     public String getHostsResource() {
353     	return valueOf(DSVC_CK_HOSTS_RESOURCE);
354     }
355 
356     /**
357      * Set the domain within the hosts resource in which to place the tables.
358      * For files resource, this value is meaningless.
359      * @param s The domain
360      */
setHostsDomain(String s)361     public void setHostsDomain(String s) {
362     	set(DSVC_CK_HOSTS_DOMAIN, s);
363     }
364 
365     /**
366      * Get the domain used for hosts data storage.
367      * @return The domain within the resource; null if not set
368      */
getHostsDomain()369     public String getHostsDomain() {
370     	return valueOf(DSVC_CK_HOSTS_DOMAIN);
371     }
372 
373     /**
374      * Test whether BOOTP compatibility is enabled.
375      * @return true if BOOTP compatibility is enabled.
376      */
isBootpCompatible()377     public boolean isBootpCompatible() {
378 	return isSet(DSVC_CK_BOOTP_COMPAT);
379     }
380 
381     /**
382      * Enable or disable BOOTP compatibility.
383      * @param state true if BOOTP compatibility is enabled, false if not.
384      * @param isAutomatic true if automatic allocation is allowed.
385      */
setBootpCompatible(boolean state, boolean isAutomatic)386     public void setBootpCompatible(boolean state, boolean isAutomatic) {
387 	if (state) {
388 	    if (isAutomatic) {
389 		set(DSVC_CK_BOOTP_COMPAT, DSVC_CV_AUTOMATIC);
390 	    } else {
391 		set(DSVC_CK_BOOTP_COMPAT, DSVC_CV_MANUAL);
392 	    }
393 	} else {
394 	    clear(DSVC_CK_BOOTP_COMPAT);
395 	}
396     }
397 
398     /**
399      * Test whether BOOTP compatibility is automatic or manual
400      * @return true if BOOTP compatibility is automatic.
401      */
isBootpAutomatic()402     public boolean isBootpAutomatic() {
403 	return DSVC_CV_AUTOMATIC.equals(valueOf(DSVC_CK_BOOTP_COMPAT));
404     }
405 
406     /**
407      * Test whether relay hop limit is set.
408      * @return true if the limit is set, false if default value is used.
409      */
isRelayHops()410     public boolean isRelayHops() {
411 	return isSet(DSVC_CK_RELAY_HOPS);
412     }
413 
414     /**
415      * Set the relay hop limit.
416      * @param state true if hop limit should be set, false if not
417      * @param hops Number of hops to limit forwarding to
418      */
setRelayHops(boolean state, Integer hops)419     public void setRelayHops(boolean state, Integer hops) {
420 	if (state) {
421 	    set(DSVC_CK_RELAY_HOPS, hops.toString());
422 	} else {
423 	    clear(DSVC_CK_RELAY_HOPS);
424 	}
425     }
426 
427     /**
428      * Get the relay hop limit.
429      * @return The number of hops currently set, or null if this isn't set.
430      */
getRelayHops()431     public Integer getRelayHops() {
432 	String hops = valueOf(DSVC_CK_RELAY_HOPS);
433 	if (hops != null) {
434 	    return new Integer(hops);
435 	} else {
436 	    return null;
437 	}
438     }
439 
440     /**
441      * Test whether a network interface list is set; failure to set an interface
442      * list implies that all interfaces will be monitored.
443      * @return true if an interface list is set
444      */
isInterfaces()445     public boolean isInterfaces() {
446 	return isSet(DSVC_CK_INTERFACES);
447     }
448 
449     /**
450      * Set the network interface list.
451      * @param state true if interface list is to be set, false if it should be
452      * cleared
453      * @param list A comma-separated list of interface names
454      */
setInterfaces(boolean state, String list)455     public void setInterfaces(boolean state, String list) {
456 	if (state) {
457 	    set(DSVC_CK_INTERFACES, list);
458 	} else {
459 	    clear(DSVC_CK_INTERFACES);
460 	}
461     }
462 
463     /**
464      * Get the list of network interfaces.
465      * @return The comma-separated list of interfaces; null if not set
466      */
getInterfaces()467     public String getInterfaces() {
468 	return valueOf(DSVC_CK_INTERFACES);
469     }
470 
471     /**
472      * Test whether ICMP address verification is enabled
473      * @return true if ICMP verification is performed
474      */
isICMPVerify()475     public boolean isICMPVerify() {
476 	/*
477 	 * Use this double-inverse comparison so that the default behavior of
478 	 * ICMP enabled is handled correctly.
479 	 */
480 	return !DSVC_CV_FALSE.equals(valueOf(DSVC_CK_ICMP_VERIFY));
481     }
482 
483     /**
484      * Set ICMP verification
485      * @param state true if verification should be done, false otherwise
486      */
setICMPVerify(boolean state)487     public void setICMPVerify(boolean state) {
488 	set(DSVC_CK_ICMP_VERIFY, state ? DSVC_CV_TRUE : DSVC_CV_FALSE);
489     }
490 
491     /**
492      * Test whether offer cache timeout is set
493      * @return true if it is set
494      */
isOfferTtl()495     public boolean isOfferTtl() {
496 	return isSet(DSVC_CK_OFFER_CACHE_TIMEOUT);
497     }
498 
499     /**
500      * Set offer cache timeout value
501      * @param state true if offer cache timeout value is set, false if server's
502      * default will be used instead
503      * @param time Number of seconds to hold offers in the cache
504      */
setOfferTtl(boolean state, Integer time)505     public void setOfferTtl(boolean state, Integer time) {
506 	if (state) {
507 	    set(DSVC_CK_OFFER_CACHE_TIMEOUT, time.toString());
508 	} else {
509 	    clear(DSVC_CK_OFFER_CACHE_TIMEOUT);
510 	}
511     }
512 
513     /**
514      * Get the offer cache timeout value
515      * @return timeout value set, or null if server default is used
516      */
getOfferTtl()517     public Integer getOfferTtl() {
518 	String s = valueOf(DSVC_CK_OFFER_CACHE_TIMEOUT);
519 	if (s != null) {
520 	    return new Integer(s);
521 	} else {
522 	    return null;
523 	}
524     }
525 
526     /**
527      * Test whether server is running in relay mode
528      * @return true if running as relay
529      */
isRelay()530     public boolean isRelay() {
531 	return DSVC_CV_RELAY.equals(valueOf(DSVC_CK_RUN_MODE));
532     }
533 
534     /**
535      * Set relay mode and server list
536      * @param state true if relay mode is desired, false for normal server
537      * @param servers list of servers to which requests should be forwarded
538      */
setRelay(boolean state, String servers)539     public void setRelay(boolean state, String servers) {
540 	if (state) {
541 	    set(DSVC_CK_RELAY_DESTINATIONS, servers);
542 	} else {
543 	    clear(DSVC_CK_RELAY_DESTINATIONS);
544 	}
545     }
546 
547     /**
548      * Get list of server targets for relay
549      * @return list of relay targets; null if not set
550      */
getRelay()551     public String getRelay() {
552 	return valueOf(DSVC_CK_RELAY_DESTINATIONS);
553     }
554 
555     /**
556      * Test for server automatic reload of dhcptab
557      * @return true if server is rescanning dhcptab
558      */
isRescan()559     public boolean isRescan() {
560 	return isSet(DSVC_CK_RESCAN_INTERVAL);
561     }
562 
563     /**
564      * Set the rescan interval
565      * @param state true if rescanning is enabled, false if not
566      * @param interval number of minutes between rescans
567      */
setRescan(boolean state, Integer interval)568     public void setRescan(boolean state, Integer interval) {
569 	if (state) {
570 	    set(DSVC_CK_RESCAN_INTERVAL, interval.toString());
571 	} else {
572 	    clear(DSVC_CK_RESCAN_INTERVAL);
573 	}
574     }
575 
576     /**
577      * Get the rescan interval
578      * @return the rescan interval in minutes, or null if rescan is not enabled
579      */
getRescan()580     public Integer getRescan() {
581 	String s = valueOf(DSVC_CK_RESCAN_INTERVAL);
582 	if (s != null) {
583 	    return new Integer(s);
584 	} else {
585 	    return null;
586 	}
587     }
588 
589     /**
590      * Test whether ownerip
591      * @return true if ownerip
592      */
isOwnerip()593     public boolean isOwnerip() {
594 	return isSet(DSVC_CK_OWNER_IP);
595     }
596 
597     /**
598      * Set ownerip server list
599      * @param state true if ownerip is desired, false for normal server
600      * @param ownerips list of servers ownerips
601      */
setOwnerip(boolean state, String ownerips)602     public void setOwnerip(boolean state, String ownerips) {
603 	if (state) {
604 	    set(DSVC_CK_OWNER_IP, ownerips);
605 	} else {
606 	    clear(DSVC_CK_OWNER_IP);
607 	}
608     }
609 
610     /**
611      * Get list of server targets for ownerip
612      * @return list of ownerip targets; null if not set
613      */
getOwnerip()614     public String getOwnerip() {
615 	return valueOf(DSVC_CK_OWNER_IP);
616     }
617 
618 
619     /**
620      * Test for server dynamic DNS updates
621      * @return true if server is updating DNS
622      */
isDnsUpdated()623     public boolean isDnsUpdated() {
624 	return isSet(DSVC_CK_NSU_TIMEOUT);
625     }
626 
627     /**
628      * Set the DNS update timeout value
629      * @param state true if DNS updates are enabled, false if not
630      * @param timeout number of seconds before timeout
631      */
setDnsTimeout(boolean state, Integer timeout)632     public void setDnsTimeout(boolean state, Integer timeout) {
633 	if (state) {
634 	    set(DSVC_CK_NSU_TIMEOUT, timeout.toString());
635 	} else {
636 	    clear(DSVC_CK_NSU_TIMEOUT);
637 	}
638     }
639 
640     /**
641      * Get the DNS update timeout value
642      * @return the timeout in seconds, or null if DNS updates are not enabled
643      */
getDnsTimeout()644     public Integer getDnsTimeout() {
645 	String s = valueOf(DSVC_CK_NSU_TIMEOUT);
646 	if (s != null) {
647 	    return new Integer(s);
648 	} else {
649 	    return null;
650 	}
651     }
652 
653     /**
654      * Test for verbose logging mode
655      * @return true if verbose logging, false for normal
656      */
isVerbose()657     public boolean isVerbose() {
658 	return DSVC_CV_TRUE.equals(valueOf(DSVC_CK_VERBOSE));
659     }
660 
661     /**
662      * Set verbose logging mode
663      * @param state true for verbose, false for normal
664      */
setVerbose(boolean state)665     public void setVerbose(boolean state) {
666 	set(DSVC_CK_VERBOSE, state ? DSVC_CV_TRUE : DSVC_CV_FALSE);
667     }
668 
669 
670     /**
671      * Test for transaction logging mode.
672      * @return true if transaction logging is enabled
673      */
isLogging()674     public boolean isLogging() {
675     	return isSet(DSVC_CK_LOGGING_FACILITY);
676     }
677 
678     /**
679      * Get the syslog facility number used for transaction logging
680      * @return facility number, which will be between 0 and 7
681      */
getLogging()682     public Integer getLogging() {
683 	String s = valueOf(DSVC_CK_LOGGING_FACILITY);
684     	if (s != null) {
685 	    return new Integer(s);
686 	} else {
687 	    return null;
688 	}
689     }
690 
691     /**
692      * Set transaction logging
693      * @param state true to enable transaction logging, false to disable
694      * @param value syslog facility number 0-7 used for logging
695      */
setLogging(boolean state, Integer value)696     public void setLogging(boolean state, Integer value) {
697         if (state) {
698 	    set(DSVC_CK_LOGGING_FACILITY, value.toString());
699 	} else {
700 	    clear(DSVC_CK_LOGGING_FACILITY);
701 	}
702     }
703 
704     /**
705      * Get the list of logging facility choices
706      * @return an array of facility numbers
707      */
getLoggingFacilities()708     public static Integer [] getLoggingFacilities() {
709     	return loggingFacilities;
710     }
711 
712     /**
713      * Return an indicator of whether the parameters may have been changed
714      * by a set() or a clear() since the last call to clearDirty().
715      *
716      * @return
717      *   True if a set() or a clear() has occurred since the last call to
718      *   clearDirty(), otherwise false.
719      */
isDirty()720     public boolean isDirty() {
721 	return dirty;
722     }
723 
724     /**
725      * Set the dirty indicator to false. Any subsequent calls to set() or
726      * clear() may set the dirty flag.
727      */
clearDirty()728     public void clearDirty() {
729 	dirty = false;
730     }
731 
732     /**
733      * Get the parameters qualifier.
734      *
735      * @param key
736      *   Parameters keyword.
737      * @return
738      *   The qualifier for the parameter if one exists, otherwise null.
739      */
getQualifier(String key)740     public Qualifier getQualifier(String key) {
741 	Qualifier qualifier = null;
742 
743 	if (key.equals(DSVC_CK_BOOTP_COMPAT)) {
744 	    qualifier =
745 		    new QualifierImpl(DSVC_CK_BOOTP_COMPAT, false, false,
746 			    new QualifierStringEnum(
747 				new String[] {
748 				    DSVC_CV_AUTOMATIC,
749 				    DSVC_CV_MANUAL
750 				}));
751 	} else if (key.equals(DSVC_CK_CACHE_TIMEOUT)) {
752 	    qualifier =
753 		    new QualifierImpl(DSVC_CK_CACHE_TIMEOUT, false, false,
754 			    new QualifierIntegerRange(
755 				0,
756 				Integer.MAX_VALUE));
757 
758 	} else if (key.equals(DSVC_CK_CONVER)) {
759 	    qualifier =
760 		    new QualifierImpl(DSVC_CK_CONVER, true, false,
761 			    new QualifierInteger());
762 
763 	} else if (key.equals(DSVC_CK_DAEMON_ENABLED)) {
764 	    qualifier =
765 		    new QualifierImpl(DSVC_CK_DAEMON_ENABLED, true, false,
766 			    new QualifierBoolean(
767 				DSVC_CV_TRUE,
768 				DSVC_CV_FALSE));
769 
770 	} else if (key.equals(DSVC_CK_DBG_MEMORY_NET)) {
771 	    qualifier =
772 		    new QualifierImpl(DSVC_CK_DBG_MEMORY_NET, false, true,
773 			    new QualifierIntegerRange(
774 				0,
775 				Integer.MAX_VALUE));
776 
777 	} else if (key.equals(DSVC_CK_DBG_PORT_OFFSET)) {
778 	    qualifier =
779 		    new QualifierImpl(DSVC_CK_DBG_PORT_OFFSET, false, true,
780 			    new QualifierIntegerRange(
781 				0,
782 				Integer.MAX_VALUE));
783 
784 	} else if (key.equals(DSVC_CK_HOSTS_DOMAIN)) {
785 	    qualifier =
786 		    new QualifierImpl(DSVC_CK_HOSTS_DOMAIN, true, false,
787 			    new QualifierStringEnum(
788 				new String[] {
789 				    DSVC_CV_DNS
790 				}));
791 	} else if (key.equals(DSVC_CK_HOSTS_RESOURCE)) {
792 	    qualifier =
793 		    new QualifierImpl(DSVC_CK_HOSTS_RESOURCE, true, false,
794 			    new QualifierStringEnum(
795 				new String[] {
796 				    DSVC_CV_DNS,
797 				    DSVC_CV_FILES
798 				}));
799 	} else if (key.equals(DSVC_CK_ICMP_VERIFY)) {
800 	    qualifier =
801 		    new QualifierImpl(DSVC_CK_ICMP_VERIFY, false, false,
802 			    new QualifierBoolean(
803 				DSVC_CV_TRUE,
804 				DSVC_CV_FALSE));
805 
806 	} else if (key.equals(DSVC_CK_INTERFACES)) {
807 	    qualifier =
808 		    new QualifierImpl(DSVC_CK_INTERFACES, false, false,
809 			    new QualifierArray(
810 				new QualifierString()));
811 
812 	} else if (key.equals(DSVC_CK_LEASE_MIN_LRU)) {
813 	    qualifier =
814 		    new QualifierImpl(DSVC_CK_LEASE_MIN_LRU, false, true,
815 			    new QualifierIntegerRange(
816 				0,
817 				Integer.MAX_VALUE));
818 
819 	} else if (key.equals(DSVC_CK_LOGGING_FACILITY)) {
820 	    qualifier =
821 		    new QualifierImpl(DSVC_CK_LOGGING_FACILITY, false, false,
822 			    new QualifierIntegerRange(
823 				DSVC_CV_LOGGING_FACILITY_MIN,
824 				DSVC_CV_LOGGING_FACILITY_MAX));
825 
826 	} else if (key.equals(DSVC_CK_MAX_CLIENTS)) {
827 	    qualifier =
828 		    new QualifierImpl(DSVC_CK_MAX_CLIENTS, false, true,
829 			    new QualifierIntegerRange(
830 				-1,
831 				Integer.MAX_VALUE));
832 
833 	} else if (key.equals(DSVC_CK_MAX_THREADS)) {
834 	    qualifier =
835 		    new QualifierImpl(DSVC_CK_MAX_THREADS, false, true,
836 			    new QualifierIntegerRange(
837 				-1,
838 				Integer.MAX_VALUE));
839 
840 	} else if (key.equals(DSVC_CK_OFFER_CACHE_TIMEOUT)) {
841 	    qualifier =
842 		    new QualifierImpl(DSVC_CK_OFFER_CACHE_TIMEOUT, false, false,
843 			    new QualifierIntegerRange(
844 				0,
845 				Integer.MAX_VALUE));
846 
847 	} else if (key.equals(DSVC_CK_PATH)) {
848 	    qualifier =
849 		    new QualifierImpl(DSVC_CK_PATH, true, false,
850 			    new QualifierString());
851 
852 	} else if (key.equals(DSVC_CK_RELAY_DESTINATIONS)) {
853 	    qualifier =
854 		    new QualifierImpl(DSVC_CK_RELAY_DESTINATIONS, false, false,
855 			    new QualifierArray(
856 				new QualifierOr(
857 				    new QualifierFQDN(),
858 				    new QualifierIPv4())));
859 
860 	} else if (key.equals(DSVC_CK_RELAY_HOPS)) {
861 	    qualifier =
862 		    new QualifierImpl(DSVC_CK_RELAY_HOPS, false, false,
863 			    new QualifierIntegerRange(
864 				0,
865 				Integer.MAX_VALUE));
866 
867 	} else if (key.equals(DSVC_CK_RESCAN_INTERVAL)) {
868 	    qualifier =
869 		    new QualifierImpl(DSVC_CK_RESCAN_INTERVAL, false, false,
870 			    new QualifierIntegerRange(
871 				0, Integer.MAX_VALUE));
872 
873 	} else if (key.equals(DSVC_CK_OWNER_IP)) {
874 	    qualifier =
875 		    new QualifierImpl(DSVC_CK_OWNER_IP, false, false,
876 			    new QualifierArray(
877 				new QualifierIPv4()));
878 
879 	} else if (key.equals(DSVC_CK_RESOURCE)) {
880 	    qualifier =
881 		    new QualifierImpl(DSVC_CK_RESOURCE, true, false,
882 			    new QualifierString());
883 
884 	} else if (key.equals(DSVC_CK_RESOURCE_CONFIG)) {
885 	    qualifier =
886 		    new QualifierImpl(DSVC_CK_RESOURCE_CONFIG, true, false,
887 			    new QualifierString());
888 
889 	} else if (key.equals(DSVC_CK_RUN_MODE)) {
890 	    qualifier =
891 		    new QualifierImpl(DSVC_CK_RUN_MODE, true, false,
892 			    new QualifierStringEnum(
893 				new String[] {
894 				    DSVC_CV_SERVER,
895 				    DSVC_CV_RELAY
896 				}));
897 	} else if (key.equals(DSVC_CK_RENOG_INTERVAL)) {
898 	    qualifier =
899 		    new QualifierImpl(DSVC_CK_RENOG_INTERVAL, false, false,
900 			    new QualifierIntegerRange(
901 				0,
902 				Integer.MAX_VALUE));
903 
904 	} else if (key.equals(DSVC_CK_NSU_TIMEOUT)) {
905 	    qualifier =
906 		    new QualifierImpl(DSVC_CK_NSU_TIMEOUT, false, false,
907 			    new QualifierIntegerRange(
908 				-1,
909 				Integer.MAX_VALUE));
910 
911 	} else if (key.equals(DSVC_CK_VERBOSE)) {
912 	    qualifier =
913 		    new QualifierImpl(DSVC_CK_VERBOSE, false, false,
914 			    new QualifierBoolean(
915 				DSVC_CV_TRUE,
916 				DSVC_CV_FALSE));
917 	}
918 
919 	return qualifier;
920     }
921 
922     /**
923      * Convert this object to a String representation
924      */
toString()925     public String toString() {
926 	StringBuffer b = new StringBuffer();
927 	for (int i = 0; i < options.size(); ++i) {
928 	    DhcpResource res = (DhcpResource)options.get(i);
929 	    b.append(res.getKey());
930 	    String s = res.getValue();
931 	    if (s != null) {
932 		b.append('=');
933 		b.append(s);
934 	    }
935 	    b.append('\n');
936 	}
937 	return b.toString();
938     }
939 }
940