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 02:41:35 +0100 (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 }