iscsiadm: add netconfig support
[open-iscsi.git] / usr / iface.c
blob5d5f7bf4c5e62afa98c38412d5d72e6501ff15ad
1 /*
2 * iSCSI iface helpers
4 * Copyright (C) 2008 Mike Christie
5 * Copyright (C) 2008 Red Hat, Inc. All rights reserved.
6 * maintained by open-iscsi@@googlegroups.com
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published
10 * by the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * See the file COPYING included with this distribution for more details.
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <limits.h>
23 #include <dirent.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <arpa/inet.h>
31 #include "log.h"
32 #include "list.h"
33 #include "iscsi_sysfs.h"
34 #include "iscsi_settings.h"
35 #include "config.h"
36 #include "transport.h"
37 #include "idbm.h"
38 #include "iface.h"
39 #include "session_info.h"
40 #include "host.h"
41 #include "fw_context.h"
42 #include "sysdeps.h"
43 #include "iscsi_err.h"
46 * Default ifaces for use with transports that do not bind to hardware
47 * by defaults (transports that let the interconnect layer to the routing
48 * by defaults).
52 * iSCSI over TCP/IP
54 static struct iface_rec iface_default = {
55 .name = "default",
56 .transport_name = "tcp",
60 * iSER
62 static struct iface_rec iface_iser = {
63 .name = "iser",
64 .transport_name = "iser",
67 static struct iface_rec *default_ifaces[] = {
68 &iface_default,
69 &iface_iser,
70 NULL,
73 static struct iface_rec *iface_match_default(struct iface_rec *iface)
75 struct iface_rec *def_iface;
76 int i = 0;
78 while ((def_iface = default_ifaces[i++])) {
79 if (!strcmp(iface->name, def_iface->name))
80 return def_iface;
82 return NULL;
85 static void iface_init(struct iface_rec *iface)
87 if (!strlen(iface->name))
88 sprintf(iface->name, DEFAULT_IFACENAME);
92 * default is to use tcp through whatever the network layer
93 * selects for us with the /etc/iscsi/initiatorname.iscsi iname.
95 void iface_setup_defaults(struct iface_rec *iface)
97 sprintf(iface->transport_name, DEFAULT_TRANSPORT);
98 iface_init(iface);
101 struct iface_rec *iface_alloc(char *ifname, int *err)
103 struct iface_rec *iface;
105 if (!strlen(ifname) || strlen(ifname) + 1 > ISCSI_MAX_IFACE_LEN) {
106 *err = ISCSI_ERR_INVAL;
107 return NULL;
110 iface = calloc(1, sizeof(*iface));
111 if (!iface) {
112 *err = ISCSI_ERR_NOMEM;
113 return NULL;
116 strlcpy(iface->name, ifname, ISCSI_MAX_IFACE_LEN);
117 INIT_LIST_HEAD(&iface->list);
118 return iface;
121 static int __iface_conf_read(struct iface_rec *iface)
123 char *iface_conf;
124 recinfo_t *info;
125 FILE *f;
126 int rc = 0;
128 iface_conf = calloc(1, PATH_MAX);
129 if (!iface_conf)
130 return ISCSI_ERR_NOMEM;
132 info = idbm_recinfo_alloc(MAX_KEYS);
133 if (!info) {
134 rc = ISCSI_ERR_NOMEM;
135 goto free_conf;
138 snprintf(iface_conf, PATH_MAX, "%s/%s", IFACE_CONFIG_DIR,
139 iface->name);
141 log_debug(5, "looking for iface conf %s", iface_conf);
142 f = fopen(iface_conf, "r");
143 if (!f) {
145 * if someone passes in default but has not defined
146 * a iface with default then we do it for them
148 if (!strcmp(iface->name, DEFAULT_IFACENAME)) {
149 iface_setup_defaults(iface);
150 rc = 0;
151 } else
152 rc = ISCSI_ERR_IDBM;
153 goto free_info;
156 iface_init(iface);
157 idbm_recinfo_iface(iface, info);
158 idbm_recinfo_config(info, f);
159 fclose(f);
161 free_info:
162 free(info);
163 free_conf:
164 free(iface_conf);
165 return rc;
168 int iface_conf_read(struct iface_rec *iface)
170 struct iface_rec *def_iface;
171 int rc;
173 def_iface = iface_match_default(iface);
174 if (def_iface) {
176 * older tools allowed default to have different
177 * transport_names so we do not want to overwrite
178 * it.
180 if (!strcmp(def_iface->name, DEFAULT_IFACENAME)) {
181 if (!strlen(iface->name))
182 strcpy(iface->name, def_iface->name);
183 if (!strlen(iface->netdev))
184 strcpy(iface->netdev, def_iface->netdev);
185 if (!strlen(iface->hwaddress))
186 strcpy(iface->hwaddress, def_iface->hwaddress);
187 if (!strlen(iface->transport_name))
188 strcpy(iface->transport_name,
189 def_iface->transport_name);
190 if (!strlen(iface->iname))
191 strcpy(iface->iname, def_iface->iname);
192 } else {
193 iface_init(iface);
194 iface_copy(iface, def_iface);
196 return 0;
199 rc = idbm_lock();
200 if (rc)
201 return rc;
203 rc = __iface_conf_read(iface);
204 idbm_unlock();
205 return rc;
208 int iface_conf_delete(struct iface_rec *iface)
210 struct iface_rec *def_iface;
211 char *iface_conf;
212 int rc = 0;
214 def_iface = iface_match_default(iface);
215 if (def_iface) {
216 log_error("iface %s is a special interface and "
217 "cannot be deleted.\n", iface->name);
218 return ISCSI_ERR_INVAL;
221 iface_conf = calloc(1, PATH_MAX);
222 if (!iface_conf)
223 return ISCSI_ERR_NOMEM;
225 sprintf(iface_conf, "%s/%s", IFACE_CONFIG_DIR, iface->name);
226 rc = idbm_lock();
227 if (rc)
228 goto free_conf;
230 if (unlink(iface_conf))
231 rc = ISCSI_ERR_IDBM;
232 idbm_unlock();
234 free_conf:
235 free(iface_conf);
236 return rc;
239 int iface_conf_write(struct iface_rec *iface)
241 struct iface_rec *def_iface;
242 char *iface_conf;
243 FILE *f;
244 int rc = 0;
246 def_iface = iface_match_default(iface);
247 if (def_iface) {
248 log_error("iface %s is a special interface and "
249 "is not stored in %s.\n", iface->name,
250 IFACE_CONFIG_DIR);
251 return ISCSI_ERR_INVAL;
254 iface_conf = calloc(1, PATH_MAX);
255 if (!iface_conf)
256 return ISCSI_ERR_NOMEM;
258 sprintf(iface_conf, "%s/%s", IFACE_CONFIG_DIR, iface->name);
259 f = fopen(iface_conf, "w");
260 if (!f) {
261 rc = ISCSI_ERR_IDBM;
262 goto free_conf;
265 rc = idbm_lock();
266 if (rc)
267 goto close_f;
269 idbm_print(IDBM_PRINT_TYPE_IFACE, iface, 1, f);
270 idbm_unlock();
272 close_f:
273 fclose(f);
274 free_conf:
275 free(iface_conf);
276 return rc;
279 int iface_conf_update(struct db_set_param *param,
280 struct iface_rec *iface)
282 struct iface_rec *def_iface;
283 recinfo_t *info;
284 int rc = 0;
286 def_iface = iface_match_default(iface);
287 if (def_iface) {
288 log_error("iface %s is a special interface and "
289 "cannot be modified.\n", iface->name);
290 return ISCSI_ERR_INVAL;
293 info = idbm_recinfo_alloc(MAX_KEYS);
294 if (!info)
295 return ISCSI_ERR_NOMEM;
297 idbm_recinfo_iface(iface, info);
298 rc = idbm_verify_param(info, param->name);
299 if (rc)
300 goto free_info;
302 rc = idbm_rec_update_param(info, param->name, param->value, 0);
303 if (rc)
304 goto free_info;
306 rc = iface_conf_write(iface);
307 free_info:
308 free(info);
309 return rc;
312 #if 0 /* Unused */
313 static int iface_get_next_id(void)
315 struct stat statb;
316 char *iface_conf;
317 int i, rc = ENOSPC;
319 iface_conf = calloc(1, PATH_MAX);
320 if (!iface_conf)
321 return ENOMEM;
323 for (i = 0; i < INT_MAX; i++) {
324 memset(iface_conf, 0, PATH_MAX);
325 /* check len */
326 snprintf(iface_conf, PATH_MAX, "iface%d", i);
327 if (strlen(iface_conf) > ISCSI_MAX_IFACE_LEN - 1) {
328 log_error("iface namespace is full. Remove unused "
329 "iface definitions from %s or send mail "
330 "to open-iscsi@googlegroups.com to report "
331 "the problem", IFACE_CONFIG_DIR);
332 rc = ENOSPC;
333 break;
335 memset(iface_conf, 0, PATH_MAX);
336 snprintf(iface_conf, PATH_MAX, "%s/iface%d", IFACE_CONFIG_DIR,
339 if (!stat(iface_conf, &statb))
340 continue;
341 if (errno == ENOENT) {
342 rc = i;
343 break;
347 free(iface_conf);
348 return rc;
350 #endif /* Unused */
352 struct iface_search {
353 struct iface_rec *pattern;
354 struct iface_rec *found;
357 static int __iface_get_by_net_binding(void *data, struct iface_rec *iface)
359 struct iface_search *search = data;
361 if (!strcmp(search->pattern->name, iface->name)) {
362 iface_copy(search->found, iface);
363 return 1;
366 if (iface_is_bound_by_hwaddr(search->pattern)) {
367 if (!strcasecmp(iface->hwaddress,
368 search->pattern->hwaddress)) {
369 iface_copy(search->found, iface);
370 return 1;
371 } else
372 return 0;
375 if (iface_is_bound_by_netdev(search->pattern)) {
376 if (!strcmp(iface->netdev, search->pattern->netdev)) {
377 iface_copy(search->found, iface);
378 return 1;
379 } else
380 return 0;
384 if (iface_is_bound_by_ipaddr(search->pattern)) {
385 if (!strcmp(iface->ipaddress, search->pattern->ipaddress)) {
386 iface_copy(search->found, iface);
387 return 1;
388 } else
389 return 0;
392 return 0;
396 * Before 2.0.870, we only could bind by netdeivce or hwaddress,
397 * so we did a simple reverse lookup to go from sysfs info to
398 * the iface name. After 2.0.870 we added a lot of options to the
399 * iface binding so we added the ifacename to the kernel.
401 * This function is for older kernels that do not export the ifacename.
402 * If the user was doing iscsi_tcp session binding we will find
403 * the iface by matching net info.
405 int iface_get_by_net_binding(struct iface_rec *pattern,
406 struct iface_rec *out_rec)
408 int num_found = 0, rc;
409 struct iface_search search;
411 if (!iface_is_bound_by_hwaddr(pattern) &&
412 !iface_is_bound_by_netdev(pattern)) {
413 sprintf(out_rec->name, DEFAULT_IFACENAME);
414 return 0;
417 search.pattern = pattern;
418 search.found = out_rec;
420 rc = iface_for_each_iface(&search, 0, &num_found,
421 __iface_get_by_net_binding);
422 if (rc == 1)
423 return 0;
424 return ISCSI_ERR_NO_OBJS_FOUND;
427 static int __iface_setup_host_bindings(void *data, struct host_info *hinfo)
429 struct iface_rec *def_iface;
430 struct iface_rec iface;
431 struct iscsi_transport *t;
432 int i = 0;
434 t = iscsi_sysfs_get_transport_by_hba(hinfo->host_no);
435 if (!t)
436 return 0;
438 /* do not setup binding for hosts using non offload drivers */
439 while ((def_iface = default_ifaces[i++])) {
440 if (!strcmp(t->name, def_iface->transport_name))
441 return 0;
444 if (iface_get_by_net_binding(&hinfo->iface, &iface) ==
445 ISCSI_ERR_NO_OBJS_FOUND) {
446 /* Must be a new port */
447 if (!strlen(hinfo->iface.hwaddress)) {
448 log_error("Invalid offload iSCSI host %u. Missing "
449 "hwaddress. Try upgrading %s driver.\n",
450 hinfo->host_no, t->name);
451 return 0;
454 memset(&iface, 0, sizeof(struct iface_rec));
455 strcpy(iface.hwaddress, hinfo->iface.hwaddress);
456 strcpy(iface.transport_name, hinfo->iface.transport_name);
457 snprintf(iface.name, sizeof(iface.name), "%s.%s",
458 t->name, hinfo->iface.hwaddress);
459 if (iface_conf_write(&iface))
460 log_error("Could not create default iface conf %s.",
461 iface.name);
462 /* fall through - will not be persistent */
464 return 0;
468 * Create a default iface for offload cards. We assume that we will
469 * be able identify each host by MAC.
471 void iface_setup_host_bindings(void)
473 int nr_found = 0;
475 if (idbm_lock())
476 return;
478 if (access(IFACE_CONFIG_DIR, F_OK) != 0) {
479 if (mkdir(IFACE_CONFIG_DIR, 0660) != 0) {
480 log_error("Could not make %s. HW/OFFLOAD iscsi "
481 "may not be supported", IFACE_CONFIG_DIR);
482 idbm_unlock();
483 return;
486 idbm_unlock();
488 if (iscsi_sysfs_for_each_host(NULL, &nr_found,
489 __iface_setup_host_bindings))
490 log_error("Could not scan scsi hosts. HW/OFFLOAD iscsi "
491 "operations may not be supported, or please "
492 "see README for instructions on setting up ifaces.");
495 void iface_copy(struct iface_rec *dst, struct iface_rec *src)
497 if (strlen(src->name))
498 strcpy(dst->name, src->name);
499 if (strlen(src->netdev))
500 strcpy(dst->netdev, src->netdev);
501 if (strlen(src->ipaddress))
502 strcpy(dst->ipaddress, src->ipaddress);
503 if (strlen(src->hwaddress))
504 strcpy(dst->hwaddress, src->hwaddress);
505 if (strlen(src->transport_name))
506 strcpy(dst->transport_name, src->transport_name);
507 if (strlen(src->iname))
508 strcpy(dst->iname, src->iname);
511 int iface_is_valid(struct iface_rec *iface)
513 if (!iface)
514 return 0;
516 if (!strlen(iface->name))
517 return 0;
519 if (!strlen(iface->transport_name))
520 return 0;
522 if (iface_is_bound_by_hwaddr(iface))
523 return 1;
525 if (iface_is_bound_by_netdev(iface))
526 return 1;
527 // if (iface_is_bound_by_ipaddr(iface))
528 // return 1;
530 /* bound by transport name */
531 return 1;
534 int iface_match(struct iface_rec *pattern, struct iface_rec *iface)
536 if (!pattern || !iface)
537 return 1;
539 if (!strlen(pattern->name))
540 return 1;
542 if (!strcmp(pattern->name, iface->name)) {
543 if (strcmp(pattern->name, DEFAULT_IFACENAME))
544 return 1;
546 * For default we allow the same name, but different
547 * transports.
549 if (!strlen(pattern->transport_name))
550 return 1;
552 if (!strcmp(pattern->transport_name, iface->transport_name))
553 return 1;
554 /* fall through */
556 return 0;
559 int iface_is_bound_by_hwaddr(struct iface_rec *iface)
561 if (iface && strlen(iface->hwaddress) &&
562 strcmp(iface->hwaddress, DEFAULT_HWADDRESS))
563 return 1;
564 return 0;
567 int iface_is_bound_by_netdev(struct iface_rec *iface)
569 if (iface && strlen(iface->netdev) &&
570 strcmp(iface->netdev, DEFAULT_NETDEV))
571 return 1;
572 return 0;
575 int iface_is_bound_by_ipaddr(struct iface_rec *iface)
577 if (iface && strlen(iface->ipaddress) &&
578 strcmp(iface->ipaddress, DEFAULT_IPADDRESS))
579 return 1;
580 return 0;
583 void iface_print(struct iface_rec *iface, char *prefix)
585 if (strlen(iface->name))
586 printf("%sIface Name: %s\n", prefix, iface->name);
587 else
588 printf("%sIface Name: %s\n", prefix, UNKNOWN_VALUE);
590 if (strlen(iface->transport_name))
591 printf("%sIface Transport: %s\n", prefix,
592 iface->transport_name);
593 else
594 printf("%sIface Transport: %s\n", prefix, UNKNOWN_VALUE);
596 if (strlen(iface->iname))
597 printf("%sIface Initiatorname: %s\n", prefix, iface->iname);
598 else
599 printf("%sIface Initiatorname: %s\n", prefix, UNKNOWN_VALUE);
601 if (!strlen(iface->ipaddress))
602 printf("%sIface IPaddress: %s\n", prefix, UNKNOWN_VALUE);
603 else if (strchr(iface->ipaddress, '.'))
604 printf("%sIface IPaddress: %s\n", prefix, iface->ipaddress);
605 else
606 printf("%sIface IPaddress: [%s]\n", prefix, iface->ipaddress);
608 if (strlen(iface->hwaddress))
609 printf("%sIface HWaddress: %s\n", prefix, iface->hwaddress);
610 else
611 printf("%sIface HWaddress: %s\n", prefix, UNKNOWN_VALUE);
613 if (strlen(iface->netdev))
614 printf("%sIface Netdev: %s\n", prefix, iface->netdev);
615 else
616 printf("%sIface Netdev: %s\n", prefix, UNKNOWN_VALUE);
619 struct iface_print_node_data {
620 struct node_rec *last_rec;
621 struct iface_rec *match_iface;
624 static int iface_print_nodes(void *data, node_rec_t *rec)
626 struct iface_print_node_data *print_data = data;
628 if (!iface_match(print_data->match_iface, &rec->iface))
629 return -1;
631 idbm_print_node_tree(print_data->last_rec, rec, "\t");
632 return 0;
636 * iface_print_tree - print out binding info
637 * @iface: iface to print out
639 * Currently this looks like the iface conf print, because we only
640 * have the binding info. When we store the iface specific node settings
641 * in the iface record then it will look different.
643 int iface_print_tree(void *data, struct iface_rec *iface)
645 struct node_rec last_rec;
646 struct iface_print_node_data print_data;
647 int num_found = 0;
649 printf("Iface: %s\n", iface->name);
651 memset(&last_rec, 0, sizeof(struct node_rec ));
653 print_data.match_iface = iface;
654 print_data.last_rec = &last_rec;
656 idbm_for_each_rec(&num_found, &print_data, iface_print_nodes);
657 return 0;
660 int iface_print_flat(void *data, struct iface_rec *iface)
662 printf("%s %s,%s,%s,%s,%s\n",
663 strlen(iface->name) ? iface->name : UNKNOWN_VALUE,
664 strlen(iface->transport_name) ? iface->transport_name :
665 UNKNOWN_VALUE,
666 strlen(iface->hwaddress) ? iface->hwaddress : UNKNOWN_VALUE,
667 strlen(iface->ipaddress) ? iface->ipaddress : UNKNOWN_VALUE,
668 strlen(iface->netdev) ? iface->netdev : UNKNOWN_VALUE,
669 strlen(iface->iname) ? iface->iname : UNKNOWN_VALUE);
670 return 0;
673 int iface_for_each_iface(void *data, int skip_def, int *nr_found,
674 iface_op_fn *fn)
676 DIR *iface_dirfd;
677 struct dirent *iface_dent;
678 struct iface_rec *iface, *def_iface;
679 int err = 0, i = 0;
681 if (!skip_def) {
682 while ((def_iface = default_ifaces[i++])) {
683 iface = iface_alloc(def_iface->name, &err);
684 if (!iface) {
685 log_error("Could not add iface %s.",
686 def_iface->name);
687 continue;
689 iface_copy(iface, def_iface);
690 err = fn(data, iface);
691 free(iface);
692 if (err)
693 return err;
694 (*nr_found)++;
698 iface_dirfd = opendir(IFACE_CONFIG_DIR);
699 if (!iface_dirfd)
700 return errno;
702 while ((iface_dent = readdir(iface_dirfd))) {
703 if (!strcmp(iface_dent->d_name, ".") ||
704 !strcmp(iface_dent->d_name, ".."))
705 continue;
707 log_debug(5, "iface_for_each_iface found %s",
708 iface_dent->d_name);
709 iface = iface_alloc(iface_dent->d_name, &err);
710 if (!iface || err) {
711 if (err == ISCSI_ERR_INVAL)
712 log_error("Invalid iface name %s. Must be "
713 "from 1 to %d characters.",
714 iface_dent->d_name,
715 ISCSI_MAX_IFACE_LEN - 1);
716 else
717 log_error("Could not add iface %s.",
718 iface_dent->d_name);
719 continue;
722 err = idbm_lock();
723 if (err) {
724 free(iface);
725 continue;
728 err = __iface_conf_read(iface);
729 idbm_unlock();
730 if (err) {
731 log_error("Could not read def iface %s (err %d)",
732 iface->name, err);
733 free(iface);
734 continue;
737 if (!iface_is_valid(iface)) {
738 log_debug(5, "iface is not valid "
739 "Iface settings " iface_fmt,
740 iface_str(iface));
741 free(iface);
742 continue;
745 err = fn(data, iface);
746 free(iface);
747 if (err)
748 break;
749 (*nr_found)++;
752 closedir(iface_dirfd);
753 return err;
756 static int iface_link(void *data, struct iface_rec *iface)
758 struct list_head *ifaces = data;
759 struct iface_rec *iface_copy;
761 iface_copy = calloc(1, sizeof(*iface_copy));
762 if (!iface_copy)
763 return ISCSI_ERR_NOMEM;
765 memcpy(iface_copy, iface, sizeof(*iface_copy));
766 INIT_LIST_HEAD(&iface_copy->list);
767 list_add_tail(&iface_copy->list, ifaces);
768 return 0;
772 * iface_link_ifaces - link non default ifaces
773 * @ifaces: list to add ifaces to
775 * This will return a list of the ifaces created by iscsiadm
776 * or the user. It does not return the static default ones.
778 void iface_link_ifaces(struct list_head *ifaces)
780 int nr_found = 0;
782 iface_for_each_iface(ifaces, 1, &nr_found, iface_link);
786 * iface_setup_from_boot_context - setup iface from boot context info
787 * @iface: iface t setup
788 * @context: boot context info
790 * Returns 1 if setup for offload.
792 int iface_setup_from_boot_context(struct iface_rec *iface,
793 struct boot_context *context)
795 struct iscsi_transport *t;
796 uint32_t hostno;
798 if (strlen(context->initiatorname))
799 strlcpy(iface->iname, context->initiatorname,
800 sizeof(iface->iname));
802 if (strlen(context->scsi_host_name)) {
803 if (sscanf(context->scsi_host_name, "iscsi_boot%u", &hostno) != 1) {
804 log_error("Could not parse %s's host no.",
805 context->scsi_host_name);
806 return 0;
808 } else if (strlen(context->iface)) {
809 /* this ifdef is only temp until distros and firmwares are updated */
810 #ifdef OFFLOAD_BOOT_SUPPORTED
811 hostno = iscsi_sysfs_get_host_no_from_hwaddress(context->mac,
812 &rc);
813 if (rc) {
815 * If the MAC in the boot info does not match a iscsi
816 * host then the MAC must be for network card, so boot
817 * is not going to be offloaded.
819 log_debug(3, "Could not match %s to host\n",
820 context->mac);
821 return 0;
824 strlcpy(iface->netdev, context->iface, sizeof(iface->netdev));
825 #else
826 return 0;
827 #endif
828 } else
829 return 0;
832 * set up for access through a offload card.
834 t = iscsi_sysfs_get_transport_by_hba(hostno);
835 if (!t) {
836 log_error("Could not get transport for host%u. "
837 "Make sure the iSCSI driver is loaded.",
838 hostno);
839 return 0;
841 strcpy(iface->transport_name, t->name);
843 memset(iface->name, 0, sizeof(iface->name));
844 snprintf(iface->name, sizeof(iface->name), "%s.%s",
845 iface->transport_name, context->mac);
847 strlcpy(iface->hwaddress, context->mac,
848 sizeof(iface->hwaddress));
849 strlcpy(iface->ipaddress, context->ipaddr,
850 sizeof(iface->ipaddress));
851 log_debug(1, "iface " iface_fmt "\n", iface_str(iface));
852 return 1;
856 * iface_create_ifaces_from_boot_contexts - create ifaces based on boot info
857 * @ifaces: list to store ifaces in
858 * @targets: list of targets to create ifaces from
860 * This function will create a iface struct based on the boot info
861 * and it will create (or update if existing already) a iface rec in
862 * the ifaces dir based on the info.
864 int iface_create_ifaces_from_boot_contexts(struct list_head *ifaces,
865 struct list_head *targets)
867 struct boot_context *context;
868 struct iface_rec *iface, *tmp_iface;
869 int rc = 0;
871 list_for_each_entry(context, targets, list) {
872 rc = 0;
873 /* use dummy name. If valid it will get overwritten below */
874 iface = iface_alloc(DEFAULT_IFACENAME, &rc);
875 if (!iface) {
876 log_error("Could not setup iface %s for boot\n",
877 context->iface);
878 goto fail;
880 if (!iface_setup_from_boot_context(iface, context)) {
881 /* no offload so forget it */
882 free(iface);
883 continue;
886 rc = iface_conf_write(iface);
887 if (rc) {
888 log_error("Could not setup default iface conf "
889 "for %s.", iface->name);
890 free(iface);
891 goto fail;
893 list_add_tail(&iface->list, ifaces);
896 return 0;
897 fail:
898 list_for_each_entry_safe(iface, tmp_iface, ifaces, list) {
899 list_del(&iface->list);
900 free(iface);
902 return rc;
905 struct iface_param_count {
906 struct iface_rec *primary;
907 int count;
911 * __iface_get_param_count - Gets netconfig parameter count for given iface
912 * @data: iface_param_count structure
913 * @iface: iface to setup
915 static int __iface_get_param_count(void *data, struct iface_rec *iface)
917 struct iface_param_count *iface_params = data;
918 int iptype = ISCSI_IFACE_TYPE_IPV4;
919 int count = 0;
921 if (strcmp(iface_params->primary->hwaddress, iface->hwaddress))
922 return 0;
924 if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
925 iptype = ISCSI_IFACE_TYPE_IPV6;
927 if (iptype == ISCSI_IFACE_TYPE_IPV4) {
929 if (strcmp(iface->state, "disable")) {
930 if (strstr(iface->bootproto, "dhcp"))
931 /* DHCP enabled */
932 count++;
933 else {
934 /* DHCP disabled */
935 count++;
937 if (strstr(iface->ipaddress, ".")) {
938 /* User configured IPv4 Address */
939 count++;
941 if (strstr(iface->subnet_mask, "."))
942 /* User configured Subnet */
943 count++;
945 if (strstr(iface->gateway, "."))
946 /* User configured Gateway */
947 count++;
948 } else
950 * IPv4 Address not valid, decrement
951 * count of DHCP
953 count--;
957 * If IPv4 configuration in iface file is valid,
958 * enable state and other parameters (if any)
960 if (count) {
961 /* iface state */
962 count++;
964 if (strcmp(iface->vlan_state, "disable")) {
965 /* vlan_state enabled */
966 count++;
968 if (iface->vlan_id)
969 /* For vlan value */
970 count++;
971 } else
972 /* vlan_state disabled */
973 count++;
975 if (iface->mtu)
976 count++;
978 if (iface->port)
979 count++;
981 } else
982 /* IPv4 is disabled, iface state */
983 count++;
985 } else if (iptype == ISCSI_IFACE_TYPE_IPV6) {
987 if (strcmp(iface->state, "disable")) {
989 /* IPv6 Address */
990 if (strstr(iface->ipv6_autocfg, "nd") ||
991 strstr(iface->ipv6_autocfg, "dhcpv6"))
992 /* Autocfg enabled */
993 count++;
994 else {
995 /* Autocfg disabled */
996 count++;
998 if (strstr(iface->ipaddress, ":"))
999 /* User configured IPv6 Address */
1000 count++;
1001 else
1003 * IPv6 Address not valid, decrement
1004 * count of IPv6 Autocfg
1006 count--;
1009 /* IPv6 LinkLocal Address */
1010 if (strstr(iface->linklocal_autocfg, "auto"))
1011 /* Autocfg enabled */
1012 count++;
1013 else {
1014 /* Autocfg disabled */
1015 count++;
1017 if (strstr(iface->ipv6_linklocal, ":"))
1018 /* User configured LinkLocal Address */
1019 count++;
1020 else
1022 * LinkLocal Address not valid,
1023 * decrement count of LinkLocal Autocfg
1025 count--;
1028 /* IPv6 Router Address */
1029 if (strstr(iface->router_autocfg, "auto"))
1030 /* Autocfg enabled */
1031 count++;
1032 else {
1033 /* Autocfg disabled */
1034 count++;
1036 if (strstr(iface->ipv6_router, ":"))
1037 /* User configured Router Address */
1038 count++;
1039 else
1041 * Router Address not valid,
1042 * decrement count of Router Autocfg
1044 count--;
1048 * If IPv6 configuration in iface file is valid,
1049 * enable state and other parameters (if any)
1051 if (count) {
1052 /* iface state */
1053 count++;
1055 if (strcmp(iface->vlan_state, "disable")) {
1056 /* vlan_state enabled */
1057 count++;
1059 if (iface->vlan_id)
1060 /* For vlan value */
1061 count++;
1062 } else
1063 /* vlan_state disabled */
1064 count++;
1066 if (iface->mtu)
1067 count++;
1069 if (iface->port)
1070 count++;
1072 } else
1073 /* IPv6 is disabled, iface state */
1074 count++;
1077 iface_params->count += count;
1078 return 0;
1082 * iface_get_param_count - Gets netconfig parameter count from iface
1083 * @iface: iface to setup
1084 * @iface_all: Flag for number of ifaces to traverse (1 for all)
1086 * Returns netconfig parameter count.
1088 int iface_get_param_count(struct iface_rec *iface, int iface_all)
1090 int num_found = 0, rc;
1091 struct iface_param_count iface_params;
1093 log_debug(8, "In iface_get_param_count\n");
1095 iface_params.primary = iface;
1096 iface_params.count = 0;
1098 if (iface_all)
1099 rc = iface_for_each_iface(&iface_params, 0, &num_found,
1100 __iface_get_param_count);
1101 else
1102 rc = __iface_get_param_count(&iface_params, iface);
1104 log_debug(8, "iface_get_param_count: rc = %d, count = %d\n",
1105 rc, iface_params.count);
1106 return iface_params.count;
1109 /* IPv4/IPv6 Port: 3260 or User defined */
1110 static int iface_fill_port(struct iovec *iov, struct iface_rec *iface,
1111 uint32_t iface_type)
1113 int len;
1114 struct iscsi_iface_param_info *net_param;
1115 uint16_t port = 3260;
1117 len = sizeof(struct iscsi_iface_param_info) + 2;
1118 iov->iov_base = calloc(len, sizeof(char));
1119 if (!(iov->iov_base))
1120 return 1;
1122 iov->iov_len = len;
1123 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1124 net_param->param = ISCSI_NET_PARAM_PORT;
1125 net_param->iface_type = iface_type;
1126 net_param->iface_num = iface->iface_num;
1127 net_param->param_type = ISCSI_NET_PARAM;
1128 net_param->len = 2;
1129 if (iface->port)
1130 port = iface->port;
1131 memcpy(net_param->value, &port, net_param->len);
1132 return 0;
1135 static int iface_fill_mtu(struct iovec *iov, struct iface_rec *iface,
1136 uint32_t iface_type)
1138 int len;
1139 struct iscsi_iface_param_info *net_param;
1140 uint16_t mtu = 0;
1142 len = sizeof(struct iscsi_iface_param_info) + 2;
1143 iov->iov_base = calloc(len, sizeof(char));
1144 if (!(iov->iov_base))
1145 return 1;
1147 iov->iov_len = len;
1148 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1149 net_param->param = ISCSI_NET_PARAM_MTU;
1150 net_param->iface_type = iface_type;
1151 net_param->iface_num = iface->iface_num;
1152 net_param->param_type = ISCSI_NET_PARAM;
1153 net_param->len = 2;
1154 mtu = iface->mtu;
1155 memcpy(net_param->value, &mtu, net_param->len);
1156 return 0;
1159 /* IPv4/IPv6 VLAN_ID: decimal value <= 4095 */
1160 static int iface_fill_vlan_id(struct iovec *iov, struct iface_rec *iface,
1161 uint32_t iface_type)
1163 int len;
1164 struct iscsi_iface_param_info *net_param;
1165 uint16_t vlan = 0;
1167 len = sizeof(struct iscsi_iface_param_info) + 2;
1168 iov->iov_base = calloc(len, sizeof(char));
1169 if (!(iov->iov_base))
1170 return 1;
1172 iov->iov_len = len;
1173 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1174 net_param->param = ISCSI_NET_PARAM_VLAN_ID;
1175 net_param->iface_type = iface_type;
1176 net_param->iface_num = iface->iface_num;
1177 net_param->param_type = ISCSI_NET_PARAM;
1178 net_param->len = 2;
1179 if (iface->vlan_id <= ISCSI_MAX_VLAN_ID &&
1180 iface->vlan_priority <= ISCSI_MAX_VLAN_PRIORITY)
1182 * Bit 15-13: User Priority of VLAN
1183 * Bit 11-00: VLAN ID
1185 vlan = (iface->vlan_priority << 13) |
1186 (iface->vlan_id & ISCSI_MAX_VLAN_ID);
1187 memcpy(net_param->value, &vlan, net_param->len);
1188 return 0;
1191 /* IPv4/IPv6 VLAN state: disable/enable */
1192 static int iface_fill_vlan_state(struct iovec *iov, struct iface_rec *iface,
1193 uint32_t iface_type)
1195 int len;
1196 struct iscsi_iface_param_info *net_param;
1198 len = sizeof(struct iscsi_iface_param_info) + 1;
1199 iov->iov_base = calloc(len, sizeof(char));
1200 if (!(iov->iov_base))
1201 return 1;
1203 iov->iov_len = len;
1204 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1205 net_param->param = ISCSI_NET_PARAM_VLAN_ENABLED;
1206 net_param->iface_type = iface_type;
1207 net_param->iface_num = iface->iface_num;
1208 net_param->param_type = ISCSI_NET_PARAM;
1209 net_param->len = 1;
1210 if (strcmp(iface->vlan_state, "disable") && iface->vlan_id)
1211 net_param->value[0] = ISCSI_VLAN_ENABLE;
1212 else /* Assume disabled */
1213 net_param->value[0] = ISCSI_VLAN_DISABLE;
1214 return 0;
1217 /* IPv4/IPv6 Network state: disable/enable */
1218 static int iface_fill_net_state(struct iovec *iov, struct iface_rec *iface,
1219 uint32_t iface_type)
1221 int len;
1222 struct iscsi_iface_param_info *net_param;
1224 len = sizeof(struct iscsi_iface_param_info) + 1;
1225 iov->iov_base = calloc(len, sizeof(char));
1226 if (!(iov->iov_base))
1227 return 1;
1229 iov->iov_len = len;
1230 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1231 net_param->param = ISCSI_NET_PARAM_IFACE_ENABLE;
1232 net_param->iface_type = iface_type;
1233 net_param->iface_num = iface->iface_num;
1234 net_param->param_type = ISCSI_NET_PARAM;
1235 net_param->len = 1;
1236 if (!strcmp(iface->state, "disable"))
1237 net_param->value[0] = ISCSI_IFACE_DISABLE;
1238 else /* Assume enabled */
1239 net_param->value[0] = ISCSI_IFACE_ENABLE;
1240 return 0;
1243 /* IPv4 Bootproto: DHCP/static */
1244 static int iface_fill_net_bootproto(struct iovec *iov, struct iface_rec *iface)
1246 int len;
1247 struct iscsi_iface_param_info *net_param;
1249 len = sizeof(struct iscsi_iface_param_info) + 1;
1250 iov->iov_base = calloc(len, sizeof(char));
1251 if (!(iov->iov_base))
1252 return 1;
1254 iov->iov_len = len;
1255 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1256 net_param->param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
1257 net_param->iface_type = ISCSI_IFACE_TYPE_IPV4;
1258 net_param->iface_num = iface->iface_num;
1259 net_param->param_type = ISCSI_NET_PARAM;
1260 net_param->len = 1;
1261 if (!strcmp(iface->bootproto, "dhcp"))
1262 net_param->value[0] = ISCSI_BOOTPROTO_DHCP;
1263 else
1264 net_param->value[0] = ISCSI_BOOTPROTO_STATIC;
1265 return 0;
1268 /* IPv6 IPAddress Autocfg: nd/dhcpv6/disable */
1269 static int iface_fill_net_autocfg(struct iovec *iov, struct iface_rec *iface)
1271 int len;
1272 struct iscsi_iface_param_info *net_param;
1274 len = sizeof(struct iscsi_iface_param_info) + 1;
1275 iov->iov_base = calloc(len, sizeof(char));
1276 if (!(iov->iov_base))
1277 return 1;
1279 iov->iov_len = len;
1280 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1281 net_param->param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
1282 net_param->iface_type = ISCSI_IFACE_TYPE_IPV6;
1283 net_param->param_type = ISCSI_NET_PARAM;
1284 net_param->len = 1;
1286 if (!strcmp(iface->ipv6_autocfg, "nd"))
1287 net_param->value[0] = ISCSI_IPV6_AUTOCFG_ND_ENABLE;
1288 else if (!strcmp(iface->ipv6_autocfg, "dhcpv6"))
1289 net_param->value[0] = ISCSI_IPV6_AUTOCFG_DHCPV6_ENABLE;
1290 else
1291 net_param->value[0] = ISCSI_IPV6_AUTOCFG_DISABLE;
1293 return 0;
1296 /* IPv6 LinkLocal Autocfg: enable/disable */
1297 static int iface_fill_linklocal_autocfg(struct iovec *iov,
1298 struct iface_rec *iface)
1300 int len;
1301 struct iscsi_iface_param_info *net_param;
1303 len = sizeof(struct iscsi_iface_param_info) + 1;
1304 iov->iov_base = calloc(len, sizeof(char));
1305 if (!(iov->iov_base))
1306 return 1;
1308 iov->iov_len = len;
1309 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1310 net_param->param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
1311 net_param->iface_type = ISCSI_IFACE_TYPE_IPV6;
1312 net_param->param_type = ISCSI_NET_PARAM;
1313 net_param->len = 1;
1315 if (strstr(iface->linklocal_autocfg, "auto"))
1316 net_param->value[0] = ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE;
1317 else
1318 net_param->value[0] = ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE;
1320 return 0;
1323 /* IPv6 Router Autocfg: enable/disable */
1324 static int iface_fill_router_autocfg(struct iovec *iov, struct iface_rec *iface)
1326 int len;
1327 struct iscsi_iface_param_info *net_param;
1329 len = sizeof(struct iscsi_iface_param_info) + 1;
1330 iov->iov_base = calloc(len, sizeof(char));
1331 if (!(iov->iov_base))
1332 return 1;
1334 iov->iov_len = len;
1335 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1336 net_param->param = ISCSI_NET_PARAM_IPV6_ROUTER_AUTOCFG;
1337 net_param->iface_type = ISCSI_IFACE_TYPE_IPV6;
1338 net_param->param_type = ISCSI_NET_PARAM;
1339 net_param->len = 1;
1341 if (strstr(iface->router_autocfg, "auto"))
1342 net_param->value[0] = ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE;
1343 else
1344 net_param->value[0] = ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE;
1346 return 0;
1349 /* IPv4 IPAddress/Subnet Mask/Gateway: 4 bytes */
1350 static int iface_fill_net_ipv4_addr(struct iovec *iov, struct iface_rec *iface,
1351 uint32_t param)
1353 int rc = 1;
1354 int len;
1355 struct iscsi_iface_param_info *net_param;
1357 len = sizeof(struct iscsi_iface_param_info) + 4;
1358 iov->iov_base = calloc(len, sizeof(char));
1359 if (!(iov->iov_base))
1360 return 1;
1362 iov->iov_len = len;
1363 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1364 net_param->param = param;
1365 net_param->iface_type = ISCSI_IFACE_TYPE_IPV4;
1366 net_param->iface_num = iface->iface_num;
1367 net_param->len = 4;
1368 net_param->param_type = ISCSI_NET_PARAM;
1370 switch (param) {
1371 case ISCSI_NET_PARAM_IPV4_ADDR:
1372 rc = inet_pton(AF_INET, iface->ipaddress, net_param->value);
1373 if (rc <= 0)
1374 goto free;
1375 break;
1376 case ISCSI_NET_PARAM_IPV4_SUBNET:
1377 rc = inet_pton(AF_INET, iface->subnet_mask, net_param->value);
1378 if (rc <= 0)
1379 goto free;
1380 break;
1381 case ISCSI_NET_PARAM_IPV4_GW:
1382 rc = inet_pton(AF_INET, iface->gateway, net_param->value);
1383 if (rc <= 0)
1384 goto free;
1385 break;
1386 default:
1387 goto free;
1390 /* validate */
1391 if (!net_param->value[0] && !net_param->value[1] &&
1392 !net_param->value[2] && !net_param->value[3])
1393 goto free;
1395 return 0;
1396 free:
1397 free(iov->iov_base);
1398 iov->iov_base = NULL;
1399 iov->iov_len = 0;
1400 return 1;
1403 /* IPv6 IPAddress/LinkLocal/Router: 16 bytes */
1404 static int iface_fill_net_ipv6_addr(struct iovec *iov, struct iface_rec *iface,
1405 uint32_t param)
1407 int rc;
1408 int len;
1409 struct iscsi_iface_param_info *net_param;
1411 len = sizeof(struct iscsi_iface_param_info) + 16;
1412 iov->iov_base = calloc(len, sizeof(char));
1413 if (!(iov->iov_base))
1414 return 1;
1416 iov->iov_len = len;
1417 net_param = (struct iscsi_iface_param_info *)(iov->iov_base);
1418 net_param->param = param;
1419 net_param->iface_type = ISCSI_IFACE_TYPE_IPV6;
1420 net_param->iface_num = iface->iface_num;
1421 net_param->param_type = ISCSI_NET_PARAM;
1422 net_param->len = 16;
1424 switch (param) {
1425 case ISCSI_NET_PARAM_IPV6_ADDR:
1426 rc = inet_pton(AF_INET6, iface->ipaddress, net_param->value);
1427 if (rc <= 0)
1428 goto free;
1429 break;
1430 case ISCSI_NET_PARAM_IPV6_LINKLOCAL:
1431 rc = inet_pton(AF_INET6, iface->ipv6_linklocal,
1432 net_param->value);
1433 if (rc <= 0)
1434 goto free;
1435 break;
1436 case ISCSI_NET_PARAM_IPV6_ROUTER:
1437 rc = inet_pton(AF_INET6, iface->ipv6_router, net_param->value);
1438 if (rc <= 0)
1439 goto free;
1440 break;
1441 default:
1442 goto free;
1445 return 0;
1446 free:
1447 free(iov->iov_base);
1448 iov->iov_base = NULL;
1449 iov->iov_len = 0;
1450 return 1;
1453 struct iface_net_config {
1454 struct iface_rec *primary;
1455 struct iovec *iovs;
1456 int count;
1459 static int __iface_build_net_config(void *data, struct iface_rec *iface)
1461 struct iface_net_config *net_config = data;
1462 struct iovec *iov;
1463 int iptype = ISCSI_IFACE_TYPE_IPV4;
1464 int count = 0;
1466 if (strcmp(net_config->primary->hwaddress, iface->hwaddress))
1467 return 0;
1469 if (strcmp(iface->bootproto, "dhcp") && !strstr(iface->ipaddress, "."))
1470 iptype = ISCSI_IFACE_TYPE_IPV6;
1472 /* start at 2, because 0 is for nlmsghdr and 1 for event */
1473 iov = net_config->iovs + 2;
1475 if (iptype == ISCSI_IFACE_TYPE_IPV4) {
1476 if (!strcmp(iface->state, "disable")) {
1477 if (!iface_fill_net_state(&iov[net_config->count],
1478 iface,
1479 ISCSI_IFACE_TYPE_IPV4)) {
1480 net_config->count++;
1481 count++;
1484 return 0;
1487 if (strstr(iface->bootproto, "dhcp")) {
1488 if (!iface_fill_net_bootproto(&iov[net_config->count],
1489 iface)) {
1490 net_config->count++;
1491 count++;
1493 } else if (strstr(iface->ipaddress, ".")) {
1494 if (!iface_fill_net_bootproto(&iov[net_config->count],
1495 iface)) {
1496 net_config->count++;
1497 count++;
1499 if (!iface_fill_net_ipv4_addr(&iov[net_config->count],
1500 iface,
1501 ISCSI_NET_PARAM_IPV4_ADDR)) {
1502 net_config->count++;
1503 count++;
1505 if (strstr(iface->subnet_mask, ".")) {
1506 if (!iface_fill_net_ipv4_addr(
1507 &iov[net_config->count], iface,
1508 ISCSI_NET_PARAM_IPV4_SUBNET)) {
1509 net_config->count++;
1510 count++;
1513 if (strstr(iface->gateway, ".")) {
1514 if (!iface_fill_net_ipv4_addr(
1515 &iov[net_config->count], iface,
1516 ISCSI_NET_PARAM_IPV4_GW)) {
1517 net_config->count++;
1518 count++;
1524 * If IPv4 configuration in iface file is valid,
1525 * fill state and other parameters (if any)
1527 if (count) {
1528 if (!iface_fill_net_state(&iov[net_config->count],
1529 iface,
1530 ISCSI_IFACE_TYPE_IPV4)) {
1531 net_config->count++;
1532 count++;
1534 if (!iface_fill_vlan_state(&iov[net_config->count],
1535 iface,
1536 ISCSI_IFACE_TYPE_IPV4)) {
1537 net_config->count++;
1538 count++;
1540 if (strcmp(iface->vlan_state, "disable") &&
1541 iface->vlan_id) {
1542 if (!iface_fill_vlan_id(&iov[net_config->count],
1543 iface, ISCSI_IFACE_TYPE_IPV4)) {
1544 net_config->count++;
1545 count++;
1548 if (iface->mtu) {
1549 if (!iface_fill_mtu(&iov[net_config->count],
1550 iface,
1551 ISCSI_IFACE_TYPE_IPV4)) {
1552 net_config->count++;
1553 count++;
1556 if (iface->port) {
1557 if (!iface_fill_port(&iov[net_config->count],
1558 iface,
1559 ISCSI_IFACE_TYPE_IPV4)) {
1560 net_config->count++;
1561 count++;
1565 } else if (iptype == ISCSI_IFACE_TYPE_IPV6) {
1566 if (!strcmp(iface->state, "disable")) {
1567 if (!iface_fill_net_state(&iov[net_config->count],
1568 iface,
1569 ISCSI_IFACE_TYPE_IPV6)) {
1570 net_config->count++;
1571 count++;
1573 return 0;
1576 /* For IPv6 Address */
1577 if (strstr(iface->ipv6_autocfg, "nd") ||
1578 strstr(iface->ipv6_autocfg, "dhcpv6")) {
1579 if (!iface_fill_net_autocfg(&iov[net_config->count],
1580 iface)) {
1581 net_config->count++;
1582 count++;
1584 } else if (strstr(iface->ipaddress, ":")) {
1585 if (!iface_fill_net_autocfg(&iov[net_config->count],
1586 iface)) {
1587 net_config->count++;
1588 count++;
1590 /* User provided IPv6 Address */
1591 if (!iface_fill_net_ipv6_addr(&iov[net_config->count],
1592 iface,
1593 ISCSI_NET_PARAM_IPV6_ADDR)) {
1594 net_config->count++;
1595 count++;
1599 /* For LinkLocal Address */
1600 if (strstr(iface->linklocal_autocfg, "auto")) {
1601 if (!iface_fill_linklocal_autocfg(
1602 &iov[net_config->count],
1603 iface)) {
1604 net_config->count++;
1605 count++;
1607 } else if (strstr(iface->ipv6_linklocal, ":")) {
1608 if (!iface_fill_linklocal_autocfg(
1609 &iov[net_config->count],
1610 iface)) {
1611 net_config->count++;
1612 count++;
1614 /* User provided Link Local Address */
1615 if (!iface_fill_net_ipv6_addr(&iov[net_config->count],
1616 iface,
1617 ISCSI_NET_PARAM_IPV6_LINKLOCAL)) {
1618 net_config->count++;
1619 count++;
1623 /* For Router Address */
1624 if (strstr(iface->router_autocfg, "auto")) {
1625 if (!iface_fill_router_autocfg(&iov[net_config->count],
1626 iface)) {
1627 net_config->count++;
1628 count++;
1630 } else if (strstr(iface->ipv6_router, ":")) {
1631 if (!iface_fill_router_autocfg(&iov[net_config->count],
1632 iface)) {
1633 net_config->count++;
1634 count++;
1636 /* User provided Router Address */
1637 if (!iface_fill_net_ipv6_addr(&iov[net_config->count],
1638 iface,
1639 ISCSI_NET_PARAM_IPV6_ROUTER)) {
1640 net_config->count++;
1641 count++;
1646 * If IPv6 configuration in iface file is valid,
1647 * fill state and other parameters
1649 if (count) {
1650 if (!iface_fill_net_state(&iov[net_config->count],
1651 iface,
1652 ISCSI_IFACE_TYPE_IPV6)) {
1653 net_config->count++;
1654 count++;
1656 if (!iface_fill_vlan_state(&iov[net_config->count],
1657 iface,
1658 ISCSI_IFACE_TYPE_IPV6)) {
1659 net_config->count++;
1660 count++;
1662 if (strcmp(iface->vlan_state, "disable") &&
1663 iface->vlan_id) {
1664 if (!iface_fill_vlan_id(&iov[net_config->count],
1665 iface,
1666 ISCSI_IFACE_TYPE_IPV6)) {
1667 net_config->count++;
1668 count++;
1671 if (iface->mtu) {
1672 if (!iface_fill_mtu(&iov[net_config->count],
1673 iface,
1674 ISCSI_IFACE_TYPE_IPV6)) {
1675 net_config->count++;
1676 count++;
1679 if (iface->port) {
1680 if (!iface_fill_port(&iov[net_config->count],
1681 iface,
1682 ISCSI_IFACE_TYPE_IPV6)) {
1683 net_config->count++;
1684 count++;
1689 return 0;
1693 * iface_build_net_config - Setup neconfig parameter buffers
1694 * @iface: iface to setup
1695 * @iface_all: Flag for number of ifaces to traverse (1 for all)
1696 * @iovs: iovec buffer for netconfig parameters
1698 * Returns total number of netconfig parameter buffers used.
1700 int iface_build_net_config(struct iface_rec *iface, int iface_all,
1701 struct iovec *iovs)
1703 int num_found = 0, rc;
1704 struct iface_net_config net_config;
1706 log_debug(8, "In iface_build_net_config\n");
1708 net_config.primary = iface;
1709 net_config.iovs = iovs;
1710 net_config.count = 0;
1712 if (iface_all)
1713 rc = iface_for_each_iface(&net_config, 0, &num_found,
1714 __iface_build_net_config);
1715 else
1716 rc = __iface_build_net_config(&net_config, iface);
1718 log_debug(8, "iface_build_net_config: rc = %d, count = %d\n",
1719 rc, net_config.count);
1720 return net_config.count;