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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 package com.sun.dhcpmgr.cli.dhcpconfig;
  26 
  27 import com.sun.dhcpmgr.cli.common.DhcpCliFunction;
  28 import com.sun.dhcpmgr.data.DhcpdOptions;
  29 import com.sun.dhcpmgr.data.DhcpDatastore;
  30 import com.sun.dhcpmgr.data.ValidationException;
  31 import com.sun.dhcpmgr.data.StandardOptions;
  32 import com.sun.dhcpmgr.bridge.ExistsException;
  33 import com.sun.dhcpmgr.bridge.TableExistsException;
  34 
  35 import java.net.InetAddress;
  36 import java.lang.IllegalArgumentException;
  37 
  38 /**
  39  * The main class for the "configure DHCP server" functionality of dhcpconfig.
  40  */
  41 public class ConfigureDhcp extends DhcpCfgFunction {
  42 
  43     /**
  44      * The valid options associated with configuring a DHCP server.
  45      */
  46     static final int supportedOptions[] = {
  47         DhcpCfg.NON_NEGOTIABLE_LEASE,
  48         DhcpCfg.LEASE_LENGTH,
  49         DhcpCfg.DNS_ADDRESSES,
  50         DhcpCfg.DNS_DOMAIN,
  51         DhcpCfg.RESOURCE,
  52         DhcpCfg.RESOURCE_CONFIG,
  53         DhcpCfg.PATH
  54     };
  55 
  56     /**
  57      * Constructs a ConfigureDhcp object.
  58      */
  59     public ConfigureDhcp() {
  60 
  61         validOptions = supportedOptions;
  62 
  63     } // constructor
  64 
  65     /**
  66      * Returns the option flag for this function.
  67      * @returns the option flag for this function.
  68      */
  69     public int getFunctionFlag() {
  70         return (DhcpCfg.CONFIGURE_DHCP);
  71     }
  72 
  73     /**
  74      * Executes the "configure DHCP server" functionality.
  75      * @return DhcpCfg.SUCCESS or DhcpCfg.FAILURE
  76      */
  77     public int execute() throws IllegalArgumentException {
  78 
  79         // Check to see if DHCP or BOOTP relay is already configured.
  80         //
  81         boolean isServer = false;
  82         boolean isRelay = false;
  83         try {
  84             DhcpdOptions opts = getSvcMgr().readDefaults();
  85             if (opts.isRelay()) {
  86                 isRelay = true;
  87             } else {
  88                 isServer = true;
  89             }
  90         } catch (Throwable e) {
  91             // this is to be expected
  92         }
  93 
  94         if (isServer) {
  95             printErrMessage(getString("config_dhcp_configured_error"));
  96             return (DhcpCfg.FAILURE);
  97         }
  98 
  99         if (isRelay) {
 100             printErrMessage(getString("config_bootp_configured_error"));
 101             return (DhcpCfg.FAILURE);
 102         }
 103 
 104         // User must define both resource and path.
 105         //
 106         if (options.valueOf(DhcpCfg.RESOURCE) == null ||
 107             options.valueOf(DhcpCfg.PATH) == null) {
 108             String msg = getString("config_null_datastore_error");
 109             throw new IllegalArgumentException(msg);
 110         }
 111 
 112         try {
 113             setDhcpDatastore(getSvcMgr().getDataStore(
 114                 options.valueOf(DhcpCfg.RESOURCE)));
 115             getDhcpDatastore().setLocation(options.valueOf(DhcpCfg.PATH));
 116             getDhcpDatastore().setConfig(
 117                 options.valueOf(DhcpCfg.RESOURCE_CONFIG));
 118         } catch (Throwable e) {
 119             // resource will not be valid
 120         }
 121 
 122 
 123         if (getDhcpDatastore() == null || !getDhcpDatastore().isEnabled()) {
 124             Object [] arguments = new Object[1];
 125             arguments[0] = getDhcpDatastore().getResource();
 126             printErrMessage(getString("config_invalid_resource_error"),
 127                 arguments);
 128             return (DhcpCfg.FAILURE);
 129         }
 130 
 131         // Retrieve the leaseLength option and check its validity.
 132         // The default (3600*24 = 1 day) should be defined as static somewhere.
 133         //
 134         Integer leaseLength = new Integer(3600*24);
 135         if (options.isSet(DhcpCfg.LEASE_LENGTH)) {
 136             try {
 137                 leaseLength =
 138                     new Integer(options.valueOf(DhcpCfg.LEASE_LENGTH));
 139             } catch (Throwable e) {
 140                 printErrMessage(getString("config_lease_error"));
 141                 return (DhcpCfg.FAILURE);
 142             }
 143 
 144             if (leaseLength.intValue() == 0) {
 145                 printErrMessage(getString("config_lease_zero_error"));
 146                 return (DhcpCfg.FAILURE);
 147             }
 148         }
 149 
 150         // Are leases negotiable
 151         //
 152         boolean leaseNegotiable =
 153             !options.isSet(DhcpCfg.NON_NEGOTIABLE_LEASE);
 154 
 155         // Get the DNS information.
 156         //
 157         String dnsDomain = options.valueOf(DhcpCfg.DNS_DOMAIN);
 158         String dnsServers = options.valueOf(DhcpCfg.DNS_ADDRESSES);
 159         if ((dnsDomain == null) != (dnsServers == null)) {
 160             String msg = getString("config_dns_error");
 161             throw new IllegalArgumentException(msg);
 162         }
 163 
 164         IPAddressList dnsAddresses = null;
 165         try {
 166             if (dnsDomain == null) {
 167                 dnsDomain = getSvcMgr().getStringOption(
 168                     StandardOptions.CD_DNSDOMAIN, "");
 169             }
 170             if (dnsServers != null) {
 171                 dnsAddresses = new IPAddressList(dnsServers);
 172             } else {
 173                 dnsAddresses = new IPAddressList(
 174                     getSvcMgr().getIPOption(StandardOptions.CD_DNSSERV, ""));
 175             }
 176         } catch (ValidationException e) {
 177             Object [] arguments = new Object[1];
 178             arguments[0] = getMessage(e);
 179             printErrMessage(getString("config_dns_server_error"), arguments);
 180             return (DhcpCfg.FAILURE);
 181         } catch (Throwable e) {
 182             // Ignore, DNS info will not be configured in the server macro.
 183         }
 184 
 185         // Create the location if it does not exist.
 186         //
 187         try {
 188             getSvcMgr().makeLocation(getDhcpDatastore());
 189         } catch (ExistsException e) {
 190             // this is o.k.
 191         } catch (Throwable e) {
 192             Object [] arguments = new Object[1];
 193             arguments[0] = getDhcpDatastore().getLocation();
 194             printErrMessage(getString("config_make_location_error"),
 195                 arguments);
 196             return (DhcpCfg.FAILURE);
 197         }
 198 
 199         // Create the DHCP configuration file
 200         //
 201         DhcpdOptions dhcpdOptions = new DhcpdOptions();
 202         dhcpdOptions.setDaemonEnabled(true);
 203         dhcpdOptions.setDhcpDatastore(getDhcpDatastore());
 204         try {
 205             getSvcMgr().writeDefaults(dhcpdOptions);
 206             printMessage(getString("config_create_conf_progress"));
 207         } catch (Throwable e) {
 208             Object [] arguments = new Object[1];
 209             arguments[0] = getMessage(e);
 210             printErrMessage(getString("config_writing_conf_error"), arguments);
 211             return (DhcpCfg.FAILURE);
 212         }
 213 
 214         // Create the dhcptab
 215         //
 216         try {
 217             getDhcptabMgr().createDhcptab(getDhcpDatastore());
 218             printMessage(getString("config_dhcptab_progress"));
 219         } catch (TableExistsException e) {
 220             // Not an error; some data stores are shared by multiple servers
 221             printMessage(getString("config_dhcptab_exists_progress"));
 222         } catch (Throwable e) {
 223             Object [] arguments = new Object[1];
 224             arguments[0] = getMessage(e);
 225             printErrMessage(getString("config_dhcptab_error"), arguments);
 226             return (DhcpCfg.FAILURE);
 227         }
 228 
 229         // Create the locale macro
 230         //
 231         try {
 232             getDhcptabMgr().createLocaleMacro();
 233             printMessage(getString("config_locale_progress"));
 234         } catch (ExistsException e) {
 235             /*
 236              * Ignore this error, if one's already there we'll assume
 237              * it's correct
 238              */
 239         } catch (Throwable e) {
 240             Object [] arguments = new Object[1];
 241             arguments[0] = getMessage(e);
 242             printErrMessage(getString("config_locale_error"), arguments);
 243             return (DhcpCfg.FAILURE);
 244         }
 245 
 246         // Create the Server macro
 247         //
 248         String svrName = null;
 249         try {
 250             svrName = getSvcMgr().getShortServerName();
 251             InetAddress svrAddress = getSvcMgr().getServerAddress();
 252             getDhcptabMgr().createServerMacro(svrName, svrAddress,
 253                 leaseLength.intValue(), leaseNegotiable, dnsDomain,
 254                 dnsAddresses);
 255             Object [] arguments = new Object[1];
 256             arguments[0] = svrName;
 257             printMessage(getString("config_server_macro_progress"), arguments);
 258         } catch (Throwable e) {
 259             // Couldn't create it; inform user because this is serious
 260             Object [] arguments = new Object[2];
 261             arguments[1] = svrName;
 262             arguments[0] = getMessage(e);
 263             printErrMessage(getString("config_server_macro_error"), arguments);
 264             return (DhcpCfg.FAILURE);
 265         }
 266 
 267         // Start it up.
 268         //
 269         try {
 270             getSvcMgr().startup();
 271             printMessage(getString("config_startup_progress"));
 272         } catch (Throwable e) {
 273             Object [] arguments = new Object[1];
 274             arguments[0] = getMessage(e);
 275             printErrMessage(getString("config_startup_error"), arguments);
 276             return (DhcpCfg.FAILURE);
 277         }
 278 
 279         return (DhcpCfg.SUCCESS);
 280 
 281     } // execute
 282 
 283 } // ConfigureDhcp