1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * ident "%Z%%M% %I% %E% SMI" 24 * 25 * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 package com.sun.dhcpmgr.data; 30 31 import java.util.*; 32 33 /** 34 * Option is a simple data class which encapsulates an option record in 35 * the dhcptab. See dhcptab(4) for the gory details on options (aka symbols). 36 * 37 * @see DhcptabRecord 38 * @see Macro 39 */ 40 public class Option extends DhcptabRecord implements Cloneable { 41 private byte context; 42 private short code; 43 private byte type; 44 private int granularity; 45 private int maximum; 46 private Vector vendors; 47 private boolean valueClean = false; 48 private boolean validValue = true; 49 50 // The Option attributes that must match their native values. 51 52 // Definition for attribute limits 53 public static short MAX_NAME_SIZE = 128; 54 55 // Option contexts. 56 public static byte STANDARD = 0; 57 public static byte EXTEND = 1; 58 public static byte VENDOR = 2; 59 public static byte SITE = 3; 60 public static byte CONTEXTS = 4; 61 public static OptionContext [] ctxts = { 62 new OptionContext(STANDARD, "Standard", "standard_option"), 63 new OptionContext(EXTEND, "Extend", "extended_option"), 64 new OptionContext(VENDOR, "Vendor=", "vendor_option"), 65 new OptionContext(SITE, "Site", "site_option") }; 66 67 // Option types. 68 public static byte ASCII = 0; 69 public static byte OCTET = 1; 70 public static byte IP = 2; 71 public static byte NUMBER = 3; 72 public static byte BOOLEAN = 4; 73 public static byte UNUMBER8 = 5; 74 public static byte UNUMBER16 = 6; 75 public static byte UNUMBER32 = 7; 76 public static byte UNUMBER64 = 8; 77 public static byte SNUMBER8 = 9; 78 public static byte SNUMBER16 = 10; 79 public static byte SNUMBER32 = 11; 80 public static byte SNUMBER64 = 12; 81 public static byte TYPES = 13; 82 83 public static OptionType [] types = { 84 new OptionType((byte)0, "ASCII", "ascii_type"), 85 new OptionType((byte)1, "OCTET", "octet_type"), 86 new OptionType((byte)2, "IP", "ip_type"), 87 new OptionType((byte)3, "NUMBER", "number_type"), 88 new OptionType((byte)4, "BOOL", "boolean_type"), 89 new OptionType((byte)6, "UNUMBER8", "unumber8_type"), 90 new OptionType((byte)7, "UNUMBER16", "unumber16_type"), 91 new OptionType((byte)8, "UNUMBER32", "unumber32_type"), 92 new OptionType((byte)9, "UNUMBER64", "unumber64_type"), 93 new OptionType((byte)10, "SNUMBER8", "snumber8_type"), 94 new OptionType((byte)11, "SNUMBER16", "snumber16_type"), 95 new OptionType((byte)12, "SNUMBER32", "snumber32_type"), 96 new OptionType((byte)13, "SNUMBER64", "snumber64_type") }; 97 98 /* 99 * These need to be the same as the definitions in libdhcputil's 100 * parser in dhcp_symbol.c 101 */ 102 public static String DSYM_CLASS_DEL_SPACE = " "; 103 public static String DSYM_CLASS_DEL = DSYM_CLASS_DEL_SPACE + "\t\n"; 104 public static String DSYM_CLASS_DEL_REGEXP = ".*[" + DSYM_CLASS_DEL + "].*"; 105 public static char DSYM_FIELD_DEL = ','; 106 public static char DSYM_QUOTE = '"'; 107 108 109 // Serialization id for this class 110 static final long serialVersionUID = 7468266817375654444L; 111 112 /** 113 * Construct an empty instance. Default to Site option, IP type. 114 */ 115 public Option() { 116 super("", DhcptabRecord.OPTION, ""); 117 valueClean = false; 118 vendors = new Vector(); 119 context = ctxts[SITE].getCode(); 120 type = types[IP].getCode(); 121 granularity = 1; 122 } 123 124 /** 125 * Construct a fully defined instance. Used by the server to create 126 * Options. 127 * @param name the option name/key 128 * @param context the option context/category code 129 * @param vendors the list of vendors (if any) 130 * @param code the option code 131 * @param type the option type code 132 * @param gran the option granularity 133 * @param max the option maximum 134 * @param sig the signature from the dhcptab 135 * @param isValid the flag indicating option definition validity 136 */ 137 public Option(String name, byte context, String [] vendors, short code, 138 byte type, int gran, int max, String sig, boolean isValid) { 139 140 super("", DhcptabRecord.OPTION, ""); 141 142 valueClean = false; 143 validValue = isValid; 144 145 setKey(name); 146 setContext(context); 147 setVendors(vendors); 148 setCode(code); 149 setType(type); 150 setGranularity(gran); 151 setMaximum(max); 152 153 if (sig != null) { 154 setSignature(sig); 155 } 156 } 157 158 /** 159 * Set the option name as specified. 160 * @param name a string representing the option name. 161 */ 162 public void setKey(String name) { 163 try { 164 super.setKey(name); 165 } catch (ValidationException e) { 166 // Can't happen. 167 } 168 } 169 170 /** 171 * Get the context for this option 172 * @return a byte for the option context (context codes are 173 * defined by the OptionContext objects in the ctxts array). 174 */ 175 public byte getContext() { 176 return context; 177 } 178 179 /** 180 * Set the context for this option (context codes are defined 181 * by the OptionContext objects in the ctxts array). 182 */ 183 public void setContext(byte c) { 184 context = c; 185 valueClean = false; 186 } 187 188 /** 189 * Enumerate the vendor list. 190 * @return an Enumeration of the vendors, which will be empty for 191 * non-vendor options. 192 */ 193 public Enumeration getVendors() { 194 return vendors.elements(); 195 } 196 197 /** 198 * Get the number of vendors for this option. 199 * @return an int count of the vendors, zero for non-vendor options. 200 */ 201 public int getVendorCount() { 202 return vendors.size(); 203 } 204 205 /** 206 * Add a vendor to the list for this option. 207 * @param v the vendor name as a String. 208 */ 209 public void addVendor(String v) throws ValidationException { 210 if (v.indexOf(DSYM_FIELD_DEL) != -1) { 211 throw new ValidationException(v); 212 } 213 vendors.addElement(v); 214 valueClean = false; 215 } 216 217 /** 218 * Empty the vendor list. 219 */ 220 public void clearVendors() { 221 vendors = new Vector(); 222 valueClean = false; 223 } 224 225 /** 226 * Remove a vendor from the list. 227 * @param index the position of the vendor to remove in the list of vendors 228 */ 229 public void removeVendorAt(int index) { 230 vendors.removeElementAt(index); 231 valueClean = false; 232 } 233 234 /** 235 * Get the vendor at a specified index in the vendor list. 236 * @param index the index of the vendor to retrieve 237 * @return the vendor name 238 */ 239 public String getVendorAt(int index) { 240 return (String)vendors.elementAt(index); 241 } 242 243 private void setVendors(String [] vendors) { 244 245 this.vendors = new Vector(); 246 247 if (vendors == null) { 248 return; 249 } 250 251 for (int i = 0; i < vendors.length; i++) { 252 this.vendors.addElement(vendors[i]); 253 } 254 255 } 256 257 /** 258 * Set the vendor name at a specified index in the list. 259 * @param vendor the vendor name 260 * @param index the position in the list to set. 261 */ 262 public void setVendorAt(String vendor, int index) { 263 if (index >= vendors.size()) { 264 vendors.setSize(index+1); 265 } 266 vendors.setElementAt(vendor, index); 267 valueClean = false; 268 } 269 270 /** 271 * Get the option code. 272 * @return the code as a short. 273 */ 274 public short getCode() { 275 return code; 276 } 277 278 /** 279 * Set the option code. 280 * @param c the code to use 281 */ 282 public void setCode(short c) { 283 code = c; 284 valueClean = false; 285 } 286 287 /** 288 * Get the type. 289 * @return a byte value for the type (type codes are 290 * defined by the OptionTypes objects in the type array). 291 * OCTET 292 */ 293 public byte getType() { 294 return type; 295 } 296 297 /** 298 * Set the type. 299 * @param t the type code (type codes are defined by the 300 * OptionTypes objects in the type array). 301 * or OCTET. 302 */ 303 public void setType(byte t) { 304 type = t; 305 valueClean = false; 306 } 307 308 /** 309 * Get the granularity. See dhcptab(4) for an explanation of granularity 310 * interpretations. 311 * @return the granularity as an int 312 */ 313 public int getGranularity() { 314 return granularity; 315 } 316 317 /** 318 * Set the granularity. See dhcptab(4) for an explanation of granularity 319 * interpretations. 320 * @param g the granularity as an int. 321 */ 322 public void setGranularity(int g) { 323 granularity = g; 324 valueClean = false; 325 } 326 327 /** 328 * Get the maximum. See dhcptab(4) for an explanation of maximum. 329 * @return the maximum as an int. 330 */ 331 public int getMaximum() { 332 return maximum; 333 } 334 335 /** 336 * Set the maximum. See dhcptab(4) for an explanation of maximum. 337 * @param m the maximum as an int. 338 */ 339 public void setMaximum(int m) { 340 maximum = m; 341 valueClean = false; 342 } 343 344 /** 345 * Return validity of this option. 346 * @return true if the option is correctly defined, false if not 347 */ 348 public boolean isValid() { 349 return (validValue); 350 } 351 352 /** 353 * Get the definition as a string in the format specified by dhcptab(4) 354 * @return a String containing the definition 355 */ 356 public String getValue() { 357 /* The value string stored is not clean, regenerate */ 358 if (!valueClean) { 359 StringBuffer b = new StringBuffer(); 360 // Start with context 361 b.append(getContextDhcptabString(context)); 362 // Vendor context next adds the vendors, separate by blanks 363 if (context == ctxts[VENDOR].getCode()) { 364 boolean first = true; 365 for (Enumeration e = getVendors(); e.hasMoreElements(); ) { 366 String s = (String)e.nextElement(); 367 if (!first) { 368 b.append(DSYM_CLASS_DEL_SPACE); 369 } else { 370 first = false; 371 } 372 // If vendor class contains whitespace, need to quote it 373 boolean needQuoting = s.matches(DSYM_CLASS_DEL_REGEXP); 374 if (needQuoting) { 375 b.append(DSYM_QUOTE); 376 } 377 b.append(s); 378 if (needQuoting) { 379 b.append(DSYM_QUOTE); 380 } 381 } 382 } 383 b.append(DSYM_FIELD_DEL); 384 // Add the code 385 b.append(code); 386 b.append(DSYM_FIELD_DEL); 387 // Add the type 388 b.append(getTypeDhcptabString(type)); 389 b.append(DSYM_FIELD_DEL); 390 // Add the granularity 391 b.append(granularity); 392 b.append(DSYM_FIELD_DEL); 393 // Add the maximum 394 b.append(maximum); 395 // Save it and note as such so we can avoid doing this again 396 try { 397 super.setValue(b.toString()); 398 } catch (ValidationException e) { 399 // This should never happen! 400 } 401 valueClean = true; 402 } 403 return super.getValue(); 404 } 405 406 // Make a copy of this option 407 public Object clone() { 408 Option o = new Option(); 409 410 o.setKey(getKey()); 411 o.setContext(getContext()); 412 o.setCode(getCode()); 413 o.vendors = new Vector(); 414 for (Enumeration en = vendors.elements(); en.hasMoreElements(); ) { 415 String s = (String)en.nextElement(); 416 o.vendors.addElement(new String(s)); 417 } 418 o.setType(getType()); 419 o.setGranularity(getGranularity()); 420 o.setMaximum(getMaximum()); 421 o.setSignature(getSignature()); 422 423 return o; 424 } 425 426 /** 427 * Returns a string representation of this object. 428 * @return a string representation of this object. 429 */ 430 public String toString() { 431 return (getKey() + " s " + getValue()); 432 } 433 434 /** 435 * Returns the context definition for the specified context. 436 * @param code the context code. 437 * @return the OptionContext for the context. 438 */ 439 public static OptionContext findContext(byte code) { 440 441 OptionContext ctxt = null; 442 443 for (int i = 0; i < CONTEXTS; i++) { 444 if (ctxts[i].getCode() == code) { 445 ctxt = ctxts[i]; 446 break; 447 } 448 } 449 450 return (ctxt); 451 } 452 453 /** 454 * Returns the dhcptab string representation of the specified context. 455 * @param code the context code. 456 * @return the dhcptab string representation of the context. 457 */ 458 public static String getContextDhcptabString(byte code) { 459 460 OptionContext ctxt = findContext(code); 461 462 if (ctxt == null) { 463 return ("undefined"); 464 } else { 465 return (ctxt.getDhcptabString()); 466 } 467 } 468 469 /** 470 * Returns the string representation of the specified context. 471 * @param code the context code. 472 * @return a string representation of the context. 473 */ 474 public static String getContextString(byte code) { 475 476 OptionContext ctxt = findContext(code); 477 478 if (ctxt == null) { 479 return ("undefined"); 480 } else { 481 return (ctxt.toString()); 482 } 483 } 484 485 /** 486 * Returns the type definition for the specified type. 487 * @param code the type code. 488 * @return the OptionType for the type. 489 */ 490 public static OptionType findType(byte code) { 491 492 OptionType type = null; 493 494 for (int i = 0; i < TYPES; i++) { 495 if (types[i].getCode() == code) { 496 type = types[i]; 497 break; 498 } 499 } 500 501 return (type); 502 } 503 504 /** 505 * Returns the dhcptab string representation of the specified type. 506 * @param code the type code. 507 * @return the dhcptab string representation of the type. 508 */ 509 public static String getTypeDhcptabString(byte code) { 510 511 OptionType type = findType(code); 512 513 if (type == null) { 514 return ("undefined"); // should never happen 515 } else { 516 return (type.getDhcptabString()); 517 } 518 } 519 520 /** 521 * Returns the string representation of the specified type. 522 * @param code the type code. 523 * @return a string representation of the type. 524 */ 525 public static String getTypeString(byte code) { 526 527 OptionType type = findType(code); 528 529 if (type == null) { 530 return ("undefined"); // should never happen 531 } else { 532 return (type.toString()); 533 } 534 } 535 }