View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  
21  package org.apache.directory.server.dhcp.options;
22  
23  
24  import java.nio.ByteBuffer;
25  import java.util.Collections;
26  import java.util.HashMap;
27  import java.util.Map;
28  
29  import org.apache.directory.server.dhcp.options.dhcp.BootfileName;
30  import org.apache.directory.server.dhcp.options.dhcp.ClientIdentifier;
31  import org.apache.directory.server.dhcp.options.dhcp.DhcpMessageType;
32  import org.apache.directory.server.dhcp.options.dhcp.IpAddressLeaseTime;
33  import org.apache.directory.server.dhcp.options.dhcp.MaximumDhcpMessageSize;
34  import org.apache.directory.server.dhcp.options.dhcp.OptionOverload;
35  import org.apache.directory.server.dhcp.options.dhcp.ParameterRequestList;
36  import org.apache.directory.server.dhcp.options.dhcp.RebindingTimeValue;
37  import org.apache.directory.server.dhcp.options.dhcp.RenewalTimeValue;
38  import org.apache.directory.server.dhcp.options.dhcp.RequestedIpAddress;
39  import org.apache.directory.server.dhcp.options.dhcp.ServerIdentifier;
40  import org.apache.directory.server.dhcp.options.dhcp.TftpServerName;
41  import org.apache.directory.server.dhcp.options.dhcp.UnrecognizedOption;
42  import org.apache.directory.server.dhcp.options.dhcp.VendorClassIdentifier;
43  import org.apache.directory.server.dhcp.options.misc.DefaultFingerServers;
44  import org.apache.directory.server.dhcp.options.misc.DefaultIrcServers;
45  import org.apache.directory.server.dhcp.options.misc.DefaultWwwServers;
46  import org.apache.directory.server.dhcp.options.misc.MobileIpHomeAgents;
47  import org.apache.directory.server.dhcp.options.misc.NbddServers;
48  import org.apache.directory.server.dhcp.options.misc.NetbiosNameServers;
49  import org.apache.directory.server.dhcp.options.misc.NetbiosNodeType;
50  import org.apache.directory.server.dhcp.options.misc.NetbiosScope;
51  import org.apache.directory.server.dhcp.options.misc.NisDomain;
52  import org.apache.directory.server.dhcp.options.misc.NisPlusDomain;
53  import org.apache.directory.server.dhcp.options.misc.NisPlusServers;
54  import org.apache.directory.server.dhcp.options.misc.NisServers;
55  import org.apache.directory.server.dhcp.options.misc.NntpServers;
56  import org.apache.directory.server.dhcp.options.misc.NtpServers;
57  import org.apache.directory.server.dhcp.options.misc.Pop3Servers;
58  import org.apache.directory.server.dhcp.options.misc.SmtpServers;
59  import org.apache.directory.server.dhcp.options.misc.StdaServers;
60  import org.apache.directory.server.dhcp.options.misc.StreetTalkServers;
61  import org.apache.directory.server.dhcp.options.misc.VendorSpecificInformation;
62  import org.apache.directory.server.dhcp.options.misc.XWindowDisplayManagers;
63  import org.apache.directory.server.dhcp.options.misc.XWindowFontServers;
64  import org.apache.directory.server.dhcp.options.perhost.DefaultIpTimeToLive;
65  import org.apache.directory.server.dhcp.options.perhost.IpForwarding;
66  import org.apache.directory.server.dhcp.options.perhost.MaximumDatagramSize;
67  import org.apache.directory.server.dhcp.options.perhost.NonLocalSourceRouting;
68  import org.apache.directory.server.dhcp.options.perhost.PathMtuAgingTimeout;
69  import org.apache.directory.server.dhcp.options.perhost.PathMtuPlateauTable;
70  import org.apache.directory.server.dhcp.options.perhost.PolicyFilter;
71  import org.apache.directory.server.dhcp.options.perinterface.AllSubnetsAreLocal;
72  import org.apache.directory.server.dhcp.options.perinterface.BroadcastAddress;
73  import org.apache.directory.server.dhcp.options.perinterface.InterfaceMtu;
74  import org.apache.directory.server.dhcp.options.perinterface.MaskSupplier;
75  import org.apache.directory.server.dhcp.options.perinterface.PerformMaskDiscovery;
76  import org.apache.directory.server.dhcp.options.perinterface.PerformRouterDiscovery;
77  import org.apache.directory.server.dhcp.options.perinterface.RouterSolicitationAddress;
78  import org.apache.directory.server.dhcp.options.perinterface.StaticRoute;
79  import org.apache.directory.server.dhcp.options.tcp.TcpDefaultTimeToLive;
80  import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveGarbage;
81  import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveInterval;
82  import org.apache.directory.server.dhcp.options.vendor.BootFileSize;
83  import org.apache.directory.server.dhcp.options.vendor.CookieServers;
84  import org.apache.directory.server.dhcp.options.vendor.DomainName;
85  import org.apache.directory.server.dhcp.options.vendor.DomainNameServers;
86  import org.apache.directory.server.dhcp.options.vendor.ExtensionsPath;
87  import org.apache.directory.server.dhcp.options.vendor.HostName;
88  import org.apache.directory.server.dhcp.options.vendor.ImpressServers;
89  import org.apache.directory.server.dhcp.options.vendor.LogServers;
90  import org.apache.directory.server.dhcp.options.vendor.LprServers;
91  import org.apache.directory.server.dhcp.options.vendor.MeritDumpFile;
92  import org.apache.directory.server.dhcp.options.vendor.NameServers;
93  import org.apache.directory.server.dhcp.options.vendor.ResourceLocationServers;
94  import org.apache.directory.server.dhcp.options.vendor.RootPath;
95  import org.apache.directory.server.dhcp.options.vendor.Routers;
96  import org.apache.directory.server.dhcp.options.vendor.SubnetMask;
97  import org.apache.directory.server.dhcp.options.vendor.SwapServer;
98  import org.apache.directory.server.dhcp.options.vendor.TimeOffset;
99  import org.apache.directory.server.dhcp.options.vendor.TimeServers;
100 import org.apache.directory.server.i18n.I18n;
101 
102 
103 /**
104  * The Dynamic Host Configuration Protocol (DHCP) provides a framework
105  * for passing configuration information to hosts on a TCP/IP network.  
106  * Configuration parameters and other control information are carried in
107  * tagged data items that are stored in the 'options' field of the DHCP
108  * message.  The data items themselves are also called "options."
109  * 
110  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
111  */
112 public abstract class DhcpOption
113 {
114     /**
115      * An array of concrete implementations of DhcpOption.
116      */
117     private static final Class<?>[] OPTION_CLASSES =
118         { 
119             BootfileName.class, 
120             ClientIdentifier.class, 
121             DhcpMessageType.class, 
122             IpAddressLeaseTime.class,
123             MaximumDhcpMessageSize.class, 
124             org.apache.directory.server.dhcp.options.dhcp.Message.class,
125             OptionOverload.class, 
126             ParameterRequestList.class, 
127             RebindingTimeValue.class, 
128             RenewalTimeValue.class,
129             RequestedIpAddress.class, 
130             ServerIdentifier.class, 
131             TftpServerName.class, 
132             VendorClassIdentifier.class,
133             ClientIdentifier.class, 
134             DhcpMessageType.class, 
135             IpAddressLeaseTime.class, 
136             MaximumDhcpMessageSize.class,
137             OptionOverload.class, 
138             ParameterRequestList.class, 
139             RebindingTimeValue.class, 
140             RenewalTimeValue.class,
141             RequestedIpAddress.class, 
142             ServerIdentifier.class, 
143             TftpServerName.class, 
144             UnrecognizedOption.class,
145             VendorClassIdentifier.class, 
146             DefaultFingerServers.class, 
147             DefaultIrcServers.class, 
148             DefaultWwwServers.class,
149             MobileIpHomeAgents.class, 
150             NbddServers.class, 
151             NetbiosNameServers.class, 
152             NetbiosNodeType.class,
153             NetbiosScope.class, 
154             NisDomain.class, 
155             NisPlusDomain.class, 
156             NisPlusServers.class, 
157             NisServers.class,
158             NntpServers.class, 
159             NtpServers.class, 
160             Pop3Servers.class, 
161             SmtpServers.class, 
162             StdaServers.class,
163             StreetTalkServers.class, 
164             VendorSpecificInformation.class, 
165             XWindowDisplayManagers.class,
166             XWindowFontServers.class, 
167             DefaultIpTimeToLive.class, 
168             IpForwarding.class, 
169             MaximumDatagramSize.class,
170             NonLocalSourceRouting.class, 
171             PathMtuAgingTimeout.class, 
172             PathMtuPlateauTable.class, 
173             PolicyFilter.class,
174             AllSubnetsAreLocal.class, 
175             BroadcastAddress.class, 
176             InterfaceMtu.class, 
177             MaskSupplier.class,
178             PerformMaskDiscovery.class, 
179             PerformRouterDiscovery.class, 
180             RouterSolicitationAddress.class,
181             StaticRoute.class, 
182             TcpDefaultTimeToLive.class, 
183             TcpKeepaliveGarbage.class, 
184             TcpKeepaliveInterval.class,
185             BootFileSize.class, 
186             CookieServers.class, 
187             DomainName.class, 
188             DomainNameServers.class, 
189             ExtensionsPath.class,
190             HostName.class, 
191             ImpressServers.class, 
192             LogServers.class, 
193             LprServers.class, 
194             MeritDumpFile.class,
195             NameServers.class, 
196             ResourceLocationServers.class, 
197             RootPath.class, Routers.class, 
198             SubnetMask.class,
199             SwapServer.class, 
200             TimeOffset.class, 
201             TimeServers.class, };
202 
203     /**
204      * A map of concrete implementations of DhcpOption indexed by tag code.
205      */
206     private static final Map<Integer, Class<?>> OPTION_CLASS_BY_CODE;
207 
208     /**
209      * A map of tag codes indexed by OptionClass subclass.
210      */
211     private static final Map<Class<?>, Integer> CODE_BY_CLASS;
212 
213     static
214     {
215         try
216         {
217             // initialize the tag-to-class and class-to-tag map
218             Map<Integer, Class<?>> classByCode = new HashMap<>();
219             Map<Class<?>, Integer> codeByClass = new HashMap<>();
220             
221             for ( int i = 0; i < OPTION_CLASSES.length; i++ )
222             {
223                 Class<?> dhcpOptionClass = OPTION_CLASSES[i];
224 
225                 if ( !DhcpOption.class.isAssignableFrom( dhcpOptionClass ) )
226                 {
227                     throw new RuntimeException( I18n.err( I18n.ERR_639, dhcpOptionClass ) );
228                 }
229 
230                 DhcpOption../../../org/apache/directory/server/dhcp/options/DhcpOption.html#DhcpOption">DhcpOption dhcpOption = ( DhcpOption ) dhcpOptionClass.newInstance();
231 
232                 int tagInt = dhcpOption.getTag();
233                 classByCode.put( tagInt, dhcpOptionClass );
234                 codeByClass.put( dhcpOptionClass, tagInt );
235             }
236 
237             OPTION_CLASS_BY_CODE = Collections.unmodifiableMap( classByCode );
238             CODE_BY_CLASS = Collections.unmodifiableMap( codeByClass );
239         }
240         catch ( Exception e )
241         {
242             throw new RuntimeException( I18n.err( I18n.ERR_640 ), e );
243         }
244     }
245 
246 
247     public static Class<?> getClassByTag( int tag )
248     {
249         return OPTION_CLASS_BY_CODE.get( tag );
250     }
251 
252 
253     public static int getTagByClass( Class<?> c )
254     {
255         return CODE_BY_CLASS.get( c );
256     }
257 
258     /**
259      * The default data array used for simple (unparsed) options.
260      */
261     private byte[] data;
262 
263 
264     /**
265      * Get the option's code tag.
266      * 
267      * @return byte
268      */
269     public abstract byte getTag();
270 
271 
272     /**
273      * Set the data (wire format) from a byte array. The default implementation
274      * just records the data as a byte array. Subclasses may parse the data into
275      * something more meaningful.
276      * 
277      * @param data
278      */
279     public void setData( byte[] data )
280     {
281         this.data = data;
282     }
283 
284 
285     /**
286      * Get the data (wire format) into a byte array. Subclasses must provide an
287      * implementation which serializes the parsed data back into a byte array if
288      * they override {@link #setData(byte[])}.
289      * 
290      * @return byte[]
291      */
292     public byte[] getData()
293     {
294         return data;
295     }
296 
297 
298     public final void writeTo( ByteBuffer out )
299     {
300         out.put( getTag() );
301 
302         // FIXME: handle continuation, i.e. options longer than 128 bytes?
303         byte[] data = getData();
304 
305         if ( data.length > 255 )
306         {
307             throw new IllegalArgumentException( I18n.err( I18n.ERR_641 ) );
308         }
309 
310         out.put( ( byte ) data.length );
311         out.put( data );
312     }
313 }