Mercurial > illumos > onarm
annotate usr/src/cmd/iscsi/iscsitgtd/isns_client.c @ 13:f60a82e85167 default tip
Revert NEC's changes to fix krb5 build
author | Andrew Stormont <andyjstormont@gmail.com> |
---|---|
date | Fri, 02 Mar 2012 22:25:26 +0000 |
parents | 1a15d5aaf794 |
children |
rev | line source |
---|---|
0 | 1 /* |
2 * CDDL HEADER START | |
3 * | |
4 * The contents of this file are subject to the terms of the | |
5 * Common Development and Distribution License (the "License"). | |
6 * You may not use this file except in compliance with the License. | |
7 * | |
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
9 * or http://www.opensolaris.org/os/licensing. | |
10 * See the License for the specific language governing permissions | |
11 * and limitations under the License. | |
12 * | |
13 * When distributing Covered Code, include this CDDL HEADER in each | |
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
15 * If applicable, add the following below this CDDL HEADER, with the | |
16 * fields enclosed by brackets "[]" replaced with your own identifying | |
17 * information: Portions Copyright [yyyy] [name of copyright owner] | |
18 * | |
19 * CDDL HEADER END | |
20 */ | |
21 | |
22 /* | |
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. | |
24 * Use is subject to license terms. | |
25 */ | |
26 | |
4
1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
Koji Uno <koji.uno@sun.com>
parents:
0
diff
changeset
|
27 #pragma ident "%Z%%M% %I% %E% SMI" |
0 | 28 |
29 #include <stdio.h> | |
30 #include <unistd.h> | |
31 #include <stdlib.h> | |
32 #include <strings.h> | |
33 #include <syslog.h> | |
34 #include <netdb.h> | |
35 #include <pthread.h> | |
36 #include <signal.h> | |
37 #include <errno.h> | |
38 #include <netinet/in.h> | |
39 #include <sys/types.h> | |
40 #include <sys/socket.h> | |
41 #include <arpa/inet.h> | |
42 | |
43 #include <iscsitgt_impl.h> | |
44 | |
45 #include "isns_protocol.h" | |
46 #include "isns_client.h" | |
47 #include "target.h" | |
48 #include "queue.h" | |
49 | |
50 | |
51 typedef struct { | |
52 uint32_t pf_family; | |
53 uint32_t ip_len; | |
54 uint32_t ai_addrlen; | |
55 union { | |
56 in_addr_t in; | |
57 in6_addr_t in6; | |
58 } ip_adr; | |
59 } ip_t; | |
60 | |
61 #define ISNS_TGT_LOGOUT 54321 | |
62 | |
63 extern target_queue_t *mgmtq; | |
64 | |
65 /* | |
66 * Global | |
67 * Parameters for ESI/SCN processing. | |
68 * scn_port: ESI/SCN port to receive ISNS_ESI & ISNS_SCN messages | |
69 * isns_args: | |
70 * eid_ip: Entity IP info | |
71 */ | |
72 static int scn_port = 0; | |
73 static esi_scn_arg_t isns_args; | |
74 static ip_t eid_ip; | |
75 static int num_reg = 0; | |
76 static pthread_t scn_tid = 0; | |
77 static Boolean_t isns_shutdown = False; | |
78 | |
79 Boolean_t isns_initialized = False; | |
80 sema_t isns_sema; | |
81 target_queue_t *mgmtq = NULL; | |
82 | |
83 static int get_ip_addr(char *node, ip_t *sa); | |
84 static int isns_op_all(uint16_t); | |
85 static int append_tpgt(tgt_node_t *, isns_pdu_t *); | |
86 static void process_esi(int, isns_pdu_t *); | |
87 static void process_scn(int, isns_pdu_t *); | |
88 static void *esi_scn_thr(void *); | |
89 static int process_rsp(isns_pdu_t *, isns_rsp_t *); | |
90 static int isns_dev_attr_reg(int, tgt_node_t *, char *, char *); | |
91 static int isns_dev_attr_dereg(int, char *); | |
92 static int isns_scn_reg(int, char *); | |
93 static int isns_scn_dereg(int so, char *node); | |
94 static tgt_node_t *find_tgt_by_name(char *, char **); | |
95 static tgt_node_t *find_next_tgt(tgt_node_t *, char **); | |
96 | |
97 /* | |
98 * find_tgt_by_name searches DB by iscsi name or local name, if found | |
99 * returns tgt_node_t. iname needs to be free by caller. | |
100 */ | |
101 static tgt_node_t * | |
102 find_tgt_by_name(char *targ, char **iname) | |
103 { | |
104 tgt_node_t *tgt = NULL; | |
105 | |
106 while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) | |
107 != NULL) { | |
108 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) | |
109 == FALSE) { | |
110 syslog(LOG_ALERT, "ISNS: Missing iscsi name\n"); | |
111 break; | |
112 } | |
113 /* match either iscsi name or local name */ | |
114 if (strcmp(targ, tgt->x_value) == 0 || | |
115 strcmp(targ, *iname) == 0) { | |
116 return (tgt); | |
117 } | |
118 free(*iname); | |
119 } | |
120 return (NULL); | |
121 } | |
122 | |
123 static tgt_node_t * | |
124 find_next_tgt(tgt_node_t *tgt, char **iname) | |
125 { | |
126 while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) | |
127 != NULL) { | |
128 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, iname) | |
129 == FALSE) { | |
130 continue; | |
131 } | |
132 return (tgt); | |
133 } | |
134 return (NULL); | |
135 } | |
136 | |
137 /* | |
138 * Find ip-addr associated with TPGT, don't send if no ip-addr is | |
139 * found for a TPGT | |
140 */ | |
141 static int | |
142 append_tpgt(tgt_node_t *tgt, isns_pdu_t *cmd) | |
143 { | |
144 tgt_node_t *t, *x; | |
145 tgt_node_t *pgt = NULL; | |
146 tgt_node_t *ip = NULL; | |
147 tgt_node_t *tpgt = NULL; | |
148 ip_t eid; | |
149 | |
150 /* Always add the default TPGT (1) */ | |
151 isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, ISNS_PG_TAG_SZ, NULL, 1); | |
152 if (isns_append_attr(cmd, ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, | |
153 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, | |
154 eid_ip.ip_len) != 0) { | |
155 return (-1); | |
156 } | |
157 if (isns_append_attr(cmd, ISNS_PG_PORTAL_PORT_ATTR_ID, | |
158 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { | |
159 return (-1); | |
160 } | |
161 | |
162 /* Get the remainning TPGT-LIST */ | |
163 if ((t = tgt_node_next(tgt, XML_ELEMENT_TPGTLIST, NULL)) | |
164 != NULL) { | |
165 /* find tgpt from tpgt-list */ | |
166 while ((pgt = tgt_node_next(t, XML_ELEMENT_TPGT, pgt)) | |
167 != NULL) { | |
168 /* update isns only if TPGT contains ip_addr */ | |
169 while ((tpgt = tgt_node_next(main_config, | |
170 XML_ELEMENT_TPGT, tpgt)) != NULL) { | |
171 if (strcmp(pgt->x_value, tpgt->x_value) != 0) | |
172 continue; | |
173 if ((ip = tgt_node_next(tpgt, | |
174 XML_ELEMENT_IPADDR, NULL)) != NULL) | |
175 break; | |
176 } | |
177 if (tpgt == NULL || ip == NULL) | |
178 continue; | |
179 if (isns_append_attr(cmd, ISNS_PG_TAG_ATTR_ID, | |
180 ISNS_PG_TAG_SZ, NULL, | |
181 strtol(pgt->x_value, NULL, 0)) != 0) { | |
182 return (-1); | |
183 } | |
184 | |
185 /* get ip-addr & port */ | |
186 for (x = tpgt->x_child; x; x = x->x_sibling) { | |
187 get_ip_addr(x->x_value, &eid); | |
188 if (isns_append_attr(cmd, | |
189 ISNS_PG_PORTAL_IP_ADDR_ATTR_ID, | |
190 eid.ai_addrlen, (void *)&eid.ip_adr, | |
191 eid.ip_len) != 0) { | |
192 return (-1); | |
193 } | |
194 if (isns_append_attr(cmd, | |
195 ISNS_PG_PORTAL_PORT_ATTR_ID, | |
196 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { | |
197 return (-1); | |
198 } | |
199 } | |
200 } | |
201 } | |
202 | |
203 return (0); | |
204 } | |
205 | |
206 /* | |
207 * process_scn() | |
208 * -Added/Updated object: nop, initiator is verified during connect | |
209 * | |
210 * -Removed object: logout_targ if still connected | |
211 * | |
212 * RFC 4171 section 5.6.5.9 | |
213 * destination attribute is always the 1st attribute in the SCN message, | |
214 * then follows by SCN_BITMAP(35) & Source_Attribute(32) | |
215 */ | |
216 static void | |
217 process_scn(int so, isns_pdu_t *scn) | |
218 { | |
219 uint8_t *ptr = scn->payload; | |
220 isns_tlv_t *tlv; | |
221 uint16_t cnt = 0; | |
222 uint32_t got_dest = 0; | |
223 uint32_t got_source = 0; | |
224 uint32_t bitmap = 0; | |
225 uint32_t got_bitmap = 0; | |
226 char dest[MAXNAMELEN]; | |
227 char source[MAXNAMELEN]; | |
228 | |
229 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u\n", | |
230 scn->payload_len); | |
231 | |
232 if (scn->payload_len < TAG_LEN_SZ) { | |
233 syslog(LOG_ALERT, "ISNS SCN message error\n"); | |
234 return; | |
235 } | |
236 | |
237 while (cnt < scn->payload_len) { | |
238 /* LINTED */ | |
239 tlv = (isns_tlv_t *)ptr; | |
240 tlv->attr_id = ntohl(tlv->attr_id); | |
241 tlv->attr_len = ntohl(tlv->attr_len); | |
242 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_SCN %u %u\n", | |
243 tlv->attr_id, tlv->attr_len); | |
244 /* | |
245 * devAttrQry the source attribute, process if node_type | |
246 * is initiator | |
247 */ | |
248 switch (tlv->attr_id) { | |
249 case ISNS_ISCSI_NAME_ATTR_ID: | |
250 if (got_dest == 0) { | |
251 bcopy(tlv->attr_value, dest, | |
252 tlv->attr_len); | |
253 queue_prt(mgmtq, Q_ISNS_DBG, | |
254 "PROCESS_SCN dest %s\n", dest); | |
255 got_dest = 1; | |
256 } else { | |
257 bcopy(tlv->attr_value, source, | |
258 tlv->attr_len); | |
259 queue_prt(mgmtq, Q_ISNS_DBG, | |
260 "PROCESS_SCN source %s\n", source); | |
261 got_source = 1; | |
262 } | |
263 break; | |
264 case ISNS_ISCSI_SCN_BITMAP_ATTR_ID: | |
265 bcopy(tlv->attr_value, &bitmap, tlv->attr_len); | |
266 bitmap = ntohl(bitmap); | |
267 queue_prt(mgmtq, Q_ISNS_DBG, | |
268 "PROCESS_SCN bitmap %u\n", bitmap); | |
269 got_bitmap = 1; | |
270 break; | |
271 default: | |
272 queue_prt(mgmtq, Q_ISNS_DBG, | |
273 "PROCESS_SCN DEFAULT\n"); | |
274 break; | |
275 } | |
276 | |
277 if (got_source && !got_bitmap) { | |
278 queue_prt(mgmtq, Q_ISNS_DBG, | |
279 "process_scn: message out-of-order\n"); | |
280 return; | |
281 } | |
282 | |
283 if (got_source && got_bitmap) { | |
284 switch (bitmap) { | |
285 case ISNS_OBJ_ADDED: | |
286 case ISNS_OBJ_UPDATED: | |
287 queue_prt(mgmtq, Q_ISNS_DBG, | |
288 "PROCESS_SCN OBJ ADDED"); | |
289 isns_update(); | |
290 break; | |
291 case ISNS_OBJ_REMOVED: | |
292 queue_prt(mgmtq, Q_ISNS_DBG, | |
293 "PROCESS_SCN OBJ REMOVED"); | |
294 /* logout target */ | |
295 if (got_dest == 0) { | |
296 syslog(LOG_ALERT, | |
297 "ISNS protocol error\n"); | |
298 continue; | |
299 } | |
300 logout_targ(dest); | |
301 break; | |
302 default: | |
303 break; | |
304 } | |
305 | |
306 /* clear got_xxx */ | |
307 got_source = 0; | |
308 got_bitmap = 1; | |
309 } | |
310 | |
311 /* next attribute */ | |
312 cnt += ISNS_ATTR_SZ(tlv->attr_len); | |
313 ptr += ISNS_ATTR_SZ(tlv->attr_len); | |
314 } | |
315 queue_prt(mgmtq, Q_ISNS_DBG, "DONE PROCESS_SCN\n"); | |
316 } | |
317 | |
318 /* | |
319 * Process ESI requires a success response only | |
320 */ | |
321 static void | |
322 process_esi(int so, isns_pdu_t *esi) | |
323 { | |
324 isns_rsp_t *cmd; | |
325 int pl_len; | |
326 | |
327 if (isns_create_pdu(ISNS_ESI_RSP, 0, (isns_pdu_t **)&cmd) != 0) { | |
328 return; | |
329 } | |
330 | |
331 pl_len = esi->payload_len + ISNS_STATUS_SZ; | |
332 if (pl_len > MAX_PDU_PAYLOAD_SZ) { | |
333 syslog(LOG_ALERT, "process_esi: payload size exceeded"); | |
334 isns_free_pdu(cmd); | |
335 return; | |
336 } | |
337 | |
338 /* change the xid to the request xid */ | |
339 cmd->xid = htons(esi->xid); | |
340 cmd->status = htonl(ISNS_RSP_SUCCESSFUL); | |
341 | |
342 /* copy original data */ | |
343 bcopy(esi->payload, cmd->data, esi->payload_len); | |
344 cmd->pdu_len = htons(pl_len); | |
345 | |
346 if (isns_send(so, (isns_pdu_t *)cmd) < 0) { | |
347 syslog(LOG_ALERT, "process_esi failed to isns_send"); | |
348 } | |
349 | |
350 isns_free_pdu(cmd); | |
351 } | |
352 | |
353 /* | |
354 * esi_scn_thr() is the thread creates an end point to receive and process | |
355 * ESI & SCN messages. This thread is created when isns_access is enabled | |
356 * and for the duration of the iscsi daemon | |
357 */ | |
358 static void | |
359 *esi_scn_thr(void *arg) | |
360 { | |
361 struct sockaddr sa, *ai; | |
362 struct sockaddr_in sin; | |
363 struct sockaddr_in6 sin6; | |
364 int so, fd; | |
365 socklen_t len; | |
366 char strport[NI_MAXSERV]; | |
367 int pf; | |
368 esi_scn_arg_t *args = (esi_scn_arg_t *)arg; | |
369 isns_pdu_t *scn = NULL; | |
370 | |
371 /* | |
372 * open isns server connect and determine which PF_INET | |
373 * to use | |
374 */ | |
375 if ((so = isns_open(args->server)) < 0) { | |
376 syslog(LOG_ERR, | |
377 "esi_scn_thr: isns server %s not found", args->server); | |
378 return (NULL); | |
379 } | |
380 len = sizeof (sa); | |
381 if (getsockname(so, &sa, &len) < 0) { | |
382 isns_close(so); | |
383 syslog(LOG_ALERT, "getsockname failed"); | |
384 return (NULL); | |
385 } | |
386 pf = sa.sa_family; | |
387 isns_close(so); | |
388 | |
389 if (pf != PF_INET && pf != PF_INET6) { | |
390 syslog(LOG_ERR, "esi_scn_thr: unknown domain type"); | |
391 return (NULL); | |
392 } | |
393 | |
394 /* | |
395 * create and bind SCN socket | |
396 * save the scn port info | |
397 */ | |
398 if ((so = socket(pf, SOCK_STREAM, 0)) == -1) { | |
399 syslog(LOG_ALERT, "socket failed"); | |
400 return (NULL); | |
401 } | |
402 | |
403 if (pf == PF_INET) { | |
404 bzero(&sin, sizeof (sin)); | |
405 sin.sin_family = PF_INET; | |
406 sin.sin_port = htons(0); | |
407 sin.sin_addr.s_addr = INADDR_ANY; | |
408 ai = (struct sockaddr *)&sin; | |
409 len = sizeof (sin); | |
410 } else { | |
411 bzero(&sin6, sizeof (sin6)); | |
412 sin6.sin6_family = PF_INET6; | |
413 sin6.sin6_port = htons(0); | |
414 sin6.sin6_addr = in6addr_any; | |
415 ai = (struct sockaddr *)&sin6; | |
416 len = sizeof (sin6); | |
417 } | |
418 | |
419 (void) setsockopt(so, SOL_SOCKET, SO_REUSEADDR, 0, 0); | |
420 | |
421 if (bind(so, ai, len) < 0) { | |
422 syslog(LOG_ALERT, "esi_scn_thr: bind failed"); | |
423 return (NULL); | |
424 } | |
425 | |
426 /* get scn port info */ | |
427 len = sizeof (sa); | |
428 if (getsockname(so, &sa, &len) < 0) { | |
429 syslog(LOG_ALERT, "getsockname failed"); | |
430 return (NULL); | |
431 } | |
432 if (getnameinfo(&sa, len, NULL, 0, strport, NI_MAXSERV, | |
433 NI_NUMERICSERV) != 0) { | |
434 syslog(LOG_ALERT, "getnameinfo failed"); | |
435 return (NULL); | |
436 } | |
437 scn_port = atoi(strport); | |
438 | |
439 sema_post(&isns_sema); | |
440 | |
441 if (listen(so, 5) < 0) { | |
442 syslog(LOG_ALERT, "esi_scn_thr: failed listen"); | |
443 return (NULL); | |
444 } | |
445 | |
446 /* listen for esi or scn messages */ | |
447 while (isns_shutdown == False) { | |
448 if ((fd = accept(so, &sa, &len)) < 0) { | |
449 syslog(LOG_ALERT, "esi_scn_thr: failed accept"); | |
450 continue; | |
451 } | |
452 | |
453 if (isns_recv(fd, (isns_rsp_t **)&scn) == 0) { | |
454 /* Just return success for ESI */ | |
455 switch (scn->func_id) { | |
456 case ISNS_ESI: | |
457 process_esi(fd, scn); | |
458 break; | |
459 case ISNS_SCN: | |
460 /* call the SCN process function */ | |
461 process_scn(fd, scn); | |
462 break; | |
463 default: | |
464 syslog(LOG_ERR, | |
465 "esi_scn_thr: Invalid funcid %d\n", | |
466 scn->func_id); | |
467 break; | |
468 } | |
469 /* free response resource */ | |
470 isns_free_pdu(scn); | |
471 } else { | |
472 syslog(LOG_ALERT, "esi_scn_thr fails isns_recv "); | |
473 } | |
474 | |
475 close(fd); | |
476 } | |
477 return (NULL); | |
478 } | |
479 | |
480 /* | |
481 * Perform operation on all targets | |
482 */ | |
483 static int | |
484 isns_op_all(uint16_t op) | |
485 { | |
486 int so; | |
487 tgt_node_t *tgt = NULL; | |
488 char *iname; | |
489 | |
490 if ((so = isns_open(isns_args.server)) == -1) { | |
491 syslog(LOG_ERR, "isns_reg failed"); | |
492 return (-1); | |
493 } | |
494 | |
495 while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) | |
496 != NULL) { | |
497 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &iname) | |
498 == FALSE) { | |
499 continue; | |
500 } | |
501 | |
502 switch (op) { | |
503 case ISNS_DEV_DEREG: | |
504 if (isns_dev_attr_dereg(so, iname) == -1) { | |
505 syslog(LOG_ERR, | |
506 "ISNS de-register failed\n"); | |
507 } | |
508 num_reg = 0; | |
509 break; | |
510 case ISNS_SCN_DEREG: | |
511 if (isns_scn_dereg(so, iname) == -1) { | |
512 syslog(LOG_ERR, | |
513 "ISNS SCN de-register failed\n"); | |
514 } | |
515 break; | |
516 case ISNS_SCN_REG: | |
517 if (isns_scn_reg(so, iname) == -1) { | |
518 syslog(LOG_ERR, | |
519 "ISNS SCN register failed\n"); | |
520 } | |
521 break; | |
522 case ISNS_TGT_LOGOUT: | |
523 logout_targ(iname); | |
524 break; | |
525 default: | |
526 break; | |
527 } | |
528 | |
529 free(iname); | |
530 } | |
531 | |
532 isns_close(so); | |
533 return (0); | |
534 } | |
535 | |
536 /* | |
537 * isns_init() needs to be call before all ISNS operations. | |
538 * Save the isns_server & entity name. | |
539 * Start esi_scn_thr to receive ESI & SCN messages | |
540 */ | |
541 int | |
542 isns_init(target_queue_t *q) | |
543 { | |
544 char *isns_srv, *isns_port; | |
545 | |
546 if (q != NULL) | |
547 mgmtq = q; | |
548 | |
549 if (isns_enabled() == False) | |
550 return (0); | |
551 | |
552 /* initialize */ | |
553 sema_init(&isns_sema, 0, USYNC_THREAD, NULL); | |
554 | |
555 /* get isns server info */ | |
556 tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, &isns_srv); | |
557 isns_port = strchr(isns_srv, ':'); | |
558 if (isns_port == NULL) { | |
559 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; | |
560 } else { | |
561 isns_args.isns_port = strtoul(isns_port + 1, NULL, 0); | |
562 if (isns_args.isns_port == 0) { | |
563 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; | |
564 } | |
565 *isns_port = '\0'; | |
566 } | |
567 bcopy(isns_srv, isns_args.server, MAXHOSTNAMELEN); | |
568 free(isns_srv); | |
569 | |
570 /* get local hostname for entity usage */ | |
571 if ((gethostname(isns_args.entity, MAXHOSTNAMELEN) < 0) || | |
572 (get_ip_addr(isns_args.entity, &eid_ip) < 0)) { | |
573 syslog(LOG_ERR, "ISNS fails to get ENTITY properties"); | |
574 return (-1); | |
575 } | |
576 | |
577 if (pthread_create(&scn_tid, NULL, esi_scn_thr, (void *)&isns_args) != | |
578 0) { | |
579 syslog(LOG_ALERT, "isns_init failed to pthread_create"); | |
580 return (-1); | |
581 } | |
582 | |
583 if (sema_wait(&isns_sema) != 0) { | |
584 syslog(LOG_ERR, "sema_wait error\n"); | |
585 } | |
586 | |
587 isns_initialized = True; | |
588 | |
589 /* | |
590 * register all targets, what happens if no targets are created yet? | |
591 * this should not be a failure, when new target gets created, update | |
592 * gets call. | |
593 * what if SCN register fails? | |
594 */ | |
595 if (isns_reg_all() == 0) { | |
596 /* scn register all targets */ | |
597 if (isns_op_all(ISNS_SCN_REG) != 0) { | |
598 syslog(LOG_ERR, "SCN registrations failed\n"); | |
599 isns_op_all(ISNS_DEV_DEREG); | |
600 return (-1); | |
601 } | |
602 } | |
603 | |
604 return (0); | |
605 } | |
606 | |
607 /* | |
608 * isns_update gets call on modify_admin, this is changes to | |
609 * isns access and/or isns server | |
610 */ | |
611 int | |
612 isns_update() | |
613 { | |
614 char *isns_srv = NULL, *isns_port; | |
615 | |
616 if (isns_initialized == False) { | |
617 /* isns enabled after iscsi started */ | |
618 if (isns_enabled() == True) { | |
619 isns_init(NULL); | |
620 } | |
621 return (0); | |
622 } | |
623 | |
624 /* | |
625 * isns is disabled after enabled, | |
626 * log off all targets and fini isns service | |
627 */ | |
628 if (isns_initialized == True && isns_enabled() == False) { | |
629 isns_fini(); | |
630 return (0); | |
631 } | |
632 | |
633 /* | |
634 * isns is already initialized and isns_access is still enabled, | |
635 * let's update the isns_server name | |
636 */ | |
637 tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, &isns_srv); | |
638 isns_port = strchr(isns_srv, ':'); | |
639 if (isns_port == NULL) { | |
640 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; | |
641 } else { | |
642 isns_args.isns_port = strtoul(isns_port + 1, NULL, 0); | |
643 if (isns_args.isns_port == 0) { | |
644 isns_args.isns_port = ISNS_DEFAULT_SERVER_PORT; | |
645 } | |
646 *isns_port = '\0'; | |
647 } | |
648 | |
649 /* | |
650 * If the iSNS server is different, then dregister all from | |
651 * the old iSNS server, and register all to the new iSNS server | |
652 */ | |
653 | |
654 if (strcmp(isns_srv, isns_args.server) != 0) { | |
655 /* de-reg from old iSNS server */ | |
656 (void) isns_dereg_all(); | |
657 | |
658 bcopy(isns_srv, isns_args.server, MAXHOSTNAMELEN); | |
659 | |
660 if (isns_reg_all() == 0) { | |
661 /* scn register all targets */ | |
662 if (isns_op_all(ISNS_SCN_REG) != 0) { | |
663 syslog(LOG_ERR, "SCN registrations failed\n"); | |
664 isns_op_all(ISNS_DEV_DEREG); | |
665 return (-1); | |
666 } | |
667 } | |
668 } | |
669 if (isns_srv != NULL) | |
670 free(isns_srv); | |
671 | |
672 return (0); | |
673 } | |
674 | |
675 /* | |
676 * isns_fini is called when isns access is disable | |
677 */ | |
678 void | |
679 isns_fini() | |
680 { | |
681 /* | |
682 * de-register all targets 1st, this prevents initiator from | |
683 * logging back in | |
684 */ | |
685 isns_op_all(ISNS_SCN_DEREG); | |
686 isns_op_all(ISNS_DEV_DEREG); | |
687 | |
688 /* log off all targets */ | |
689 isns_op_all(ISNS_TGT_LOGOUT); | |
690 | |
691 isns_initialized = False; | |
692 } | |
693 | |
694 static int | |
695 get_ip_addr(char *node, ip_t *sa) | |
696 { | |
697 struct addrinfo *ai = NULL, *aip; | |
698 struct sockaddr_in *sin; | |
699 struct sockaddr_in6 *sin6; | |
700 | |
701 if (getaddrinfo(node, NULL, NULL, &ai) != 0) { | |
702 syslog(LOG_ALERT, "ISNS server not found"); | |
703 return (-1); | |
704 } | |
705 | |
706 bzero(sa, sizeof (ip_t)); | |
707 aip = ai; | |
708 do { | |
709 sa->ai_addrlen = aip->ai_addrlen; | |
710 sa->pf_family = aip->ai_family; | |
711 switch (aip->ai_family) { | |
712 case PF_INET: | |
713 /* LINTED */ | |
714 sin = (struct sockaddr_in *)aip->ai_addr; | |
715 sa->ip_len = sizeof (in_addr_t); | |
716 bcopy(&sin->sin_addr, (void *)&sa->ip_adr.in, | |
717 sa->ip_len); | |
718 freeaddrinfo(ai); | |
719 return (0); | |
720 case PF_INET6: | |
721 /* LINTED */ | |
722 sin6 = (struct sockaddr_in6 *)aip->ai_addr; | |
723 sa->ip_len = sizeof (in6_addr_t); | |
724 bcopy(&sin6->sin6_addr, &sa->ip_adr.in6, | |
725 sa->ip_len); | |
726 freeaddrinfo(ai); | |
727 return (0); | |
728 default: | |
729 continue; | |
730 } | |
731 } while ((aip = aip->ai_next) != NULL); | |
732 | |
733 freeaddrinfo(ai); | |
734 return (-1); | |
735 } | |
736 | |
737 /* | |
738 * Process isns response, need to verify same transaction id, func_id | |
739 * as the isns command, the isns command is in network byte order, | |
740 * the isns response is in host byte order | |
741 */ | |
742 static int | |
743 process_rsp(isns_pdu_t *cmd, isns_rsp_t *rsp) | |
744 { | |
745 queue_prt(mgmtq, Q_ISNS_DBG, "PROCESS_RSP"); | |
746 /* | |
747 * Process responses: | |
748 * -verify sucessful response | |
749 * -verify match xid | |
750 * -process operating attributes | |
751 * For DevAttrReg & DevAttrQry and most isns command, | |
752 * the response func_id is command_func_id | 0x8000. | |
753 */ | |
754 rsp->status = ntohl(rsp->status); | |
755 if (rsp->status != ISNS_RSP_SUCCESSFUL || | |
756 rsp->xid != ntohs(cmd->xid) || | |
757 rsp->func_id != (ntohs(cmd->func_id) | 0x8000)) { | |
758 queue_prt(mgmtq, Q_ISNS_DBG, | |
759 "cmd failed with: status= %d xid= %d %d "\ | |
760 "response attribute %x\n", rsp->status, rsp->xid,\ | |
761 ntohs(cmd->xid), rsp->func_id); | |
762 return (-1); | |
763 } | |
764 | |
765 return (0); | |
766 } | |
767 | |
768 /* | |
769 * DevAttrDereg | |
770 */ | |
771 static int | |
772 isns_dev_attr_dereg(int so, char *node) | |
773 { | |
774 isns_pdu_t *cmd = NULL; | |
775 isns_rsp_t *rsp = NULL; | |
776 uint32_t flags = 0; | |
777 int ret = -1; | |
778 | |
779 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_DEREG"); | |
780 | |
781 if (isns_create_pdu(ISNS_DEV_DEREG, flags, &cmd) != 0) { | |
782 return (-1); | |
783 } | |
784 | |
785 /* add source attribute */ | |
786 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
787 STRLEN(node), node, 0) != 0) { | |
788 goto error; | |
789 } | |
790 | |
791 /* add delimiter */ | |
792 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { | |
793 goto error; | |
794 } | |
795 | |
796 /* add operation attributes */ | |
797 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
798 STRLEN(node), node, 0) != 0) { | |
799 goto error; | |
800 } | |
801 | |
802 /* send pdu */ | |
803 if (isns_send(so, cmd) == -1) { | |
804 syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_send"); | |
805 goto error; | |
806 } | |
807 | |
808 /* get isns response */ | |
809 if (isns_recv(so, &rsp) == -1) { | |
810 syslog(LOG_ERR, "isns_dev_attr_dereg fails isns_recv "); | |
811 goto error; | |
812 } | |
813 | |
814 /* process response */ | |
815 if (process_rsp(cmd, rsp) == 0) { | |
816 num_reg--; | |
817 ret = 0; | |
818 } | |
819 | |
820 error: | |
821 /* Free all resouces here */ | |
822 if (cmd) | |
823 isns_free_pdu(cmd); | |
824 if (rsp) | |
825 isns_free_pdu(rsp); | |
826 return (ret); | |
827 } | |
828 | |
829 /* | |
830 * Register a new node, need to find another node that is already registered | |
831 * DevAttrReg | |
832 * RFC 4171 Section 5.6.5.5 indicated SCN-port-tag (23) needed to be | |
833 * included in the registration | |
834 * Also need to register ESI-port-tag (20) see Section 6.3.5 | |
835 */ | |
836 static int | |
837 isns_dev_attr_reg(int so, tgt_node_t *tgt, char *node, char *alias) | |
838 { | |
839 isns_pdu_t *cmd = NULL; | |
840 isns_rsp_t *rsp = NULL; | |
841 uint32_t flags = 0; | |
842 int ret = 0; | |
843 Boolean_t found = False; | |
844 tgt_node_t *src = NULL; | |
845 char *src_nm = NULL; | |
846 | |
847 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_REG"); | |
848 | |
849 if ((so = isns_open(isns_args.server)) == -1) { | |
850 return (-1); | |
851 } | |
852 | |
853 if (num_reg == 0) { | |
854 flags |= ISNS_FLAG_REPLACE_REG; | |
855 } | |
856 | |
857 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { | |
858 return (-1); | |
859 } | |
860 | |
861 if (num_reg == 0) { | |
862 /* add new node to source attribute */ | |
863 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
864 STRLEN(node), node, 0) != 0) { | |
865 goto error; | |
866 } | |
867 } else { | |
868 /* find a registered node to use */ | |
869 do { | |
870 src = find_next_tgt(src, &src_nm); | |
871 if (src == NULL) { | |
872 syslog(LOG_ALERT, "ISNS out of sync\n"); | |
873 goto error; | |
874 } | |
875 if (tgt == src) { | |
876 free(src_nm); | |
877 continue; | |
878 } else { | |
879 found = True; | |
880 } | |
881 } while (found == False); | |
882 | |
883 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
884 STRLEN(src_nm), src_nm, 0) != 0) { | |
885 goto error; | |
886 } | |
887 } | |
888 | |
889 /* add message key attribute */ | |
890 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, | |
891 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { | |
892 goto error; | |
893 } | |
894 | |
895 /* add delimiter */ | |
896 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { | |
897 goto error; | |
898 } | |
899 | |
900 /* add operation attributes */ | |
901 | |
902 /* entity id */ | |
903 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, | |
904 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { | |
905 goto error; | |
906 } | |
907 | |
908 /* entity type */ | |
909 if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, | |
910 ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { | |
911 goto error; | |
912 } | |
913 | |
914 /* | |
915 * Register entity portal properties the 1st time | |
916 */ | |
917 if (num_reg == 0) { | |
918 /* portal ip-addr */ | |
919 if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, | |
920 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, | |
921 eid_ip.ip_len) != 0) { | |
922 goto error; | |
923 } | |
924 | |
925 /* portal port */ | |
926 if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, | |
927 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { | |
928 goto error; | |
929 } | |
930 | |
931 /* ESI interval */ | |
932 if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, | |
933 ISNS_ESI_TICK_SZ, NULL, 10) != 0) { | |
934 goto error; | |
935 } | |
936 | |
937 /* scn port */ | |
938 if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, | |
939 ISNS_PORT_SZ, NULL, scn_port) != 0) { | |
940 goto error; | |
941 } | |
942 | |
943 /* esi port */ | |
944 if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, | |
945 ISNS_PORT_SZ, NULL, scn_port) != 0) { | |
946 goto error; | |
947 } | |
948 } | |
949 | |
950 /* iscsi node name */ | |
951 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
952 STRLEN(node), node, 0) != 0) { | |
953 goto error; | |
954 } | |
955 | |
956 /* iscsi node type */ | |
957 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, | |
958 ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE) != 0) { | |
959 goto error; | |
960 } | |
961 | |
962 /* iscsi node alias */ | |
963 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, | |
964 STRLEN(alias), alias, 0) != 0) { | |
965 goto error; | |
966 } | |
967 | |
968 /* PGT */ | |
969 if (append_tpgt(tgt, cmd) != 0) { | |
970 goto error; | |
971 } | |
972 | |
973 /* send pdu */ | |
974 if (isns_send(so, cmd) == -1) { | |
975 goto error; | |
976 } | |
977 | |
978 /* get isns response */ | |
979 if (isns_recv(so, &rsp) == -1) { | |
980 goto error; | |
981 } | |
982 | |
983 /* process response */ | |
984 if ((ret = process_rsp(cmd, rsp)) == 0) { | |
985 num_reg++; | |
986 } | |
987 | |
988 error: | |
989 /* Free all resouces here */ | |
990 if (cmd) | |
991 isns_free_pdu(cmd); | |
992 if (rsp) | |
993 isns_free_pdu(rsp); | |
994 if (src_nm) | |
995 free(src_nm); | |
996 return (ret); | |
997 } | |
998 | |
999 /* | |
1000 * DevAttrQry for iscsi initiator | |
1001 * See RFC 4171 Sect. 5.6.5.2 for query detail | |
1002 */ | |
1003 static int | |
1004 isns_dev_attr_qry(int so, char *target, char *initiator) | |
1005 { | |
1006 isns_pdu_t *cmd; | |
1007 isns_rsp_t *rsp; | |
1008 uint32_t flags = 0; | |
1009 int ret = -1; | |
1010 size_t remain; | |
1011 isns_tlv_t *tlv; | |
1012 uint8_t *ptr; | |
1013 | |
1014 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_DEV_ATTR_QRY"); | |
1015 | |
1016 if (isns_create_pdu(ISNS_DEV_ATTR_QRY, flags, &cmd) != 0) { | |
1017 return (-1); | |
1018 } | |
1019 | |
1020 /* source attribute */ | |
1021 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1022 STRLEN(target), target, 0) == -1) { | |
1023 goto error; | |
1024 } | |
1025 | |
1026 /* message key attribute */ | |
1027 /* iscsi initiator node type */ | |
1028 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, | |
1029 ISNS_NODE_TYP_SZ, NULL, ISNS_INITIATOR_NODE_TYPE) == -1) { | |
1030 goto error; | |
1031 } | |
1032 | |
1033 /* delimiter */ | |
1034 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { | |
1035 goto error; | |
1036 } | |
1037 | |
1038 /* | |
1039 * operating attributes | |
1040 * Query Iscsi initiator with zero length TLV operating | |
1041 * attribute | |
1042 */ | |
1043 | |
1044 /* iscsi name */ | |
1045 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1046 0, NULL, 0) != 0) { | |
1047 goto error; | |
1048 } | |
1049 | |
1050 if (isns_send(so, cmd) == -1) { | |
1051 syslog(LOG_ERR, "isns_dev_attr_qry fails isns_send"); | |
1052 goto error; | |
1053 } | |
1054 | |
1055 /* recv response */ | |
1056 if (isns_recv(so, &rsp) == -1) { | |
1057 syslog(LOG_ERR, "isns_dev_attr_qry fails isns_recv "); | |
1058 goto error; | |
1059 } | |
1060 | |
1061 /* process response */ | |
1062 if ((ret = process_rsp(cmd, rsp)) == 0) { | |
1063 /* compare initiator name to the response, success if found */ | |
1064 /* subtract out status word */ | |
1065 remain = rsp->pdu_len - ISNS_STATUS_SZ; | |
1066 ptr = rsp->data; | |
1067 | |
1068 while (remain > 0) { | |
1069 /* LINTED */ | |
1070 tlv = (isns_tlv_t *)ptr; | |
1071 | |
1072 /* debug only */ | |
1073 print_ntoh_tlv(tlv); | |
1074 | |
1075 /* process tag-len-value */ | |
1076 ntoh_tlv(tlv); | |
1077 /* | |
1078 * let's process the data, only interested | |
1079 * in iscsi name, skip everything else for | |
1080 * now. | |
1081 */ | |
1082 if (tlv->attr_id == ISNS_ISCSI_NAME_ATTR_ID) { | |
1083 if (strncmp((char *)tlv->attr_value, initiator, | |
1084 tlv->attr_len) == 0) { | |
1085 break; | |
1086 } | |
1087 } | |
1088 /* next tlv */ | |
1089 remain -= ISNS_ATTR_SZ(tlv->attr_len); | |
1090 ptr += ISNS_ATTR_SZ(tlv->attr_len); | |
1091 } | |
1092 ret = (remain > 0) ? 1 : 0; | |
1093 } | |
1094 | |
1095 error: | |
1096 if (cmd) | |
1097 isns_free_pdu(cmd); | |
1098 if (rsp) | |
1099 isns_free_pdu(rsp); | |
1100 return (ret); | |
1101 } | |
1102 | |
1103 /* | |
1104 * SCNReg | |
1105 * See RFC 4171 Section 5.6.5.5 | |
1106 */ | |
1107 static int | |
1108 isns_scn_reg(int so, char *node) | |
1109 { | |
1110 isns_pdu_t *cmd; | |
1111 isns_rsp_t *rsp; | |
1112 uint32_t flags = 0; | |
1113 uint32_t bitmap = 0; | |
1114 int ret = -1; | |
1115 | |
1116 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_REG"); | |
1117 | |
1118 if (isns_create_pdu(ISNS_SCN_REG, flags, &cmd) != 0) { | |
1119 return (-1); | |
1120 } | |
1121 | |
1122 /* source attribute */ | |
1123 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1124 STRLEN(node), node, 0) == -1) { | |
1125 goto error; | |
1126 } | |
1127 | |
1128 /* message key attribute */ | |
1129 /* iscsi initiator node name */ | |
1130 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1131 STRLEN(node), node, 0) != 0) { | |
1132 goto error; | |
1133 } | |
1134 | |
1135 /* delimiter */ | |
1136 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { | |
1137 goto error; | |
1138 } | |
1139 | |
1140 /* SCN bitmap */ | |
1141 bitmap = ISNS_INIT_SELF_INFO_ONLY | ISNS_OBJ_REMOVED | | |
1142 ISNS_OBJ_ADDED | ISNS_OBJ_UPDATED; | |
1143 if (isns_append_attr(cmd, ISNS_ISCSI_SCN_BITMAP_ATTR_ID, | |
1144 ISNS_SCN_BITMAP_SZ, NULL, bitmap) == -1) { | |
1145 goto error; | |
1146 } | |
1147 | |
1148 if (isns_send(so, cmd) == -1) { | |
1149 syslog(LOG_ERR, "isns_scn_reg fails isns_send"); | |
1150 goto error; | |
1151 } | |
1152 | |
1153 if (isns_recv(so, &rsp) == -1) { | |
1154 syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); | |
1155 goto error; | |
1156 } | |
1157 | |
1158 /* process response */ | |
1159 if (process_rsp(cmd, rsp) == 0) { | |
1160 ret = 0; | |
1161 } | |
1162 | |
1163 error: | |
1164 if (cmd) | |
1165 isns_free_pdu(cmd); | |
1166 if (rsp) | |
1167 isns_free_pdu(rsp); | |
1168 return (ret); | |
1169 } | |
1170 | |
1171 | |
1172 /* | |
1173 * SCNDereg | |
1174 */ | |
1175 static int | |
1176 isns_scn_dereg(int so, char *node) | |
1177 { | |
1178 isns_pdu_t *cmd = NULL; | |
1179 isns_rsp_t *rsp = NULL; | |
1180 uint32_t flags = 0; | |
1181 int ret = -1; | |
1182 | |
1183 queue_prt(mgmtq, Q_ISNS_DBG, "ISNS_SCN_DEREG"); | |
1184 | |
1185 if (isns_create_pdu(ISNS_SCN_DEREG, flags, &cmd) != 0) { | |
1186 return (-1); | |
1187 } | |
1188 | |
1189 /* source attribute */ | |
1190 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1191 STRLEN(node), node, 0) == -1) { | |
1192 goto error; | |
1193 } | |
1194 | |
1195 /* message key attribute */ | |
1196 /* iscsi initiator node name */ | |
1197 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1198 STRLEN(node), node, 0) != 0) { | |
1199 goto error; | |
1200 } | |
1201 | |
1202 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) == -1) { | |
1203 goto error; | |
1204 } | |
1205 | |
1206 if (isns_send(so, cmd) == -1) { | |
1207 syslog(LOG_ERR, "isns_scn_reg fails isns_send"); | |
1208 goto error; | |
1209 } | |
1210 | |
1211 if (isns_recv(so, &rsp) == -1) { | |
1212 syslog(LOG_ERR, "isns_scn_reg fails isns_recv "); | |
1213 goto error; | |
1214 } | |
1215 | |
1216 /* process response */ | |
1217 if (process_rsp(cmd, rsp) == 0) { | |
1218 ret = 0; | |
1219 } | |
1220 | |
1221 error: | |
1222 if (cmd) | |
1223 isns_free_pdu(cmd); | |
1224 if (rsp) | |
1225 isns_free_pdu(rsp); | |
1226 return (ret); | |
1227 } | |
1228 | |
1229 /* | |
1230 * isns_reg is called to register new target | |
1231 */ | |
1232 int | |
1233 isns_reg(char *targ) | |
1234 { | |
1235 int so; | |
1236 tgt_node_t *tgt; | |
1237 char *iqn; | |
1238 | |
1239 if ((so = isns_open(isns_args.server)) == -1) { | |
1240 syslog(LOG_ERR, "isns_reg failed"); | |
1241 return (-1); | |
1242 } | |
1243 | |
1244 /* | |
1245 * Open targets_config and devAttrReg all nodes | |
1246 */ | |
1247 if ((tgt = find_tgt_by_name(targ, &iqn)) != NULL) { | |
1248 if (isns_dev_attr_reg(so, tgt, iqn, tgt->x_value) != 0) { | |
1249 syslog(LOG_ALERT, "ISNS registration failed %s\n", | |
1250 tgt->x_value); | |
1251 } | |
1252 if (isns_scn_reg(so, iqn) == -1) { | |
1253 syslog(LOG_ERR, "ISNS SCN register failed\n"); | |
1254 } | |
1255 free(iqn); | |
1256 } | |
1257 | |
1258 isns_close(so); | |
1259 return (0); | |
1260 } | |
1261 | |
1262 | |
1263 /* | |
1264 * Register all iscsi target nodes from the XML database | |
1265 * Alway use the ISNS_FLAG_REPLACE_REG flag | |
1266 */ | |
1267 int | |
1268 isns_reg_all() | |
1269 { | |
1270 int so; | |
1271 uint32_t flags = ISNS_FLAG_REPLACE_REG; | |
1272 isns_pdu_t *cmd; | |
1273 isns_rsp_t *rsp; | |
1274 char *n = NULL; | |
1275 char *a = NULL; | |
1276 char alias[MAXNAMELEN]; | |
1277 char iname[MAXNAMELEN]; | |
1278 tgt_node_t *tgt = NULL; | |
1279 int ret = -1; | |
1280 int tgt_cnt = 0; | |
1281 | |
1282 /* | |
1283 * get the 1st target and use it for the source attribute | |
1284 */ | |
1285 if ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) | |
1286 == NULL) { | |
1287 return (0); | |
1288 } | |
1289 if (tgt->x_value == NULL) { | |
1290 syslog(LOG_ALERT, "ISNS: target with NULL local name\n"); | |
1291 return (-1); | |
1292 } | |
1293 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) | |
1294 == FALSE) { | |
1295 syslog(LOG_ALERT, "ISNS: no XML_ELEMENT_INAME found\n"); | |
1296 return (-1); | |
1297 } | |
1298 strcpy(iname, n); | |
1299 free(n); | |
1300 | |
1301 if ((so = isns_open(isns_args.server)) == -1) { | |
1302 syslog(LOG_ALERT, "ISNS: fails to connect to %s\n", | |
1303 isns_args.server); | |
1304 return (-1); | |
1305 } | |
1306 | |
1307 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd) != 0) { | |
1308 goto error; | |
1309 } | |
1310 | |
1311 /* source attribute */ | |
1312 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1313 STRLEN(iname), iname, 0) != 0) { | |
1314 goto error; | |
1315 } | |
1316 | |
1317 /* add message key attribute */ | |
1318 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, | |
1319 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { | |
1320 goto error; | |
1321 } | |
1322 | |
1323 /* add delimiter */ | |
1324 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) != 0) { | |
1325 goto error; | |
1326 } | |
1327 | |
1328 /* entity id */ | |
1329 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, | |
1330 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { | |
1331 goto error; | |
1332 } | |
1333 | |
1334 /* entity type */ | |
1335 if (isns_append_attr(cmd, ISNS_ENTITY_PROTOCOL_ATTR_ID, | |
1336 ISNS_ENTITY_TYP_SZ, NULL, ISNS_ENTITY_PROTOCOL_ISCSI) != 0) { | |
1337 goto error; | |
1338 } | |
1339 | |
1340 /* portal ip-addr */ | |
1341 if (isns_append_attr(cmd, ISNS_PORTAL_IP_ADDR_ATTR_ID, | |
1342 eid_ip.ai_addrlen, (void *)&eid_ip.ip_adr, | |
1343 eid_ip.ip_len) != 0) { | |
1344 goto error; | |
1345 } | |
1346 | |
1347 /* portal port */ | |
1348 if (isns_append_attr(cmd, ISNS_PORTAL_PORT_ATTR_ID, | |
1349 ISNS_PORT_SZ, NULL, iscsi_port) != 0) { | |
1350 goto error; | |
1351 } | |
1352 | |
1353 /* ESI interval */ | |
1354 if (isns_append_attr(cmd, ISNS_ESI_INTERVAL_ATTR_ID, | |
1355 ISNS_ESI_TICK_SZ, NULL, 10) != 0) { | |
1356 goto error; | |
1357 } | |
1358 | |
1359 | |
1360 /* scn port */ | |
1361 if (isns_append_attr(cmd, ISNS_SCN_PORT_ATTR_ID, | |
1362 ISNS_PORT_SZ, NULL, scn_port) != 0) { | |
1363 goto error; | |
1364 } | |
1365 | |
1366 /* esi port */ | |
1367 if (isns_append_attr(cmd, ISNS_ESI_PORT_ATTR_ID, | |
1368 ISNS_PORT_SZ, NULL, scn_port) != 0) { | |
1369 goto error; | |
1370 } | |
1371 | |
1372 /* | |
1373 * Open targets_config and devAttrReg all nodes | |
1374 */ | |
1375 tgt = NULL; | |
1376 while ((tgt = tgt_node_next(targets_config, XML_ELEMENT_TARG, tgt)) | |
1377 != NULL) { | |
1378 if (tgt->x_value == NULL) { | |
1379 syslog(LOG_ALERT, "ISNS: target with NULL name\n"); | |
1380 continue; | |
1381 } | |
1382 /* use this value as alias if alias is not set */ | |
1383 strcpy(alias, tgt->x_value); | |
1384 | |
1385 if (tgt_find_value_str(tgt, XML_ELEMENT_INAME, &n) | |
1386 == FALSE) { | |
1387 continue; | |
1388 } | |
1389 strcpy(iname, n); | |
1390 free(n); | |
1391 | |
1392 /* find alias */ | |
1393 if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &a) | |
1394 == TRUE) { | |
1395 strcpy(alias, a); | |
1396 free(a); | |
1397 } | |
1398 | |
1399 tgt_cnt++; /* increment target count */ | |
1400 | |
1401 /* operation attributes */ | |
1402 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1403 STRLEN(iname), iname, 0) != 0) { | |
1404 goto error; | |
1405 } | |
1406 if (isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, | |
1407 4, NULL, ISNS_TARGET_NODE_TYPE) != 0) { | |
1408 goto error; | |
1409 } | |
1410 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, | |
1411 STRLEN(alias), alias, 0) != 0) { | |
1412 goto error; | |
1413 } | |
1414 | |
1415 if (append_tpgt(tgt, cmd) != 0) { | |
1416 goto error; | |
1417 } | |
1418 | |
1419 } | |
1420 | |
1421 /* send pdu */ | |
1422 if (isns_send(so, cmd) == -1) { | |
1423 goto error; | |
1424 } | |
1425 | |
1426 /* get isns response */ | |
1427 if (isns_recv(so, &rsp) == -1) { | |
1428 goto error; | |
1429 } | |
1430 | |
1431 /* process response */ | |
1432 if (process_rsp(cmd, rsp) == 0) { | |
1433 ret = 0; | |
1434 num_reg = tgt_cnt; | |
1435 queue_prt(mgmtq, Q_ISNS_DBG, "DevAttrRegAll successful"); | |
1436 } else { | |
1437 syslog(LOG_ALERT, "DevAttrReg failed"); | |
1438 } | |
1439 | |
1440 error: | |
1441 if (cmd) | |
1442 isns_free_pdu(cmd); | |
1443 if (rsp) | |
1444 isns_free_pdu(rsp); | |
1445 isns_close(so); | |
1446 return (ret); | |
1447 } | |
1448 | |
1449 /* | |
1450 * Deregister an iscsi target node | |
1451 */ | |
1452 int | |
1453 isns_dereg(char *name) | |
1454 { | |
1455 int so; | |
1456 int ret; | |
1457 | |
1458 if ((so = isns_open(isns_args.server)) == -1) { | |
1459 return (-1); | |
1460 } | |
1461 | |
1462 ret = isns_dev_attr_dereg(so, name); | |
1463 | |
1464 isns_close(so); | |
1465 return (ret); | |
1466 } | |
1467 | |
1468 /* | |
1469 * Update an existing iscsi target property | |
1470 */ | |
1471 int | |
1472 isns_dev_update(char *targ, uint32_t mods) | |
1473 { | |
1474 int so; | |
1475 int flags = 0; /* update only */ | |
1476 char *iname = NULL; | |
1477 char *dummy = NULL; | |
1478 char alias[MAXNAMELEN]; | |
1479 tgt_node_t *tgt = NULL; | |
1480 isns_pdu_t *cmd; | |
1481 isns_rsp_t *rsp; | |
1482 int ret = -1; | |
1483 | |
1484 if (mods == 0) | |
1485 return (0); | |
1486 | |
1487 if ((tgt = find_tgt_by_name(targ, &iname)) != NULL) { | |
1488 if (tgt_find_value_str(tgt, XML_ELEMENT_ALIAS, &dummy) == | |
1489 True) { | |
1490 strcpy(alias, dummy); | |
1491 free(dummy); | |
1492 } else | |
1493 strcpy(alias, tgt->x_value); | |
1494 | |
1495 if ((so = isns_open(isns_args.server)) < 0) { | |
1496 goto error; | |
1497 } | |
1498 | |
1499 if (isns_create_pdu(ISNS_DEV_ATTR_REG, flags, &cmd)) { | |
1500 goto error; | |
1501 } | |
1502 /* source attr, msg key, delimiter */ | |
1503 if (isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, | |
1504 STRLEN(iname), iname, 0) != 0) { | |
1505 goto error; | |
1506 } | |
1507 if (isns_append_attr(cmd, ISNS_EID_ATTR_ID, | |
1508 STRLEN(isns_args.entity), isns_args.entity, 0) != 0) { | |
1509 goto error; | |
1510 } | |
1511 if (isns_append_attr(cmd, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0) | |
1512 != 0) { | |
1513 goto error; | |
1514 } | |
1515 | |
1516 /* | |
1517 * get current operating attributes, alias & portal group | |
1518 * objects, these should be the only things that get change | |
1519 */ | |
1520 isns_append_attr(cmd, ISNS_ISCSI_NAME_ATTR_ID, STRLEN(iname), | |
1521 iname, 0); | |
1522 isns_append_attr(cmd, ISNS_ISCSI_NODE_TYPE_ATTR_ID, | |
1523 ISNS_NODE_TYP_SZ, NULL, ISNS_TARGET_NODE_TYPE); | |
1524 | |
1525 if (mods & ISNS_MOD_ALIAS) | |
1526 if (isns_append_attr(cmd, ISNS_ISCSI_ALIAS_ATTR_ID, | |
1527 STRLEN(alias), alias, 0) != 0) { | |
1528 goto error; | |
1529 } | |
1530 | |
1531 if (mods & ISNS_MOD_TPGT) | |
1532 if (append_tpgt(tgt, cmd) != 0) { | |
1533 goto error; | |
1534 } | |
1535 | |
1536 if (isns_send(so, (isns_pdu_t *)cmd) < 0) { | |
1537 goto error; | |
1538 } | |
1539 | |
1540 if (isns_recv(so, &rsp) == -1) { | |
1541 goto error; | |
1542 } | |
1543 | |
1544 /* process response, if failed do a isns_reg_all */ | |
1545 if ((ret = process_rsp(cmd, rsp)) == -1) { | |
1546 if (isns_reg_all() != 0 || isns_scn_reg_all() != 0) { | |
1547 syslog(LOG_ALERT, "ISNS register failed\n"); | |
1548 goto error; | |
1549 } | |
1550 ret = 0; | |
1551 } else { | |
1552 if (isns_scn_reg(so, iname) == -1) { | |
1553 syslog(LOG_ERR, "ISNS SCN register failed\n"); | |
1554 goto error; | |
1555 } | |
1556 ret = 0; | |
1557 } | |
1558 } else { | |
1559 syslog(LOG_ERR, "ISNS: fails to update target %s\n", alias); | |
1560 } | |
1561 | |
1562 error: | |
1563 if (cmd) | |
1564 isns_free_pdu(cmd); | |
1565 if (rsp) | |
1566 isns_free_pdu(rsp); | |
1567 if (iname) | |
1568 free(iname); | |
1569 isns_close(so); | |
1570 return (ret); | |
1571 } | |
1572 | |
1573 | |
1574 /* | |
1575 * Deregister all iscsi target nodes from the XML database | |
1576 */ | |
1577 int | |
1578 isns_dereg_all() | |
1579 { | |
1580 return (isns_op_all(ISNS_DEV_DEREG)); | |
1581 } | |
1582 | |
1583 int | |
1584 isns_scn_reg_all() | |
1585 { | |
1586 return (isns_op_all(ISNS_SCN_REG)); | |
1587 } | |
1588 | |
1589 int | |
1590 isns_scn_dereg_all() | |
1591 { | |
1592 return (isns_op_all(ISNS_SCN_DEREG)); | |
1593 } | |
1594 | |
1595 /* | |
1596 * Query an iscsi initiator node | |
1597 */ | |
1598 Boolean_t | |
1599 isns_qry_initiator(char *target, char *initiator) | |
1600 { | |
1601 int so; | |
1602 int ret; | |
1603 | |
1604 if ((so = isns_open(isns_args.server)) == -1) { | |
1605 syslog(LOG_ERR, "isns_qry failed"); | |
1606 return (-1); | |
1607 } | |
1608 | |
1609 ret = isns_dev_attr_qry(so, target, initiator); | |
1610 | |
1611 isns_close(so); | |
1612 return (ret == 1 ? True : False); | |
1613 } | |
1614 | |
1615 Boolean_t | |
1616 isns_enabled() | |
1617 { | |
1618 Boolean_t isns_access = False; | |
1619 char *isns_srv = NULL; | |
1620 | |
1621 (void) tgt_find_value_boolean(main_config, XML_ELEMENT_ISNS_ACCESS, | |
1622 &isns_access); | |
1623 /* get isns server info */ | |
1624 if (isns_access == True) { | |
1625 if (tgt_find_value_str(main_config, XML_ELEMENT_ISNS_SERV, | |
1626 &isns_srv) == True) { | |
1627 free(isns_srv); | |
1628 return (True); | |
1629 } | |
1630 } | |
1631 return (False); | |
1632 } |