623e295db825ead7804dab19fd5989cd99228c2a
[mirror/scst/.git] / iscsi-scst / usr / ctldev.c
1 /*
2  *  Copyright (C) 2004 - 2005 FUJITA Tomonori <tomof@acm.org>
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.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  */
15
16 #include <ctype.h>
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26
27 #include "iscsid.h"
28
29 #define CTL_DEVICE      "/dev/iscsi-scst-ctl"
30
31 int kernel_open(int *max_data_seg_len)
32 {
33         FILE *f;
34         char devname[256];
35         char buf[256];
36         int devn;
37         int ctlfd = -1;
38         int err;
39         struct iscsi_kern_register_info reg = { 0 };
40
41         if (!(f = fopen("/proc/devices", "r"))) {
42                 err = -errno;
43                 perror("Cannot open control path to the driver");
44                 goto out_err;
45         }
46
47         devn = 0;
48         while (!feof(f)) {
49                 if (!fgets(buf, sizeof (buf), f)) {
50                         break;
51                 }
52                 if (sscanf(buf, "%d %s", &devn, devname) != 2) {
53                         continue;
54                 }
55                 if (!strcmp(devname, "iscsi-scst-ctl")) {
56                         break;
57                 }
58                 devn = 0;
59         }
60
61         fclose(f);
62         if (!devn) {
63                 err = -ENOENT;
64                 printf("cannot find iscsictl in /proc/devices - "
65                      "make sure the module is loaded\n");
66                 goto out_err;
67         }
68
69         unlink(CTL_DEVICE);
70         if (mknod(CTL_DEVICE, (S_IFCHR | 0600), (devn << 8))) {
71                 err = -errno;
72                 printf("cannot create %s %d\n", CTL_DEVICE, errno);
73                 goto out_err;
74         }
75
76         ctlfd = open(CTL_DEVICE, O_RDWR);
77         if (ctlfd < 0) {
78                 err = -errno;
79                 printf("cannot open %s %d\n", CTL_DEVICE, errno);
80                 goto out_err;
81         }
82
83         reg.version = (uintptr_t)ISCSI_SCST_INTERFACE_VERSION;
84
85         err = ioctl(ctlfd, REGISTER_USERD, &reg);
86         if (err < 0) {
87                 err = -errno;
88                 log_error("Unable to register: %s. Incompatible version of the "
89                         "kernel module?\n", strerror(errno));
90                 goto out_close;
91         } else {
92                 log_debug(0, "MAX_DATA_SEG_LEN %d", err);
93                 *max_data_seg_len = err;
94         }
95
96 out:
97         return ctlfd;
98
99 out_close:
100         close(ctlfd);
101
102 out_err:
103         ctlfd = err;
104         goto out;
105 }
106
107 int kernel_target_create(u32 *tid, char *name)
108 {
109         int err;
110         struct iscsi_kern_target_info info;
111
112         memset(&info, 0, sizeof(info));
113
114         memcpy(info.name, name, sizeof(info.name) - 1);
115         info.tid = *tid;
116         if ((err = ioctl(ctrl_fd, ADD_TARGET, &info)) < 0) {
117                 err = -errno;
118                 log_error("Can't create target %u: %s\n", *tid,
119                         strerror(errno));
120         } else
121                 *tid = info.tid;
122
123         return err;
124 }
125
126 int kernel_target_destroy(u32 tid)
127 {
128         struct iscsi_kern_target_info info;
129         int res;
130
131         memset(&info, 0, sizeof(info));
132         info.tid = tid;
133
134         res = ioctl(ctrl_fd, DEL_TARGET, &info);
135         if (res < 0) {
136                 res = -errno;
137                 log_error("Can't destroy target %d %u\n", errno, tid);
138         }
139
140         return res;
141 }
142
143 int kernel_conn_destroy(u32 tid, u64 sid, u32 cid)
144 {
145         int err;
146         struct iscsi_kern_conn_info info;
147
148         info.tid = tid;
149         info.sid = sid;
150         info.cid = cid;
151
152         if ((err = ioctl(ctrl_fd, DEL_CONN, &info)) < 0) {
153                 err = -errno;
154                 log_error("Can't destroy conn (errno %d, tid %u, sid 0x%"
155                         PRIx64 ", cid %u\n", errno, tid, sid, cid);
156         }
157
158         return err;
159 }
160
161 int kernel_param_get(u32 tid, u64 sid, int type, struct iscsi_param *param)
162 {
163         int err, i;
164         struct iscsi_kern_param_info info;
165
166         memset(&info, 0, sizeof(info));
167         info.tid = tid;
168         info.sid = sid;
169         info.param_type = type;
170
171         if ((err = ioctl(ctrl_fd, ISCSI_PARAM_GET, &info)) < 0) {
172                 err = -errno;
173                 log_debug(1, "Can't get session param for session 0x%" PRIu64 
174                         " (tid %u, err %d): %s\n", sid, tid, err, strerror(errno));
175         }
176
177         if (type == key_session)
178                 for (i = 0; i < session_key_last; i++)
179                         param[i].val = info.session_param[i];
180         else
181                 for (i = 0; i < target_key_last; i++)
182                         param[i].val = info.target_param[i];
183
184         return err;
185 }
186
187 int kernel_param_set(u32 tid, u64 sid, int type, u32 partial,
188         struct iscsi_param *param)
189 {
190         int i, err;
191         struct iscsi_kern_param_info info;
192
193         memset(&info, 0, sizeof(info));
194         info.tid = tid;
195         info.sid = sid;
196         info.param_type = type;
197         info.partial = partial;
198
199         if (info.param_type == key_session)
200                 for (i = 0; i < session_key_last; i++)
201                         info.session_param[i] = param[i].val;
202         else
203                 for (i = 0; i < target_key_last; i++)
204                         info.target_param[i] = param[i].val;
205
206         if ((err = ioctl(ctrl_fd, ISCSI_PARAM_SET, &info)) < 0) {
207                 err = -errno;
208                 log_error("Can't set session param for session 0x%" PRIu64 
209                         " (tid %u, type %d, partial %d, err %d): %s\n", sid,
210                         tid, type, partial, err, strerror(errno));
211         }
212
213         return err;
214 }
215
216 int kernel_session_create(u32 tid, u64 sid, u32 exp_cmd_sn,
217         char *name, char *user)
218 {
219         struct iscsi_kern_session_info info;
220         int res;
221
222         memset(&info, 0, sizeof(info));
223
224         info.tid = tid;
225         info.sid = sid;
226         info.exp_cmd_sn = exp_cmd_sn;
227         strncpy(info.initiator_name, name, sizeof(info.initiator_name) - 1);
228         strncpy(info.user_name, user, sizeof(info.user_name) - 1);
229
230         res = ioctl(ctrl_fd, ADD_SESSION, &info);
231         if (res < 0) {
232                 res = -errno;
233                 log_error("Can't create sess 0x%" PRIu64 " (tid %d, "
234                         "initiator %s): %s\n", sid, tid, name, strerror(errno));
235         }
236
237         return res;
238 }
239
240 int kernel_session_destroy(u32 tid, u64 sid)
241 {
242         struct iscsi_kern_session_info info;
243         int res;
244
245         memset(&info, 0, sizeof(info));
246
247         info.tid = tid;
248         info.sid = sid;
249
250         res = ioctl(ctrl_fd, DEL_SESSION, &info);
251         if (res < 0) {
252                 res = -errno;
253                 log_error("Can't destroy sess 0x%" PRIu64 " (tid %d): %s\n",
254                         sid, tid, strerror(errno));
255         }
256
257         return res;
258 }
259
260 int kernel_conn_create(u32 tid, u64 sid, u32 cid, u32 stat_sn, u32 exp_stat_sn,
261                              int fd, u32 hdigest, u32 ddigest)
262 {
263         struct iscsi_kern_conn_info info;
264         int res;
265
266         memset(&info, 0, sizeof(info));
267
268         info.tid = tid;
269         info.sid = sid;
270         info.cid = cid;
271         info.stat_sn = stat_sn;
272         info.exp_stat_sn = exp_stat_sn;
273         info.fd = fd;
274         info.header_digest = hdigest;
275         info.data_digest = ddigest;
276
277         res = ioctl(ctrl_fd, ADD_CONN, &info);
278         if (res < 0) {
279                 res = -errno;
280                 log_error("Can't create conn %x (sess 0x%" PRIu64 ", tid %d): %s\n",
281                         cid, sid, tid, strerror(errno));
282         }
283
284         return res;
285 }