xref: /freebsd/usr.sbin/ctld/conf.cc (revision 2736dc8c28a33ba911fd59f87b587a3d9722e975)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2012 The FreeBSD Foundation
5  *
6  * This software was developed by Edward Tomasz Napierala under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31 
32 #include <sys/types.h>
33 #include <assert.h>
34 #include <stddef.h>
35 #include <stdint.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <string.h>
40 #include <cam/scsi/scsi_all.h>
41 
42 #include "conf.h"
43 #include "ctld.h"
44 
45 static struct conf *conf = NULL;
46 static struct auth_group *auth_group = NULL;
47 static struct portal_group *portal_group = NULL;
48 static struct target *target = NULL;
49 static struct lun *lun = NULL;
50 
51 void
conf_start(struct conf * new_conf)52 conf_start(struct conf *new_conf)
53 {
54 	assert(conf == NULL);
55 	conf = new_conf;
56 }
57 
58 void
conf_finish(void)59 conf_finish(void)
60 {
61 	auth_group = NULL;
62 	portal_group = NULL;
63 	target = NULL;
64 	lun = NULL;
65 	conf = NULL;
66 }
67 
68 bool
isns_add_server(const char * addr)69 isns_add_server(const char *addr)
70 {
71 	return (isns_new(conf, addr));
72 }
73 
74 void
conf_set_debug(int debug)75 conf_set_debug(int debug)
76 {
77 	conf->conf_debug = debug;
78 }
79 
80 void
conf_set_isns_period(int period)81 conf_set_isns_period(int period)
82 {
83 	conf->conf_isns_period = period;
84 }
85 
86 void
conf_set_isns_timeout(int timeout)87 conf_set_isns_timeout(int timeout)
88 {
89 	conf->conf_isns_timeout = timeout;
90 }
91 
92 void
conf_set_maxproc(int maxproc)93 conf_set_maxproc(int maxproc)
94 {
95 	conf->conf_maxproc = maxproc;
96 }
97 
98 bool
conf_set_pidfile_path(const char * path)99 conf_set_pidfile_path(const char *path)
100 {
101 	if (conf->conf_pidfile_path != NULL) {
102 		log_warnx("pidfile specified more than once");
103 		return (false);
104 	}
105 	conf->conf_pidfile_path = checked_strdup(path);
106 	return (true);
107 }
108 
109 void
conf_set_timeout(int timeout)110 conf_set_timeout(int timeout)
111 {
112 	conf->conf_timeout = timeout;
113 }
114 
115 static bool
_auth_group_set_type(struct auth_group * ag,const char * str)116 _auth_group_set_type(struct auth_group *ag, const char *str)
117 {
118 	int type;
119 
120 	if (strcmp(str, "none") == 0) {
121 		type = AG_TYPE_NO_AUTHENTICATION;
122 	} else if (strcmp(str, "deny") == 0) {
123 		type = AG_TYPE_DENY;
124 	} else if (strcmp(str, "chap") == 0) {
125 		type = AG_TYPE_CHAP;
126 	} else if (strcmp(str, "chap-mutual") == 0) {
127 		type = AG_TYPE_CHAP_MUTUAL;
128 	} else {
129 		log_warnx("invalid auth-type \"%s\" for %s", str, ag->ag_label);
130 		return (false);
131 	}
132 
133 	if (ag->ag_type != AG_TYPE_UNKNOWN && ag->ag_type != type) {
134 		log_warnx("cannot set auth-type to \"%s\" for %s; "
135 		    "already has a different type", str, ag->ag_label);
136 		return (false);
137 	}
138 
139 	ag->ag_type = type;
140 
141 	return (true);
142 }
143 
144 bool
auth_group_add_chap(const char * user,const char * secret)145 auth_group_add_chap(const char *user, const char *secret)
146 {
147 	return (auth_new_chap(auth_group, user, secret));
148 }
149 
150 bool
auth_group_add_chap_mutual(const char * user,const char * secret,const char * user2,const char * secret2)151 auth_group_add_chap_mutual(const char *user, const char *secret,
152     const char *user2, const char *secret2)
153 {
154 	return (auth_new_chap_mutual(auth_group, user, secret, user2, secret2));
155 }
156 
157 bool
auth_group_add_initiator_name(const char * name)158 auth_group_add_initiator_name(const char *name)
159 {
160 	return (auth_name_new(auth_group, name));
161 }
162 
163 bool
auth_group_add_initiator_portal(const char * portal)164 auth_group_add_initiator_portal(const char *portal)
165 {
166 	return (auth_portal_new(auth_group, portal));
167 }
168 
169 bool
auth_group_set_type(const char * type)170 auth_group_set_type(const char *type)
171 {
172 	return (_auth_group_set_type(auth_group, type));
173 }
174 
175 bool
auth_group_start(const char * name)176 auth_group_start(const char *name)
177 {
178 	/*
179 	 * Make it possible to redefine the default auth-group. but
180 	 * only once.
181 	 */
182 	if (strcmp(name, "default") == 0) {
183 		if (conf->conf_default_ag_defined) {
184 			log_warnx("duplicated auth-group \"default\"");
185 			return (false);
186 		}
187 
188 		conf->conf_default_ag_defined = true;
189 		auth_group = auth_group_find(conf, "default");
190 		return (true);
191 	}
192 
193 	auth_group = auth_group_new(conf, name);
194 	return (auth_group != NULL);
195 }
196 
197 void
auth_group_finish(void)198 auth_group_finish(void)
199 {
200 	auth_group = NULL;
201 }
202 
203 bool
portal_group_start(const char * name)204 portal_group_start(const char *name)
205 {
206 	/*
207 	 * Make it possible to redefine the default portal-group. but
208 	 * only once.
209 	 */
210 	if (strcmp(name, "default") == 0) {
211 		if (conf->conf_default_pg_defined) {
212 			log_warnx("duplicated portal-group \"default\"");
213 			return (false);
214 		}
215 
216 		conf->conf_default_pg_defined = true;
217 		portal_group = portal_group_find(conf, "default");
218 		return (true);
219 	}
220 
221 	portal_group = portal_group_new(conf, name);
222 	return (portal_group != NULL);
223 }
224 
225 void
portal_group_finish(void)226 portal_group_finish(void)
227 {
228 	portal_group = NULL;
229 }
230 
231 bool
portal_group_add_listen(const char * listen,bool iser)232 portal_group_add_listen(const char *listen, bool iser)
233 {
234 	return (portal_group_add_portal(portal_group, listen, iser));
235 }
236 
237 bool
portal_group_add_option(const char * name,const char * value)238 portal_group_add_option(const char *name, const char *value)
239 {
240 	return (option_new(portal_group->pg_options, name, value));
241 }
242 
243 bool
portal_group_set_discovery_auth_group(const char * name)244 portal_group_set_discovery_auth_group(const char *name)
245 {
246 	if (portal_group->pg_discovery_auth_group != NULL) {
247 		log_warnx("discovery-auth-group for portal-group "
248 		    "\"%s\" specified more than once",
249 		    portal_group->pg_name);
250 		return (false);
251 	}
252 	portal_group->pg_discovery_auth_group = auth_group_find(conf, name);
253 	if (portal_group->pg_discovery_auth_group == NULL) {
254 		log_warnx("unknown discovery-auth-group \"%s\" "
255 		    "for portal-group \"%s\"", name, portal_group->pg_name);
256 		return (false);
257 	}
258 	return (true);
259 }
260 
261 bool
portal_group_set_dscp(u_int dscp)262 portal_group_set_dscp(u_int dscp)
263 {
264 	if (dscp >= 0x40) {
265 		log_warnx("invalid DSCP value %u for portal-group \"%s\"",
266 		    dscp, portal_group->pg_name);
267 		return (false);
268 	}
269 
270 	portal_group->pg_dscp = dscp;
271 	return (true);
272 }
273 
274 bool
portal_group_set_filter(const char * str)275 portal_group_set_filter(const char *str)
276 {
277 	int filter;
278 
279 	if (strcmp(str, "none") == 0) {
280 		filter = PG_FILTER_NONE;
281 	} else if (strcmp(str, "portal") == 0) {
282 		filter = PG_FILTER_PORTAL;
283 	} else if (strcmp(str, "portal-name") == 0) {
284 		filter = PG_FILTER_PORTAL_NAME;
285 	} else if (strcmp(str, "portal-name-auth") == 0) {
286 		filter = PG_FILTER_PORTAL_NAME_AUTH;
287 	} else {
288 		log_warnx("invalid discovery-filter \"%s\" for portal-group "
289 		    "\"%s\"; valid values are \"none\", \"portal\", "
290 		    "\"portal-name\", and \"portal-name-auth\"",
291 		    str, portal_group->pg_name);
292 		return (false);
293 	}
294 
295 	if (portal_group->pg_discovery_filter != PG_FILTER_UNKNOWN &&
296 	    portal_group->pg_discovery_filter != filter) {
297 		log_warnx("cannot set discovery-filter to \"%s\" for "
298 		    "portal-group \"%s\"; already has a different "
299 		    "value", str, portal_group->pg_name);
300 		return (false);
301 	}
302 
303 	portal_group->pg_discovery_filter = filter;
304 
305 	return (true);
306 }
307 
308 void
portal_group_set_foreign(void)309 portal_group_set_foreign(void)
310 {
311 	portal_group->pg_foreign = true;
312 }
313 
314 bool
portal_group_set_offload(const char * offload)315 portal_group_set_offload(const char *offload)
316 {
317 
318 	if (portal_group->pg_offload != NULL) {
319 		log_warnx("cannot set offload to \"%s\" for "
320 		    "portal-group \"%s\"; already defined",
321 		    offload, portal_group->pg_name);
322 		return (false);
323 	}
324 
325 	portal_group->pg_offload = checked_strdup(offload);
326 
327 	return (true);
328 }
329 
330 bool
portal_group_set_pcp(u_int pcp)331 portal_group_set_pcp(u_int pcp)
332 {
333 	if (pcp > 7) {
334 		log_warnx("invalid PCP value %u for portal-group \"%s\"",
335 		    pcp, portal_group->pg_name);
336 		return (false);
337 	}
338 
339 	portal_group->pg_pcp = pcp;
340 	return (true);
341 }
342 
343 bool
portal_group_set_redirection(const char * addr)344 portal_group_set_redirection(const char *addr)
345 {
346 
347 	if (portal_group->pg_redirection != NULL) {
348 		log_warnx("cannot set redirection to \"%s\" for "
349 		    "portal-group \"%s\"; already defined",
350 		    addr, portal_group->pg_name);
351 		return (false);
352 	}
353 
354 	portal_group->pg_redirection = checked_strdup(addr);
355 
356 	return (true);
357 }
358 
359 void
portal_group_set_tag(uint16_t tag)360 portal_group_set_tag(uint16_t tag)
361 {
362 	portal_group->pg_tag = tag;
363 }
364 
365 bool
lun_start(const char * name)366 lun_start(const char *name)
367 {
368 	lun = lun_new(conf, name);
369 	return (lun != NULL);
370 }
371 
372 void
lun_finish(void)373 lun_finish(void)
374 {
375 	lun = NULL;
376 }
377 
378 bool
lun_add_option(const char * name,const char * value)379 lun_add_option(const char *name, const char *value)
380 {
381 	return (option_new(lun->l_options, name, value));
382 }
383 
384 bool
lun_set_backend(const char * value)385 lun_set_backend(const char *value)
386 {
387 	if (lun->l_backend != NULL) {
388 		log_warnx("backend for lun \"%s\" specified more than once",
389 		    lun->l_name);
390 		return (false);
391 	}
392 
393 	lun->l_backend = checked_strdup(value);
394 	return (true);
395 }
396 
397 bool
lun_set_blocksize(size_t value)398 lun_set_blocksize(size_t value)
399 {
400 	if (lun->l_blocksize != 0) {
401 		log_warnx("blocksize for lun \"%s\" specified more than once",
402 		    lun->l_name);
403 		return (false);
404 	}
405 	lun->l_blocksize = value;
406 	return (true);
407 }
408 
409 bool
lun_set_device_type(const char * value)410 lun_set_device_type(const char *value)
411 {
412 	uint64_t device_type;
413 
414 	if (strcasecmp(value, "disk") == 0 ||
415 	    strcasecmp(value, "direct") == 0)
416 		device_type = T_DIRECT;
417 	else if (strcasecmp(value, "processor") == 0)
418 		device_type = T_PROCESSOR;
419 	else if (strcasecmp(value, "cd") == 0 ||
420 	    strcasecmp(value, "cdrom") == 0 ||
421 	    strcasecmp(value, "dvd") == 0 ||
422 	    strcasecmp(value, "dvdrom") == 0)
423 		device_type = T_CDROM;
424 	else if (expand_number(value, &device_type) != 0 || device_type > 15) {
425 		log_warnx("invalid device-type \"%s\" for lun \"%s\"", value,
426 		    lun->l_name);
427 		return (false);
428 	}
429 
430 	lun->l_device_type = device_type;
431 	return (true);
432 }
433 
434 bool
lun_set_device_id(const char * value)435 lun_set_device_id(const char *value)
436 {
437 	if (lun->l_device_id != NULL) {
438 		log_warnx("device_id for lun \"%s\" specified more than once",
439 		    lun->l_name);
440 		return (false);
441 	}
442 
443 	lun->l_device_id = checked_strdup(value);
444 	return (true);
445 }
446 
447 bool
lun_set_path(const char * value)448 lun_set_path(const char *value)
449 {
450 	if (lun->l_path != NULL) {
451 		log_warnx("path for lun \"%s\" specified more than once",
452 		    lun->l_name);
453 		return (false);
454 	}
455 
456 	lun->l_path = checked_strdup(value);
457 	return (true);
458 }
459 
460 bool
lun_set_serial(const char * value)461 lun_set_serial(const char *value)
462 {
463 	if (lun->l_serial != NULL) {
464 		log_warnx("serial for lun \"%s\" specified more than once",
465 		    lun->l_name);
466 		return (false);
467 	}
468 
469 	lun->l_serial = checked_strdup(value);
470 	return (true);
471 }
472 
473 bool
lun_set_size(uint64_t value)474 lun_set_size(uint64_t value)
475 {
476 	if (lun->l_size != 0) {
477 		log_warnx("size for lun \"%s\" specified more than once",
478 		    lun->l_name);
479 		return (false);
480 	}
481 
482 	lun->l_size = value;
483 	return (true);
484 }
485 
486 bool
lun_set_ctl_lun(uint32_t value)487 lun_set_ctl_lun(uint32_t value)
488 {
489 
490 	if (lun->l_ctl_lun >= 0) {
491 		log_warnx("ctl_lun for lun \"%s\" specified more than once",
492 		    lun->l_name);
493 		return (false);
494 	}
495 	lun->l_ctl_lun = value;
496 	return (true);
497 }
498 
499 bool
target_start(const char * name)500 target_start(const char *name)
501 {
502 	target = target_new(conf, name);
503 	return (target != NULL);
504 }
505 
506 void
target_finish(void)507 target_finish(void)
508 {
509 	target = NULL;
510 }
511 
512 bool
target_add_chap(const char * user,const char * secret)513 target_add_chap(const char *user, const char *secret)
514 {
515 	if (target->t_auth_group != NULL) {
516 		if (target->t_auth_group->ag_name != NULL) {
517 			log_warnx("cannot use both auth-group and "
518 			    "chap for target \"%s\"", target->t_name);
519 			return (false);
520 		}
521 	} else {
522 		target->t_auth_group = auth_group_new(conf, target);
523 		if (target->t_auth_group == NULL)
524 			return (false);
525 	}
526 	return (auth_new_chap(target->t_auth_group, user, secret));
527 }
528 
529 bool
target_add_chap_mutual(const char * user,const char * secret,const char * user2,const char * secret2)530 target_add_chap_mutual(const char *user, const char *secret,
531     const char *user2, const char *secret2)
532 {
533 	if (target->t_auth_group != NULL) {
534 		if (target->t_auth_group->ag_name != NULL) {
535 			log_warnx("cannot use both auth-group and "
536 			    "chap-mutual for target \"%s\"", target->t_name);
537 			return (false);
538 		}
539 	} else {
540 		target->t_auth_group = auth_group_new(conf, target);
541 		if (target->t_auth_group == NULL)
542 			return (false);
543 	}
544 	return (auth_new_chap_mutual(target->t_auth_group, user, secret, user2,
545 	    secret2));
546 }
547 
548 bool
target_add_initiator_name(const char * name)549 target_add_initiator_name(const char *name)
550 {
551 	if (target->t_auth_group != NULL) {
552 		if (target->t_auth_group->ag_name != NULL) {
553 			log_warnx("cannot use both auth-group and "
554 			    "initiator-name for target \"%s\"", target->t_name);
555 			return (false);
556 		}
557 	} else {
558 		target->t_auth_group = auth_group_new(conf, target);
559 		if (target->t_auth_group == NULL)
560 			return (false);
561 	}
562 	return (auth_name_new(target->t_auth_group, name));
563 }
564 
565 bool
target_add_initiator_portal(const char * addr)566 target_add_initiator_portal(const char *addr)
567 {
568 	if (target->t_auth_group != NULL) {
569 		if (target->t_auth_group->ag_name != NULL) {
570 			log_warnx("cannot use both auth-group and "
571 			    "initiator-portal for target \"%s\"",
572 			    target->t_name);
573 			return (false);
574 		}
575 	} else {
576 		target->t_auth_group = auth_group_new(conf, target);
577 		if (target->t_auth_group == NULL)
578 			return (false);
579 	}
580 	return (auth_portal_new(target->t_auth_group, addr));
581 }
582 
583 bool
target_add_lun(u_int id,const char * name)584 target_add_lun(u_int id, const char *name)
585 {
586 	struct lun *t_lun;
587 
588 	if (id >= MAX_LUNS) {
589 		log_warnx("LUN %u too big for target \"%s\"", id,
590 		    target->t_name);
591 		return (false);
592 	}
593 
594 	if (target->t_luns[id] != NULL) {
595 		log_warnx("duplicate LUN %u for target \"%s\"", id,
596 		    target->t_name);
597 		return (false);
598 	}
599 
600 	t_lun = lun_find(conf, name);
601 	if (t_lun == NULL) {
602 		log_warnx("unknown LUN named %s used for target \"%s\"",
603 		    name, target->t_name);
604 		return (false);
605 	}
606 
607 	target->t_luns[id] = t_lun;
608 	return (true);
609 }
610 
611 bool
target_add_portal_group(const char * pg_name,const char * ag_name)612 target_add_portal_group(const char *pg_name, const char *ag_name)
613 {
614 	struct portal_group *pg;
615 	struct auth_group *ag;
616 	struct port *p;
617 
618 	pg = portal_group_find(conf, pg_name);
619 	if (pg == NULL) {
620 		log_warnx("unknown portal-group \"%s\" for target \"%s\"",
621 		    pg_name, target->t_name);
622 		return (false);
623 	}
624 
625 	if (ag_name != NULL) {
626 		ag = auth_group_find(conf, ag_name);
627 		if (ag == NULL) {
628 			log_warnx("unknown auth-group \"%s\" for target \"%s\"",
629 			    ag_name, target->t_name);
630 			return (false);
631 		}
632 	} else
633 		ag = NULL;
634 
635 	p = port_new(conf, target, pg);
636 	if (p == NULL) {
637 		log_warnx("can't link portal-group \"%s\" to target \"%s\"",
638 		    pg_name, target->t_name);
639 		return (false);
640 	}
641 	p->p_auth_group = ag;
642 	return (true);
643 }
644 
645 bool
target_set_alias(const char * alias)646 target_set_alias(const char *alias)
647 {
648 	if (target->t_alias != NULL) {
649 		log_warnx("alias for target \"%s\" specified more than once",
650 		    target->t_name);
651 		return (false);
652 	}
653 	target->t_alias = checked_strdup(alias);
654 	return (true);
655 }
656 
657 bool
target_set_auth_group(const char * name)658 target_set_auth_group(const char *name)
659 {
660 	if (target->t_auth_group != NULL) {
661 		if (target->t_auth_group->ag_name != NULL)
662 			log_warnx("auth-group for target \"%s\" "
663 			    "specified more than once", target->t_name);
664 		else
665 			log_warnx("cannot use both auth-group and explicit "
666 			    "authorisations for target \"%s\"", target->t_name);
667 		return (false);
668 	}
669 	target->t_auth_group = auth_group_find(conf, name);
670 	if (target->t_auth_group == NULL) {
671 		log_warnx("unknown auth-group \"%s\" for target \"%s\"", name,
672 		    target->t_name);
673 		return (false);
674 	}
675 	return (true);
676 }
677 
678 bool
target_set_auth_type(const char * type)679 target_set_auth_type(const char *type)
680 {
681 	if (target->t_auth_group != NULL) {
682 		if (target->t_auth_group->ag_name != NULL) {
683 			log_warnx("cannot use both auth-group and "
684 			    "auth-type for target \"%s\"", target->t_name);
685 			return (false);
686 		}
687 	} else {
688 		target->t_auth_group = auth_group_new(conf, target);
689 		if (target->t_auth_group == NULL)
690 			return (false);
691 	}
692 	return (_auth_group_set_type(target->t_auth_group, type));
693 }
694 
695 bool
target_set_physical_port(const char * pport)696 target_set_physical_port(const char *pport)
697 {
698 	if (target->t_pport != NULL) {
699 		log_warnx("cannot set multiple physical ports for target "
700 		    "\"%s\"", target->t_name);
701 		return (false);
702 	}
703 	target->t_pport = checked_strdup(pport);
704 	return (true);
705 }
706 
707 bool
target_set_redirection(const char * addr)708 target_set_redirection(const char *addr)
709 {
710 
711 	if (target->t_redirection != NULL) {
712 		log_warnx("cannot set redirection to \"%s\" for "
713 		    "target \"%s\"; already defined",
714 		    addr, target->t_name);
715 		return (false);
716 	}
717 
718 	target->t_redirection = checked_strdup(addr);
719 
720 	return (true);
721 }
722 
723 bool
target_start_lun(u_int id)724 target_start_lun(u_int id)
725 {
726 	struct lun *new_lun;
727 	char *name;
728 
729 	if (id >= MAX_LUNS) {
730 		log_warnx("LUN %u too big for target \"%s\"", id,
731 		    target->t_name);
732 		return (false);
733 	}
734 
735 	if (target->t_luns[id] != NULL) {
736 		log_warnx("duplicate LUN %u for target \"%s\"", id,
737 		    target->t_name);
738 		return (false);
739 	}
740 
741 	if (asprintf(&name, "%s,lun,%u", target->t_name, id) <= 0)
742 		log_err(1, "asprintf");
743 
744 	new_lun = lun_new(conf, name);
745 	if (new_lun == NULL)
746 		return (false);
747 
748 	lun_set_scsiname(new_lun, name);
749 	free(name);
750 
751 	target->t_luns[id] = new_lun;
752 
753 	lun = new_lun;
754 	return (true);
755 }
756