001 /*
002 * Copyright 2005 The Apache Software Foundation
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 */
017
018 package org.apache.directory.server.dhcp.options;
019
020
021 import java.nio.ByteBuffer;
022 import java.util.Collections;
023 import java.util.HashMap;
024 import java.util.Map;
025
026 import org.apache.directory.server.dhcp.options.dhcp.BootfileName;
027 import org.apache.directory.server.dhcp.options.dhcp.ClientIdentifier;
028 import org.apache.directory.server.dhcp.options.dhcp.DhcpMessageType;
029 import org.apache.directory.server.dhcp.options.dhcp.IpAddressLeaseTime;
030 import org.apache.directory.server.dhcp.options.dhcp.MaximumDhcpMessageSize;
031 import org.apache.directory.server.dhcp.options.dhcp.OptionOverload;
032 import org.apache.directory.server.dhcp.options.dhcp.ParameterRequestList;
033 import org.apache.directory.server.dhcp.options.dhcp.RebindingTimeValue;
034 import org.apache.directory.server.dhcp.options.dhcp.RenewalTimeValue;
035 import org.apache.directory.server.dhcp.options.dhcp.RequestedIpAddress;
036 import org.apache.directory.server.dhcp.options.dhcp.ServerIdentifier;
037 import org.apache.directory.server.dhcp.options.dhcp.TftpServerName;
038 import org.apache.directory.server.dhcp.options.dhcp.UnrecognizedOption;
039 import org.apache.directory.server.dhcp.options.dhcp.VendorClassIdentifier;
040 import org.apache.directory.server.dhcp.options.misc.DefaultFingerServers;
041 import org.apache.directory.server.dhcp.options.misc.DefaultIrcServers;
042 import org.apache.directory.server.dhcp.options.misc.DefaultWwwServers;
043 import org.apache.directory.server.dhcp.options.misc.MobileIpHomeAgents;
044 import org.apache.directory.server.dhcp.options.misc.NbddServers;
045 import org.apache.directory.server.dhcp.options.misc.NetbiosNameServers;
046 import org.apache.directory.server.dhcp.options.misc.NetbiosNodeType;
047 import org.apache.directory.server.dhcp.options.misc.NetbiosScope;
048 import org.apache.directory.server.dhcp.options.misc.NisDomain;
049 import org.apache.directory.server.dhcp.options.misc.NisPlusDomain;
050 import org.apache.directory.server.dhcp.options.misc.NisPlusServers;
051 import org.apache.directory.server.dhcp.options.misc.NisServers;
052 import org.apache.directory.server.dhcp.options.misc.NntpServers;
053 import org.apache.directory.server.dhcp.options.misc.NtpServers;
054 import org.apache.directory.server.dhcp.options.misc.Pop3Servers;
055 import org.apache.directory.server.dhcp.options.misc.SmtpServers;
056 import org.apache.directory.server.dhcp.options.misc.StdaServers;
057 import org.apache.directory.server.dhcp.options.misc.StreetTalkServers;
058 import org.apache.directory.server.dhcp.options.misc.VendorSpecificInformation;
059 import org.apache.directory.server.dhcp.options.misc.XWindowDisplayManagers;
060 import org.apache.directory.server.dhcp.options.misc.XWindowFontServers;
061 import org.apache.directory.server.dhcp.options.perhost.DefaultIpTimeToLive;
062 import org.apache.directory.server.dhcp.options.perhost.IpForwarding;
063 import org.apache.directory.server.dhcp.options.perhost.MaximumDatagramSize;
064 import org.apache.directory.server.dhcp.options.perhost.NonLocalSourceRouting;
065 import org.apache.directory.server.dhcp.options.perhost.PathMtuAgingTimeout;
066 import org.apache.directory.server.dhcp.options.perhost.PathMtuPlateauTable;
067 import org.apache.directory.server.dhcp.options.perhost.PolicyFilter;
068 import org.apache.directory.server.dhcp.options.perinterface.AllSubnetsAreLocal;
069 import org.apache.directory.server.dhcp.options.perinterface.BroadcastAddress;
070 import org.apache.directory.server.dhcp.options.perinterface.InterfaceMtu;
071 import org.apache.directory.server.dhcp.options.perinterface.MaskSupplier;
072 import org.apache.directory.server.dhcp.options.perinterface.PerformMaskDiscovery;
073 import org.apache.directory.server.dhcp.options.perinterface.PerformRouterDiscovery;
074 import org.apache.directory.server.dhcp.options.perinterface.RouterSolicitationAddress;
075 import org.apache.directory.server.dhcp.options.perinterface.StaticRoute;
076 import org.apache.directory.server.dhcp.options.tcp.TcpDefaultTimeToLive;
077 import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveGarbage;
078 import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveInterval;
079 import org.apache.directory.server.dhcp.options.vendor.BootFileSize;
080 import org.apache.directory.server.dhcp.options.vendor.CookieServers;
081 import org.apache.directory.server.dhcp.options.vendor.DomainName;
082 import org.apache.directory.server.dhcp.options.vendor.DomainNameServers;
083 import org.apache.directory.server.dhcp.options.vendor.ExtensionsPath;
084 import org.apache.directory.server.dhcp.options.vendor.HostName;
085 import org.apache.directory.server.dhcp.options.vendor.ImpressServers;
086 import org.apache.directory.server.dhcp.options.vendor.LogServers;
087 import org.apache.directory.server.dhcp.options.vendor.LprServers;
088 import org.apache.directory.server.dhcp.options.vendor.MeritDumpFile;
089 import org.apache.directory.server.dhcp.options.vendor.NameServers;
090 import org.apache.directory.server.dhcp.options.vendor.ResourceLocationServers;
091 import org.apache.directory.server.dhcp.options.vendor.RootPath;
092 import org.apache.directory.server.dhcp.options.vendor.Routers;
093 import org.apache.directory.server.dhcp.options.vendor.SubnetMask;
094 import org.apache.directory.server.dhcp.options.vendor.SwapServer;
095 import org.apache.directory.server.dhcp.options.vendor.TimeOffset;
096 import org.apache.directory.server.dhcp.options.vendor.TimeServers;
097 import org.apache.directory.server.i18n.I18n;
098
099
100 /**
101 * The Dynamic Host Configuration Protocol (DHCP) provides a framework
102 * for passing configuration information to hosts on a TCP/IP network.
103 * Configuration parameters and other control information are carried in
104 * tagged data items that are stored in the 'options' field of the DHCP
105 * message. The data items themselves are also called "options."
106 *
107 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
108 * @version $Rev: 902331 $, $Date: 2010-01-23 03:41:35 +0200 (Sat, 23 Jan 2010) $
109 */
110 public abstract class DhcpOption
111 {
112 /**
113 * An array of concrete implementations of DhcpOption.
114 */
115 private static Class OPTION_CLASSES[] =
116 { BootfileName.class, ClientIdentifier.class, DhcpMessageType.class, IpAddressLeaseTime.class,
117 MaximumDhcpMessageSize.class, org.apache.directory.server.dhcp.options.dhcp.Message.class,
118 OptionOverload.class, ParameterRequestList.class, RebindingTimeValue.class, RenewalTimeValue.class,
119 RequestedIpAddress.class, ServerIdentifier.class, TftpServerName.class, VendorClassIdentifier.class,
120 ClientIdentifier.class, DhcpMessageType.class, IpAddressLeaseTime.class, MaximumDhcpMessageSize.class,
121 OptionOverload.class, ParameterRequestList.class, RebindingTimeValue.class, RenewalTimeValue.class,
122 RequestedIpAddress.class, ServerIdentifier.class, TftpServerName.class, UnrecognizedOption.class,
123 VendorClassIdentifier.class, DefaultFingerServers.class, DefaultIrcServers.class, DefaultWwwServers.class,
124 MobileIpHomeAgents.class, NbddServers.class, NetbiosNameServers.class, NetbiosNodeType.class,
125 NetbiosScope.class, NisDomain.class, NisPlusDomain.class, NisPlusServers.class, NisServers.class,
126 NntpServers.class, NtpServers.class, Pop3Servers.class, SmtpServers.class, StdaServers.class,
127 StreetTalkServers.class, VendorSpecificInformation.class, XWindowDisplayManagers.class,
128 XWindowFontServers.class, DefaultIpTimeToLive.class, IpForwarding.class, MaximumDatagramSize.class,
129 NonLocalSourceRouting.class, PathMtuAgingTimeout.class, PathMtuPlateauTable.class, PolicyFilter.class,
130 AllSubnetsAreLocal.class, BroadcastAddress.class, InterfaceMtu.class, MaskSupplier.class,
131 PerformMaskDiscovery.class, PerformRouterDiscovery.class, RouterSolicitationAddress.class,
132 StaticRoute.class, TcpDefaultTimeToLive.class, TcpKeepaliveGarbage.class, TcpKeepaliveInterval.class,
133 BootFileSize.class, CookieServers.class, DomainName.class, DomainNameServers.class, ExtensionsPath.class,
134 HostName.class, ImpressServers.class, LogServers.class, LprServers.class, MeritDumpFile.class,
135 NameServers.class, ResourceLocationServers.class, RootPath.class, Routers.class, SubnetMask.class,
136 SwapServer.class, TimeOffset.class, TimeServers.class, };
137
138 /**
139 * A map of concrete implementations of DhcpOption indexed by tag code.
140 */
141 private static Map OPTION_CLASS_BY_CODE;
142
143 /**
144 * A map of tag codes indexed by OptionClass subclass.
145 */
146 private static Map CODE_BY_CLASS;
147
148 static
149 {
150 try
151 {
152 // initialize the tag-to-class and class-to-tag map
153 Map classByCode = new HashMap();
154 Map codeByClass = new HashMap();
155 for ( int i = 0; i < OPTION_CLASSES.length; i++ )
156 {
157 Class c = OPTION_CLASSES[i];
158
159 if ( !DhcpOption.class.isAssignableFrom( c ) )
160 throw new RuntimeException( I18n.err( I18n.ERR_639, c ) );
161
162 DhcpOption o = ( DhcpOption ) c.newInstance();
163
164 Integer tagInt = new Integer( o.getTag() );
165 classByCode.put( tagInt, c );
166 codeByClass.put( c, tagInt );
167 }
168
169 OPTION_CLASS_BY_CODE = Collections.unmodifiableMap( classByCode );
170 CODE_BY_CLASS = Collections.unmodifiableMap( codeByClass );
171 }
172 catch ( Exception e )
173 {
174 throw new RuntimeException( I18n.err( I18n.ERR_640 ), e );
175 }
176 }
177
178
179 public static Class getClassByTag( int tag )
180 {
181 return ( Class ) OPTION_CLASS_BY_CODE.get( new Integer( tag ) );
182 }
183
184
185 public static int getTagByClass( Class c )
186 {
187 return ( ( Integer ) CODE_BY_CLASS.get( c ) ).intValue();
188 }
189
190 /**
191 * The default data array used for simple (unparsed) options.
192 */
193 private byte[] data;
194
195
196 /**
197 * Get the option's code tag.
198 *
199 * @return byte
200 */
201 public abstract byte getTag();
202
203
204 /**
205 * Set the data (wire format) from a byte array. The default implementation
206 * just records the data as a byte array. Subclasses may parse the data into
207 * something more meaningful.
208 *
209 * @param data
210 */
211 public void setData( byte data[] )
212 {
213 this.data = data;
214 }
215
216
217 /**
218 * Get the data (wire format) into a byte array. Subclasses must provide an
219 * implementation which serializes the parsed data back into a byte array if
220 * they override {@link #setData(byte[])}.
221 *
222 * @return byte[]
223 */
224 public byte[] getData()
225 {
226 return data;
227 }
228
229
230 public final void writeTo( ByteBuffer out )
231 {
232 out.put( getTag() );
233
234 // FIXME: handle continuation, i.e. options longer than 128 bytes?
235 byte data[] = getData();
236 if ( data.length > 255 )
237 throw new IllegalArgumentException( I18n.err( I18n.ERR_641 ) );
238
239 out.put( ( byte ) data.length );
240 out.put( data );
241 }
242 }