001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 021package org.apache.directory.server.dhcp.options; 022 023 024import java.nio.ByteBuffer; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.Map; 028 029import org.apache.directory.server.dhcp.options.dhcp.BootfileName; 030import org.apache.directory.server.dhcp.options.dhcp.ClientIdentifier; 031import org.apache.directory.server.dhcp.options.dhcp.DhcpMessageType; 032import org.apache.directory.server.dhcp.options.dhcp.IpAddressLeaseTime; 033import org.apache.directory.server.dhcp.options.dhcp.MaximumDhcpMessageSize; 034import org.apache.directory.server.dhcp.options.dhcp.OptionOverload; 035import org.apache.directory.server.dhcp.options.dhcp.ParameterRequestList; 036import org.apache.directory.server.dhcp.options.dhcp.RebindingTimeValue; 037import org.apache.directory.server.dhcp.options.dhcp.RenewalTimeValue; 038import org.apache.directory.server.dhcp.options.dhcp.RequestedIpAddress; 039import org.apache.directory.server.dhcp.options.dhcp.ServerIdentifier; 040import org.apache.directory.server.dhcp.options.dhcp.TftpServerName; 041import org.apache.directory.server.dhcp.options.dhcp.UnrecognizedOption; 042import org.apache.directory.server.dhcp.options.dhcp.VendorClassIdentifier; 043import org.apache.directory.server.dhcp.options.misc.DefaultFingerServers; 044import org.apache.directory.server.dhcp.options.misc.DefaultIrcServers; 045import org.apache.directory.server.dhcp.options.misc.DefaultWwwServers; 046import org.apache.directory.server.dhcp.options.misc.MobileIpHomeAgents; 047import org.apache.directory.server.dhcp.options.misc.NbddServers; 048import org.apache.directory.server.dhcp.options.misc.NetbiosNameServers; 049import org.apache.directory.server.dhcp.options.misc.NetbiosNodeType; 050import org.apache.directory.server.dhcp.options.misc.NetbiosScope; 051import org.apache.directory.server.dhcp.options.misc.NisDomain; 052import org.apache.directory.server.dhcp.options.misc.NisPlusDomain; 053import org.apache.directory.server.dhcp.options.misc.NisPlusServers; 054import org.apache.directory.server.dhcp.options.misc.NisServers; 055import org.apache.directory.server.dhcp.options.misc.NntpServers; 056import org.apache.directory.server.dhcp.options.misc.NtpServers; 057import org.apache.directory.server.dhcp.options.misc.Pop3Servers; 058import org.apache.directory.server.dhcp.options.misc.SmtpServers; 059import org.apache.directory.server.dhcp.options.misc.StdaServers; 060import org.apache.directory.server.dhcp.options.misc.StreetTalkServers; 061import org.apache.directory.server.dhcp.options.misc.VendorSpecificInformation; 062import org.apache.directory.server.dhcp.options.misc.XWindowDisplayManagers; 063import org.apache.directory.server.dhcp.options.misc.XWindowFontServers; 064import org.apache.directory.server.dhcp.options.perhost.DefaultIpTimeToLive; 065import org.apache.directory.server.dhcp.options.perhost.IpForwarding; 066import org.apache.directory.server.dhcp.options.perhost.MaximumDatagramSize; 067import org.apache.directory.server.dhcp.options.perhost.NonLocalSourceRouting; 068import org.apache.directory.server.dhcp.options.perhost.PathMtuAgingTimeout; 069import org.apache.directory.server.dhcp.options.perhost.PathMtuPlateauTable; 070import org.apache.directory.server.dhcp.options.perhost.PolicyFilter; 071import org.apache.directory.server.dhcp.options.perinterface.AllSubnetsAreLocal; 072import org.apache.directory.server.dhcp.options.perinterface.BroadcastAddress; 073import org.apache.directory.server.dhcp.options.perinterface.InterfaceMtu; 074import org.apache.directory.server.dhcp.options.perinterface.MaskSupplier; 075import org.apache.directory.server.dhcp.options.perinterface.PerformMaskDiscovery; 076import org.apache.directory.server.dhcp.options.perinterface.PerformRouterDiscovery; 077import org.apache.directory.server.dhcp.options.perinterface.RouterSolicitationAddress; 078import org.apache.directory.server.dhcp.options.perinterface.StaticRoute; 079import org.apache.directory.server.dhcp.options.tcp.TcpDefaultTimeToLive; 080import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveGarbage; 081import org.apache.directory.server.dhcp.options.tcp.TcpKeepaliveInterval; 082import org.apache.directory.server.dhcp.options.vendor.BootFileSize; 083import org.apache.directory.server.dhcp.options.vendor.CookieServers; 084import org.apache.directory.server.dhcp.options.vendor.DomainName; 085import org.apache.directory.server.dhcp.options.vendor.DomainNameServers; 086import org.apache.directory.server.dhcp.options.vendor.ExtensionsPath; 087import org.apache.directory.server.dhcp.options.vendor.HostName; 088import org.apache.directory.server.dhcp.options.vendor.ImpressServers; 089import org.apache.directory.server.dhcp.options.vendor.LogServers; 090import org.apache.directory.server.dhcp.options.vendor.LprServers; 091import org.apache.directory.server.dhcp.options.vendor.MeritDumpFile; 092import org.apache.directory.server.dhcp.options.vendor.NameServers; 093import org.apache.directory.server.dhcp.options.vendor.ResourceLocationServers; 094import org.apache.directory.server.dhcp.options.vendor.RootPath; 095import org.apache.directory.server.dhcp.options.vendor.Routers; 096import org.apache.directory.server.dhcp.options.vendor.SubnetMask; 097import org.apache.directory.server.dhcp.options.vendor.SwapServer; 098import org.apache.directory.server.dhcp.options.vendor.TimeOffset; 099import org.apache.directory.server.dhcp.options.vendor.TimeServers; 100import 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 */ 112public 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 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}