iscsid_lists.c revision 1.1 1 /* $NetBSD: iscsid_lists.c,v 1.1 2011/10/23 21:11:23 agc Exp $ */
2
3 /*-
4 * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32
33 #include "iscsid_globals.h"
34
35 /* counter for initiator ID */
36 STATIC uint32_t initiator_id = 0;
37
38 /* -------------------------------------------------------------------------- */
39
40 /*#ifdef ISCSI_NOTHREAD */
41 #if 0
42
43 /*
44 * verify_session:
45 * Verify that a specific session still exists, delete it if not.
46 *
47 * Parameter: The session pointer.
48 */
49
50 STATIC void
51 verify_session(session_t * sess)
52 {
53 generic_entry_t *curr, *next;
54 int nosess = 0;
55
56 for (curr = sess->connections.tqh_first; curr != NULL && !nosess; curr = next) {
57 next = curr->link.tqe_next;
58 nosess = verify_connection((connection_t *) curr) == ISCSI_STATUS_INVALID_SESSION_ID;
59 }
60
61 if (!nosess && sess->num_connections)
62 return;
63
64 TAILQ_REMOVE(&list[SESSION_LIST].list, &sess->entry, link);
65 list[SESSION_LIST].num_entries--;
66
67 while ((curr = TAILQ_FIRST(&sess->connections)) != NULL) {
68 TAILQ_REMOVE(&sess->connections, curr, link);
69 free(curr);
70 }
71 free(sess);
72 }
73
74
75 /*
76 * verify_sessions:
77 * Verify that all sessions in the list still exist.
78 */
79
80 void
81 verify_sessions(void)
82 {
83 generic_entry_t *curr, *next;
84
85 for (curr = list[SESSION_LIST].list.tqh_first; curr != NULL; curr = next) {
86 next = curr->link.tqe_next;
87 verify_session((session_t *) curr);
88 }
89 }
90
91 #endif
92
93 /* -------------------------------------------------------------------------- */
94
95 /*
96 * find_id:
97 * Find a list element by ID.
98 *
99 * Parameter: the list head and the ID to search for
100 *
101 * Returns: The pointer to the element (or NULL if not found)
102 */
103
104 generic_entry_t *
105 find_id(generic_list_t * head, uint32_t id)
106 {
107 generic_entry_t *curr;
108
109 if (!id)
110 return NULL;
111
112 TAILQ_FOREACH(curr, head, link)
113 if (curr->sid.id == (int)id)
114 break;
115
116 return curr;
117 }
118
119 /*
120 * find_name:
121 * Find a list entry by name.
122 *
123 * Parameter: the list head and the symbolic name to search for
124 *
125 * Returns: The pointer to the entry (or NULL if not found)
126 */
127
128 generic_entry_t *
129 find_name(generic_list_t * head, uint8_t * name)
130 {
131 generic_entry_t *curr;
132
133 if (!*name)
134 return NULL;
135
136 TAILQ_FOREACH(curr, head, link)
137 if (strcmp((char *)curr->sid.name, (char *)name) == 0)
138 break;
139
140 return curr;
141 }
142
143
144 /*
145 * find_sym_id:
146 * Find a list entry by name or numeric id.
147 *
148 * Parameter: the list head and the symbolic id to search for
149 *
150 * Returns: The pointer to the entry (or NULL if not found)
151 */
152
153 generic_entry_t *
154 find_sym_id(generic_list_t * head, iscsid_sym_id_t * sid)
155 {
156
157 if (sid->id != 0)
158 return find_id(head, sid->id);
159
160 return (sid->name[0]) ? find_name(head, sid->name) : NULL;
161 }
162
163
164 /*
165 * get_id:
166 * Get the numeric ID for a symbolic ID
167 *
168 * Parameter: the list head and the symbolic id
169 *
170 * Returns: The numeric ID (0 if not found)
171 */
172
173 uint32_t
174 get_id(generic_list_t * head, iscsid_sym_id_t * sid)
175 {
176 generic_entry_t *ent;
177
178 if (sid->id != 0)
179 return sid->id;
180
181 ent = find_name(head, sid->name);
182 return (ent != NULL) ? ent->sid.id : 0;
183 }
184
185
186 /*
187 * find_target_name:
188 * Find a target by TargetName.
189 *
190 * Parameter: the target name
191 *
192 * Returns: The pointer to the target (or NULL if not found)
193 */
194
195 target_t *
196 find_target(iscsid_list_kind_t lst, iscsid_sym_id_t * sid)
197 {
198 target_t *targ;
199
200 if ((targ = (target_t *)find_sym_id (&list [lst].list, sid)) != NULL)
201 return targ;
202 if (lst == TARGET_LIST) {
203 portal_t *portal;
204
205 if ((portal = find_portal (sid)) != NULL)
206 return portal->target;
207 }
208 return NULL;
209 }
210
211
212 /*
213 * find_target_name:
214 * Find a target by TargetName.
215 *
216 * Parameter: the target name
217 *
218 * Returns: The pointer to the target (or NULL if not found)
219 */
220
221 target_t *
222 find_TargetName(iscsid_list_kind_t lst, uint8_t * name)
223 {
224 generic_entry_t *curr;
225
226 if (lst == PORTAL_LIST)
227 lst = TARGET_LIST;
228
229 TAILQ_FOREACH(curr, &list[lst].list, link)
230 if (strcmp((char *)((target_t *) curr)->TargetName, (char *)name) == 0)
231 break;
232
233 DEB(10, ("Find_TagetName returns %x\n", (int) curr));
234
235 return (target_t *) curr;
236 }
237
238
239 /*
240 * find_portal_by_addr:
241 * Find a Portal by Address.
242 *
243 * Parameter: the associated target, and the address
244 *
245 * Returns: The pointer to the portal (or NULL if not found)
246 */
247
248 portal_t *
249 find_portal_by_addr(target_t * target, iscsi_portal_address_t * addr)
250 {
251 generic_entry_t *curr;
252
253 TAILQ_FOREACH(curr, &list[PORTAL_LIST].list, link) {
254 DEB(10, ("Find_portal_by_addr - addr %s port %d target %x\n",
255 ((portal_t *) curr)->addr.address,
256 ((portal_t *) curr)->addr.port,
257 (int) ((portal_t *) curr)->target));
258
259 if (strcmp((char *)((portal_t *) curr)->addr.address, (char *)addr->address) == 0 &&
260 (!addr->port || ((portal_t *) curr)->addr.port == addr->port) &&
261 ((portal_t *) curr)->target == target)
262 break;
263 }
264
265 DEB(10, ("Find_portal_by_addr returns %x\n", (int) curr));
266 return (portal_t *) curr;
267 }
268
269
270 /*
271 * find_send_target_by_addr:
272 * Find a Send Target by Address.
273 *
274 * Parameter: the address
275 *
276 * Returns: The pointer to the portal (or NULL if not found)
277 */
278
279 send_target_t *
280 find_send_target_by_addr(iscsi_portal_address_t * addr)
281 {
282 generic_entry_t *curr;
283
284 TAILQ_FOREACH(curr, &list[SEND_TARGETS_LIST].list, link) {
285 if (strcmp((char *)((send_target_t *) curr)->addr.address, (char *)addr->address) == 0 &&
286 (!addr->port || ((send_target_t *) curr)->addr.port == addr->port))
287 break;
288 }
289
290 DEB(10, ("Find_send_target_by_addr returns %x\n", (int) curr));
291 return (send_target_t *) curr;
292 }
293
294
295 /*
296 * get_list:
297 * Handle GET_LIST request: Return the list of IDs contained in the list.
298 *
299 * Parameter:
300 * par The request parameters.
301 * prsp Pointer to address of response buffer.
302 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
303 * for static buffer.
304 */
305
306 void
307 get_list(iscsid_get_list_req_t * par, iscsid_response_t ** prsp, int *prsp_temp)
308 {
309 iscsid_get_list_rsp_t *res;
310 iscsid_response_t *rsp = *prsp;
311 int num;
312 uint32_t *idp;
313 generic_list_t *plist;
314 generic_entry_t *curr;
315
316 DEB(10, ("get_list, kind %d\n", par->list_kind));
317
318 if (par->list_kind == SESSION_LIST)
319 LOCK_SESSIONS;
320 else if (par->list_kind >= NUM_DAEMON_LISTS) {
321 rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
322 return;
323 }
324
325 plist = &list[par->list_kind].list;
326 num = list[par->list_kind].num_entries;
327
328 if (!num) {
329 if (par->list_kind == SESSION_LIST)
330 UNLOCK_SESSIONS;
331 rsp->status = ISCSID_STATUS_LIST_EMPTY;
332 return;
333 }
334
335 rsp = make_rsp(sizeof(iscsid_get_list_rsp_t) +
336 (num - 1) * sizeof(uint32_t), prsp, prsp_temp);
337 if (rsp == NULL) {
338 if (par->list_kind == SESSION_LIST)
339 UNLOCK_SESSIONS;
340 return;
341 }
342 /* copy the ID of all list entries */
343 res = (iscsid_get_list_rsp_t *) rsp->parameter;
344 res->num_entries = num;
345 idp = res->id;
346
347 TAILQ_FOREACH(curr, plist, link)
348 * idp++ = curr->sid.id;
349
350 if (par->list_kind == SESSION_LIST)
351 UNLOCK_SESSIONS;
352 }
353
354
355 /*
356 * search_list:
357 * Handle SEARCH_LIST request: Search the given list for the string or
358 * address.
359 * Note: Not all combinations of list and search type make sense.
360 *
361 * Parameter:
362 * par The request parameters.
363 * prsp Pointer to address of response buffer.
364 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
365 * for static buffer.
366 */
367
368 void
369 search_list(iscsid_search_list_req_t * par, iscsid_response_t ** prsp,
370 int *prsp_temp)
371 {
372 iscsid_response_t *rsp = *prsp;
373 generic_entry_t *elem = NULL;
374
375 DEB(10, ("search_list, list_kind %d, search_kind %d\n",
376 par->list_kind, par->search_kind));
377
378 if (par->list_kind == SESSION_LIST)
379 LOCK_SESSIONS;
380 else if (par->list_kind >= NUM_DAEMON_LISTS) {
381 rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
382 return;
383 }
384
385 if (!list[par->list_kind].num_entries) {
386 if (par->list_kind == SESSION_LIST)
387 UNLOCK_SESSIONS;
388 rsp->status = ISCSID_STATUS_NOT_FOUND;
389 return;
390 }
391
392 switch (par->search_kind) {
393 case FIND_ID:
394 elem = find_id(&list[par->list_kind].list, par->intval);
395 break;
396
397 case FIND_NAME:
398 elem = find_name(&list[par->list_kind].list, par->strval);
399 break;
400
401 case FIND_TARGET_NAME:
402 switch (par->list_kind) {
403 case TARGET_LIST:
404 case PORTAL_LIST:
405 case SEND_TARGETS_LIST:
406 elem = (generic_entry_t *) find_TargetName(par->list_kind,
407 par->strval);
408 break;
409
410 case SESSION_LIST:
411 TAILQ_FOREACH(elem, &list[SESSION_LIST].list, link)
412 if (strcmp((char *)((session_t *) elem)->target.TargetName,
413 (char *)par->strval) == 0)
414 break;
415 break;
416
417 default:
418 rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
419 break;
420 }
421 break;
422
423 case FIND_ADDRESS:
424 switch (par->list_kind) {
425 case PORTAL_LIST:
426 TAILQ_FOREACH(elem, &list[PORTAL_LIST].list, link) {
427 if (strcmp((char *)((portal_t *) elem)->addr.address, (char *)par->strval) == 0 &&
428 (!par->intval ||
429 ((portal_t *) elem)->addr.port == par->intval))
430 break;
431 }
432 break;
433
434 case SEND_TARGETS_LIST:
435 TAILQ_FOREACH(elem, &list[SEND_TARGETS_LIST].list, link) {
436 if (strcmp((char *)((send_target_t *) elem)->addr.address,
437 (char *)par->strval) == 0 &&
438 (!par->intval ||
439 ((send_target_t *) elem)->addr.port == par->intval))
440 break;
441 }
442 break;
443
444 case ISNS_LIST:
445 TAILQ_FOREACH(elem, &list[ISNS_LIST].list, link) {
446 if (strcmp((char *)((isns_t *) elem)->address, (char *)par->strval) == 0 &&
447 (!par->intval || ((isns_t *) elem)->port == par->intval))
448 break;
449 }
450 break;
451
452 default:
453 rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
454 break;
455 }
456 break;
457
458 default:
459 rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
460 return;
461 }
462
463 if (elem == NULL) {
464 if (par->list_kind == SESSION_LIST)
465 UNLOCK_SESSIONS;
466 rsp->status = ISCSID_STATUS_NOT_FOUND;
467 return;
468 }
469
470 rsp = make_rsp(sizeof(iscsid_sym_id_t), prsp, prsp_temp);
471 if (rsp == NULL) {
472 if (par->list_kind == SESSION_LIST)
473 UNLOCK_SESSIONS;
474 return;
475 }
476
477 (void) memcpy(rsp->parameter, &elem->sid, sizeof(elem->sid));
478 if (par->list_kind == SESSION_LIST)
479 UNLOCK_SESSIONS;
480 }
481
482
483 /*
484 * get_session_list:
485 * Handle GET_SESSION_LIST request: Return a list of sessions complete
486 * with basic session info.
487 *
488 * Parameter:
489 * prsp Pointer to address of response buffer.
490 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
491 * for static buffer.
492 */
493
494 void
495 get_session_list(iscsid_response_t ** prsp, int *prsp_temp)
496 {
497 iscsid_get_session_list_rsp_t *res;
498 iscsid_response_t *rsp = *prsp;
499 iscsid_session_list_entry_t *ent;
500 generic_list_t *plist;
501 generic_entry_t *curr;
502 session_t *sess;
503 connection_t *conn;
504 int num;
505
506 DEB(10, ("get_session_list\n"));
507
508 LOCK_SESSIONS;
509 plist = &list[SESSION_LIST].list;
510 num = list[SESSION_LIST].num_entries;
511
512 if (!num) {
513 UNLOCK_SESSIONS;
514 rsp->status = ISCSID_STATUS_LIST_EMPTY;
515 return;
516 }
517
518 rsp = make_rsp(sizeof(iscsid_get_session_list_rsp_t) +
519 (num - 1) * sizeof(iscsid_session_list_entry_t),
520 prsp, prsp_temp);
521 if (rsp == NULL) {
522 UNLOCK_SESSIONS;
523 return;
524 }
525 /* copy the ID of all list entries */
526 res = (iscsid_get_session_list_rsp_t *) rsp->parameter;
527 res->num_entries = num;
528 ent = res->session;
529
530 TAILQ_FOREACH(curr, plist, link) {
531 sess = (session_t *) curr;
532 conn = (connection_t *) TAILQ_FIRST(&sess->connections);
533
534 ent->session_id = sess->entry.sid;
535 ent->first_connection_id = conn->entry.sid.id;
536 ent->num_connections = sess->num_connections;
537 ent->portal_id = conn->portal.sid.id;
538 ent->initiator_id = conn->initiator_id;
539 ent++;
540 }
541 UNLOCK_SESSIONS;
542 }
543
544 /*
545 * get_connection_list:
546 * Handle GET_CONNECTION_LIST request: Return a list of connections
547 * for a session.
548 *
549 * Parameter:
550 * prsp Pointer to address of response buffer.
551 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
552 * for static buffer.
553 */
554
555 void
556 get_connection_list(iscsid_sym_id_t *req, iscsid_response_t **prsp,
557 int *prsp_temp)
558 {
559 iscsid_get_connection_list_rsp_t *res;
560 iscsid_response_t *rsp = *prsp;
561 iscsid_connection_list_entry_t *ent;
562 generic_entry_t *curr;
563 session_t *sess;
564 connection_t *conn;
565 int num;
566
567 DEB(10, ("get_connection_list\n"));
568
569 LOCK_SESSIONS;
570 if ((sess = find_session(req)) == NULL) {
571 UNLOCK_SESSIONS;
572 rsp->status = ISCSID_STATUS_INVALID_SESSION_ID;
573 return;
574 }
575
576 num = sess->num_connections;
577 rsp = make_rsp(sizeof(iscsid_get_connection_list_rsp_t) +
578 (num - 1) * sizeof(iscsid_connection_list_entry_t),
579 prsp, prsp_temp);
580 if (rsp == NULL) {
581 UNLOCK_SESSIONS;
582 return;
583 }
584 /* copy the ID of all list entries */
585 res = (iscsid_get_connection_list_rsp_t *) rsp->parameter;
586 res->num_connections = num;
587 ent = res->connection;
588
589 TAILQ_FOREACH(curr, &sess->connections, link) {
590 conn = (connection_t *) curr;
591 ent->connection_id = conn->entry.sid;
592 ent->target_portal_id = conn->portal.sid;
593 ent->target_portal = conn->portal.addr;
594 ent++;
595 }
596 UNLOCK_SESSIONS;
597 }
598
599
600 /*
601 * get_connection_info:
602 * Handle GET_CONNECTION_INFO request: Return information about a connection
603 *
604 * Parameter:
605 * par The request parameters.
606 * prsp Pointer to address of response buffer.
607 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
608 * for static buffer.
609 */
610
611 void
612 get_connection_info(iscsid_get_connection_info_req_t * req,
613 iscsid_response_t ** prsp, int *prsp_temp)
614 {
615 iscsid_get_connection_info_rsp_t *res;
616 iscsid_response_t *rsp = *prsp;
617 session_t *sess;
618 connection_t *conn;
619 initiator_t *init = NULL;
620
621 DEB(10, ("get_connection_info, session %d, connection %d\n",
622 req->session_id.id, req->connection_id.id));
623
624 LOCK_SESSIONS;
625 if ((sess = find_session(&req->session_id)) == NULL) {
626 UNLOCK_SESSIONS;
627 rsp->status = ISCSID_STATUS_INVALID_SESSION_ID;
628 return;
629 }
630 if (!req->connection_id.id && !req->connection_id.name[0]) {
631 conn = (connection_t *) TAILQ_FIRST(&sess->connections);
632 } else if ((conn = find_connection(sess, &req->connection_id)) == NULL) {
633 UNLOCK_SESSIONS;
634 rsp->status = ISCSID_STATUS_INVALID_CONNECTION_ID;
635 return;
636 }
637
638 rsp = make_rsp(sizeof(iscsid_get_connection_info_rsp_t), prsp, prsp_temp);
639 if (rsp == NULL) {
640 UNLOCK_SESSIONS;
641 return;
642 }
643
644 if (conn->initiator_id)
645 init = find_initiator_id(conn->initiator_id);
646
647 res = (iscsid_get_connection_info_rsp_t *) rsp->parameter;
648
649 res->session_id = sess->entry.sid;
650 res->connection_id = conn->entry.sid;
651 res->target_portal_id = conn->portal.sid;
652 res->target_portal = conn->portal.addr;
653 strlcpy((char *)res->TargetName, (char *)conn->target.TargetName,
654 sizeof(res->TargetName));
655 strlcpy((char *)res->TargetAlias, (char *)conn->target.TargetAlias,
656 sizeof(res->TargetAlias));
657 if (init != NULL) {
658 res->initiator_id = init->entry.sid;
659 strlcpy((char *)res->initiator_address, (char *)init->address,
660 sizeof(res->initiator_address));
661 }
662 UNLOCK_SESSIONS;
663 }
664
665 /* ------------------------------------------------------------------------- */
666
667 /*
668 * find_initator_by_addr:
669 * Find an Initiator Portal by Address.
670 *
671 * Parameter: the address
672 *
673 * Returns: The pointer to the portal (or NULL if not found)
674 */
675
676 STATIC initiator_t *
677 find_initiator_by_addr(uint8_t * addr)
678 {
679 generic_entry_t *curr;
680
681 TAILQ_FOREACH(curr, &list[INITIATOR_LIST].list, link)
682 if (strcmp((char *)((initiator_t *) curr)->address, (char *)addr) == 0)
683 break;
684
685 DEB(9, ("Find_initiator_by_addr returns %x\n", (int) curr));
686 return (initiator_t *) curr;
687 }
688
689
690 /*
691 * add_initiator_portal:
692 * Add an initiator portal.
693 *
694 * Parameter:
695 * par The request parameters.
696 * prsp Pointer to address of response buffer.
697 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
698 * for static buffer.
699 */
700
701 void
702 add_initiator_portal(iscsid_add_initiator_req_t *par, iscsid_response_t **prsp,
703 int *prsp_temp)
704 {
705 iscsid_add_initiator_rsp_t *res;
706 iscsid_response_t *rsp = *prsp;
707 initiator_t *init;
708
709 DEB(9, ("AddInitiatorPortal '%s' (name '%s')\n", par->address, par->name));
710
711 if (find_initiator_by_addr(par->address) != NULL) {
712 rsp->status = ISCSID_STATUS_DUPLICATE_ENTRY;
713 return;
714 }
715
716 if (find_initiator_name(par->name) != NULL) {
717 rsp->status = ISCSID_STATUS_DUPLICATE_NAME;
718 return;
719 }
720
721 if ((init = calloc(1, sizeof(*init))) == NULL) {
722 rsp->status = ISCSID_STATUS_NO_RESOURCES;
723 return;
724 }
725
726 DEB(9, ("AddInitiatorPortal initiator_id = %d\n", initiator_id));
727
728 for (initiator_id++;
729 !initiator_id || find_initiator_id(initiator_id) != NULL;)
730 initiator_id++;
731
732 init->entry.sid.id = initiator_id;
733 strlcpy((char *)init->entry.sid.name, (char *)par->name, sizeof(init->entry.sid.name));
734 strlcpy((char *)init->address, (char *)par->address, sizeof(init->address));
735
736 rsp = make_rsp(sizeof(iscsid_add_initiator_rsp_t), prsp, prsp_temp);
737 if (rsp == NULL)
738 return;
739
740 LOCK_SESSIONS;
741 TAILQ_INSERT_TAIL(&list[INITIATOR_LIST].list, &init->entry, link);
742 list[INITIATOR_LIST].num_entries++;
743 UNLOCK_SESSIONS;
744
745 res = (iscsid_add_initiator_rsp_t *) rsp->parameter;
746 res->portal_id = init->entry.sid.id;
747 }
748
749
750 /*
751 * remove_initiator_portal:
752 * Handle REMOVE_INITIATOR request: Removes an initiator entry.
753 *
754 * Parameter:
755 * par The request parameter containing the ID.
756 *
757 * Returns: status
758 */
759
760 uint32_t
761 remove_initiator_portal(iscsid_sym_id_t * par)
762 {
763 initiator_t *init;
764
765 if ((init = find_initiator(par)) == NULL)
766 return ISCSID_STATUS_INVALID_INITIATOR_ID;
767
768 LOCK_SESSIONS;
769 list[INITIATOR_LIST].num_entries--;
770
771 TAILQ_REMOVE(&list[INITIATOR_LIST].list, &init->entry, link);
772 UNLOCK_SESSIONS;
773
774 free(init);
775
776 return ISCSID_STATUS_SUCCESS;
777 }
778
779
780
781 /*
782 * get_initiator_portal:
783 * Handle GET_INITIATOR_PORTAL request: Return information about the given
784 * initiator portal.
785 *
786 * Parameter:
787 * par The request parameters.
788 * prsp Pointer to address of response buffer.
789 * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
790 * for static buffer.
791 */
792
793 void
794 get_initiator_portal(iscsid_sym_id_t *par, iscsid_response_t **prsp,
795 int *prsp_temp)
796 {
797 iscsid_get_initiator_rsp_t *res;
798 iscsid_response_t *rsp = *prsp;
799 initiator_t *init;
800
801 DEB(10, ("get_initiator_portal, id %d (%s)\n", par->id, par->name));
802
803 if ((init = find_initiator(par)) == NULL) {
804 rsp->status = ISCSID_STATUS_INVALID_INITIATOR_ID;
805 return;
806 }
807
808 rsp = make_rsp(sizeof(iscsid_get_initiator_rsp_t), prsp, prsp_temp);
809 if (rsp == NULL)
810 return;
811
812 res = (iscsid_get_initiator_rsp_t *) rsp->parameter;
813 res->portal_id = init->entry.sid;
814 strlcpy((char *)res->address, (char *)init->address, sizeof(res->address));
815 }
816
817
818 /*
819 * select_initiator:
820 * Select the initiator portal to use.
821 * Selects the portal with the least number of active connections.
822 *
823 * Returns:
824 * Pointer to the portal, NULL if no portals are defined.
825 *
826 * NOTE: Called with session list locked, so don't lock again.
827 */
828
829 initiator_t *
830 select_initiator(void)
831 {
832 generic_entry_t *curr;
833 initiator_t *imin = NULL;
834 uint32_t ccnt = 64 * 1024; /* probably not more than 64k connections... */
835
836 if (!list[INITIATOR_LIST].num_entries)
837 return NULL;
838
839 TAILQ_FOREACH(curr, &list[INITIATOR_LIST].list, link) {
840 if ((((initiator_t *) curr)->active_connections < ccnt)) {
841 ccnt = ((initiator_t *) curr)->active_connections;
842 imin = (initiator_t *) curr;
843 }
844 }
845 return imin;
846 }
847
848 /* ------------------------------------------------------------------------- */
849
850 /*
851 * event_kill_session:
852 * Handle SESSION_TERMINATED event: Remove session and all associated
853 * connections.
854 *
855 * Parameter:
856 * sid Session ID
857 */
858
859 void
860 event_kill_session(uint32_t sid)
861 {
862 session_t *sess;
863 connection_t *conn;
864 portal_t *portal;
865 initiator_t *init;
866
867 LOCK_SESSIONS;
868
869 sess = find_session_id(sid);
870
871 if (sess == NULL) {
872 UNLOCK_SESSIONS;
873 return;
874 }
875
876 TAILQ_REMOVE(&list[SESSION_LIST].list, &sess->entry, link);
877 list[SESSION_LIST].num_entries--;
878
879 UNLOCK_SESSIONS;
880
881 while ((conn = (connection_t *) TAILQ_FIRST(&sess->connections)) != NULL) {
882 TAILQ_REMOVE(&sess->connections, &conn->entry, link);
883
884 portal = find_portal_id(conn->portal.sid.id);
885 if (portal != NULL)
886 portal->active_connections--;
887
888 init = find_initiator_id(conn->initiator_id);
889 if (init != NULL)
890 init->active_connections--;
891
892 free(conn);
893 }
894 free(sess);
895 }
896
897
898 /*
899 * event_kill_connection:
900 * Handle CONNECTION_TERMINATED event: Remove connection from session.
901 *
902 * Parameter:
903 * sid Session ID
904 * cid Connection ID
905 */
906
907 void
908 event_kill_connection(uint32_t sid, uint32_t cid)
909 {
910 session_t *sess;
911 connection_t *conn;
912 portal_t *portal;
913 initiator_t *init;
914
915 LOCK_SESSIONS;
916
917 sess = find_session_id(sid);
918 if (sess == NULL) {
919 UNLOCK_SESSIONS;
920 return;
921 }
922
923 conn = find_connection_id(sess, cid);
924 if (conn == NULL) {
925 UNLOCK_SESSIONS;
926 return;
927 }
928
929 TAILQ_REMOVE(&sess->connections, &conn->entry, link);
930 sess->num_connections--;
931
932 init = find_initiator_id(conn->initiator_id);
933 if (init != NULL)
934 init->active_connections--;
935
936 UNLOCK_SESSIONS;
937
938 portal = find_portal_id(conn->portal.sid.id);
939 if (portal != NULL)
940 portal->active_connections--;
941
942 free(conn);
943 }
944