Fix for user space part of the iSCSI target, which refused connections in the procfs...
[mirror/scst/.git] / iscsi-scst / usr / target.c
1 /*
2  *  Copyright (C) 2002 - 2003 Ardis Technolgies <roman@ardistech.com>
3  *  Copyright (C) 2007 - 2009 Vladislav Bolkhovitin
4  *  Copyright (C) 2007 - 2009 ID7 Ltd.
5  *
6  *  This program is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU General Public License
8  *  as published by the Free Software Foundation, version 2
9  *  of the License.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  */
16
17 #include <ctype.h>
18 #include <dirent.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/stat.h>
24
25 #include "iscsid.h"
26
27 struct __qelem targets_list = LIST_HEAD_INIT(targets_list);
28
29 void target_list_build(struct connection *conn, char *addr, char *name)
30 {
31         struct target *target;
32
33         list_for_each_entry(target, &targets_list, tlist) {
34                 if (name && strcmp(target->name, name))
35                         continue;
36                 if (config_initiator_access(target->tid, conn->fd) ||
37                     isns_scn_access(target->tid, conn->fd, conn->initiator))
38                         continue;
39
40                 text_key_add(conn, "TargetName", target->name);
41                 text_key_add(conn, "TargetAddress", addr);
42         }
43 }
44
45 u32 target_find_id_by_name(const char *name)
46 {
47         struct target *target;
48
49         list_for_each_entry(target, &targets_list, tlist) {
50                 if (!strcasecmp(target->name, name))
51                         return target->tid;
52         }
53
54         return 0;
55 }
56
57 struct target *target_find_by_name(const char *name)
58 {
59         struct target *target;
60
61         list_for_each_entry(target, &targets_list, tlist) {
62                 if (!strcasecmp(target->name, name))
63                         return target;
64         }
65
66         return NULL;
67 }
68
69 struct target *target_find_by_id(u32 tid)
70 {
71         struct target *target;
72
73         list_for_each_entry(target, &targets_list, tlist) {
74                 if (target->tid == tid)
75                         return target;
76         }
77
78         return NULL;
79 }
80
81 static void all_accounts_del(u32 tid, int dir)
82 {
83         char name[ISCSI_NAME_LEN], pass[ISCSI_NAME_LEN];
84
85         memset(name, 0, sizeof(name));
86
87         for (; config_account_query(tid, dir, name, pass) != -ENOENT;
88                 memset(name, 0, sizeof(name))) {
89                 config_account_del(tid, dir, name);
90         }
91
92 }
93
94 int target_del(u32 tid)
95 {
96         struct target *target = target_find_by_id(tid);
97         int err = kernel_target_destroy(tid);
98
99         if (err < 0 && err != -ENOENT)
100                 return err;
101         else if (!err && !target)
102                 /* A leftover kernel object was cleaned up - don't complain. */
103                 return 0;
104
105         if (!target)
106                 return -ENOENT;
107
108         remque(&target->tlist);
109
110         if (!list_empty(&target->sessions_list)) {
111                 log_error("%s: target %u still has sessions\n", __FUNCTION__,
112                           tid);
113                 exit(-1);
114         }
115
116         all_accounts_del(tid, AUTH_DIR_INCOMING);
117         all_accounts_del(tid, AUTH_DIR_OUTGOING);
118
119         isns_target_deregister(target->name);
120         free(target);
121
122         return 0;
123 }
124
125 int target_add(u32 *tid, char *name)
126 {
127         struct target *target;
128         int err;
129         struct iscsi_param tgt_params[target_key_last];
130         struct iscsi_param sess_params[session_key_last];
131
132         if (!name)
133                 return -EINVAL;
134
135         if (!(target = malloc(sizeof(*target))))
136                 return -ENOMEM;
137
138         memset(target, 0, sizeof(*target));
139         memcpy(target->name, name, sizeof(target->name) - 1);
140
141         if ((err = kernel_target_create(tid, name)) < 0)
142                 goto out_free;
143
144         param_set_defaults(tgt_params, target_keys);
145         err = kernel_param_set(*tid, 0, key_target, 0, tgt_params);
146         if (err != 0)
147                 goto out_destroy;
148
149         param_set_defaults(sess_params, session_keys);
150         err = kernel_param_set(*tid, 0, key_session, 0, sess_params);
151         if (err != 0)
152                 goto out_destroy;
153
154         INIT_LIST_HEAD(&target->tlist);
155         INIT_LIST_HEAD(&target->sessions_list);
156         INIT_LIST_HEAD(&target->isns_head);
157         target->tid = *tid;
158 #ifdef CONFIG_SCST_PROC
159         target->tgt_enabled = 1;
160 #endif
161         insque(&target->tlist, &targets_list);
162
163         isns_target_register(name);
164
165 out:
166         return err;
167
168 out_destroy:
169         kernel_target_destroy(*tid);
170
171 out_free:
172         free(target);
173         goto out;
174 }