Commit 290aa376 authored by Jitendra Bhivare's avatar Jitendra Bhivare Committed by Martin K. Petersen

scsi: be2iscsi: Check all zeroes IP before issuing IOCTL

Redefine FW IP types.
Before issuing IOCTL to clear IP, check if IP is all zeroes.
All zeroes IP implies IP is not set in FW so FW fails that IOCTL.
Signed-off-by: default avatarJitendra Bhivare <jitendra.bhivare@broadcom.com>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent d8383b34
...@@ -365,6 +365,14 @@ struct ip_addr_format { ...@@ -365,6 +365,14 @@ struct ip_addr_format {
u16 size_of_structure; u16 size_of_structure;
u8 reserved; u8 reserved;
u8 ip_type; u8 ip_type;
#define BEISCSI_IP_TYPE_V4 0x1
#define BEISCSI_IP_TYPE_STATIC_V4 0x3
#define BEISCSI_IP_TYPE_DHCP_V4 0x5
/* type v4 values < type v6 values */
#define BEISCSI_IP_TYPE_V6 0x10
#define BEISCSI_IP_TYPE_ROUTABLE_V6 0x30
#define BEISCSI_IP_TYPE_LINK_LOCAL_V6 0x50
#define BEISCSI_IP_TYPE_AUTO_V6 0x90
u8 addr[16]; u8 addr[16];
u32 rsvd0; u32 rsvd0;
} __packed; } __packed;
......
...@@ -279,12 +279,12 @@ void beiscsi_iface_create_default(struct beiscsi_hba *phba) ...@@ -279,12 +279,12 @@ void beiscsi_iface_create_default(struct beiscsi_hba *phba)
{ {
struct be_cmd_get_if_info_resp *if_info; struct be_cmd_get_if_info_resp *if_info;
if (!beiscsi_if_get_info(phba, BE2_IPV4, &if_info)) { if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V4, &if_info)) {
beiscsi_iface_create_ipv4(phba); beiscsi_iface_create_ipv4(phba);
kfree(if_info); kfree(if_info);
} }
if (!beiscsi_if_get_info(phba, BE2_IPV6, &if_info)) { if (!beiscsi_if_get_info(phba, BEISCSI_IP_TYPE_V6, &if_info)) {
beiscsi_iface_create_ipv6(phba); beiscsi_iface_create_ipv6(phba);
kfree(if_info); kfree(if_info);
} }
...@@ -358,14 +358,15 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost, ...@@ -358,14 +358,15 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
break; break;
case ISCSI_NET_PARAM_IPV4_GW: case ISCSI_NET_PARAM_IPV4_GW:
gw = info->value; gw = info->value;
ret = beiscsi_if_set_gw(phba, BE2_IPV4, gw); ret = beiscsi_if_set_gw(phba, BEISCSI_IP_TYPE_V4, gw);
break; break;
case ISCSI_NET_PARAM_IPV4_BOOTPROTO: case ISCSI_NET_PARAM_IPV4_BOOTPROTO:
if (info->value[0] == ISCSI_BOOTPROTO_DHCP) if (info->value[0] == ISCSI_BOOTPROTO_DHCP)
ret = beiscsi_if_en_dhcp(phba, BE2_IPV4); ret = beiscsi_if_en_dhcp(phba, BEISCSI_IP_TYPE_V4);
else if (info->value[0] == ISCSI_BOOTPROTO_STATIC) else if (info->value[0] == ISCSI_BOOTPROTO_STATIC)
/* release DHCP IP address */ /* release DHCP IP address */
ret = beiscsi_if_en_static(phba, BE2_IPV4, NULL, NULL); ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
NULL, NULL);
else else
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
"BS_%d : Invalid BOOTPROTO: %d\n", "BS_%d : Invalid BOOTPROTO: %d\n",
...@@ -378,7 +379,8 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost, ...@@ -378,7 +379,8 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
info = nla_data(nla); info = nla_data(nla);
subnet = info->value; subnet = info->value;
} }
ret = beiscsi_if_en_static(phba, BE2_IPV4, ip, subnet); ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
ip, subnet);
break; break;
case ISCSI_NET_PARAM_IPV4_SUBNET: case ISCSI_NET_PARAM_IPV4_SUBNET:
/* /*
...@@ -391,7 +393,8 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost, ...@@ -391,7 +393,8 @@ beiscsi_iface_config_ipv4(struct Scsi_Host *shost,
info = nla_data(nla); info = nla_data(nla);
ip = info->value; ip = info->value;
} }
ret = beiscsi_if_en_static(phba, BE2_IPV4, ip, subnet); ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V4,
ip, subnet);
break; break;
} }
...@@ -416,7 +419,7 @@ beiscsi_iface_config_ipv6(struct Scsi_Host *shost, ...@@ -416,7 +419,7 @@ beiscsi_iface_config_ipv6(struct Scsi_Host *shost,
} }
break; break;
case ISCSI_NET_PARAM_IPV6_ADDR: case ISCSI_NET_PARAM_IPV6_ADDR:
ret = beiscsi_if_en_static(phba, BE2_IPV6, ret = beiscsi_if_en_static(phba, BEISCSI_IP_TYPE_V6,
iface_param->value, NULL); iface_param->value, NULL);
break; break;
} }
...@@ -511,10 +514,10 @@ static int __beiscsi_iface_get_param(struct beiscsi_hba *phba, ...@@ -511,10 +514,10 @@ static int __beiscsi_iface_get_param(struct beiscsi_hba *phba,
int param, char *buf) int param, char *buf)
{ {
struct be_cmd_get_if_info_resp *if_info; struct be_cmd_get_if_info_resp *if_info;
int len, ip_type = BE2_IPV4; int len, ip_type = BEISCSI_IP_TYPE_V4;
if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6)
ip_type = BE2_IPV6; ip_type = BEISCSI_IP_TYPE_V6;
len = beiscsi_if_get_info(phba, ip_type, &if_info); len = beiscsi_if_get_info(phba, ip_type, &if_info);
if (len) if (len)
...@@ -602,7 +605,7 @@ int beiscsi_iface_get_param(struct iscsi_iface *iface, ...@@ -602,7 +605,7 @@ int beiscsi_iface_get_param(struct iscsi_iface *iface,
break; break;
case ISCSI_NET_PARAM_IPV4_GW: case ISCSI_NET_PARAM_IPV4_GW:
memset(&gateway, 0, sizeof(gateway)); memset(&gateway, 0, sizeof(gateway));
len = beiscsi_if_get_gw(phba, BE2_IPV4, &gateway); len = beiscsi_if_get_gw(phba, BEISCSI_IP_TYPE_V4, &gateway);
if (!len) if (!len)
len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr); len = sprintf(buf, "%pI4\n", &gateway.ip_addr.addr);
break; break;
...@@ -635,7 +638,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep, ...@@ -635,7 +638,7 @@ int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport);
break; break;
case ISCSI_PARAM_CONN_ADDRESS: case ISCSI_PARAM_CONN_ADDRESS:
if (beiscsi_ep->ip_type == BE2_IPV4) if (beiscsi_ep->ip_type == BEISCSI_IP_TYPE_V4)
len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr);
else else
len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
......
...@@ -23,13 +23,6 @@ ...@@ -23,13 +23,6 @@
#include "be_main.h" #include "be_main.h"
#include "be_mgmt.h" #include "be_mgmt.h"
#define BE2_IPV4 0x1
#define BE2_IPV6 0x10
#define BE2_DHCP_V4 0x05
#define NON_BLOCKING 0x0
#define BLOCKING 0x1
void beiscsi_iface_create_default(struct beiscsi_hba *phba); void beiscsi_iface_create_default(struct beiscsi_hba *phba);
void beiscsi_iface_destroy_default(struct beiscsi_hba *phba); void beiscsi_iface_destroy_default(struct beiscsi_hba *phba);
......
...@@ -389,7 +389,7 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) ...@@ -389,7 +389,7 @@ static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)
(char *)&boot_sess->target_name); (char *)&boot_sess->target_name);
break; break;
case ISCSI_BOOT_TGT_IP_ADDR: case ISCSI_BOOT_TGT_IP_ADDR:
if (boot_conn->dest_ipaddr.ip_type == 0x1) if (boot_conn->dest_ipaddr.ip_type == BEISCSI_IP_TYPE_V4)
rc = sprintf(buf, "%pI4\n", rc = sprintf(buf, "%pI4\n",
(char *)&boot_conn->dest_ipaddr.addr); (char *)&boot_conn->dest_ipaddr.addr);
else else
......
...@@ -844,7 +844,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -844,7 +844,7 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
nonemb_cmd->size); nonemb_cmd->size);
if (dst_addr->sa_family == PF_INET) { if (dst_addr->sa_family == PF_INET) {
__be32 s_addr = daddr_in->sin_addr.s_addr; __be32 s_addr = daddr_in->sin_addr.s_addr;
req->ip_address.ip_type = BE2_IPV4; req->ip_address.ip_type = BEISCSI_IP_TYPE_V4;
req->ip_address.addr[0] = s_addr & 0x000000ff; req->ip_address.addr[0] = s_addr & 0x000000ff;
req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8; req->ip_address.addr[1] = (s_addr & 0x0000ff00) >> 8;
req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16; req->ip_address.addr[2] = (s_addr & 0x00ff0000) >> 16;
...@@ -852,17 +852,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba, ...@@ -852,17 +852,17 @@ int mgmt_open_connection(struct beiscsi_hba *phba,
req->tcp_port = ntohs(daddr_in->sin_port); req->tcp_port = ntohs(daddr_in->sin_port);
beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr;
beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port);
beiscsi_ep->ip_type = BE2_IPV4; beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V4;
} else { } else {
/* else its PF_INET6 family */ /* else its PF_INET6 family */
req->ip_address.ip_type = BE2_IPV6; req->ip_address.ip_type = BEISCSI_IP_TYPE_V6;
memcpy(&req->ip_address.addr, memcpy(&req->ip_address.addr,
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16); &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
req->tcp_port = ntohs(daddr_in6->sin6_port); req->tcp_port = ntohs(daddr_in6->sin6_port);
beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port);
memcpy(&beiscsi_ep->dst6_addr, memcpy(&beiscsi_ep->dst6_addr,
&daddr_in6->sin6_addr.in6_u.u6_addr8, 16); &daddr_in6->sin6_addr.in6_u.u6_addr8, 16);
beiscsi_ep->ip_type = BE2_IPV6; beiscsi_ep->ip_type = BEISCSI_IP_TYPE_V6;
} }
req->cid = cid; req->cid = cid;
i = phba->nxt_cqid++; i = phba->nxt_cqid++;
...@@ -1008,6 +1008,16 @@ unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba) ...@@ -1008,6 +1008,16 @@ unsigned int beiscsi_if_get_handle(struct beiscsi_hba *phba)
return status; return status;
} }
static inline bool beiscsi_if_zero_ip(u8 *ip, u32 ip_type)
{
u32 len;
len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;
while (len && !ip[len - 1])
len--;
return (len == 0);
}
static int beiscsi_if_mod_gw(struct beiscsi_hba *phba, static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
u32 action, u32 ip_type, u8 *gw) u32 action, u32 ip_type, u8 *gw)
{ {
...@@ -1025,7 +1035,7 @@ static int beiscsi_if_mod_gw(struct beiscsi_hba *phba, ...@@ -1025,7 +1035,7 @@ static int beiscsi_if_mod_gw(struct beiscsi_hba *phba,
req->action = action; req->action = action;
req->ip_addr.ip_type = ip_type; req->ip_addr.ip_type = ip_type;
memcpy(req->ip_addr.addr, gw, memcpy(req->ip_addr.addr, gw,
(ip_type == BE2_IPV4) ? IP_V4_LEN : IP_V6_LEN); (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN);
return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0);
} }
...@@ -1042,6 +1052,7 @@ int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw) ...@@ -1042,6 +1052,7 @@ int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)
return rt_val; return rt_val;
} }
if (!beiscsi_if_zero_ip(gw_resp.ip_addr.addr, ip_type)) {
rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type, rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, ip_type,
gw_resp.ip_addr.addr); gw_resp.ip_addr.addr);
if (rt_val) { if (rt_val) {
...@@ -1049,6 +1060,7 @@ int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw) ...@@ -1049,6 +1060,7 @@ int beiscsi_if_set_gw(struct beiscsi_hba *phba, u32 ip_type, u8 *gw)
"BG_%d : Failed to clear Gateway Addr Set\n"); "BG_%d : Failed to clear Gateway Addr Set\n");
return rt_val; return rt_val;
} }
}
rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw); rt_val = beiscsi_if_mod_gw(phba, IP_ACTION_ADD, ip_type, gw);
if (rt_val) if (rt_val)
...@@ -1138,7 +1150,7 @@ beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip, ...@@ -1138,7 +1150,7 @@ beiscsi_if_set_ip(struct beiscsi_hba *phba, u8 *ip,
req->ip_params.ip_record.ip_addr.size_of_structure = req->ip_params.ip_record.ip_addr.size_of_structure =
sizeof(struct be_ip_addr_subnet_format); sizeof(struct be_ip_addr_subnet_format);
req->ip_params.ip_record.ip_addr.ip_type = ip_type; req->ip_params.ip_record.ip_addr.ip_type = ip_type;
ip_len = ip_type == BE2_IPV4 ? IP_V4_LEN : IP_V6_LEN; ip_len = (ip_type < BEISCSI_IP_TYPE_V6) ? IP_V4_LEN : IP_V6_LEN;
memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len); memcpy(req->ip_params.ip_record.ip_addr.addr, ip, ip_len);
if (subnet) if (subnet)
memcpy(req->ip_params.ip_record.ip_addr.subnet_mask, memcpy(req->ip_params.ip_record.ip_addr.subnet_mask,
...@@ -1190,10 +1202,12 @@ int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type, ...@@ -1190,10 +1202,12 @@ int beiscsi_if_en_static(struct beiscsi_hba *phba, u32 ip_type,
} }
} }
/* first delete any old IP set */ /* first delete any IP set */
if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {
rc = beiscsi_if_clr_ip(phba, if_info); rc = beiscsi_if_clr_ip(phba, if_info);
if (rc) if (rc)
goto exit; goto exit;
}
/* if ip == NULL then this is called just to release DHCP IP */ /* if ip == NULL then this is called just to release DHCP IP */
if (ip) if (ip)
...@@ -1222,10 +1236,12 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) ...@@ -1222,10 +1236,12 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
goto exit; goto exit;
} }
/* first delete any old static IP set */ /* first delete any IP set */
if (!beiscsi_if_zero_ip(if_info->ip_addr.addr, ip_type)) {
rc = beiscsi_if_clr_ip(phba, if_info); rc = beiscsi_if_clr_ip(phba, if_info);
if (rc) if (rc)
goto exit; goto exit;
}
/* delete gateway settings if mode change is to DHCP */ /* delete gateway settings if mode change is to DHCP */
memset(&gw_resp, 0, sizeof(gw_resp)); memset(&gw_resp, 0, sizeof(gw_resp));
...@@ -1237,6 +1253,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) ...@@ -1237,6 +1253,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
goto exit; goto exit;
} }
gw = (u8 *)&gw_resp.ip_addr.addr; gw = (u8 *)&gw_resp.ip_addr.addr;
if (!beiscsi_if_zero_ip(gw, if_info->ip_addr.ip_type)) {
rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL, rc = beiscsi_if_mod_gw(phba, IP_ACTION_DEL,
if_info->ip_addr.ip_type, gw); if_info->ip_addr.ip_type, gw);
if (rc) { if (rc) {
...@@ -1244,6 +1261,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) ...@@ -1244,6 +1261,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
"BG_%d : Failed to clear Gateway Addr Set\n"); "BG_%d : Failed to clear Gateway Addr Set\n");
goto exit; goto exit;
} }
}
rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd, rc = mgmt_alloc_cmd_data(phba, &nonemb_cmd,
OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR,
...@@ -1252,7 +1270,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type) ...@@ -1252,7 +1270,7 @@ int beiscsi_if_en_dhcp(struct beiscsi_hba *phba, u32 ip_type)
goto exit; goto exit;
dhcpreq = nonemb_cmd.va; dhcpreq = nonemb_cmd.va;
dhcpreq->flags = BLOCKING; dhcpreq->flags = 1; /* 1 - blocking; 0 - non-blocking */
dhcpreq->retry_count = 1; dhcpreq->retry_count = 1;
dhcpreq->interface_hndl = phba->interface_handle; dhcpreq->interface_hndl = phba->interface_handle;
dhcpreq->ip_type = ip_type; dhcpreq->ip_type = ip_type;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment