|
Packit |
eace71 |
/*
|
|
Packit |
eace71 |
* Copyright (C) IBM Corporation. 2007
|
|
Packit |
eace71 |
* Author: Doug Maxey <dwm@austin.ibm.com>
|
|
Packit |
eace71 |
* based on code written by "Prasanna Mumbai" <mumbai.prasanna@gmail.com>
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This program is free software: you can redistribute it and/or modify
|
|
Packit |
eace71 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
eace71 |
* the Free Software Foundation, either version 2 of the License, or
|
|
Packit |
eace71 |
* (at your option) any later version.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
eace71 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
eace71 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
eace71 |
* GNU General Public License for more details.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
eace71 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
#include <stddef.h>
|
|
Packit |
eace71 |
#include <stdio.h>
|
|
Packit |
eace71 |
#include <string.h>
|
|
Packit |
eace71 |
#include <stdlib.h>
|
|
Packit |
eace71 |
#include <unistd.h>
|
|
Packit |
eace71 |
#include <stddef.h>
|
|
Packit |
eace71 |
#include <errno.h>
|
|
Packit |
eace71 |
#include <sys/socket.h>
|
|
Packit |
eace71 |
#include <sys/ioctl.h>
|
|
Packit |
eace71 |
#include <netinet/in.h>
|
|
Packit |
eace71 |
#include <arpa/inet.h>
|
|
Packit |
eace71 |
#include <net/route.h>
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
#include "fw_context.h"
|
|
Packit |
eace71 |
#include "fwparam.h"
|
|
Packit |
eace71 |
#include "idbm_fields.h"
|
|
Packit |
eace71 |
#include "iscsi_net_util.h"
|
|
Packit |
eace71 |
#include "iscsi_err.h"
|
|
Packit |
eace71 |
#include "config.h"
|
|
Packit |
eace71 |
#include "iface.h"
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
/**
|
|
Packit |
eace71 |
* fw_setup_nics - setup nics (ethXs) based on ibft net info
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* If this is a offload card, this function does nothing. The
|
|
Packit |
eace71 |
* net info is used by the iscsi iface settings for the iscsi
|
|
Packit |
eace71 |
* function.
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
int fw_setup_nics(void)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
struct boot_context *context;
|
|
Packit |
eace71 |
struct list_head targets;
|
|
Packit |
eace71 |
char *iface_prev = NULL, transport[16];
|
|
Packit |
eace71 |
int needs_bringup = 0, ret = 0, err;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
INIT_LIST_HEAD(&targets;;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
ret = fw_get_targets(&targets;;
|
|
Packit |
eace71 |
if (ret || list_empty(&targets)) {
|
|
Packit |
eace71 |
printf("Could not setup fw entries.\n");
|
|
Packit |
eace71 |
return ISCSI_ERR_NO_OBJS_FOUND;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
/*
|
|
Packit |
eace71 |
* For each target in iBFT bring up required NIC and use routing
|
|
Packit |
eace71 |
* to force iSCSI traffic through correct NIC
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
list_for_each_entry(context, &targets, list) {
|
|
Packit |
eace71 |
if (iface_prev == NULL || strcmp(context->iface, iface_prev)) {
|
|
Packit |
eace71 |
/* Note: test above works because there is a
|
|
Packit |
eace71 |
* maximum of two targets in the iBFT
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
iface_prev = context->iface;
|
|
Packit |
eace71 |
needs_bringup = 1;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
if (net_get_transport_name_from_netdev(context->iface, transport)) {
|
|
Packit |
eace71 |
/* Setup software NIC, */
|
|
Packit |
eace71 |
printf("Setting up software interface %s\n", context->iface);
|
|
Packit |
eace71 |
err = net_setup_netdev(context->iface, context->ipaddr,
|
|
Packit |
eace71 |
context->mask, context->gateway,
|
|
Packit |
eace71 |
context->vlan,
|
|
Packit |
eace71 |
context->target_ipaddr, needs_bringup);
|
|
Packit |
eace71 |
if (err) {
|
|
Packit |
eace71 |
printf("Setting up software interface %s failed\n",
|
|
Packit |
eace71 |
context->iface);
|
|
Packit |
eace71 |
ret = err;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
} else {
|
|
Packit |
eace71 |
/* Setup offload NIC. */
|
|
Packit |
eace71 |
struct iface_rec iface;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
memset(&iface, 0, sizeof(iface));
|
|
Packit |
eace71 |
iface_setup_defaults(&iface);
|
|
Packit |
eace71 |
printf("Setting up offload interface %s\n", context->iface);
|
|
Packit |
eace71 |
if (!iface_setup_from_boot_context(&iface, context)) {
|
|
Packit |
eace71 |
printf("Setting up offload interface %s failed\n",
|
|
Packit |
eace71 |
context->iface);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
ret = ISCSI_ERR;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
fw_free_targets(&targets;;
|
|
Packit |
eace71 |
if (ret)
|
|
Packit |
eace71 |
return ISCSI_ERR;
|
|
Packit |
eace71 |
else
|
|
Packit |
eace71 |
return 0;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
/**
|
|
Packit |
eace71 |
* fw_get_entry - return boot context of portal used for boot
|
|
Packit |
eace71 |
* @context: firmware info of portal
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* Returns non-zero if no portal was used for boot.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This function is not thread safe.
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
int fw_get_entry(struct boot_context *context)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
int ret;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
ret = fwparam_ppc_boot_info(context);
|
|
Packit |
eace71 |
if (ret)
|
|
Packit |
eace71 |
ret = fwparam_sysfs_boot_info(context);
|
|
Packit |
eace71 |
return ret;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
/**
|
|
Packit |
eace71 |
* fw_get_targets - get a boot_context struct for each target
|
|
Packit |
eace71 |
* @list: list to add entires on.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* Returns zero if entries were found that can be traversed with the
|
|
Packit |
eace71 |
* list.h helpers, or non-zero if no entries are found.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* fw_free_targets should be called to free the list.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* This function is not thread safe.
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
int fw_get_targets(struct list_head *list)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
int ret;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
ret = fwparam_ppc_get_targets(list);
|
|
Packit |
eace71 |
if (ret)
|
|
Packit |
eace71 |
ret = fwparam_sysfs_get_targets(list);
|
|
Packit |
eace71 |
return ret;
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
void fw_free_targets(struct list_head *list)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
struct boot_context *curr, *tmp;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (!list || list_empty(list))
|
|
Packit |
eace71 |
return;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
list_for_each_entry_safe(curr, tmp, list, list) {
|
|
Packit |
eace71 |
list_del(&curr->list);
|
|
Packit |
eace71 |
free(curr);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static void dump_initiator(struct boot_context *context)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
struct iface_rec iface;
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
memset(&iface, 0, sizeof(iface));
|
|
Packit |
eace71 |
iface_setup_defaults(&iface);
|
|
Packit |
eace71 |
iface_setup_from_boot_context(&iface, context);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (strlen(context->initiatorname))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_INAME, context->initiatorname);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (strlen(context->isid))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_ISID, context->isid);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_TRANSPORTNAME, iface.transport_name);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static void dump_target(struct boot_context *context)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
if (strlen(context->targetname))
|
|
Packit |
eace71 |
printf("%s = %s\n", NODE_NAME, context->targetname);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (strlen(context->target_ipaddr))
|
|
Packit |
eace71 |
printf(CONN_ADDR" = %s\n", 0, context->target_ipaddr);
|
|
Packit |
eace71 |
printf(CONN_PORT" = %d\n", 0, context->target_port);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (strlen(context->chap_name))
|
|
Packit |
eace71 |
printf("%s = %s\n", SESSION_USERNAME, context->chap_name);
|
|
Packit |
eace71 |
if (strlen(context->chap_password))
|
|
Packit |
eace71 |
printf("%s = %s\n", SESSION_PASSWORD, context->chap_password);
|
|
Packit |
eace71 |
if (strlen(context->chap_name_in))
|
|
Packit |
eace71 |
printf("%s = %s\n", SESSION_USERNAME_IN, context->chap_name_in);
|
|
Packit |
eace71 |
if (strlen(context->chap_password_in))
|
|
Packit |
eace71 |
printf("%s = %s\n", SESSION_PASSWORD_IN,
|
|
Packit |
eace71 |
context->chap_password_in);
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
if (strlen(context->lun))
|
|
Packit |
eace71 |
printf("%s = %s\n", NODE_BOOT_LUN, context->lun);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
static void dump_network(struct boot_context *context)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
/* Dump the 8 byte mac address (not iser support) */
|
|
Packit |
eace71 |
if (strlen(context->mac))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_HWADDR, context->mac);
|
|
Packit |
eace71 |
/*
|
|
Packit |
eace71 |
* If the 'origin' field is 3 (IBFT_IP_PREFIX_ORIGIN_DHCP),
|
|
Packit |
eace71 |
* then DHCP is used.
|
|
Packit |
eace71 |
* Otherwise evaluate the 'dhcp' field, if this has a valid
|
|
Packit |
eace71 |
* address then DHCP was used (broadcom sends 0.0.0.0).
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
if ((context->origin == IBFT_IP_PREFIX_ORIGIN_DHCP) ||
|
|
Packit |
eace71 |
(strlen(context->dhcp) && strcmp(context->dhcp, "0.0.0.0")))
|
|
Packit |
eace71 |
printf("%s = DHCP\n", IFACE_BOOT_PROTO);
|
|
Packit |
eace71 |
else
|
|
Packit |
eace71 |
printf("%s = STATIC\n", IFACE_BOOT_PROTO);
|
|
Packit |
eace71 |
if (strlen(context->ipaddr))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_IPADDR, context->ipaddr);
|
|
Packit |
eace71 |
if (context->prefix)
|
|
Packit |
eace71 |
printf("%s = %d\n", IFACE_PREFIX_LEN, context->prefix);
|
|
Packit |
eace71 |
if (strlen(context->mask))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_SUBNET_MASK, context->mask);
|
|
Packit |
eace71 |
if (strlen(context->gateway))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_GATEWAY, context->gateway);
|
|
Packit |
eace71 |
if (strlen(context->primary_dns))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_PRIMARY_DNS, context->primary_dns);
|
|
Packit |
eace71 |
if (strlen(context->secondary_dns))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_SEC_DNS, context->secondary_dns);
|
|
Packit |
eace71 |
if (strlen(context->vlan))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_VLAN_ID, context->vlan);
|
|
Packit |
eace71 |
if (strlen(context->iface))
|
|
Packit |
eace71 |
printf("%s = %s\n", IFACE_NETNAME, context->iface);
|
|
Packit |
eace71 |
}
|
|
Packit |
eace71 |
|
|
Packit |
eace71 |
/**
|
|
Packit |
eace71 |
* fw_print_entry - print boot context info of portal used for boot
|
|
Packit |
eace71 |
* @context: firmware info of portal
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* Does not print anything if no portal was used for boot.
|
|
Packit |
eace71 |
*
|
|
Packit |
eace71 |
* TODO: Merge this in with idbm.c helpers.
|
|
Packit |
eace71 |
*/
|
|
Packit |
eace71 |
void fw_print_entry(struct boot_context *context)
|
|
Packit |
eace71 |
{
|
|
Packit |
eace71 |
printf("%s\n", ISCSI_BEGIN_REC);
|
|
Packit |
eace71 |
dump_initiator(context);
|
|
Packit |
eace71 |
dump_network(context);
|
|
Packit |
eace71 |
dump_target(context);
|
|
Packit |
eace71 |
printf("%s\n", ISCSI_END_REC);
|
|
Packit |
eace71 |
}
|