Ejemplo n.º 1
0
function subnet_modify($options = "")
{
    global $conf, $self, $onadb;
    //printmsg('DEBUG => subnet_modify('.implode (";",$options).') called', 3);
    // Version - UPDATE on every edit!
    $version = '1.08';
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !$options['subnet'] or !($options['set_ip'] or $options['set_netmask'] or $options['set_type'] or $options['set_name'] or array_key_exists('set_vlan', $options) or $options['set_security_level'])) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

subnet_modify-v{$version}
Modify a subnet (subnet) record

  Synopsis: subnet_modify [KEY=VALUE] ...

  Where:
    subnet=[ID|IP]           select subnet by search string

  Update:
    set_ip=IP                 change subnet "subnet" address
    set_netmask=MASK          change subnet netmask
    set_name=TEXT      change subnet name (i.e. "LAN-1234")
    set_type=TYPE             change subnet type by name or id
    set_vlan=VLAN             change vlan by name, number
    campus=CAMPUS             vlan campus name or id to help identify vlan
    set_security_level=LEVEL  numeric security level ({$conf['ona_lvl']})



EOM
);
    }
    $check_boundaries = 0;
    // Find the subnet record we're modifying
    list($status, $rows, $subnet) = ona_find_subnet($options['subnet']);
    if ($status or !$rows) {
        $self['error'] = "ERROR => Subnet not found";
        return array(2, $self['error'] . "\n");
    }
    // Check permissions
    if (!auth('subnet_modify')) {
        $self['error'] = "Permission denied!";
        printmsg($self['error'], 0);
        return array(3, $self['error'] . "\n");
    }
    // Validate the ip address
    if (!$options['set_ip']) {
        $options['set_ip'] = $subnet['ip_addr'];
    } else {
        $check_boundaries = 1;
        $options['set_ip'] = $setip = ip_mangle($options['set_ip'], 'numeric');
        // FIXME: what if ip_mangle returns a GMP object?
        if ($options['set_ip'] == -1) {
            $self['error'] = "ERROR => The IP address specified is invalid!";
            return array(4, $self['error'] . "\n");
        }
    }
    // Validate the netmask is okay
    if (!$options['set_netmask']) {
        $options['set_netmask'] = $subnet['ip_mask'];
        $cidr = ip_mangle($options['set_netmask'], 'cidr');
    } else {
        $check_boundaries = 1;
        $cidr = ip_mangle($options['set_netmask'], 'cidr');
        // FIXME: what if ip_mangle returns a GMP object?
        $options['set_netmask'] = ip_mangle($options['set_netmask'], 'numeric');
        if ($cidr == -1 or $options['set_netmask'] == -1) {
            $self['error'] = "ERROR => The netmask specified is invalid!";
            return array(5, $self['error'] . "\n");
        }
    }
    if (is_ipv4($setip)) {
        $padding = 32;
        $fmt = 'dotted';
        $ip1 = ip_mangle($setip, 'binary');
        $num_hosts = 0xffffffff - $options['set_netmask'];
        $first_host = $options['set_ip'] + 1;
        $last_host = $options['set_ip'] + $num_hosts;
        $str_last_host = $last_host;
        $last_last_host = $last_host - 1;
    } else {
        $padding = 128;
        $fmt = 'ipv6gz';
        $ip1 = ip_mangle($setip, 'bin128');
        $first_host = gmp_strval(gmp_add($options['set_ip'], 1));
        $sub = gmp_sub("340282366920938463463374607431768211455", $options['set_netmask']);
        $last_host = gmp_add($options['set_ip'], $sub);
        $str_last_host = gmp_strval($last_host);
        $last_last_host = gmp_strval(gmp_sub($last_host, 1));
    }
    // Validate that the subnet IP & netmask combo are valid together.
    $ip2 = str_pad(substr($ip1, 0, $cidr), $padding, '0');
    $ip1 = ip_mangle($ip1, $fmt);
    $ip2 = ip_mangle($ip2, $fmt);
    if ($ip1 != $ip2) {
        $self['error'] = "ERROR => Invalid subnet specified - did you mean: {$ip2}/{$cidr}?";
        return array(6, $self['error'] . "\n");
    }
    // If our IP or netmask changed we need to make sure that
    // we won't abandon any host interfaces.
    // We also need to verify that the new boundaries are valid and
    // don't interefere with any other subnets.
    if ($check_boundaries == 1) {
        // *** Check to see if the new subnet overlaps any existing ONA subnets *** //
        // I convert the IP address to dotted format when calling ona_find_subnet()
        // because it saves it from doing a few unnecessary sql queries.
        // Look for overlaps like this (where new subnet address starts inside an existing subnet):
        //            [ -- new subnet -- ]
        //    [ -- old subnet --]
        list($status, $rows, $record) = ona_find_subnet(ip_mangle($options['set_ip'], 'dotted'));
        if ($rows and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet starts inside an existing subnet.";
            return array(7, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for overlaps like this (where the new subnet ends inside an existing subnet):
        //    [ -- new subnet -- ]
        //           [ -- old subnet --]
        // Find last address of our subnet, and see if it's inside of any other subnet:
        list($status, $rows, $record) = ona_find_subnet(ip_mangle($str_last_host, 'dotted'));
        if ($rows and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet ends inside an existing subnet.";
            return array(8, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for overlaps like this (where the new subnet entirely overlaps an existing subnet):
        //    [ -------- new subnet --------- ]
        //           [ -- old subnet --]
        //
        // Do a cool SQL query to find all subnets whose start address is >= or <= the
        // new subnet base address.
        $where = "ip_addr >= {$options['set_ip']} AND ip_addr <= {$str_last_host}";
        list($status, $rows, $record) = ona_get_subnet_record($where);
        if ($rows > 1 or $rows == 1 and $record['id'] != $subnet['id']) {
            $self['error'] = "ERROR => Subnet address conflict! New subnet would encompass an existing subnet.";
            return array(9, $self['error'] . "\n" . "ERROR  => Conflicting subnet record ID: {$record['id']}\n");
        }
        // Look for any hosts that are currently in our subnet that would be
        // abandoned if we were to make the proposed changes.
        // Look for hosts on either side of the new subnet boundaries:
        //            [--- new subnet ---]
        //         *      **   *            *   <-- Hosts: the first and last host would be a problem!
        //       [------- old subnet --------]
        //
        $where1 = "subnet_id = {$subnet['id']} AND ip_addr < {$first_host}";
        $where2 = "subnet_id = {$subnet['id']} AND ip_addr > {$last_last_host}";
        list($status, $rows1, $record) = ona_get_interface_record($where1);
        list($status, $rows2, $record) = ona_get_interface_record($where2);
        if ($rows1 or $rows2) {
            $num = $rows1 + $rows2;
            $self['error'] = "ERROR => Changes would abandon {$num} hosts in an unallocated ip space";
            return array(10, $self['error'] . "\n");
        }
        // Look for any dhcp pools that are currently in our subnet that would be
        // abandoned if we were to make the proposed changes.
        // Look for existin pools with start/end values outside of new subnet range
        //            [--- new subnet ---]
        //                      [--cur pool--]
        //       [------- old subnet --------]
        //
        $where1 = "subnet_id = {$subnet['id']} AND ip_addr_start < {$options['set_ip']}";
        $where2 = "subnet_id = {$subnet['id']} AND ip_addr_end > {$str_last_host}";
        list($status, $rows1, $record) = ona_get_dhcp_pool_record($where1);
        list($status, $rows2, $record) = ona_get_dhcp_pool_record($where2);
        if ($rows1 or $rows2) {
            $num = $rows1 + $rows2;
            $self['error'] = "ERROR => Changes would abandon a DHCP pool in an unallocated ip space, adjust pool sizes first";
            return array(10, $self['error'] . "\n");
        }
    }
    //
    // Define the fields we're updating
    //
    // This variable will contain the updated info we'll insert into the DB
    $SET = array();
    $SET['ip_addr'] = $options['set_ip'];
    $SET['ip_mask'] = $options['set_netmask'];
    // Set options['set_security_level']?
    // Sanitize "security_level" option
    if (array_key_exists('set_security_level', $options)) {
        $options['set_security_level'] = sanitize_security_level($options['set_security_level']);
        if ($options['set_security_level'] == -1) {
            return array(11, $self['error'] . "\n");
        }
        $SET['lvl'] = $options['set_security_level'];
    }
    // Set options['set_name']?
    if ($options['set_name']) {
        // BUSINESS RULE: We require subnet names to be in upper case and spaces are converted to -'s.
        $options['set_name'] = trim($options['set_name']);
        $options['set_name'] = preg_replace('/\\s+/', '-', $options['set_name']);
        $options['set_name'] = strtoupper($options['set_name']);
        // Make sure there's not another subnet with this name
        list($status, $rows, $tmp) = ona_get_subnet_record(array('name' => $options['set_name']));
        if ($status or $rows > 1 or $rows == 1 and $tmp['id'] != $subnet['id']) {
            $self['error'] = "ERROR => That name is already used by another subnet!";
            return array(12, $self['error'] . "\n");
        }
        $SET['name'] = $options['set_name'];
    }
    // Set options['set_type']?
    if ($options['set_type']) {
        // Find the type from $options[type]
        list($status, $rows, $subnet_type) = ona_find_subnet_type($options['set_type']);
        if ($status or $rows != 1) {
            $self['error'] = "ERROR => Invalid subnet type specified!";
            return array(13, $self['error'] . "\n");
        }
        printmsg("Subnet type selected: {$subnet_type['display_name']} ({$subnet_type['short_name']})", 1);
        $SET['subnet_type_id'] = $subnet_type['id'];
    }
    // Set options['set_vlan']?
    if (array_key_exists('set_vlan', $options) or $options['campus']) {
        if (!$options['set_vlan']) {
            $SET['vlan_id'] = '';
        } else {
            // Find the VLAN ID from $options[set_vlan] and $options[campus]
            list($status, $rows, $vlan) = ona_find_vlan($options['set_vlan'], $options['campus']);
            if ($status or $rows != 1) {
                $self['error'] = "ERROR => The vlan/campus pair specified is invalid!";
                return array(15, $self['error'] . "\n");
            }
            printmsg("VLAN selected: {$vlan['name']} in {$vlan['vlan_campus_name']} campus", 1);
            $SET['vlan_id'] = $vlan['id'];
        }
    }
    // Update the subnet record
    list($status, $rows) = db_update_record($onadb, 'subnets', array('id' => $subnet['id']), $SET);
    if ($status or !$rows) {
        return array(16, $self['error'] . "\n");
    }
    // Load the updated record for display
    list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $subnet['id']));
    // Return the (human-readable) success notice
    $text = format_array($SET);
    $self['error'] = "INFO => Subnet UPDATED";
    return array(0, $self['error'] . ":\n{$text}\n");
}
Ejemplo n.º 2
0
function custom_attribute_display($options = "")
{
    // The important globals
    global $conf, $self, $onadb;
    $text_array = array();
    // Version - UPDATE on every edit!
    $version = '1.02';
    printmsg("DEBUG => custom_attribute_display({$options}) called", 3);
    // Parse incoming options string to an array
    $options = parse_options($options);
    // Return the usage summary if we need to
    if ($options['help'] or !$options['host'] and !$options['id'] and !$options['subnet'] and !$options['vlan']) {
        // NOTE: Help message lines should not exceed 80 characters for proper display on a console
        $self['error'] = 'ERROR => Insufficient parameters';
        return array(1, <<<EOM

custom_attribute_display-v{$version}
Display the custom attribute specified or attributes for a host

  Synopsis: custom_attribute_display

  Where:
    id=ID                     custom attribute ID
    OR
    host=ID or NAME[.DOMAIN]  display custom attributes for specified host
    OR
    subnet=ID or NAME         display custom attributes for specified subnet
    OR
    vlan=NAME                 display custom attributes for specified VLAN

  Optional:
    type=ID or NAME           If you specify a type and a host or subnet you
                              will only get back a 1 or a 0 indicating that
                              that type is set or not set for the host or subnet

EOM
);
    }
    // if a type was set, check if it is associated with the host or subnet and return 1 or 0
    if ($options['type']) {
        $field = is_numeric($options['type']) ? 'id' : 'name';
        list($status, $rows, $catype) = ona_get_custom_attribute_type_record(array($field => $options['type']));
        // error if we cant find the type specified
        if (!$catype['id']) {
            $self['error'] = "ERROR => The custom attribute type specified, {$options['type']}, does not exist!";
            return array(5, $self['error']);
        }
        $where['custom_attribute_type_id'] = $catype['id'];
    }
    // Search for the host first
    if ($options['host']) {
        list($status, $rows, $host) = ona_find_host($options['host']);
        // Error if the host doesn't exist
        if (!$host['id']) {
            $self['error'] = "ERROR => The host specified, {$options['host']}, does not exist!";
            return array(2, $self['error']);
        } else {
            $where['table_id_ref'] = $host['id'];
            $where['table_name_ref'] = 'hosts';
            list($status, $rows, $cas) = db_get_records($onadb, 'custom_attributes', $where);
        }
        $anchor = 'host';
        $desc = $host['fqdn'];
    }
    // Search for subnet
    if ($options['subnet']) {
        list($status, $rows, $subnet) = ona_find_subnet($options['subnet']);
        // Error if the record doesn't exist
        if (!$subnet['id']) {
            $self['error'] = "ERROR => The subnet specified, {$options['subnet']}, does not exist!";
            return array(3, $self['error']);
        } else {
            $where['table_id_ref'] = $subnet['id'];
            $where['table_name_ref'] = 'subnets';
            list($status, $rows, $cas) = db_get_records($onadb, 'custom_attributes', $where);
        }
        $anchor = 'subnet';
        $desc = $subnet['description'];
    }
    // Search for vlan
    if ($options['vlan']) {
        list($status, $rows, $vlan) = ona_find_vlan($options['vlan']);
        // Error if the record doesn't exist
        if (!$vlan['id']) {
            $self['error'] = "ERROR => The VLAN specified, {$options['vlan']}, does not exist!";
            return array(3, $self['error']);
        } else {
            $where['table_id_ref'] = $vlan['id'];
            $where['table_name_ref'] = 'vlans';
            list($status, $rows, $cas) = db_get_records($onadb, 'custom_attributes', $where);
        }
        $anchor = 'vlan';
        $desc = $vlan['description'];
    }
    // Now find the ID of the record, returns a specific record only
    if ($options['id']) {
        list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $options['id']));
        if (!$ca['id']) {
            $self['error'] = "ERROR => The custom attribute specified, {$options['id']}, is invalid!";
            return array(4, $self['error']);
        }
        $text_array = $ca;
        $text .= "CUSTOM ATTRIBUTE ENTRY RECORD ({$ca['id']})\n";
        $text .= format_array($ca);
    } elseif ($options['type']) {
        // If we requested type, now is the time to return a response if it is found associated.
        if ($cas[0]) {
            $text .= '1';
            $text_array['has_attribute'] = 'Y';
        } else {
            $text .= '0';
            $text_array['has_attribute'] = 'N';
        }
    } else {
        // Build text to return
        $text .= strtoupper($anchor) . " CUSTOM ATTRIBUTE RECORDS ({$desc})\n";
        // Display the record(s)
        $i = 0;
        do {
            $text .= "\nASSOCIATED CUSTOM ATTRIBUTE ENTRY RECORD ({$i} of {$rows})\n";
            $text .= format_array($cas[$i]);
            list($status, $carows, $ca) = ona_get_custom_attribute_type_record(array('id' => $cas[$i]['custom_attribute_type_id']));
            $text_array[$ca['name']] = $cas[$i]['value'];
            $i++;
        } while ($i < $rows);
    }
    // change the output format if other than default
    if ($options['format'] == 'json') {
        $text = $text_array;
    }
    if ($options['format'] == 'yaml') {
        $text = $text_array;
    }
    // Return the success notice
    return array(0, $text);
}
Ejemplo n.º 3
0
function ws_editor($window_name, $form = '')
{
    global $conf, $self, $onadb;
    global $font_family, $color, $style, $images;
    $window = array();
    // Check permissions
    if (!auth('custom_attribute_del')) {
        $response = new xajaxResponse();
        $response->addScript("alert('Permission denied!');");
        return $response->getXML();
    }
    // If an array in a string was provided, build the array and store it in $form
    $form = parse_options_string($form);
    // If $form is a number, it's a record id- so we transform $form into an array
    if ($form['id']) {
        list($status, $rows, $ca) = ona_get_custom_attribute_record(array('id' => $form['id']));
        $window['title'] = "Edit Custom Attribute";
    } else {
        $window['title'] = "Add Custom Attribute";
    }
    // Load the subnet record and associated info.
    if (is_numeric($form['subnet_id'])) {
        list($status, $rows, $subnet) = ona_get_subnet_record(array('id' => $form['subnet_id']));
        // Setup a title description for this edit type
        $window['edit_type'] = "Subnet";
        $window['edit_type_value'] = $subnet['name'];
    }
    // If they are adding a new CA entry they will usually pass a host_id in
    if (is_numeric($form['host_id'])) {
        list($status, $rows, $host) = ona_find_host($form['host_id']);
        // Setup a title description for this edit type
        $window['edit_type'] = "Host";
        $window['edit_type_value'] = $host['fqdn'];
    }
    if (is_numeric($form['vlan_id'])) {
        list($status, $rows, $vlan) = ona_find_vlan($form['vlan_id']);
        // Setup a title description for this edit type
        $window['edit_type'] = "Vlan";
        $window['edit_type_value'] = $vlan['name'];
    }
    // Escape data for display in html
    foreach (array_keys((array) $subnet) as $key) {
        $subnet[$key] = htmlentities($subnet[$key], ENT_QUOTES, $conf['php_charset']);
    }
    foreach (array_keys((array) $host) as $key) {
        $host[$key] = htmlentities($host[$key], ENT_QUOTES, $conf['php_charset']);
    }
    // Build dhcp option list
    list($status, $rows, $catypes) = db_get_records($onadb, 'custom_attribute_types', 'id >= 1', 'name');
    $ca_type_list = '';
    foreach ($catypes as $record) {
        $selected = "";
        if ($record['id'] == $ca['custom_attribute_type_id']) {
            $selected = "SELECTED=\"selected\"";
        }
        if ($record['id']) {
            $ca_type_list .= "<option {$selected} value=\"{$record['id']}\">{$record['name']}</option>\n";
        }
    }
    // Javascript to run after the window is built
    $window['js'] = <<<EOL
        /* Put a minimize icon in the title bar */
        el('{$window_name}_title_r').innerHTML =
            '&nbsp;<a onClick="toggle_window(\\'{$window_name}\\');" title="Minimize window" style="cursor: pointer;"><img src="{$images}/icon_minimize.gif" border="0" /></a>' +
            el('{$window_name}_title_r').innerHTML;

        /* Put a help icon in the title bar */
        el('{$window_name}_title_r').innerHTML =
            '&nbsp;<a href="{$_ENV['help_url']}{$window_name}" target="null" title="Help" style="cursor: pointer;"><img src="{$images}/silk/help.png" border="0" /></a>' +
            el('{$window_name}_title_r').innerHTML;

        el('{$window_name}_form').onsubmit = function() { return false; };
EOL;
    // Define the window's inner html
    $window['html'] = <<<EOL

    <!-- Custom Attribute Edit Form -->
    <form id="{$window_name}_form" onSubmit="return false;">
    <input type="hidden" name="host" value="{$host['id']}">
    <input type="hidden" name="subnet" value="{$subnet['id']}">
    <input type="hidden" name="vlan" value="{$vlan['id']}">
    <input type="hidden" name="id" value="{$ca['id']}">
    <input type="hidden" name="js" value="{$form['js']}">
    <table cellspacing="0" border="0" cellpadding="0" style="background-color: {$color['window_content_bg']}; padding-left: 20px; padding-right: 20px; padding-top: 5px; padding-bottom: 5px;">

        <!-- Custom Attribute RECORD -->
        <tr>
            <td align="left" nowrap="true"><b><u>CA Record</u></b>&nbsp;</td>
            <td class="padding" align="left" width="100%">&nbsp;</td>
        </tr>

        <tr>
            <td align="right" nowrap="true">
                {$window['edit_type']}:
            </td>
            <td class="padding" align="left" width="100%">
                {$window['edit_type_value']}
            </td>
        </tr>

        <tr>
            <td class="input_required" align="right" nowrap="true">
                Type
            </td>
            <td class="padding" align="left" width="100%">
                <select id="type" name="type" class="edit" accesskey="t">
                    {$ca_type_list}
                </select>
            </td>
        </tr>

        <tr>
            <td class="input_required" align="right" nowrap="true">
                Value
            </td>
            <td class="padding" align="left" width="100%">
                <textarea
                    name="value"
                    alt="Value"
                    class="edit"
                    rows="5"
                    cols="25"
                >{$ca['value']}</textarea>
            </td>
        </tr>



        <tr>
            <td align="right" valign="top" nowrap="true">
                &nbsp;
            </td>
            <td class="padding" align="right" width="100%">
                <input type="hidden" name="overwrite" value="{$overwrite}">
                <input class="edit" type="button" name="cancel" value="Cancel" onClick="removeElement('{$window_name}');">
                <input class="edit" type="button"
                    name="submit"
                    value="Save"
                    accesskey=" "
                    onClick="xajax_window_submit('{$window_name}', xajax.getFormValues('{$window_name}_form'), 'save');"
                >
            </td>
        </tr>

    </table>
    </form>
EOL;
    return window_open($window_name, $window);
}