|
@@ -727,10 +727,11 @@ static void iscsi_session_release(struct device *dev)
|
|
|
kfree(session);
|
|
|
}
|
|
|
|
|
|
-static int iscsi_is_session_dev(const struct device *dev)
|
|
|
+int iscsi_is_session_dev(const struct device *dev)
|
|
|
{
|
|
|
return dev->release == iscsi_session_release;
|
|
|
}
|
|
|
+EXPORT_SYMBOL_GPL(iscsi_is_session_dev);
|
|
|
|
|
|
static int iscsi_iter_session_fn(struct device *dev, void *data)
|
|
|
{
|
|
@@ -2001,6 +2002,96 @@ iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
|
|
|
+{
|
|
|
+ struct iscsi_uevent *ev = NLMSG_DATA(nlh);
|
|
|
+ struct Scsi_Host *shost = NULL;
|
|
|
+ struct iscsi_chap_rec *chap_rec;
|
|
|
+ struct iscsi_internal *priv;
|
|
|
+ struct sk_buff *skbchap;
|
|
|
+ struct nlmsghdr *nlhchap;
|
|
|
+ struct iscsi_uevent *evchap;
|
|
|
+ uint32_t chap_buf_size;
|
|
|
+ int len, err = 0;
|
|
|
+ char *buf;
|
|
|
+
|
|
|
+ if (!transport->get_chap)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ priv = iscsi_if_transport_lookup(transport);
|
|
|
+ if (!priv)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
|
|
|
+ len = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
|
|
|
+
|
|
|
+ shost = scsi_host_lookup(ev->u.get_chap.host_no);
|
|
|
+ if (!shost) {
|
|
|
+ printk(KERN_ERR "%s: failed. Cound not find host no %u\n",
|
|
|
+ __func__, ev->u.get_chap.host_no);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ int actual_size;
|
|
|
+
|
|
|
+ skbchap = alloc_skb(len, GFP_KERNEL);
|
|
|
+ if (!skbchap) {
|
|
|
+ printk(KERN_ERR "can not deliver chap: OOM\n");
|
|
|
+ err = -ENOMEM;
|
|
|
+ goto exit_get_chap;
|
|
|
+ }
|
|
|
+
|
|
|
+ nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
|
|
|
+ (len - sizeof(*nlhchap)), 0);
|
|
|
+ evchap = NLMSG_DATA(nlhchap);
|
|
|
+ memset(evchap, 0, sizeof(*evchap));
|
|
|
+ evchap->transport_handle = iscsi_handle(transport);
|
|
|
+ evchap->type = nlh->nlmsg_type;
|
|
|
+ evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
|
|
|
+ evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
|
|
|
+ evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
|
|
|
+ buf = (char *) ((char *)evchap + sizeof(*evchap));
|
|
|
+ memset(buf, 0, chap_buf_size);
|
|
|
+
|
|
|
+ err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
|
|
|
+ &evchap->u.get_chap.num_entries, buf);
|
|
|
+
|
|
|
+ actual_size = NLMSG_SPACE(sizeof(*ev) + chap_buf_size);
|
|
|
+ skb_trim(skbchap, NLMSG_ALIGN(actual_size));
|
|
|
+ nlhchap->nlmsg_len = actual_size;
|
|
|
+
|
|
|
+ err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID,
|
|
|
+ GFP_KERNEL);
|
|
|
+ } while (err < 0 && err != -ECONNREFUSED);
|
|
|
+
|
|
|
+exit_get_chap:
|
|
|
+ scsi_host_put(shost);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int iscsi_delete_chap(struct iscsi_transport *transport,
|
|
|
+ struct iscsi_uevent *ev)
|
|
|
+{
|
|
|
+ struct Scsi_Host *shost;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ if (!transport->delete_chap)
|
|
|
+ return -ENOSYS;
|
|
|
+
|
|
|
+ shost = scsi_host_lookup(ev->u.delete_chap.host_no);
|
|
|
+ if (!shost) {
|
|
|
+ printk(KERN_ERR "%s could not find host no %u\n",
|
|
|
+ __func__, ev->u.delete_chap.host_no);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
+ err = transport->delete_chap(shost, ev->u.delete_chap.chap_tbl_idx);
|
|
|
+ scsi_host_put(shost);
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
static int
|
|
|
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
|
|
|
{
|
|
@@ -2149,6 +2240,12 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
|
|
|
case ISCSI_UEVENT_PING:
|
|
|
err = iscsi_send_ping(transport, ev);
|
|
|
break;
|
|
|
+ case ISCSI_UEVENT_GET_CHAP:
|
|
|
+ err = iscsi_get_chap(transport, nlh);
|
|
|
+ break;
|
|
|
+ case ISCSI_UEVENT_DELETE_CHAP:
|
|
|
+ err = iscsi_delete_chap(transport, ev);
|
|
|
+ break;
|
|
|
default:
|
|
|
err = -ENOSYS;
|
|
|
break;
|
|
@@ -2198,6 +2295,8 @@ iscsi_if_rx(struct sk_buff *skb)
|
|
|
*/
|
|
|
if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
|
|
|
break;
|
|
|
+ if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
|
|
|
+ break;
|
|
|
err = iscsi_if_send_reply(group, nlh->nlmsg_seq,
|
|
|
nlh->nlmsg_type, 0, 0, ev, sizeof(*ev));
|
|
|
} while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
|