2 * iSCSI Discovery Database Library
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * Copyright (C) 2006 Mike Christie
6 * Copyright (C) 2006 Red Hat, Inc. All rights reserved.
7 * maintained by open-iscsi@@googlegroups.com
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * See the file COPYING included with this distribution for more details.
34 #include "idbm_fields.h"
36 #include "iscsi_util.h"
37 #include "iscsi_settings.h"
38 #include "transport.h"
39 #include "iscsi_sysfs.h"
42 #include "fw_context.h"
43 #include "iscsi_err.h"
45 #define IDBM_HIDE 0 /* Hide parameter when print. */
46 #define IDBM_SHOW 1 /* Show parameter when print. */
47 #define IDBM_MASKED 2 /* Show "stars" instead of real value when print */
49 static struct idbm
*db
;
51 #define __recinfo_str(_key, _info, _rec, _name, _show, _n, _mod) do { \
52 _info[_n].type = TYPE_STR; \
53 strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
54 if (strlen((char*)_rec->_name)) \
55 strlcpy((char*)_info[_n].value, (char*)_rec->_name, \
57 _info[_n].data = &_rec->_name; \
58 _info[_n].data_len = sizeof(_rec->_name); \
59 _info[_n].visible = _show; \
60 _info[_n].can_modify = _mod; \
64 #define __recinfo_int(_key, _info, _rec, _name, _show, _n, _mod) do { \
65 _info[_n].type = TYPE_INT; \
66 strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
67 snprintf(_info[_n].value, VALUE_MAXVAL, "%d", _rec->_name); \
68 _info[_n].data = &_rec->_name; \
69 _info[_n].data_len = sizeof(_rec->_name); \
70 _info[_n].visible = _show; \
71 _info[_n].can_modify = _mod; \
75 #define __recinfo_uint8(_key, _info, _rec, _name, _show, _n, _mod) do { \
76 _info[_n].type = TYPE_UINT8; \
77 strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
78 snprintf(_info[_n].value, VALUE_MAXVAL, "%d", _rec->_name); \
79 _info[_n].data = &_rec->_name; \
80 _info[_n].data_len = sizeof(_rec->_name); \
81 _info[_n].visible = _show; \
82 _info[_n].can_modify = _mod; \
86 #define __recinfo_uint16(_key, _info, _rec, _name, _show, _n, _mod) do { \
87 _info[_n].type = TYPE_UINT16; \
88 strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
89 snprintf(_info[_n].value, VALUE_MAXVAL, "%d", _rec->_name); \
90 _info[_n].data = &_rec->_name; \
91 _info[_n].data_len = sizeof(_rec->_name); \
92 _info[_n].visible = _show; \
93 _info[_n].can_modify = _mod; \
97 #define __recinfo_int_o2(_key,_info,_rec,_name,_show,_op0,_op1,_n, _mod) do { \
98 _info[_n].type = TYPE_INT_O; \
99 strlcpy(_info[_n].name, _key, NAME_MAXVAL); \
100 if (_rec->_name == 0) strlcpy(_info[_n].value, _op0, VALUE_MAXVAL); \
101 if (_rec->_name == 1) strlcpy(_info[_n].value, _op1, VALUE_MAXVAL); \
102 _info[_n].data = &_rec->_name; \
103 _info[_n].data_len = sizeof(_rec->_name); \
104 _info[_n].visible = _show; \
105 _info[_n].opts[0] = _op0; \
106 _info[_n].opts[1] = _op1; \
107 _info[_n].numopts = 2; \
108 _info[_n].can_modify = _mod; \
112 #define __recinfo_int_o3(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_n, \
114 __recinfo_int_o2(_key,_info,_rec,_name,_show,_op0,_op1,_n, _mod); \
116 if (_rec->_name == 2) strlcpy(_info[_n].value, _op2, VALUE_MAXVAL);\
117 _info[_n].opts[2] = _op2; \
118 _info[_n].numopts = 3; \
122 #define __recinfo_int_o4(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_op3,_n, \
124 __recinfo_int_o3(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_n, _mod); \
126 if (_rec->_name == 3) strlcpy(_info[_n].value, _op3, VALUE_MAXVAL); \
127 _info[_n].opts[3] = _op3; \
128 _info[_n].numopts = 4; \
132 #define __recinfo_int_o5(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_op3, \
133 _op4,_n, _mod) do { \
134 __recinfo_int_o4(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_op3, \
137 if (_rec->_name == 4) strlcpy(_info[_n].value, _op4, VALUE_MAXVAL); \
138 _info[_n].opts[4] = _op4; \
139 _info[_n].numopts = 5; \
143 #define __recinfo_int_o6(_key,_info,_rec,_name,_show,_op0,_op1,_op2, \
144 _op3,_op4,_op5,_n,_mod) do { \
145 __recinfo_int_o5(_key,_info,_rec,_name,_show,_op0,_op1,_op2,_op3, \
148 if (_rec->_name == 5) strlcpy(_info[_n].value, _op5, VALUE_MAXVAL); \
149 _info[_n].opts[5] = _op5; \
150 _info[_n].numopts = 6; \
155 idbm_recinfo_discovery(discovery_rec_t
*r
, recinfo_t
*ri
)
159 __recinfo_int_o2(DISC_STARTUP
, ri
, r
, startup
, IDBM_SHOW
,
160 "manual", "automatic", num
, 1);
161 __recinfo_int_o6(DISC_TYPE
, ri
, r
, type
, IDBM_SHOW
,
162 "sendtargets", "isns", "offload_send_targets", "slp",
163 "static", "fw", num
, 0);
165 case DISCOVERY_TYPE_SENDTARGETS
:
166 __recinfo_str(DISC_ST_ADDR
, ri
, r
,
167 address
, IDBM_SHOW
, num
, 0);
168 __recinfo_int(DISC_ST_PORT
, ri
, r
,
169 port
, IDBM_SHOW
, num
, 0);
170 __recinfo_int_o2(DISC_ST_AUTH_METHOD
, ri
, r
,
171 u
.sendtargets
.auth
.authmethod
,
172 IDBM_SHOW
, "None", "CHAP", num
, 1);
173 __recinfo_str(DISC_ST_USERNAME
, ri
, r
,
174 u
.sendtargets
.auth
.username
, IDBM_SHOW
, num
, 1);
175 __recinfo_str(DISC_ST_PASSWORD
, ri
, r
,
176 u
.sendtargets
.auth
.password
, IDBM_MASKED
, num
, 1);
177 __recinfo_int(DISC_ST_PASSWORD_LEN
, ri
, r
,
178 u
.sendtargets
.auth
.password_length
, IDBM_HIDE
, num
, 1);
179 __recinfo_str(DISC_ST_USERNAME_IN
, ri
, r
,
180 u
.sendtargets
.auth
.username_in
, IDBM_SHOW
, num
, 1);
181 __recinfo_str(DISC_ST_PASSWORD_IN
, ri
, r
,
182 u
.sendtargets
.auth
.password_in
, IDBM_MASKED
, num
, 1);
183 __recinfo_int(DISC_ST_PASSWORD_IN_LEN
, ri
, r
,
184 u
.sendtargets
.auth
.password_in_length
, IDBM_HIDE
,
186 __recinfo_int(DISC_ST_LOGIN_TMO
, ri
, r
,
187 u
.sendtargets
.conn_timeo
.login_timeout
,
189 __recinfo_int_o2(DISC_ST_USE_DISC_DAEMON
, ri
, r
,
190 u
.sendtargets
.use_discoveryd
,
191 IDBM_SHOW
, "No", "Yes", num
, 1);
192 __recinfo_int(DISC_ST_DISC_DAEMON_POLL_INVAL
, ri
, r
,
193 u
.sendtargets
.discoveryd_poll_inval
,
195 __recinfo_int(DISC_ST_REOPEN_MAX
, ri
, r
,
196 u
.sendtargets
.reopen_max
,
198 __recinfo_int(DISC_ST_AUTH_TMO
, ri
, r
,
199 u
.sendtargets
.conn_timeo
.auth_timeout
,
201 __recinfo_int(DISC_ST_ACTIVE_TMO
, ri
, r
,
202 u
.sendtargets
.conn_timeo
.active_timeout
,
204 __recinfo_int(DISC_ST_MAX_RECV_DLEN
, ri
, r
,
205 u
.sendtargets
.conn_conf
.MaxRecvDataSegmentLength
,
208 case DISCOVERY_TYPE_ISNS
:
209 __recinfo_str(DISC_ISNS_ADDR
, ri
, r
,
210 address
, IDBM_SHOW
, num
, 0);
211 __recinfo_int(DISC_ISNS_PORT
, ri
, r
,
212 port
, IDBM_SHOW
, num
, 0);
213 __recinfo_int_o2(DISC_ISNS_USE_DISC_DAEMON
, ri
, r
,
214 u
.isns
.use_discoveryd
,
215 IDBM_SHOW
, "No", "Yes", num
, 1);
216 __recinfo_int(DISC_ISNS_DISC_DAEMON_POLL_INVAL
, ri
, r
,
217 u
.isns
.discoveryd_poll_inval
,
226 idbm_recinfo_node(node_rec_t
*r
, recinfo_t
*ri
)
230 __recinfo_str(NODE_NAME
, ri
, r
, name
, IDBM_SHOW
, num
, 0);
231 __recinfo_int(NODE_TPGT
, ri
, r
, tpgt
, IDBM_SHOW
, num
, 0);
232 __recinfo_int_o3(NODE_STARTUP
, ri
, r
, startup
,
233 IDBM_SHOW
, "manual", "automatic", "onboot", num
, 1);
234 __recinfo_int_o2(NODE_LEADING_LOGIN
, ri
, r
, leading_login
, IDBM_SHOW
,
235 "No", "Yes", num
, 1);
237 * Note: because we do not add the iface.iscsi_ifacename to
238 * sysfs iscsiadm does some weird matching. We can change the iface
239 * values if a session is not running, but node record ifaces values
240 * have to be changed and so do the iface record ones.
242 * Users should nornmally not want to change the iface ones
243 * in the node record directly and instead do it through
244 * the iface mode which will do the right thing (althought that
245 * needs some locking).
247 __recinfo_str(IFACE_HWADDR
, ri
, r
, iface
.hwaddress
, IDBM_SHOW
, num
, 1);
248 __recinfo_str(IFACE_IPADDR
, ri
, r
, iface
.ipaddress
, IDBM_SHOW
, num
, 1);
249 __recinfo_str(IFACE_ISCSINAME
, ri
, r
, iface
.name
, IDBM_SHOW
, num
, 1);
250 __recinfo_str(IFACE_NETNAME
, ri
, r
, iface
.netdev
, IDBM_SHOW
, num
, 1);
252 * svn 780 compat: older versions used node.transport_name and
253 * rec->transport_name
255 __recinfo_str(IFACE_TRANSPORTNAME
, ri
, r
, iface
.transport_name
,
257 __recinfo_str(IFACE_INAME
, ri
, r
, iface
.iname
, IDBM_SHOW
, num
, 1);
258 __recinfo_str(NODE_DISC_ADDR
, ri
, r
, disc_address
, IDBM_SHOW
,
260 __recinfo_int(NODE_DISC_PORT
, ri
, r
, disc_port
, IDBM_SHOW
,
262 __recinfo_int_o6(NODE_DISC_TYPE
, ri
, r
, disc_type
, IDBM_SHOW
,
263 "send_targets", "isns", "offload_send_targets", "slp",
264 "static", "fw", num
, 0);
265 __recinfo_int(SESSION_INIT_CMDSN
, ri
, r
,
266 session
.initial_cmdsn
, IDBM_SHOW
, num
, 1);
267 __recinfo_int(SESSION_INIT_LOGIN_RETRY
, ri
, r
,
268 session
.initial_login_retry_max
, IDBM_SHOW
, num
, 1);
269 __recinfo_int(SESSION_XMIT_THREAD_PRIORITY
, ri
, r
,
270 session
.xmit_thread_priority
, IDBM_SHOW
, num
, 1);
271 __recinfo_int(SESSION_CMDS_MAX
, ri
, r
,
272 session
.cmds_max
, IDBM_SHOW
, num
, 1);
273 __recinfo_int(SESSION_QDEPTH
, ri
, r
,
274 session
.queue_depth
, IDBM_SHOW
, num
, 1);
275 __recinfo_int(SESSION_NR_SESSIONS
, ri
, r
,
276 session
.nr_sessions
, IDBM_SHOW
, num
, 1);
277 __recinfo_int_o2(SESSION_AUTH_METHOD
, ri
, r
, session
.auth
.authmethod
,
278 IDBM_SHOW
, "None", "CHAP", num
, 1);
279 __recinfo_str(SESSION_USERNAME
, ri
, r
,
280 session
.auth
.username
, IDBM_SHOW
, num
, 1);
281 __recinfo_str(SESSION_PASSWORD
, ri
, r
,
282 session
.auth
.password
, IDBM_MASKED
, num
, 1);
283 __recinfo_int(SESSION_PASSWORD_LEN
, ri
, r
,
284 session
.auth
.password_length
, IDBM_HIDE
, num
, 1);
285 __recinfo_str(SESSION_USERNAME_IN
, ri
, r
,
286 session
.auth
.username_in
, IDBM_SHOW
, num
, 1);
287 __recinfo_str(SESSION_PASSWORD_IN
, ri
, r
,
288 session
.auth
.password_in
, IDBM_MASKED
, num
, 1);
289 __recinfo_int(SESSION_PASSWORD_IN_LEN
, ri
, r
,
290 session
.auth
.password_in_length
, IDBM_HIDE
, num
, 1);
291 __recinfo_int(SESSION_REPLACEMENT_TMO
, ri
, r
,
292 session
.timeo
.replacement_timeout
,
294 __recinfo_int(SESSION_ABORT_TMO
, ri
, r
,
295 session
.err_timeo
.abort_timeout
,
297 __recinfo_int(SESSION_LU_RESET_TMO
, ri
, r
,
298 session
.err_timeo
.lu_reset_timeout
,
300 __recinfo_int(SESSION_TGT_RESET_TMO
, ri
, r
,
301 session
.err_timeo
.tgt_reset_timeout
,
303 __recinfo_int(SESSION_HOST_RESET_TMO
, ri
, r
,
304 session
.err_timeo
.host_reset_timeout
,
306 __recinfo_int_o2(SESSION_FAST_ABORT
, ri
, r
,
307 session
.iscsi
.FastAbort
, IDBM_SHOW
, "No", "Yes",
309 __recinfo_int_o2(SESSION_INITIAL_R2T
, ri
, r
,
310 session
.iscsi
.InitialR2T
, IDBM_SHOW
,
311 "No", "Yes", num
, 1);
312 __recinfo_int_o2(SESSION_IMM_DATA
, ri
, r
,
313 session
.iscsi
.ImmediateData
,
314 IDBM_SHOW
, "No", "Yes", num
, 1);
315 __recinfo_int(SESSION_FIRST_BURST
, ri
, r
,
316 session
.iscsi
.FirstBurstLength
, IDBM_SHOW
, num
, 1);
317 __recinfo_int(SESSION_MAX_BURST
, ri
, r
,
318 session
.iscsi
.MaxBurstLength
, IDBM_SHOW
, num
, 1);
319 __recinfo_int(SESSION_DEF_TIME2RETAIN
, ri
, r
,
320 session
.iscsi
.DefaultTime2Retain
, IDBM_SHOW
, num
, 1);
321 __recinfo_int(SESSION_DEF_TIME2WAIT
, ri
, r
,
322 session
.iscsi
.DefaultTime2Wait
, IDBM_SHOW
, num
, 1);
323 __recinfo_int(SESSION_MAX_CONNS
, ri
, r
,
324 session
.iscsi
.MaxConnections
, IDBM_SHOW
, num
, 1);
325 __recinfo_int(SESSION_MAX_R2T
, ri
, r
,
326 session
.iscsi
.MaxOutstandingR2T
, IDBM_SHOW
, num
, 1);
327 __recinfo_int(SESSION_ERL
, ri
, r
,
328 session
.iscsi
.ERL
, IDBM_SHOW
, num
, 1);
330 for (i
= 0; i
< ISCSI_CONN_MAX
; i
++) {
331 char key
[NAME_MAXVAL
];
333 sprintf(key
, CONN_ADDR
, i
);
334 __recinfo_str(key
, ri
, r
, conn
[i
].address
, IDBM_SHOW
, num
, 0);
335 sprintf(key
, CONN_PORT
, i
);
336 __recinfo_int(key
, ri
, r
, conn
[i
].port
, IDBM_SHOW
, num
, 0);
337 sprintf(key
, CONN_STARTUP
, i
);
338 __recinfo_int_o3(key
, ri
, r
, conn
[i
].startup
, IDBM_SHOW
,
339 "manual", "automatic", "onboot", num
, 1);
340 sprintf(key
, CONN_WINDOW_SIZE
, i
);
341 __recinfo_int(key
, ri
, r
, conn
[i
].tcp
.window_size
,
343 sprintf(key
, CONN_SERVICE_TYPE
, i
);
344 __recinfo_int(key
, ri
, r
, conn
[i
].tcp
.type_of_service
,
346 sprintf(key
, CONN_LOGOUT_TMO
, i
);
347 __recinfo_int(key
, ri
, r
, conn
[i
].timeo
.logout_timeout
,
349 sprintf(key
, CONN_LOGIN_TMO
, i
);
350 __recinfo_int(key
, ri
, r
, conn
[i
].timeo
.login_timeout
,
352 sprintf(key
, CONN_AUTH_TMO
, i
);
353 __recinfo_int(key
, ri
, r
, conn
[i
].timeo
.auth_timeout
,
356 sprintf(key
, CONN_NOP_INT
, i
);
357 __recinfo_int(key
, ri
, r
, conn
[i
].timeo
.noop_out_interval
,
359 sprintf(key
, CONN_NOP_TMO
, i
);
360 __recinfo_int(key
, ri
, r
, conn
[i
].timeo
.noop_out_timeout
,
363 sprintf(key
, CONN_MAX_XMIT_DLEN
, i
);
364 __recinfo_int(key
, ri
, r
,
365 conn
[i
].iscsi
.MaxXmitDataSegmentLength
, IDBM_SHOW
,
367 sprintf(key
, CONN_MAX_RECV_DLEN
, i
);
368 __recinfo_int(key
, ri
, r
,
369 conn
[i
].iscsi
.MaxRecvDataSegmentLength
, IDBM_SHOW
,
371 sprintf(key
, CONN_HDR_DIGEST
, i
);
372 __recinfo_int_o4(key
, ri
, r
, conn
[i
].iscsi
.HeaderDigest
,
373 IDBM_SHOW
, "None", "CRC32C", "CRC32C,None",
374 "None,CRC32C", num
, 1);
375 sprintf(key
, CONN_DATA_DIGEST
, i
);
376 __recinfo_int_o4(key
, ri
, r
, conn
[i
].iscsi
.DataDigest
, IDBM_SHOW
,
377 "None", "CRC32C", "CRC32C,None",
378 "None,CRC32C", num
, 1);
379 sprintf(key
, CONN_IFMARKER
, i
);
380 __recinfo_int_o2(key
, ri
, r
, conn
[i
].iscsi
.IFMarker
, IDBM_SHOW
,
381 "No", "Yes", num
, 1);
382 sprintf(key
, CONN_OFMARKER
, i
);
383 __recinfo_int_o2(key
, ri
, r
, conn
[i
].iscsi
.OFMarker
, IDBM_SHOW
,
384 "No", "Yes", num
, 1);
388 void idbm_recinfo_iface(iface_rec_t
*r
, recinfo_t
*ri
)
392 __recinfo_str(IFACE_ISCSINAME
, ri
, r
, name
, IDBM_SHOW
, num
, 0);
393 __recinfo_str(IFACE_NETNAME
, ri
, r
, netdev
, IDBM_SHOW
, num
, 1);
394 __recinfo_str(IFACE_IPADDR
, ri
, r
, ipaddress
, IDBM_SHOW
, num
, 1);
395 __recinfo_str(IFACE_HWADDR
, ri
, r
, hwaddress
, IDBM_SHOW
, num
, 1);
396 __recinfo_str(IFACE_TRANSPORTNAME
, ri
, r
, transport_name
,
398 __recinfo_str(IFACE_INAME
, ri
, r
, iname
, IDBM_SHOW
, num
, 1);
399 __recinfo_str(IFACE_BOOT_PROTO
, ri
, r
, bootproto
, IDBM_SHOW
, num
, 1);
400 __recinfo_str(IFACE_SUBNET_MASK
, ri
, r
, subnet_mask
,
402 __recinfo_str(IFACE_GATEWAY
, ri
, r
, gateway
, IDBM_SHOW
, num
, 1);
403 __recinfo_str(IFACE_IPV6_AUTOCFG
, ri
, r
, ipv6_autocfg
,
405 __recinfo_str(IFACE_LINKLOCAL_AUTOCFG
, ri
, r
, linklocal_autocfg
,
407 __recinfo_str(IFACE_ROUTER_AUTOCFG
, ri
, r
, router_autocfg
,
409 __recinfo_str(IFACE_LINKLOCAL
, ri
, r
, ipv6_linklocal
,
411 __recinfo_str(IFACE_ROUTER
, ri
, r
, ipv6_router
, IDBM_SHOW
, num
, 1);
412 __recinfo_str(IFACE_STATE
, ri
, r
, state
, IDBM_SHOW
, num
, 1);
413 __recinfo_uint16(IFACE_VLAN_ID
, ri
, r
, vlan_id
, IDBM_SHOW
, num
, 1);
414 __recinfo_uint8(IFACE_VLAN_PRIORITY
, ri
, r
, vlan_priority
,
416 __recinfo_str(IFACE_VLAN_STATE
, ri
, r
, vlan_state
, IDBM_SHOW
, num
, 1);
417 __recinfo_int(IFACE_NUM
, ri
, r
, iface_num
, IDBM_SHOW
, num
, 1);
418 __recinfo_uint16(IFACE_MTU
, ri
, r
, mtu
, IDBM_SHOW
, num
, 1);
419 __recinfo_uint16(IFACE_PORT
, ri
, r
, port
, IDBM_SHOW
, num
, 1);
422 recinfo_t
*idbm_recinfo_alloc(int max_keys
)
426 info
= malloc(sizeof(recinfo_t
)*max_keys
);
429 memset(info
, 0, sizeof(recinfo_t
)*max_keys
);
433 void idbm_print(int type
, void *rec
, int show
, FILE *f
)
438 info
= idbm_recinfo_alloc(MAX_KEYS
);
443 case IDBM_PRINT_TYPE_DISCOVERY
:
444 idbm_recinfo_discovery((discovery_rec_t
*)rec
, info
);
446 case IDBM_PRINT_TYPE_NODE
:
447 idbm_recinfo_node((node_rec_t
*)rec
, info
);
449 case IDBM_PRINT_TYPE_IFACE
:
450 idbm_recinfo_iface((struct iface_rec
*)rec
, info
);
454 fprintf(f
, "%s\n", ISCSI_BEGIN_REC
);
455 for (i
= 0; i
< MAX_KEYS
; i
++) {
456 if (!info
[i
].visible
)
458 if (!show
&& info
[i
].visible
== IDBM_MASKED
) {
459 if (*(char*)info
[i
].data
) {
460 fprintf(f
, "%s = ********\n", info
[i
].name
);
466 if (strlen(info
[i
].value
))
467 fprintf(f
, "%s = %s\n", info
[i
].name
, info
[i
].value
);
468 else if (f
== stdout
)
469 fprintf(f
, "%s = <empty>\n", info
[i
].name
);
471 fprintf(f
, "%s\n", ISCSI_END_REC
);
477 idbm_setup_session_defaults(struct iscsi_session_operational_config
*conf
)
479 conf
->InitialR2T
= 0;
480 conf
->ImmediateData
= 1;
481 conf
->FirstBurstLength
= DEF_INI_FIRST_BURST_LEN
;
482 conf
->MaxBurstLength
= DEF_INI_MAX_BURST_LEN
;
483 conf
->DefaultTime2Wait
= ISCSI_DEF_TIME2WAIT
;
484 conf
->DefaultTime2Retain
= 0;
485 conf
->MaxConnections
= 1;
486 conf
->MaxOutstandingR2T
= 1;
491 static void idbm_setup_conn_defaults(struct iscsi_conn_operational_config
*conf
)
493 conf
->MaxXmitDataSegmentLength
= 0;
494 conf
->MaxRecvDataSegmentLength
= DEF_INI_MAX_RECV_SEG_LEN
;
495 conf
->HeaderDigest
= CONFIG_DIGEST_NEVER
;
496 conf
->DataDigest
= CONFIG_DIGEST_NEVER
;
502 idbm_discovery_setup_defaults(discovery_rec_t
*rec
, discovery_type_e type
)
504 memset(rec
, 0, sizeof(discovery_rec_t
));
506 rec
->startup
= ISCSI_STARTUP_MANUAL
;
509 case DISCOVERY_TYPE_SENDTARGETS
:
510 rec
->u
.sendtargets
.discoveryd_poll_inval
= 30;
511 rec
->u
.sendtargets
.use_discoveryd
= 0;
512 rec
->u
.sendtargets
.reopen_max
= 5;
513 rec
->u
.sendtargets
.auth
.authmethod
= 0;
514 rec
->u
.sendtargets
.auth
.password_length
= 0;
515 rec
->u
.sendtargets
.auth
.password_in_length
= 0;
516 rec
->u
.sendtargets
.conn_timeo
.login_timeout
=15;
517 rec
->u
.sendtargets
.conn_timeo
.auth_timeout
= 45;
518 rec
->u
.sendtargets
.conn_timeo
.active_timeout
=30;
519 idbm_setup_session_defaults(&rec
->u
.sendtargets
.session_conf
);
520 idbm_setup_conn_defaults(&rec
->u
.sendtargets
.conn_conf
);
521 /* override def setting */
522 rec
->u
.sendtargets
.conn_conf
.MaxRecvDataSegmentLength
=
523 DEF_INI_DISC_MAX_RECV_SEG_LEN
;
525 case DISCOVERY_TYPE_SLP
:
526 rec
->u
.slp
.interfaces
= NULL
;
527 rec
->u
.slp
.scopes
= NULL
;
528 rec
->u
.slp
.poll_interval
= 5 * 60; /* 5 minutes */
529 rec
->u
.slp
.auth
.authmethod
= 0;
530 rec
->u
.slp
.auth
.password_length
= 0;
531 rec
->u
.slp
.auth
.password_in_length
= 0;
532 rec
->u
.slp
.auth
.password_in_length
= 0;
534 case DISCOVERY_TYPE_ISNS
:
535 rec
->u
.isns
.use_discoveryd
= 0;
536 rec
->u
.isns
.discoveryd_poll_inval
= -1;
543 int idbm_rec_update_param(recinfo_t
*info
, char *name
, char *value
,
551 for (i
=0; i
<MAX_KEYS
; i
++) {
552 if (!strcmp(name
, info
[i
].name
)) {
554 log_debug(7, "updated '%s', '%s' => '%s'", name
,
555 info
[i
].value
, value
);
556 /* parse recinfo by type */
557 if (info
[i
].type
== TYPE_INT
) {
561 *(int*)info
[i
].data
=
562 strtoul(value
, NULL
, 10);
564 } else if (info
[i
].type
== TYPE_UINT8
) {
568 *(uint8_t *)info
[i
].data
=
569 strtoul(value
, NULL
, 10);
571 } else if (info
[i
].type
== TYPE_UINT16
) {
575 *(uint16_t *)info
[i
].data
=
576 strtoul(value
, NULL
, 10);
578 } else if (info
[i
].type
== TYPE_STR
) {
582 strlcpy((char*)info
[i
].data
,
583 value
, info
[i
].data_len
);
586 for (j
=0; j
<info
[i
].numopts
; j
++) {
587 if (!strcmp(value
, info
[i
].opts
[j
])) {
591 *(int*)info
[i
].data
= j
;
596 log_warning("config file line %d contains "
597 "unknown value format '%s' for "
598 "parameter name '%s'",
599 line_number
, value
, name
);
601 log_error("unknown value format '%s' for "
602 "parameter name '%s'", value
, name
);
608 return ISCSI_ERR_INVAL
;
611 strlcpy((char*)info
[i
].value
, value
, VALUE_MAXVAL
);
613 #define check_password_param(_param) \
614 if (!passwd_done && !strcmp(#_param, name)) { \
616 name = #_param "_length"; \
617 snprintf(passwd_len, 8, "%d", (int)strlen(value)); \
618 value = passwd_len; \
619 goto setup_passwd_len; \
622 check_password_param(node
.session
.auth
.password
);
623 check_password_param(node
.session
.auth
.password_in
);
624 check_password_param(discovery
.sendtargets
.auth
.password
);
625 check_password_param(discovery
.sendtargets
.auth
.password_in
);
626 check_password_param(discovery
.slp
.auth
.password
);
627 check_password_param(discovery
.slp
.auth
.password_in
);
633 * TODO: we can also check for valid values here.
635 int idbm_verify_param(recinfo_t
*info
, char *name
)
639 for (i
= 0; i
< MAX_KEYS
; i
++) {
640 if (strcmp(name
, info
[i
].name
))
643 log_debug(7, "verify %s %d\n", name
, info
[i
].can_modify
);
644 if (info
[i
].can_modify
)
647 log_error("Cannot modify %s. It is used to look up "
648 "the record and cannot be changed.", name
);
649 return ISCSI_ERR_INVAL
;
653 log_error("Cannot modify %s. Invalid param name.", name
);
654 return ISCSI_ERR_INVAL
;
657 void idbm_recinfo_config(recinfo_t
*info
, FILE *f
)
659 char name
[NAME_MAXVAL
];
660 char value
[VALUE_MAXVAL
];
661 char *line
, *nl
, buffer
[2048];
665 fseek(f
, 0, SEEK_SET
);
667 /* process the config file */
669 line
= fgets(buffer
, sizeof (buffer
), f
);
674 nl
= line
+ strlen(line
) - 1;
676 log_warning("Config file line %d too long.",
681 line
= strstrip(line
);
682 /* process any non-empty, non-comment lines */
683 if (!*line
|| *line
== '\0' || *line
== '\n' || *line
== '#')
687 i
=0; nl
= line
; *name
= 0;
688 while (*nl
&& !isspace(c
= *nl
) && *nl
!= '=') {
689 *(name
+i
) = *nl
; i
++; nl
++;
692 log_warning("config file line %d do not has value",
697 /* skip after-name traling spaces */
698 while (*nl
&& isspace(c
= *nl
)) nl
++;
699 if (*nl
&& *nl
!= '=') {
700 log_warning("config file line %d has not '=' sepa",
706 /* skip after-sepa traling spaces */
707 while (*nl
&& isspace(c
= *nl
)) nl
++;
709 log_warning("config file line %d do not has value",
716 *(value
+i
) = *nl
; i
++; nl
++;
720 idbm_rec_update_param(info
, name
, value
, line_number
);
725 * TODO: remove db's copy of nrec and infos
727 static void idbm_sync_config(void)
732 /* in case of no configuration file found we just
733 * initialize default node and default discovery records
734 * from hard-coded default values */
735 idbm_node_setup_defaults(&db
->nrec
);
736 idbm_discovery_setup_defaults(&db
->drec_st
, DISCOVERY_TYPE_SENDTARGETS
);
737 idbm_discovery_setup_defaults(&db
->drec_slp
, DISCOVERY_TYPE_SLP
);
738 idbm_discovery_setup_defaults(&db
->drec_isns
, DISCOVERY_TYPE_ISNS
);
740 idbm_recinfo_discovery(&db
->drec_st
, db
->dinfo_st
);
741 idbm_recinfo_discovery(&db
->drec_slp
, db
->dinfo_slp
);
742 idbm_recinfo_discovery(&db
->drec_isns
, db
->dinfo_isns
);
743 idbm_recinfo_node(&db
->nrec
, db
->ninfo
);
745 if (!db
->get_config_file
) {
746 log_debug(1, "Could not get config file. No config file fn\n");
750 config_file
= db
->get_config_file();
752 log_debug(1, "Could not get config file for sync config\n");
756 f
= fopen(config_file
, "r");
758 log_debug(1, "cannot open configuration file %s. "
759 "Default location is %s.\n",
760 config_file
, CONFIG_FILE
);
763 log_debug(5, "updating defaults from '%s'", config_file
);
765 idbm_recinfo_config(db
->dinfo_st
, f
);
766 idbm_recinfo_config(db
->dinfo_slp
, f
);
767 idbm_recinfo_config(db
->dinfo_isns
, f
);
768 idbm_recinfo_config(db
->ninfo
, f
);
771 /* update password lengths */
772 if (*db
->drec_st
.u
.sendtargets
.auth
.password
)
773 db
->drec_st
.u
.sendtargets
.auth
.password_length
=
774 strlen((char*)db
->drec_st
.u
.sendtargets
.auth
.password
);
775 if (*db
->drec_st
.u
.sendtargets
.auth
.password_in
)
776 db
->drec_st
.u
.sendtargets
.auth
.password_in_length
=
777 strlen((char*)db
->drec_st
.u
.sendtargets
.auth
.password_in
);
778 if (*db
->drec_slp
.u
.slp
.auth
.password
)
779 db
->drec_slp
.u
.slp
.auth
.password_length
=
780 strlen((char*)db
->drec_slp
.u
.slp
.auth
.password
);
781 if (*db
->drec_slp
.u
.slp
.auth
.password_in
)
782 db
->drec_slp
.u
.slp
.auth
.password_in_length
=
783 strlen((char*)db
->drec_slp
.u
.slp
.auth
.password_in
);
784 if (*db
->nrec
.session
.auth
.password
)
785 db
->nrec
.session
.auth
.password_length
=
786 strlen((char*)db
->nrec
.session
.auth
.password
);
787 if (*db
->nrec
.session
.auth
.password_in
)
788 db
->nrec
.session
.auth
.password_in_length
=
789 strlen((char*)db
->nrec
.session
.auth
.password_in
);
792 void idbm_node_setup_from_conf(node_rec_t
*rec
)
794 memset(rec
, 0, sizeof(*rec
));
795 idbm_node_setup_defaults(rec
);
797 memcpy(rec
, &db
->nrec
, sizeof(*rec
));
800 int idbm_print_discovery_info(discovery_rec_t
*rec
, int show
)
802 idbm_print(IDBM_PRINT_TYPE_DISCOVERY
, rec
, show
, stdout
);
806 int idbm_print_node_info(void *data
, node_rec_t
*rec
)
808 int show
= *((int *)data
);
810 idbm_print(IDBM_PRINT_TYPE_NODE
, rec
, show
, stdout
);
814 int idbm_print_iface_info(void *data
, struct iface_rec
*iface
)
816 int show
= *((int *)data
);
818 idbm_print(IDBM_PRINT_TYPE_IFACE
, iface
, show
, stdout
);
822 int idbm_print_node_flat(void *data
, node_rec_t
*rec
)
824 if (strchr(rec
->conn
[0].address
, '.'))
825 printf("%s:%d,%d %s\n", rec
->conn
[0].address
, rec
->conn
[0].port
,
826 rec
->tpgt
, rec
->name
);
828 printf("[%s]:%d,%d %s\n", rec
->conn
[0].address
,
829 rec
->conn
[0].port
, rec
->tpgt
, rec
->name
);
833 int idbm_print_node_tree(struct node_rec
*last_rec
, struct node_rec
*rec
,
836 if (!last_rec
|| strcmp(last_rec
->name
, rec
->name
)) {
837 printf("%sTarget: %s\n", prefix
, rec
->name
);
839 memset(last_rec
, 0, sizeof(node_rec_t
));
843 ((strcmp(last_rec
->conn
[0].address
, rec
->conn
[0].address
) ||
844 last_rec
->conn
[0].port
!= rec
->conn
[0].port
))) {
845 if (strchr(rec
->conn
[0].address
, '.'))
846 printf("%s\tPortal: %s:%d,%d\n", prefix
,
847 rec
->conn
[0].address
,
848 rec
->conn
[0].port
, rec
->tpgt
);
850 printf("%s\tPortal: [%s]:%d,%d\n", prefix
,
851 rec
->conn
[0].address
,
852 rec
->conn
[0].port
, rec
->tpgt
);
856 memcpy(last_rec
, rec
, sizeof(node_rec_t
));
860 int idbm_print_node_and_iface_tree(void *data
, node_rec_t
*rec
)
862 idbm_print_node_tree(data
, rec
, "");
863 printf("\t\tIface Name: %s\n", rec
->iface
.name
);
868 get_params_from_disc_link(char *link
, char **target
, char **tpgt
,
869 char **address
, char **port
, char **ifaceid
)
872 *address
= strchr(*target
, ',');
874 return ISCSI_ERR_INVAL
;
875 *(*address
)++ = '\0';
876 *port
= strchr(*address
, ',');
878 return ISCSI_ERR_INVAL
;
880 *tpgt
= strchr(*port
, ',');
882 return ISCSI_ERR_INVAL
;
884 *ifaceid
= strchr(*tpgt
, ',');
886 return ISCSI_ERR_INVAL
;
887 *(*ifaceid
)++ = '\0';
900 if (access(LOCK_DIR
, F_OK
) != 0) {
901 if (mkdir(LOCK_DIR
, 0660) != 0) {
902 log_error("Could not open %s: %s\n", LOCK_DIR
,
904 return ISCSI_ERR_IDBM
;
908 fd
= open(LOCK_FILE
, O_RDWR
| O_CREAT
, 0666);
912 for (i
= 0; i
< 3000; i
++) {
913 ret
= link(LOCK_FILE
, LOCK_WRITE_FILE
);
917 if (errno
!= EEXIST
) {
918 log_error("Maybe you are not root?");
919 log_error("Could not lock discovery DB: %s: %s",
920 LOCK_WRITE_FILE
, strerror(errno
));
921 return ISCSI_ERR_IDBM
;
923 log_debug(2, "Waiting for discovery DB lock");
932 void idbm_unlock(void)
940 unlink(LOCK_WRITE_FILE
);
945 * If the portal is a file then we are doing the old style default
946 * session behavior (svn pre 780).
948 static FILE *idbm_open_rec_r(char *portal
, char *config
)
952 log_debug(5, "Looking for config file %s config %s.", portal
, config
);
954 if (stat(portal
, &statb
)) {
955 log_debug(5, "Could not stat %s err %d.", portal
, errno
);
959 if (S_ISDIR(statb
.st_mode
)) {
960 strlcat(portal
, "/", PATH_MAX
);
961 strlcat(portal
, config
, PATH_MAX
);
963 return fopen(portal
, "r");
966 static int __idbm_rec_read(node_rec_t
*out_rec
, char *conf
)
972 info
= idbm_recinfo_alloc(MAX_KEYS
);
974 return ISCSI_ERR_NOMEM
;
980 f
= fopen(conf
, "r");
982 log_debug(5, "Could not open %s err %s\n", conf
,
988 memset(out_rec
, 0, sizeof(*out_rec
));
989 idbm_node_setup_defaults(out_rec
);
990 idbm_recinfo_node(out_rec
, info
);
991 idbm_recinfo_config(info
, f
);
1002 idbm_rec_read(node_rec_t
*out_rec
, char *targetname
, int tpgt
,
1003 char *ip
, int port
, struct iface_rec
*iface
)
1009 portal
= calloc(1, PATH_MAX
);
1011 return ISCSI_ERR_IDBM
;
1013 /* try old style portal as config */
1014 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d", NODE_CONFIG_DIR
,
1015 targetname
, ip
, port
);
1016 log_debug(5, "rec read looking for config file %s.", portal
);
1017 if (!stat(portal
, &statb
))
1020 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR
,
1021 targetname
, ip
, port
, tpgt
, iface
->name
);
1022 log_debug(5, "rec read looking for config file %s.", portal
);
1023 if (!strlen(iface
->name
)) {
1024 rc
= ISCSI_ERR_INVAL
;
1028 if (stat(portal
, &statb
)) {
1029 log_debug(5, "Could not stat %s: %s.", portal
, strerror(errno
));
1031 return ISCSI_ERR_IDBM
;
1035 rc
= __idbm_rec_read(out_rec
, portal
);
1041 static int print_discovered_flat(void *data
, node_rec_t
*rec
)
1043 struct discovery_rec
*drec
= data
;
1045 if (rec
->disc_type
!= drec
->type
)
1048 if (drec
->type
== DISCOVERY_TYPE_SENDTARGETS
||
1049 drec
->type
== DISCOVERY_TYPE_ISNS
) {
1050 if (rec
->disc_port
!= drec
->port
||
1051 strcmp(rec
->disc_address
, drec
->address
))
1055 idbm_print_node_flat(NULL
, rec
);
1061 struct discovered_tree_info
{
1062 struct discovery_rec
*drec
;
1063 struct node_rec
*last_rec
;
1066 static int print_discovered_tree(void *data
, node_rec_t
*rec
)
1068 struct discovered_tree_info
*tree_info
= data
;
1069 struct discovery_rec
*drec
= tree_info
->drec
;
1071 if (rec
->disc_type
!= drec
->type
)
1074 if (strlen(drec
->address
)) {
1075 if (rec
->disc_port
!= drec
->port
||
1076 strcmp(rec
->disc_address
, drec
->address
))
1080 idbm_print_node_and_iface_tree(tree_info
->last_rec
, rec
);
1086 static int idbm_print_discovered(discovery_rec_t
*drec
, int info_level
)
1091 idbm_for_each_rec(&num_found
, drec
, print_discovered_flat
);
1093 struct discovered_tree_info tree_info
;
1094 struct node_rec last_rec
;
1096 memset(&last_rec
, 0, sizeof(struct node_rec
));
1098 tree_info
.drec
= drec
;
1099 tree_info
.last_rec
= &last_rec
;
1101 idbm_for_each_rec(&num_found
, &tree_info
, print_discovered_tree
);
1106 static int idbm_for_each_drec(int type
, char *config_root
, void *data
,
1107 idbm_drec_op_fn
*fn
)
1110 struct dirent
*entity_dent
;
1112 discovery_rec_t drec
;
1115 entity_dirfd
= opendir(config_root
);
1119 while ((entity_dent
= readdir(entity_dirfd
))) {
1120 if (!strcmp(entity_dent
->d_name
, ".") ||
1121 !strcmp(entity_dent
->d_name
, ".."))
1124 log_debug(5, "found %s\n", entity_dent
->d_name
);
1126 tmp_port
= strchr(entity_dent
->d_name
, ',');
1130 * pre 872 tools dumped the target portal symlinks in the isns
1131 * dir instead of the server. If we find one of those links
1132 * (by checking if there is a valid port) we skip it.
1134 if (strchr(tmp_port
, ':') || strchr(tmp_port
, '.'))
1138 memset(&drec
, 0, sizeof(drec
));
1139 if (idbm_discovery_read(&drec
, type
, entity_dent
->d_name
,
1141 log_error("Could not read discovery record for "
1142 "%s:%s.", entity_dent
->d_name
, tmp_port
);
1146 if (!fn(data
, &drec
))
1149 closedir(entity_dirfd
);
1153 int idbm_for_each_st_drec(void *data
, idbm_drec_op_fn
*fn
)
1155 return idbm_for_each_drec(DISCOVERY_TYPE_SENDTARGETS
, ST_CONFIG_DIR
,
1159 int idbm_for_each_isns_drec(void *data
, idbm_drec_op_fn
*fn
)
1161 return idbm_for_each_drec(DISCOVERY_TYPE_ISNS
, ISNS_CONFIG_DIR
,
1165 static int __idbm_print_all_by_drec(void *data
, struct discovery_rec
*drec
)
1167 int info_level
= *(int *)data
;
1169 if (info_level
>= 1) {
1170 printf("DiscoveryAddress: %s,%d\n",
1171 drec
->address
, drec
->port
);
1172 idbm_print_discovered(drec
, info_level
);
1174 printf("%s:%d via %s\n", drec
->address
, drec
->port
,
1175 drec
->type
== DISCOVERY_TYPE_ISNS
?
1176 "isns" : "sendtargets");
1180 static int idbm_print_all_st(int info_level
)
1184 rc
= idbm_for_each_st_drec(&info_level
, __idbm_print_all_by_drec
);
1190 static int idbm_print_all_isns(int info_level
)
1194 rc
= idbm_for_each_isns_drec(&info_level
, __idbm_print_all_by_drec
);
1200 int idbm_print_all_discovery(int info_level
)
1202 discovery_rec_t
*drec
;
1205 if (info_level
< 1) {
1206 found
= idbm_print_all_st(info_level
);
1207 found
+= idbm_print_all_isns(info_level
);
1211 drec
= calloc(1, sizeof(*drec
));
1216 printf("SENDTARGETS:\n");
1217 tmp
= idbm_print_all_st(info_level
);
1219 printf("No targets found.\n");
1224 tmp
= idbm_print_all_isns(info_level
);
1227 * pre 872 tools did not store the server ip,port so
1228 * we drop down here, to just look for target portals.
1230 drec
->type
= DISCOVERY_TYPE_ISNS
;
1231 tmp
= idbm_print_discovered(drec
, info_level
);
1233 printf("No targets found.\n");
1238 printf("STATIC:\n");
1239 drec
->type
= DISCOVERY_TYPE_STATIC
;
1240 tmp
= idbm_print_discovered(drec
, info_level
);
1242 printf("No targets found.\n");
1246 printf("FIRMWARE:\n");
1247 drec
->type
= DISCOVERY_TYPE_FW
;
1248 tmp
= idbm_print_discovered(drec
, info_level
);
1250 printf("No targets found.\n");
1258 * idbm_for_each_iface - iterate over bound iface recs
1259 * @found: nr of recs found so far
1260 * @data: data pointer passed to fn
1261 * @fn: iterator function ran over each bound iface rec
1262 * @targetname: rec's target name
1263 * @tpgt: rec's portal group tag
1264 * @ip: rec's ip address
1267 * This will run fn over all recs with the {targetname,tpgt,ip,port}
1268 * id. It does not iterate over the ifaces setup in /etc/iscsi/ifaces.
1270 * fn should return -1 if it skipped the rec, a ISCSI_ERR error code if
1271 * the operation failed or 0 if fn was run successfully.
1273 static int idbm_for_each_iface(int *found
, void *data
,
1274 idbm_iface_op_fn
*fn
,
1275 char *targetname
, int tpgt
, char *ip
, int port
)
1278 struct dirent
*iface_dent
;
1284 portal
= calloc(1, PATH_MAX
);
1286 return ISCSI_ERR_NOMEM
;
1291 /* old style portal as a config */
1292 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d", NODE_CONFIG_DIR
, targetname
,
1294 if (stat(portal
, &statb
)) {
1295 log_error("iface iter could not stat %s.", portal
);
1296 rc
= ISCSI_ERR_IDBM
;
1300 rc
= __idbm_rec_read(&rec
, portal
);
1304 rc
= fn(data
, &rec
);
1312 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR
,
1313 targetname
, ip
, port
, tpgt
);
1315 iface_dirfd
= opendir(portal
);
1317 log_error("iface iter could not read dir %s.", portal
);
1318 rc
= ISCSI_ERR_IDBM
;
1322 while ((iface_dent
= readdir(iface_dirfd
))) {
1325 if (!strcmp(iface_dent
->d_name
, ".") ||
1326 !strcmp(iface_dent
->d_name
, ".."))
1329 log_debug(5, "iface iter found %s.", iface_dent
->d_name
);
1330 memset(portal
, 0, PATH_MAX
);
1331 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR
,
1332 targetname
, ip
, port
, tpgt
, iface_dent
->d_name
);
1333 if (__idbm_rec_read(&rec
, portal
))
1336 curr_rc
= fn(data
, &rec
);
1337 /* less than zero means it was not a match */
1338 if (curr_rc
> 0 && !rc
)
1340 else if (curr_rc
== 0)
1344 closedir(iface_dirfd
);
1352 * The portal could be a file or dir with interfaces
1354 int idbm_for_each_portal(int *found
, void *data
, idbm_portal_op_fn
*fn
,
1358 struct dirent
*portal_dent
;
1362 portal
= calloc(1, PATH_MAX
);
1364 return ISCSI_ERR_NOMEM
;
1366 snprintf(portal
, PATH_MAX
, "%s/%s", NODE_CONFIG_DIR
, targetname
);
1367 portal_dirfd
= opendir(portal
);
1368 if (!portal_dirfd
) {
1369 rc
= ISCSI_ERR_IDBM
;
1373 while ((portal_dent
= readdir(portal_dirfd
))) {
1374 char *tmp_port
, *tmp_tpgt
;
1377 if (!strcmp(portal_dent
->d_name
, ".") ||
1378 !strcmp(portal_dent
->d_name
, ".."))
1381 log_debug(5, "found %s\n", portal_dent
->d_name
);
1382 tmp_port
= strchr(portal_dent
->d_name
, ',');
1386 tmp_tpgt
= strchr(tmp_port
, ',');
1390 curr_rc
= fn(found
, data
, targetname
,
1391 tmp_tpgt
? atoi(tmp_tpgt
) : -1,
1392 portal_dent
->d_name
, atoi(tmp_port
));
1393 /* less than zero means it was not a match */
1394 if (curr_rc
> 0 && !rc
)
1397 closedir(portal_dirfd
);
1403 int idbm_for_each_node(int *found
, void *data
, idbm_node_op_fn
*fn
)
1406 struct dirent
*node_dent
;
1411 node_dirfd
= opendir(NODE_CONFIG_DIR
);
1413 /* on start up node dir may not be created */
1416 while ((node_dent
= readdir(node_dirfd
))) {
1419 if (!strcmp(node_dent
->d_name
, ".") ||
1420 !strcmp(node_dent
->d_name
, ".."))
1423 log_debug(5, "searching %s\n", node_dent
->d_name
);
1424 curr_rc
= fn(found
, data
, node_dent
->d_name
);
1425 /* less than zero means it was not a match */
1426 if (curr_rc
> 0 && !rc
)
1430 closedir(node_dirfd
);
1434 static int iface_fn(void *data
, node_rec_t
*rec
)
1436 struct rec_op_data
*op_data
= data
;
1438 return op_data
->fn(op_data
->data
, rec
);
1441 static int portal_fn(int *found
, void *data
, char *targetname
,
1442 int tpgt
, char *ip
, int port
)
1444 return idbm_for_each_iface(found
, data
, iface_fn
, targetname
,
1448 static int node_fn(int *found
, void *data
, char *targetname
)
1450 return idbm_for_each_portal(found
, data
, portal_fn
, targetname
);
1453 int idbm_for_each_rec(int *found
, void *data
, idbm_iface_op_fn
*fn
)
1455 struct rec_op_data op_data
;
1457 memset(&op_data
, 0, sizeof(struct rec_op_data
));
1458 op_data
.data
= data
;
1461 return idbm_for_each_node(found
, &op_data
, node_fn
);
1467 } disc_type_to_config_vals
[] = {
1468 { ST_CONFIG_DIR
, ST_CONFIG_NAME
},
1469 { ISNS_CONFIG_DIR
, ISNS_CONFIG_NAME
},
1473 idbm_discovery_read(discovery_rec_t
*out_rec
, int drec_type
,
1474 char *addr
, int port
)
1482 return ISCSI_ERR_INVAL
;
1484 memset(out_rec
, 0, sizeof(discovery_rec_t
));
1486 info
= idbm_recinfo_alloc(MAX_KEYS
);
1488 return ISCSI_ERR_NOMEM
;
1490 portal
= malloc(PATH_MAX
);
1492 rc
= ISCSI_ERR_NOMEM
;
1496 snprintf(portal
, PATH_MAX
, "%s/%s,%d",
1497 disc_type_to_config_vals
[drec_type
].config_root
,
1499 log_debug(5, "Looking for config file %s\n", portal
);
1505 f
= idbm_open_rec_r(portal
,
1506 disc_type_to_config_vals
[drec_type
].config_name
);
1508 log_debug(1, "Could not open %s: %s\n", portal
,
1510 rc
= ISCSI_ERR_IDBM
;
1514 idbm_discovery_setup_defaults(out_rec
, drec_type
);
1515 idbm_recinfo_discovery(out_rec
, info
);
1516 idbm_recinfo_config(info
, f
);
1529 * If the portal is a file then we are doing the old style default
1530 * session behavior (svn pre 780).
1532 static FILE *idbm_open_rec_w(char *portal
, char *config
)
1538 log_debug(5, "Looking for config file %s\n", portal
);
1540 err
= stat(portal
, &statb
);
1544 if (!S_ISDIR(statb
.st_mode
)) {
1546 * Old style portal as a file. Let's update it.
1548 if (unlink(portal
)) {
1549 log_error("Could not convert %s to %s/%s. "
1550 "err %d\n", portal
, portal
,
1556 if (mkdir(portal
, 0660) != 0) {
1557 log_error("Could not make dir %s err %d\n",
1563 strlcat(portal
, "/", PATH_MAX
);
1564 strlcat(portal
, config
, PATH_MAX
);
1565 f
= fopen(portal
, "w");
1567 log_error("Could not open %s err %d\n", portal
, errno
);
1571 static int idbm_rec_write(node_rec_t
*rec
)
1578 portal
= malloc(PATH_MAX
);
1580 log_error("Could not alloc portal\n");
1581 return ISCSI_ERR_NOMEM
;
1584 snprintf(portal
, PATH_MAX
, "%s", NODE_CONFIG_DIR
);
1585 if (access(portal
, F_OK
) != 0) {
1586 if (mkdir(portal
, 0660) != 0) {
1587 log_error("Could not make %s: %s\n", portal
,
1589 rc
= ISCSI_ERR_IDBM
;
1594 snprintf(portal
, PATH_MAX
, "%s/%s", NODE_CONFIG_DIR
, rec
->name
);
1595 if (access(portal
, F_OK
) != 0) {
1596 if (mkdir(portal
, 0660) != 0) {
1597 log_error("Could not make %s: %s\n", portal
,
1599 rc
= ISCSI_ERR_IDBM
;
1604 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d", NODE_CONFIG_DIR
,
1605 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
);
1606 log_debug(5, "Looking for config file %s", portal
);
1612 rc
= stat(portal
, &statb
);
1616 * older iscsiadm versions had you create the config then set
1617 * set the tgpt. In new versions you must pass all the info in
1620 if (rec
->tpgt
== PORTAL_GROUP_TAG_UNKNOWN
)
1621 /* drop down to old style portal as config */
1627 if (!S_ISDIR(statb
.st_mode
)) {
1629 * older iscsiadm versions had you create the config then set
1630 * set the tgpt. In new versions you must pass all the info in
1633 if (rec
->tpgt
== PORTAL_GROUP_TAG_UNKNOWN
)
1634 /* drop down to old style portal as config */
1637 * Old style portal as a file, but with tpgt. Let's update it.
1639 if (unlink(portal
)) {
1640 log_error("Could not convert %s: %s\n", portal
,
1642 rc
= ISCSI_ERR_IDBM
;
1646 rc
= ISCSI_ERR_INVAL
;
1651 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR
,
1652 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
);
1653 if (stat(portal
, &statb
)) {
1654 if (mkdir(portal
, 0660) != 0) {
1655 log_error("Could not make dir %s: %s\n",
1656 portal
, strerror(errno
));
1657 rc
= ISCSI_ERR_IDBM
;
1662 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR
,
1663 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
,
1666 f
= fopen(portal
, "w");
1668 log_error("Could not open %s: %sd\n", portal
, strerror(errno
));
1669 rc
= ISCSI_ERR_IDBM
;
1673 idbm_print(IDBM_PRINT_TYPE_NODE
, rec
, 1, f
);
1683 idbm_discovery_write(discovery_rec_t
*rec
)
1690 return ISCSI_ERR_INVAL
;
1692 portal
= malloc(PATH_MAX
);
1694 log_error("Could not alloc portal\n");
1695 return ISCSI_ERR_NOMEM
;
1702 snprintf(portal
, PATH_MAX
, "%s",
1703 disc_type_to_config_vals
[rec
->type
].config_root
);
1704 if (access(portal
, F_OK
) != 0) {
1705 if (mkdir(portal
, 0660) != 0) {
1706 log_error("Could not make %s: %s\n", portal
,
1708 rc
= ISCSI_ERR_IDBM
;
1713 snprintf(portal
, PATH_MAX
, "%s/%s,%d",
1714 disc_type_to_config_vals
[rec
->type
].config_root
,
1715 rec
->address
, rec
->port
);
1717 f
= idbm_open_rec_w(portal
,
1718 disc_type_to_config_vals
[rec
->type
].config_name
);
1720 log_error("Could not open %s: %s\n", portal
, strerror(errno
));
1721 rc
= ISCSI_ERR_IDBM
;
1725 idbm_print(IDBM_PRINT_TYPE_DISCOVERY
, rec
, 1, f
);
1734 int idbm_add_discovery(discovery_rec_t
*newrec
)
1736 discovery_rec_t rec
;
1738 if (!idbm_discovery_read(&rec
, newrec
->type
, newrec
->address
,
1740 log_debug(7, "disc rec already exists");
1743 log_debug(7, "adding new DB record");
1745 return idbm_discovery_write(newrec
);
1748 static int setup_disc_to_node_link(char *disc_portal
, node_rec_t
*rec
)
1753 switch (rec
->disc_type
) {
1754 case DISCOVERY_TYPE_SENDTARGETS
:
1755 /* st dir setup when we create its discovery node */
1756 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%d/%s,%s,%d,%d,%s",
1758 rec
->disc_address
, rec
->disc_port
, rec
->name
,
1759 rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
,
1762 case DISCOVERY_TYPE_FW
:
1763 if (access(FW_CONFIG_DIR
, F_OK
) != 0) {
1764 if (mkdir(FW_CONFIG_DIR
, 0660) != 0) {
1765 log_error("Could not make %s: %s",
1766 FW_CONFIG_DIR
, strerror(errno
));
1767 rc
= ISCSI_ERR_IDBM
;
1771 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%s,%d,%d,%s",
1772 FW_CONFIG_DIR
, rec
->name
,
1773 rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
,
1776 case DISCOVERY_TYPE_STATIC
:
1777 if (access(STATIC_CONFIG_DIR
, F_OK
) != 0) {
1778 if (mkdir(STATIC_CONFIG_DIR
, 0660) != 0) {
1779 log_error("Could not make %s; %s",
1780 STATIC_CONFIG_DIR
, strerror(errno
));
1781 rc
= ISCSI_ERR_IDBM
;
1785 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%s,%d,%d,%s",
1786 STATIC_CONFIG_DIR
, rec
->name
,
1787 rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
,
1790 case DISCOVERY_TYPE_ISNS
:
1791 if (access(ISNS_CONFIG_DIR
, F_OK
) != 0) {
1792 if (mkdir(ISNS_CONFIG_DIR
, 0660) != 0) {
1793 log_error("Could not make %s: %s",
1794 ISNS_CONFIG_DIR
, strerror(errno
));
1795 rc
= ISCSI_ERR_IDBM
;
1800 * Older tools lumped all portals together in the
1801 * isns config dir. In 2.0-872, the isns dir added
1802 * a isns server (ddress and port) dir like sendtargets.
1804 * If we found a older style link we return that so it
1805 * can be removed. If this function is called for
1806 * addition of a rec then the older link should have been
1807 * removed and we break down below.
1809 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%s,%d,%d,%s",
1811 rec
->name
, rec
->conn
[0].address
,
1812 rec
->conn
[0].port
, rec
->tpgt
, rec
->iface
.name
);
1813 if (!stat(disc_portal
, &statb
)) {
1814 log_debug(7, "using old style isns dir %s.",
1819 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%d",
1820 ISNS_CONFIG_DIR
, rec
->disc_address
, rec
->disc_port
);
1821 if (!stat(disc_portal
, &statb
) && S_ISDIR(statb
.st_mode
)) {
1823 * if there is a dir for this isns server then
1824 * assume we are using the new style links
1826 snprintf(disc_portal
, PATH_MAX
,
1827 "%s/%s,%d/%s,%s,%d,%d,%s",
1828 ISNS_CONFIG_DIR
, rec
->disc_address
,
1829 rec
->disc_port
, rec
->name
,
1830 rec
->conn
[0].address
, rec
->conn
[0].port
,
1831 rec
->tpgt
, rec
->iface
.name
);
1835 /* adding a older link */
1836 snprintf(disc_portal
, PATH_MAX
, "%s/%s,%s,%d,%d,%s",
1837 ISNS_CONFIG_DIR
, rec
->name
, rec
->conn
[0].address
,
1838 rec
->conn
[0].port
, rec
->tpgt
, rec
->iface
.name
);
1840 case DISCOVERY_TYPE_SLP
:
1842 rc
= ISCSI_ERR_INVAL
;
1848 int idbm_add_node(node_rec_t
*newrec
, discovery_rec_t
*drec
, int overwrite
)
1851 char *node_portal
, *disc_portal
;
1854 if (!idbm_rec_read(&rec
, newrec
->name
, newrec
->tpgt
,
1855 newrec
->conn
[0].address
, newrec
->conn
[0].port
,
1860 rc
= idbm_delete_node(&rec
);
1863 log_debug(7, "overwriting existing record");
1865 log_debug(7, "adding new DB record");
1868 newrec
->disc_type
= drec
->type
;
1869 newrec
->disc_port
= drec
->port
;
1870 strcpy(newrec
->disc_address
, drec
->address
);
1873 rc
= idbm_rec_write(newrec
);
1875 * if a old app passed in a bogus tpgt then we do not create links
1876 * since it will set a different tpgt in another iscsiadm call
1878 if (rc
|| !drec
|| newrec
->tpgt
== PORTAL_GROUP_TAG_UNKNOWN
)
1881 node_portal
= calloc(2, PATH_MAX
);
1883 return ISCSI_ERR_NOMEM
;
1885 disc_portal
= node_portal
+ PATH_MAX
;
1886 snprintf(node_portal
, PATH_MAX
, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR
,
1887 newrec
->name
, newrec
->conn
[0].address
, newrec
->conn
[0].port
,
1889 rc
= setup_disc_to_node_link(disc_portal
, newrec
);
1893 log_debug(7, "node addition making link from %s to %s", node_portal
,
1900 if (symlink(node_portal
, disc_portal
)) {
1901 if (errno
== EEXIST
)
1902 log_debug(7, "link from %s to %s exists", node_portal
,
1905 rc
= ISCSI_ERR_IDBM
;
1906 log_error("Could not make link from disc source %s to "
1907 "node %s: %s", disc_portal
, node_portal
,
1917 static int idbm_bind_iface_to_nodes(idbm_disc_nodes_fn
*disc_node_fn
,
1918 void *data
, struct iface_rec
*iface
,
1919 struct list_head
*bound_recs
)
1921 struct node_rec
*rec
, *tmp
;
1922 struct list_head new_recs
;
1925 INIT_LIST_HEAD(&new_recs
);
1926 rc
= disc_node_fn(data
, iface
, &new_recs
);
1930 list_for_each_entry_safe(rec
, tmp
, &new_recs
, list
) {
1931 list_del_init(&rec
->list
);
1932 list_add_tail(&rec
->list
, bound_recs
);
1933 iface_copy(&rec
->iface
, iface
);
1939 discovery_error_fatal(int err
)
1944 /* Transport errors or timeouts are not fatal */
1945 case ISCSI_ERR_TRANS
:
1946 case ISCSI_ERR_TRANS_TIMEOUT
:
1952 int idbm_bind_ifaces_to_nodes(idbm_disc_nodes_fn
*disc_node_fn
,
1953 void *data
, struct list_head
*ifaces
,
1954 struct list_head
*bound_recs
)
1956 struct list_head def_ifaces
;
1957 struct node_rec
*rec
, *tmp_rec
;
1958 struct iface_rec
*iface
, *tmp_iface
;
1959 struct iscsi_transport
*t
;
1960 int rc
= 0, found
= 0;
1962 INIT_LIST_HEAD(&def_ifaces
);
1964 if (!ifaces
|| list_empty(ifaces
)) {
1965 iface_link_ifaces(&def_ifaces
);
1967 list_for_each_entry_safe(iface
, tmp_iface
, &def_ifaces
, list
) {
1968 list_del(&iface
->list
);
1969 t
= iscsi_sysfs_get_transport_by_name(iface
->transport_name
);
1971 * only auto bind to software iscsi if it is
1972 * not the default iface (that is handled below)
1974 if (!t
|| strcmp(t
->name
, DEFAULT_TRANSPORT
) ||
1975 !strcmp(iface
->name
, DEFAULT_IFACENAME
)) {
1980 rc
= idbm_bind_iface_to_nodes(disc_node_fn
, data
, iface
,
1983 if (discovery_error_fatal(rc
))
1988 /* create default iface with old/default behavior */
1990 struct iface_rec def_iface
;
1992 memset(&def_iface
, 0, sizeof(struct iface_rec
));
1993 iface_setup_defaults(&def_iface
);
1994 return idbm_bind_iface_to_nodes(disc_node_fn
, data
,
1995 &def_iface
, bound_recs
);
1998 list_for_each_entry(iface
, ifaces
, list
) {
1999 if (strcmp(iface
->name
, DEFAULT_IFACENAME
) &&
2000 !iface_is_valid(iface
)) {
2001 log_error("iface %s is not valid. Will not "
2002 "bind node to it. Iface settings "
2003 iface_fmt
, iface
->name
,
2008 rc
= idbm_bind_iface_to_nodes(disc_node_fn
, data
, iface
,
2010 if (discovery_error_fatal(rc
))
2017 list_for_each_entry_safe(iface
, tmp_iface
, &def_ifaces
, list
) {
2018 list_del(&iface
->list
);
2022 list_for_each_entry_safe(rec
, tmp_rec
, bound_recs
, list
) {
2023 list_del(&rec
->list
);
2029 static void idbm_rm_disc_node_links(char *disc_dir
)
2031 char *target
= NULL
, *tpgt
= NULL
, *port
= NULL
;
2032 char *address
= NULL
, *iface_id
= NULL
;
2034 struct dirent
*disc_dent
;
2037 rec
= calloc(1, sizeof(*rec
));
2041 disc_dirfd
= opendir(disc_dir
);
2045 /* rm links to nodes */
2046 while ((disc_dent
= readdir(disc_dirfd
))) {
2047 if (!strcmp(disc_dent
->d_name
, ".") ||
2048 !strcmp(disc_dent
->d_name
, ".."))
2052 if (get_params_from_disc_link(disc_dent
->d_name
, &target
, &tpgt
,
2053 &address
, &port
, &iface_id
)) {
2054 log_error("Improperly formed disc to node link");
2058 log_debug(5, "disc removal removing link %s %s %s %s",
2059 target
, address
, port
, iface_id
);
2061 memset(rec
, 0, sizeof(*rec
));
2062 strlcpy(rec
->name
, target
, TARGET_NAME_MAXLEN
);
2063 rec
->tpgt
= atoi(tpgt
);
2064 rec
->conn
[0].port
= atoi(port
);
2065 strlcpy(rec
->conn
[0].address
, address
, NI_MAXHOST
);
2066 strlcpy(rec
->iface
.name
, iface_id
, ISCSI_MAX_IFACE_LEN
);
2068 if (idbm_delete_node(rec
))
2069 log_error("Could not delete node %s/%s/%s,%s/%s",
2070 NODE_CONFIG_DIR
, target
, address
, port
,
2074 closedir(disc_dirfd
);
2079 int idbm_delete_discovery(discovery_rec_t
*drec
)
2085 portal
= calloc(1, PATH_MAX
);
2087 return ISCSI_ERR_NOMEM
;
2089 snprintf(portal
, PATH_MAX
, "%s/%s,%d",
2090 disc_type_to_config_vals
[drec
->type
].config_root
,
2091 drec
->address
, drec
->port
);
2092 log_debug(5, "Removing config file %s\n", portal
);
2094 if (stat(portal
, &statb
)) {
2095 log_debug(5, "Could not stat %s to delete disc err %d\n",
2100 if (S_ISDIR(statb
.st_mode
)) {
2101 strlcat(portal
, "/", PATH_MAX
);
2103 disc_type_to_config_vals
[drec
->type
].config_name
,
2108 log_debug(5, "Could not remove %s err %d\n", portal
, errno
);
2110 memset(portal
, 0, PATH_MAX
);
2111 snprintf(portal
, PATH_MAX
, "%s/%s,%d",
2112 disc_type_to_config_vals
[drec
->type
].config_root
,
2113 drec
->address
, drec
->port
);
2114 idbm_rm_disc_node_links(portal
);
2117 if (S_ISDIR(statb
.st_mode
)) {
2118 memset(portal
, 0, PATH_MAX
);
2119 snprintf(portal
, PATH_MAX
, "%s/%s,%d",
2120 disc_type_to_config_vals
[drec
->type
].config_root
,
2121 drec
->address
, drec
->port
);
2131 * Backwards Compat or SLP:
2132 * if there is no link then this is pre svn 780 version where
2133 * we did not link the disc source and node
2135 static int idbm_remove_disc_to_node_link(node_rec_t
*rec
,
2142 tmprec
= malloc(sizeof(*tmprec
));
2144 return ISCSI_ERR_NOMEM
;
2146 memset(portal
, 0, PATH_MAX
);
2147 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR
,
2148 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
, rec
->tpgt
,
2151 rc
= __idbm_rec_read(tmprec
, portal
);
2153 /* old style recs will not have tpgt or a link so skip */
2158 log_debug(7, "found drec %s %d\n",
2159 tmprec
->disc_address
, tmprec
->disc_port
);
2160 /* rm link from discovery source to node */
2161 memset(portal
, 0, PATH_MAX
);
2162 rc
= setup_disc_to_node_link(portal
, tmprec
);
2170 if (!stat(portal
, &statb
)) {
2171 if (unlink(portal
)) {
2172 log_error("Could not remove link %s: %s\n",
2173 portal
, strerror(errno
));
2174 rc
= ISCSI_ERR_IDBM
;
2176 log_debug(7, "rmd %s", portal
);
2178 log_debug(7, "Could not stat %s", portal
);
2186 static int st_disc_filter(const struct dirent
*dir
)
2188 return strcmp(dir
->d_name
, ".") && strcmp(dir
->d_name
, "..") &&
2189 strcmp(dir
->d_name
, ST_CONFIG_NAME
);
2192 int idbm_delete_node(node_rec_t
*rec
)
2196 int rc
= 0, dir_rm_rc
= 0;
2198 portal
= calloc(1, PATH_MAX
);
2200 return ISCSI_ERR_NOMEM
;
2202 rc
= idbm_remove_disc_to_node_link(rec
, portal
);
2206 memset(portal
, 0, PATH_MAX
);
2207 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d", NODE_CONFIG_DIR
,
2208 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
);
2209 log_debug(5, "Removing config file %s iface id %s\n",
2210 portal
, rec
->iface
.name
);
2216 if (!stat(portal
, &statb
))
2219 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d/%s", NODE_CONFIG_DIR
,
2220 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
,
2221 rec
->tpgt
, rec
->iface
.name
);
2222 log_debug(5, "Removing config file %s", portal
);
2224 if (!stat(portal
, &statb
))
2227 log_error("Could not stat %s to delete node: %s\n",
2228 portal
, strerror(errno
));
2229 rc
= ISCSI_ERR_IDBM
;
2233 if (unlink(portal
)) {
2234 log_error("Could not remove %s: %s\n", portal
, strerror(errno
));
2235 rc
= ISCSI_ERR_IDBM
;
2239 memset(portal
, 0, PATH_MAX
);
2240 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR
,
2241 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
,
2243 if (!stat(portal
, &statb
)) {
2244 struct dirent
**namelist
;
2247 memset(portal
, 0, PATH_MAX
);
2248 snprintf(portal
, PATH_MAX
, "%s/%s/%s,%d,%d", NODE_CONFIG_DIR
,
2249 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
,
2251 n
= scandir(portal
, &namelist
, st_disc_filter
, alphasort
);
2255 dir_rm_rc
= rmdir(portal
);
2257 for (i
= 0; i
< n
; i
++)
2263 memset(portal
, 0, PATH_MAX
);
2264 snprintf(portal
, PATH_MAX
, "%s/%s", NODE_CONFIG_DIR
, rec
->name
);
2275 idbm_sendtargets_defaults(struct iscsi_sendtargets_config
*cfg
)
2278 memcpy(cfg
, &db
->drec_st
.u
.sendtargets
,
2279 sizeof(struct iscsi_sendtargets_config
));
2283 idbm_isns_defaults(struct iscsi_isns_config
*cfg
)
2286 memcpy(cfg
, &db
->drec_isns
.u
.isns
,
2287 sizeof(struct iscsi_isns_config
));
2291 idbm_slp_defaults(struct iscsi_slp_config
*cfg
)
2293 memcpy(cfg
, &db
->drec_slp
.u
.slp
,
2294 sizeof(struct iscsi_slp_config
));
2297 int idbm_node_set_param(void *data
, node_rec_t
*rec
)
2299 struct db_set_param
*param
= data
;
2303 info
= idbm_recinfo_alloc(MAX_KEYS
);
2305 return ISCSI_ERR_NOMEM
;
2307 idbm_recinfo_node(rec
, info
);
2309 rc
= idbm_verify_param(info
, param
->name
);
2313 rc
= idbm_rec_update_param(info
, param
->name
, param
->value
, 0);
2317 rc
= idbm_rec_write(rec
);
2326 int idbm_discovery_set_param(void *data
, discovery_rec_t
*rec
)
2328 struct db_set_param
*param
= data
;
2332 info
= idbm_recinfo_alloc(MAX_KEYS
);
2334 return ISCSI_ERR_NOMEM
;
2336 idbm_recinfo_discovery((discovery_rec_t
*)rec
, info
);
2338 rc
= idbm_verify_param(info
, param
->name
);
2342 rc
= idbm_rec_update_param(info
, param
->name
, param
->value
, 0);
2346 rc
= idbm_discovery_write((discovery_rec_t
*)rec
);
2355 int idbm_init(idbm_get_config_file_fn
*fn
)
2357 /* make sure root db dir is there */
2358 if (access(ISCSI_CONFIG_ROOT
, F_OK
) != 0) {
2359 if (mkdir(ISCSI_CONFIG_ROOT
, 0660) != 0) {
2360 log_error("Could not make %s %d\n", ISCSI_CONFIG_ROOT
,
2366 db
= malloc(sizeof(idbm_t
));
2368 log_error("out of memory on idbm allocation");
2369 return ISCSI_ERR_NOMEM
;
2371 memset(db
, 0, sizeof(idbm_t
));
2372 db
->get_config_file
= fn
;
2376 void idbm_terminate(void)
2383 * idbm_create_rec - allocate and setup a node record
2384 * @targetname: target name
2385 * @tgpt: target portal group
2386 * @ip: ip address of portal
2387 * @port: port of portal
2388 * @iface: iscsi iface info
2389 * @verbose: flag indicating whether to log ifaces setup errors
2391 * The iface only needs to have the name set. This function will
2392 * read in the other values.
2394 struct node_rec
*idbm_create_rec(char *targetname
, int tpgt
, char *ip
,
2395 int port
, struct iface_rec
*iface
,
2398 struct node_rec
*rec
;
2400 rec
= calloc(1, sizeof(*rec
));
2402 log_error("Could not not allocate memory to create node "
2407 idbm_node_setup_defaults(rec
);
2409 strlcpy(rec
->name
, targetname
, TARGET_NAME_MAXLEN
);
2411 rec
->conn
[0].port
= port
;
2413 strlcpy(rec
->conn
[0].address
, ip
, NI_MAXHOST
);
2414 memset(&rec
->iface
, 0, sizeof(struct iface_rec
));
2416 iface_copy(&rec
->iface
, iface
);
2417 if (strlen(iface
->name
)) {
2418 if (iface_conf_read(&rec
->iface
)) {
2420 log_error("Could not read iface info "
2421 "for %s.", iface
->name
);
2432 struct node_rec
*idbm_create_rec_from_boot_context(struct boot_context
*context
)
2434 struct node_rec
*rec
;
2436 /* tpgt hard coded to 1 ??? */
2437 rec
= idbm_create_rec(context
->targetname
, 1,
2438 context
->target_ipaddr
, context
->target_port
,
2441 log_error("Could not setup rec for fw discovery login.");
2445 iface_setup_defaults(&rec
->iface
);
2446 strlcpy(rec
->session
.auth
.username
, context
->chap_name
,
2447 sizeof(context
->chap_name
));
2448 strlcpy((char *)rec
->session
.auth
.password
, context
->chap_password
,
2449 sizeof(context
->chap_password
));
2450 strlcpy(rec
->session
.auth
.username_in
, context
->chap_name_in
,
2451 sizeof(context
->chap_name_in
));
2452 strlcpy((char *)rec
->session
.auth
.password_in
,
2453 context
->chap_password_in
,
2454 sizeof(context
->chap_password_in
));
2455 rec
->session
.auth
.password_length
=
2456 strlen((char *)context
->chap_password
);
2457 rec
->session
.auth
.password_in_length
=
2458 strlen((char *)context
->chap_password_in
);
2460 iface_setup_from_boot_context(&rec
->iface
, context
);
2465 void idbm_node_setup_defaults(node_rec_t
*rec
)
2469 memset(rec
, 0, sizeof(node_rec_t
));
2471 INIT_LIST_HEAD(&rec
->list
);
2473 rec
->tpgt
= PORTAL_GROUP_TAG_UNKNOWN
;
2474 rec
->disc_type
= DISCOVERY_TYPE_STATIC
;
2475 rec
->leading_login
= 0;
2476 rec
->session
.cmds_max
= CMDS_MAX
;
2477 rec
->session
.xmit_thread_priority
= XMIT_THREAD_PRIORITY
;
2478 rec
->session
.initial_cmdsn
= 0;
2479 rec
->session
.queue_depth
= QUEUE_DEPTH
;
2480 rec
->session
.nr_sessions
= 1;
2481 rec
->session
.initial_login_retry_max
= DEF_INITIAL_LOGIN_RETRIES_MAX
;
2482 rec
->session
.reopen_max
= 32;
2483 rec
->session
.auth
.authmethod
= 0;
2484 rec
->session
.auth
.password_length
= 0;
2485 rec
->session
.auth
.password_in_length
= 0;
2486 rec
->session
.err_timeo
.abort_timeout
= DEF_ABORT_TIMEO
;
2487 rec
->session
.err_timeo
.lu_reset_timeout
= DEF_LU_RESET_TIMEO
;
2488 rec
->session
.err_timeo
.tgt_reset_timeout
= DEF_TGT_RESET_TIMEO
;
2489 rec
->session
.err_timeo
.host_reset_timeout
= DEF_HOST_RESET_TIMEO
;
2490 rec
->session
.timeo
.replacement_timeout
= DEF_REPLACEMENT_TIMEO
;
2491 rec
->session
.info
= NULL
;
2492 rec
->session
.sid
= 0;
2493 rec
->session
.multiple
= 0;
2494 idbm_setup_session_defaults(&rec
->session
.iscsi
);
2496 for (i
=0; i
<ISCSI_CONN_MAX
; i
++) {
2497 rec
->conn
[i
].startup
= ISCSI_STARTUP_MANUAL
;
2498 rec
->conn
[i
].port
= ISCSI_LISTEN_PORT
;
2499 rec
->conn
[i
].tcp
.window_size
= TCP_WINDOW_SIZE
;
2500 rec
->conn
[i
].tcp
.type_of_service
= 0;
2501 rec
->conn
[i
].timeo
.login_timeout
= DEF_LOGIN_TIMEO
;
2502 rec
->conn
[i
].timeo
.logout_timeout
= DEF_LOGOUT_TIMEO
;
2503 rec
->conn
[i
].timeo
.auth_timeout
= 45;
2505 rec
->conn
[i
].timeo
.noop_out_interval
= DEF_NOOP_OUT_INTERVAL
;
2506 rec
->conn
[i
].timeo
.noop_out_timeout
= DEF_NOOP_OUT_TIMEO
;
2508 idbm_setup_conn_defaults(&rec
->conn
[i
].iscsi
);
2511 iface_setup_defaults(&rec
->iface
);
2515 idbm_find_rec_in_list(struct list_head
*rec_list
, char *targetname
, char *addr
,
2516 int port
, struct iface_rec
*iface
)
2518 struct node_rec
*rec
;
2520 list_for_each_entry(rec
, rec_list
, list
) {
2521 if (__iscsi_match_session(rec
, targetname
, addr
, port
, iface
,