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.
27 #include <sys/types.h>
29 #include <arpa/inet.h>
33 #include "iscsi_sysfs.h"
34 #include "iscsi_settings.h"
36 #include "transport.h"
39 #include "session_info.h"
41 #include "fw_context.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
54 static struct iface_rec iface_default
= {
56 .transport_name
= "tcp",
62 static struct iface_rec iface_iser
= {
64 .transport_name
= "iser",
67 static struct iface_rec
*default_ifaces
[] = {
73 static struct iface_rec
*iface_match_default(struct iface_rec
*iface
)
75 struct iface_rec
*def_iface
;
78 while ((def_iface
= default_ifaces
[i
++])) {
79 if (!strcmp(iface
->name
, def_iface
->name
))
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
);
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
;
110 iface
= calloc(1, sizeof(*iface
));
112 *err
= ISCSI_ERR_NOMEM
;
116 strlcpy(iface
->name
, ifname
, ISCSI_MAX_IFACE_LEN
);
117 INIT_LIST_HEAD(&iface
->list
);
121 static int __iface_conf_read(struct iface_rec
*iface
)
128 iface_conf
= calloc(1, PATH_MAX
);
130 return ISCSI_ERR_NOMEM
;
132 info
= idbm_recinfo_alloc(MAX_KEYS
);
134 rc
= ISCSI_ERR_NOMEM
;
138 snprintf(iface_conf
, PATH_MAX
, "%s/%s", IFACE_CONFIG_DIR
,
141 log_debug(5, "looking for iface conf %s", iface_conf
);
142 f
= fopen(iface_conf
, "r");
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
);
157 idbm_recinfo_iface(iface
, info
);
158 idbm_recinfo_config(info
, f
);
168 int iface_conf_read(struct iface_rec
*iface
)
170 struct iface_rec
*def_iface
;
173 def_iface
= iface_match_default(iface
);
176 * older tools allowed default to have different
177 * transport_names so we do not want to overwrite
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
);
194 iface_copy(iface
, def_iface
);
203 rc
= __iface_conf_read(iface
);
208 int iface_conf_delete(struct iface_rec
*iface
)
210 struct iface_rec
*def_iface
;
214 def_iface
= iface_match_default(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
);
223 return ISCSI_ERR_NOMEM
;
225 sprintf(iface_conf
, "%s/%s", IFACE_CONFIG_DIR
, iface
->name
);
230 if (unlink(iface_conf
))
239 int iface_conf_write(struct iface_rec
*iface
)
241 struct iface_rec
*def_iface
;
246 def_iface
= iface_match_default(iface
);
248 log_error("iface %s is a special interface and "
249 "is not stored in %s.\n", iface
->name
,
251 return ISCSI_ERR_INVAL
;
254 iface_conf
= calloc(1, PATH_MAX
);
256 return ISCSI_ERR_NOMEM
;
258 sprintf(iface_conf
, "%s/%s", IFACE_CONFIG_DIR
, iface
->name
);
259 f
= fopen(iface_conf
, "w");
269 idbm_print(IDBM_PRINT_TYPE_IFACE
, iface
, 1, f
);
279 int iface_conf_update(struct db_set_param
*param
,
280 struct iface_rec
*iface
)
282 struct iface_rec
*def_iface
;
286 def_iface
= iface_match_default(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
);
295 return ISCSI_ERR_NOMEM
;
297 idbm_recinfo_iface(iface
, info
);
298 rc
= idbm_verify_param(info
, param
->name
);
302 rc
= idbm_rec_update_param(info
, param
->name
, param
->value
, 0);
306 rc
= iface_conf_write(iface
);
313 static int iface_get_next_id(void)
319 iface_conf
= calloc(1, PATH_MAX
);
323 for (i
= 0; i
< INT_MAX
; i
++) {
324 memset(iface_conf
, 0, PATH_MAX
);
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
);
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
))
341 if (errno
== ENOENT
) {
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
);
366 if (iface_is_bound_by_hwaddr(search
->pattern
)) {
367 if (!strcasecmp(iface
->hwaddress
,
368 search
->pattern
->hwaddress
)) {
369 iface_copy(search
->found
, iface
);
375 if (iface_is_bound_by_netdev(search
->pattern
)) {
376 if (!strcmp(iface
->netdev
, search
->pattern
->netdev
)) {
377 iface_copy(search
->found
, iface
);
384 if (iface_is_bound_by_ipaddr(search->pattern)) {
385 if (!strcmp(iface->ipaddress, search->pattern->ipaddress)) {
386 iface_copy(search->found, iface);
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
);
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
);
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
;
434 t
= iscsi_sysfs_get_transport_by_hba(hinfo
->host_no
);
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
))
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
);
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.",
462 /* fall through - will not be persistent */
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)
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
);
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
)
516 if (!strlen(iface
->name
))
519 if (!strlen(iface
->transport_name
))
522 if (iface_is_bound_by_hwaddr(iface
))
525 if (iface_is_bound_by_netdev(iface
))
527 // if (iface_is_bound_by_ipaddr(iface))
530 /* bound by transport name */
534 int iface_match(struct iface_rec
*pattern
, struct iface_rec
*iface
)
536 if (!pattern
|| !iface
)
539 if (!strlen(pattern
->name
))
542 if (!strcmp(pattern
->name
, iface
->name
)) {
543 if (strcmp(pattern
->name
, DEFAULT_IFACENAME
))
546 * For default we allow the same name, but different
549 if (!strlen(pattern
->transport_name
))
552 if (!strcmp(pattern
->transport_name
, iface
->transport_name
))
559 int iface_is_bound_by_hwaddr(struct iface_rec
*iface
)
561 if (iface
&& strlen(iface
->hwaddress
) &&
562 strcmp(iface
->hwaddress
, DEFAULT_HWADDRESS
))
567 int iface_is_bound_by_netdev(struct iface_rec
*iface
)
569 if (iface
&& strlen(iface
->netdev
) &&
570 strcmp(iface
->netdev
, DEFAULT_NETDEV
))
575 int iface_is_bound_by_ipaddr(struct iface_rec
*iface
)
577 if (iface
&& strlen(iface
->ipaddress
) &&
578 strcmp(iface
->ipaddress
, DEFAULT_IPADDRESS
))
583 void iface_print(struct iface_rec
*iface
, char *prefix
)
585 if (strlen(iface
->name
))
586 printf("%sIface Name: %s\n", prefix
, iface
->name
);
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
);
594 printf("%sIface Transport: %s\n", prefix
, UNKNOWN_VALUE
);
596 if (strlen(iface
->iname
))
597 printf("%sIface Initiatorname: %s\n", prefix
, iface
->iname
);
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
);
606 printf("%sIface IPaddress: [%s]\n", prefix
, iface
->ipaddress
);
608 if (strlen(iface
->hwaddress
))
609 printf("%sIface HWaddress: %s\n", prefix
, iface
->hwaddress
);
611 printf("%sIface HWaddress: %s\n", prefix
, UNKNOWN_VALUE
);
613 if (strlen(iface
->netdev
))
614 printf("%sIface Netdev: %s\n", prefix
, iface
->netdev
);
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
))
631 idbm_print_node_tree(print_data
->last_rec
, rec
, "\t");
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
;
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
);
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
:
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
);
673 int iface_for_each_iface(void *data
, int skip_def
, int *nr_found
,
677 struct dirent
*iface_dent
;
678 struct iface_rec
*iface
, *def_iface
;
682 while ((def_iface
= default_ifaces
[i
++])) {
683 iface
= iface_alloc(def_iface
->name
, &err
);
685 log_error("Could not add iface %s.",
689 iface_copy(iface
, def_iface
);
690 err
= fn(data
, iface
);
698 iface_dirfd
= opendir(IFACE_CONFIG_DIR
);
702 while ((iface_dent
= readdir(iface_dirfd
))) {
703 if (!strcmp(iface_dent
->d_name
, ".") ||
704 !strcmp(iface_dent
->d_name
, ".."))
707 log_debug(5, "iface_for_each_iface found %s",
709 iface
= iface_alloc(iface_dent
->d_name
, &err
);
711 if (err
== ISCSI_ERR_INVAL
)
712 log_error("Invalid iface name %s. Must be "
713 "from 1 to %d characters.",
715 ISCSI_MAX_IFACE_LEN
- 1);
717 log_error("Could not add iface %s.",
728 err
= __iface_conf_read(iface
);
731 log_error("Could not read def iface %s (err %d)",
737 if (!iface_is_valid(iface
)) {
738 log_debug(5, "iface is not valid "
739 "Iface settings " iface_fmt
,
745 err
= fn(data
, iface
);
752 closedir(iface_dirfd
);
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
));
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
);
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
)
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
;
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
);
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
,
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",
824 strlcpy(iface
->netdev
, context
->iface
, sizeof(iface
->netdev
));
832 * set up for access through a offload card.
834 t
= iscsi_sysfs_get_transport_by_hba(hostno
);
836 log_error("Could not get transport for host%u. "
837 "Make sure the iSCSI driver is loaded.",
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
));
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
;
871 list_for_each_entry(context
, targets
, list
) {
873 /* use dummy name. If valid it will get overwritten below */
874 iface
= iface_alloc(DEFAULT_IFACENAME
, &rc
);
876 log_error("Could not setup iface %s for boot\n",
880 if (!iface_setup_from_boot_context(iface
, context
)) {
881 /* no offload so forget it */
886 rc
= iface_conf_write(iface
);
888 log_error("Could not setup default iface conf "
889 "for %s.", iface
->name
);
893 list_add_tail(&iface
->list
, ifaces
);
898 list_for_each_entry_safe(iface
, tmp_iface
, ifaces
, list
) {
899 list_del(&iface
->list
);
905 struct iface_param_count
{
906 struct iface_rec
*primary
;
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
;
921 if (strcmp(iface_params
->primary
->hwaddress
, iface
->hwaddress
))
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"))
937 if (strstr(iface
->ipaddress
, ".")) {
938 /* User configured IPv4 Address */
941 if (strstr(iface
->subnet_mask
, "."))
942 /* User configured Subnet */
945 if (strstr(iface
->gateway
, "."))
946 /* User configured Gateway */
950 * IPv4 Address not valid, decrement
957 * If IPv4 configuration in iface file is valid,
958 * enable state and other parameters (if any)
964 if (strcmp(iface
->vlan_state
, "disable")) {
965 /* vlan_state enabled */
972 /* vlan_state disabled */
982 /* IPv4 is disabled, iface state */
985 } else if (iptype
== ISCSI_IFACE_TYPE_IPV6
) {
987 if (strcmp(iface
->state
, "disable")) {
990 if (strstr(iface
->ipv6_autocfg
, "nd") ||
991 strstr(iface
->ipv6_autocfg
, "dhcpv6"))
992 /* Autocfg enabled */
995 /* Autocfg disabled */
998 if (strstr(iface
->ipaddress
, ":"))
999 /* User configured IPv6 Address */
1003 * IPv6 Address not valid, decrement
1004 * count of IPv6 Autocfg
1009 /* IPv6 LinkLocal Address */
1010 if (strstr(iface
->linklocal_autocfg
, "auto"))
1011 /* Autocfg enabled */
1014 /* Autocfg disabled */
1017 if (strstr(iface
->ipv6_linklocal
, ":"))
1018 /* User configured LinkLocal Address */
1022 * LinkLocal Address not valid,
1023 * decrement count of LinkLocal Autocfg
1028 /* IPv6 Router Address */
1029 if (strstr(iface
->router_autocfg
, "auto"))
1030 /* Autocfg enabled */
1033 /* Autocfg disabled */
1036 if (strstr(iface
->ipv6_router
, ":"))
1037 /* User configured Router Address */
1041 * Router Address not valid,
1042 * decrement count of Router Autocfg
1048 * If IPv6 configuration in iface file is valid,
1049 * enable state and other parameters (if any)
1055 if (strcmp(iface
->vlan_state
, "disable")) {
1056 /* vlan_state enabled */
1060 /* For vlan value */
1063 /* vlan_state disabled */
1073 /* IPv6 is disabled, iface state */
1077 iface_params
->count
+= count
;
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;
1099 rc
= iface_for_each_iface(&iface_params
, 0, &num_found
,
1100 __iface_get_param_count
);
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
)
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
))
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
;
1131 memcpy(net_param
->value
, &port
, net_param
->len
);
1135 static int iface_fill_mtu(struct iovec
*iov
, struct iface_rec
*iface
,
1136 uint32_t iface_type
)
1139 struct iscsi_iface_param_info
*net_param
;
1142 len
= sizeof(struct iscsi_iface_param_info
) + 2;
1143 iov
->iov_base
= calloc(len
, sizeof(char));
1144 if (!(iov
->iov_base
))
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
;
1155 memcpy(net_param
->value
, &mtu
, net_param
->len
);
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
)
1164 struct iscsi_iface_param_info
*net_param
;
1167 len
= sizeof(struct iscsi_iface_param_info
) + 2;
1168 iov
->iov_base
= calloc(len
, sizeof(char));
1169 if (!(iov
->iov_base
))
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
;
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
);
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
)
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
))
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
;
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
;
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
)
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
))
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
;
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
;
1243 /* IPv4 Bootproto: DHCP/static */
1244 static int iface_fill_net_bootproto(struct iovec
*iov
, struct iface_rec
*iface
)
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
))
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
;
1261 if (!strcmp(iface
->bootproto
, "dhcp"))
1262 net_param
->value
[0] = ISCSI_BOOTPROTO_DHCP
;
1264 net_param
->value
[0] = ISCSI_BOOTPROTO_STATIC
;
1268 /* IPv6 IPAddress Autocfg: nd/dhcpv6/disable */
1269 static int iface_fill_net_autocfg(struct iovec
*iov
, struct iface_rec
*iface
)
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
))
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
;
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
;
1291 net_param
->value
[0] = ISCSI_IPV6_AUTOCFG_DISABLE
;
1296 /* IPv6 LinkLocal Autocfg: enable/disable */
1297 static int iface_fill_linklocal_autocfg(struct iovec
*iov
,
1298 struct iface_rec
*iface
)
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
))
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
;
1315 if (strstr(iface
->linklocal_autocfg
, "auto"))
1316 net_param
->value
[0] = ISCSI_IPV6_LINKLOCAL_AUTOCFG_ENABLE
;
1318 net_param
->value
[0] = ISCSI_IPV6_LINKLOCAL_AUTOCFG_DISABLE
;
1323 /* IPv6 Router Autocfg: enable/disable */
1324 static int iface_fill_router_autocfg(struct iovec
*iov
, struct iface_rec
*iface
)
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
))
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
;
1341 if (strstr(iface
->router_autocfg
, "auto"))
1342 net_param
->value
[0] = ISCSI_IPV6_ROUTER_AUTOCFG_ENABLE
;
1344 net_param
->value
[0] = ISCSI_IPV6_ROUTER_AUTOCFG_DISABLE
;
1349 /* IPv4 IPAddress/Subnet Mask/Gateway: 4 bytes */
1350 static int iface_fill_net_ipv4_addr(struct iovec
*iov
, struct iface_rec
*iface
,
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
))
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
;
1368 net_param
->param_type
= ISCSI_NET_PARAM
;
1371 case ISCSI_NET_PARAM_IPV4_ADDR
:
1372 rc
= inet_pton(AF_INET
, iface
->ipaddress
, net_param
->value
);
1376 case ISCSI_NET_PARAM_IPV4_SUBNET
:
1377 rc
= inet_pton(AF_INET
, iface
->subnet_mask
, net_param
->value
);
1381 case ISCSI_NET_PARAM_IPV4_GW
:
1382 rc
= inet_pton(AF_INET
, iface
->gateway
, net_param
->value
);
1391 if (!net_param
->value
[0] && !net_param
->value
[1] &&
1392 !net_param
->value
[2] && !net_param
->value
[3])
1397 free(iov
->iov_base
);
1398 iov
->iov_base
= NULL
;
1403 /* IPv6 IPAddress/LinkLocal/Router: 16 bytes */
1404 static int iface_fill_net_ipv6_addr(struct iovec
*iov
, struct iface_rec
*iface
,
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
))
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;
1425 case ISCSI_NET_PARAM_IPV6_ADDR
:
1426 rc
= inet_pton(AF_INET6
, iface
->ipaddress
, net_param
->value
);
1430 case ISCSI_NET_PARAM_IPV6_LINKLOCAL
:
1431 rc
= inet_pton(AF_INET6
, iface
->ipv6_linklocal
,
1436 case ISCSI_NET_PARAM_IPV6_ROUTER
:
1437 rc
= inet_pton(AF_INET6
, iface
->ipv6_router
, net_param
->value
);
1447 free(iov
->iov_base
);
1448 iov
->iov_base
= NULL
;
1453 struct iface_net_config
{
1454 struct iface_rec
*primary
;
1459 static int __iface_build_net_config(void *data
, struct iface_rec
*iface
)
1461 struct iface_net_config
*net_config
= data
;
1463 int iptype
= ISCSI_IFACE_TYPE_IPV4
;
1466 if (strcmp(net_config
->primary
->hwaddress
, iface
->hwaddress
))
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
],
1479 ISCSI_IFACE_TYPE_IPV4
)) {
1480 net_config
->count
++;
1487 if (strstr(iface
->bootproto
, "dhcp")) {
1488 if (!iface_fill_net_bootproto(&iov
[net_config
->count
],
1490 net_config
->count
++;
1493 } else if (strstr(iface
->ipaddress
, ".")) {
1494 if (!iface_fill_net_bootproto(&iov
[net_config
->count
],
1496 net_config
->count
++;
1499 if (!iface_fill_net_ipv4_addr(&iov
[net_config
->count
],
1501 ISCSI_NET_PARAM_IPV4_ADDR
)) {
1502 net_config
->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
++;
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
++;
1524 * If IPv4 configuration in iface file is valid,
1525 * fill state and other parameters (if any)
1528 if (!iface_fill_net_state(&iov
[net_config
->count
],
1530 ISCSI_IFACE_TYPE_IPV4
)) {
1531 net_config
->count
++;
1534 if (!iface_fill_vlan_state(&iov
[net_config
->count
],
1536 ISCSI_IFACE_TYPE_IPV4
)) {
1537 net_config
->count
++;
1540 if (strcmp(iface
->vlan_state
, "disable") &&
1542 if (!iface_fill_vlan_id(&iov
[net_config
->count
],
1543 iface
, ISCSI_IFACE_TYPE_IPV4
)) {
1544 net_config
->count
++;
1549 if (!iface_fill_mtu(&iov
[net_config
->count
],
1551 ISCSI_IFACE_TYPE_IPV4
)) {
1552 net_config
->count
++;
1557 if (!iface_fill_port(&iov
[net_config
->count
],
1559 ISCSI_IFACE_TYPE_IPV4
)) {
1560 net_config
->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
],
1569 ISCSI_IFACE_TYPE_IPV6
)) {
1570 net_config
->count
++;
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
],
1581 net_config
->count
++;
1584 } else if (strstr(iface
->ipaddress
, ":")) {
1585 if (!iface_fill_net_autocfg(&iov
[net_config
->count
],
1587 net_config
->count
++;
1590 /* User provided IPv6 Address */
1591 if (!iface_fill_net_ipv6_addr(&iov
[net_config
->count
],
1593 ISCSI_NET_PARAM_IPV6_ADDR
)) {
1594 net_config
->count
++;
1599 /* For LinkLocal Address */
1600 if (strstr(iface
->linklocal_autocfg
, "auto")) {
1601 if (!iface_fill_linklocal_autocfg(
1602 &iov
[net_config
->count
],
1604 net_config
->count
++;
1607 } else if (strstr(iface
->ipv6_linklocal
, ":")) {
1608 if (!iface_fill_linklocal_autocfg(
1609 &iov
[net_config
->count
],
1611 net_config
->count
++;
1614 /* User provided Link Local Address */
1615 if (!iface_fill_net_ipv6_addr(&iov
[net_config
->count
],
1617 ISCSI_NET_PARAM_IPV6_LINKLOCAL
)) {
1618 net_config
->count
++;
1623 /* For Router Address */
1624 if (strstr(iface
->router_autocfg
, "auto")) {
1625 if (!iface_fill_router_autocfg(&iov
[net_config
->count
],
1627 net_config
->count
++;
1630 } else if (strstr(iface
->ipv6_router
, ":")) {
1631 if (!iface_fill_router_autocfg(&iov
[net_config
->count
],
1633 net_config
->count
++;
1636 /* User provided Router Address */
1637 if (!iface_fill_net_ipv6_addr(&iov
[net_config
->count
],
1639 ISCSI_NET_PARAM_IPV6_ROUTER
)) {
1640 net_config
->count
++;
1646 * If IPv6 configuration in iface file is valid,
1647 * fill state and other parameters
1650 if (!iface_fill_net_state(&iov
[net_config
->count
],
1652 ISCSI_IFACE_TYPE_IPV6
)) {
1653 net_config
->count
++;
1656 if (!iface_fill_vlan_state(&iov
[net_config
->count
],
1658 ISCSI_IFACE_TYPE_IPV6
)) {
1659 net_config
->count
++;
1662 if (strcmp(iface
->vlan_state
, "disable") &&
1664 if (!iface_fill_vlan_id(&iov
[net_config
->count
],
1666 ISCSI_IFACE_TYPE_IPV6
)) {
1667 net_config
->count
++;
1672 if (!iface_fill_mtu(&iov
[net_config
->count
],
1674 ISCSI_IFACE_TYPE_IPV6
)) {
1675 net_config
->count
++;
1680 if (!iface_fill_port(&iov
[net_config
->count
],
1682 ISCSI_IFACE_TYPE_IPV6
)) {
1683 net_config
->count
++;
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
,
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;
1713 rc
= iface_for_each_iface(&net_config
, 0, &num_found
,
1714 __iface_build_net_config
);
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
;