View Javadoc

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