17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5921e7e07Smeem * Common Development and Distribution License (the "License").
6921e7e07Smeem * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22e11c3f44Smeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
2480d556f9SHans Rosenfeld *
2580d556f9SHans Rosenfeld * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include "mpd_defs.h"
297c478bd9Sstevel@tonic-gate #include "mpd_tables.h"
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate int debug = 0; /* Debug flag */
327c478bd9Sstevel@tonic-gate static int pollfd_num = 0; /* Num. of poll descriptors */
337c478bd9Sstevel@tonic-gate static struct pollfd *pollfds = NULL; /* Array of poll descriptors */
347c478bd9Sstevel@tonic-gate /* All times below in ms */
357c478bd9Sstevel@tonic-gate int user_failure_detection_time; /* user specified failure detection */
367c478bd9Sstevel@tonic-gate /* time (fdt) */
377c478bd9Sstevel@tonic-gate int user_probe_interval; /* derived from user specified fdt */
387c478bd9Sstevel@tonic-gate
3927438c18SJon Anderson /*
4027438c18SJon Anderson * Structure to store mib2 information returned by the kernel.
4127438c18SJon Anderson * This is used to process routing table information.
4227438c18SJon Anderson */
4327438c18SJon Anderson typedef struct mib_item_s {
4427438c18SJon Anderson struct mib_item_s *mi_next;
4527438c18SJon Anderson struct opthdr mi_opthdr;
4627438c18SJon Anderson void *mi_valp;
4727438c18SJon Anderson } mib_item_t;
4827438c18SJon Anderson
497c478bd9Sstevel@tonic-gate static int rtsock_v4; /* AF_INET routing socket */
507c478bd9Sstevel@tonic-gate static int rtsock_v6; /* AF_INET6 routing socket */
517c478bd9Sstevel@tonic-gate int ifsock_v4 = -1; /* IPv4 socket for ioctls */
527c478bd9Sstevel@tonic-gate int ifsock_v6 = -1; /* IPv6 socket for ioctls */
537c478bd9Sstevel@tonic-gate static int lsock_v4; /* Listen socket to detect mpathd */
547c478bd9Sstevel@tonic-gate static int lsock_v6; /* Listen socket to detect mpathd */
557c478bd9Sstevel@tonic-gate static int mibfd = -1; /* fd to get mib info */
567c478bd9Sstevel@tonic-gate static boolean_t force_mcast = _B_FALSE; /* Only for test purposes */
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate static uint_t last_initifs_time; /* Time when initifs was last run */
597c478bd9Sstevel@tonic-gate static char **argv0; /* Saved for re-exec on SIGHUP */
607c478bd9Sstevel@tonic-gate boolean_t handle_link_notifications = _B_TRUE;
6127438c18SJon Anderson static int ipRouteEntrySize; /* Size of IPv4 route entry */
6227438c18SJon Anderson static int ipv6RouteEntrySize; /* Size of IPv6 route entry */
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static void initlog(void);
657c478bd9Sstevel@tonic-gate static void run_timeouts(void);
667c478bd9Sstevel@tonic-gate static void initifs(void);
677c478bd9Sstevel@tonic-gate static void check_if_removed(struct phyint_instance *pii);
687c478bd9Sstevel@tonic-gate static void select_test_ifs(void);
6927438c18SJon Anderson static void update_router_list(mib_item_t *item);
7027438c18SJon Anderson static void mib_get_constants(mib_item_t *item);
7127438c18SJon Anderson static int mibwalk(void (*proc)(mib_item_t *));
727c478bd9Sstevel@tonic-gate static void ire_process_v4(mib2_ipRouteEntry_t *buf, size_t len);
737c478bd9Sstevel@tonic-gate static void ire_process_v6(mib2_ipv6RouteEntry_t *buf, size_t len);
747c478bd9Sstevel@tonic-gate static void router_add_common(int af, char *ifname,
757c478bd9Sstevel@tonic-gate struct in6_addr nexthop);
767c478bd9Sstevel@tonic-gate static void init_router_targets();
777c478bd9Sstevel@tonic-gate static void cleanup(void);
787c478bd9Sstevel@tonic-gate static int setup_listener(int af);
797c478bd9Sstevel@tonic-gate static void check_config(void);
80e6ed03fcSmeem static void check_testconfig(void);
8106cdd167Smeem static void check_addr_unique(struct phyint_instance *,
8206cdd167Smeem struct sockaddr_storage *);
837c478bd9Sstevel@tonic-gate static void init_host_targets(void);
847c478bd9Sstevel@tonic-gate static void dup_host_targets(struct phyint_instance *desired_pii);
857c478bd9Sstevel@tonic-gate static void loopback_cmd(int sock, int family);
867c478bd9Sstevel@tonic-gate static boolean_t daemonize(void);
877c478bd9Sstevel@tonic-gate static int closefunc(void *, int);
887c478bd9Sstevel@tonic-gate static unsigned int process_cmd(int newfd, union mi_commands *mpi);
897c478bd9Sstevel@tonic-gate static unsigned int process_query(int fd, mi_query_t *miq);
90e11c3f44Smeem static unsigned int send_addrinfo(int fd, ipmp_addrinfo_t *adinfop);
917c478bd9Sstevel@tonic-gate static unsigned int send_groupinfo(int fd, ipmp_groupinfo_t *grinfop);
927c478bd9Sstevel@tonic-gate static unsigned int send_grouplist(int fd, ipmp_grouplist_t *grlistp);
937c478bd9Sstevel@tonic-gate static unsigned int send_ifinfo(int fd, ipmp_ifinfo_t *ifinfop);
947c478bd9Sstevel@tonic-gate static unsigned int send_result(int fd, unsigned int error, int syserror);
957c478bd9Sstevel@tonic-gate
96e11c3f44Smeem addrlist_t *localaddrs;
9787e66ffcSrk
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate * Return the current time in milliseconds (from an arbitrary reference)
1007c478bd9Sstevel@tonic-gate * truncated to fit into an int. Truncation is ok since we are interested
1017c478bd9Sstevel@tonic-gate * only in differences and not the absolute values.
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate uint_t
getcurrenttime(void)1047c478bd9Sstevel@tonic-gate getcurrenttime(void)
1057c478bd9Sstevel@tonic-gate {
1067c478bd9Sstevel@tonic-gate uint_t cur_time; /* In ms */
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * Use of a non-user-adjustable source of time is
1107c478bd9Sstevel@tonic-gate * required. However millisecond precision is sufficient.
1117c478bd9Sstevel@tonic-gate * divide by 10^6
1127c478bd9Sstevel@tonic-gate */
1137c478bd9Sstevel@tonic-gate cur_time = (uint_t)(gethrtime() / 1000000LL);
1147c478bd9Sstevel@tonic-gate return (cur_time);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate
117e6ed03fcSmeem uint64_t
getcurrentsec(void)118e6ed03fcSmeem getcurrentsec(void)
119e6ed03fcSmeem {
120e6ed03fcSmeem return (gethrtime() / NANOSEC);
121e6ed03fcSmeem }
122e6ed03fcSmeem
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * Add fd to the set being polled. Returns 0 if ok; -1 if failed.
1257c478bd9Sstevel@tonic-gate */
1267c478bd9Sstevel@tonic-gate int
poll_add(int fd)1277c478bd9Sstevel@tonic-gate poll_add(int fd)
1287c478bd9Sstevel@tonic-gate {
1297c478bd9Sstevel@tonic-gate int i;
1307c478bd9Sstevel@tonic-gate int new_num;
1317c478bd9Sstevel@tonic-gate struct pollfd *newfds;
1327c478bd9Sstevel@tonic-gate retry:
1337c478bd9Sstevel@tonic-gate /* Check if already present */
1347c478bd9Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) {
1357c478bd9Sstevel@tonic-gate if (pollfds[i].fd == fd)
1367c478bd9Sstevel@tonic-gate return (0);
1377c478bd9Sstevel@tonic-gate }
1387c478bd9Sstevel@tonic-gate /* Check for empty spot already present */
1397c478bd9Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) {
1407c478bd9Sstevel@tonic-gate if (pollfds[i].fd == -1) {
1417c478bd9Sstevel@tonic-gate pollfds[i].fd = fd;
1427c478bd9Sstevel@tonic-gate return (0);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate }
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /* Allocate space for 32 more fds and initialize to -1 */
1477c478bd9Sstevel@tonic-gate new_num = pollfd_num + 32;
1487c478bd9Sstevel@tonic-gate newfds = realloc(pollfds, new_num * sizeof (struct pollfd));
1497c478bd9Sstevel@tonic-gate if (newfds == NULL) {
1507c478bd9Sstevel@tonic-gate logperror("poll_add: realloc");
1517c478bd9Sstevel@tonic-gate return (-1);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate for (i = pollfd_num; i < new_num; i++) {
1547c478bd9Sstevel@tonic-gate newfds[i].fd = -1;
1557c478bd9Sstevel@tonic-gate newfds[i].events = POLLIN;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate pollfd_num = new_num;
1587c478bd9Sstevel@tonic-gate pollfds = newfds;
1597c478bd9Sstevel@tonic-gate goto retry;
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate /*
1637c478bd9Sstevel@tonic-gate * Remove fd from the set being polled. Returns 0 if ok; -1 if failed.
1647c478bd9Sstevel@tonic-gate */
165e11c3f44Smeem int
poll_remove(int fd)1667c478bd9Sstevel@tonic-gate poll_remove(int fd)
1677c478bd9Sstevel@tonic-gate {
1687c478bd9Sstevel@tonic-gate int i;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /* Check if already present */
1717c478bd9Sstevel@tonic-gate for (i = 0; i < pollfd_num; i++) {
1727c478bd9Sstevel@tonic-gate if (pollfds[i].fd == fd) {
1737c478bd9Sstevel@tonic-gate pollfds[i].fd = -1;
1747c478bd9Sstevel@tonic-gate return (0);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate return (-1);
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /*
1817c478bd9Sstevel@tonic-gate * Extract information about the phyint instance. If the phyint instance still
1827c478bd9Sstevel@tonic-gate * exists in the kernel then set pii_in_use, else clear it. check_if_removed()
1837c478bd9Sstevel@tonic-gate * will use it to detect phyint instances that don't exist any longer and
1847c478bd9Sstevel@tonic-gate * remove them, from our database of phyint instances.
1857c478bd9Sstevel@tonic-gate * Return value:
1867c478bd9Sstevel@tonic-gate * returns true if the phyint instance exists in the kernel,
1877c478bd9Sstevel@tonic-gate * returns false otherwise
1887c478bd9Sstevel@tonic-gate */
1897c478bd9Sstevel@tonic-gate static boolean_t
pii_process(int af,char * name,struct phyint_instance ** pii_p)1907c478bd9Sstevel@tonic-gate pii_process(int af, char *name, struct phyint_instance **pii_p)
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate int err;
1937c478bd9Sstevel@tonic-gate struct phyint_instance *pii;
1947c478bd9Sstevel@tonic-gate struct phyint_instance *pii_other;
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate if (debug & D_PHYINT)
1977c478bd9Sstevel@tonic-gate logdebug("pii_process(%s %s)\n", AF_STR(af), name);
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate pii = phyint_inst_lookup(af, name);
2007c478bd9Sstevel@tonic-gate if (pii == NULL) {
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate * Phyint instance does not exist in our tables,
2037c478bd9Sstevel@tonic-gate * create new phyint instance
2047c478bd9Sstevel@tonic-gate */
2057c478bd9Sstevel@tonic-gate pii = phyint_inst_init_from_k(af, name);
2067c478bd9Sstevel@tonic-gate } else {
2077c478bd9Sstevel@tonic-gate /* Phyint exists in our tables */
2087c478bd9Sstevel@tonic-gate err = phyint_inst_update_from_k(pii);
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate switch (err) {
2117c478bd9Sstevel@tonic-gate case PI_IOCTL_ERROR:
2127c478bd9Sstevel@tonic-gate /* Some ioctl error. don't change anything */
2137c478bd9Sstevel@tonic-gate pii->pii_in_use = 1;
2147c478bd9Sstevel@tonic-gate break;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate case PI_GROUP_CHANGED:
2177c478bd9Sstevel@tonic-gate case PI_IFINDEX_CHANGED:
2187c478bd9Sstevel@tonic-gate /*
219e11c3f44Smeem * Interface index or group membership has changed.
220e11c3f44Smeem * Delete the old state and recreate based on the new
221e11c3f44Smeem * state (it may no longer be in a group).
2227c478bd9Sstevel@tonic-gate */
2237c478bd9Sstevel@tonic-gate pii_other = phyint_inst_other(pii);
2247c478bd9Sstevel@tonic-gate if (pii_other != NULL)
2257c478bd9Sstevel@tonic-gate phyint_inst_delete(pii_other);
2267c478bd9Sstevel@tonic-gate phyint_inst_delete(pii);
2277c478bd9Sstevel@tonic-gate pii = phyint_inst_init_from_k(af, name);
2287c478bd9Sstevel@tonic-gate break;
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate case PI_DELETED:
2317c478bd9Sstevel@tonic-gate /* Phyint instance has disappeared from kernel */
2327c478bd9Sstevel@tonic-gate pii->pii_in_use = 0;
2337c478bd9Sstevel@tonic-gate break;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate case PI_OK:
2367c478bd9Sstevel@tonic-gate /* Phyint instance exists and is fine */
2377c478bd9Sstevel@tonic-gate pii->pii_in_use = 1;
2387c478bd9Sstevel@tonic-gate break;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate default:
2417c478bd9Sstevel@tonic-gate /* Unknown status */
2427c478bd9Sstevel@tonic-gate logerr("pii_process: Unknown status %d\n", err);
2437c478bd9Sstevel@tonic-gate break;
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate *pii_p = pii;
2487c478bd9Sstevel@tonic-gate if (pii != NULL)
2497c478bd9Sstevel@tonic-gate return (pii->pii_in_use ? _B_TRUE : _B_FALSE);
2507c478bd9Sstevel@tonic-gate else
2517c478bd9Sstevel@tonic-gate return (_B_FALSE);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate * Scan all interfaces to detect changes as well as new and deleted interfaces
2567c478bd9Sstevel@tonic-gate */
2577c478bd9Sstevel@tonic-gate static void
initifs()2587c478bd9Sstevel@tonic-gate initifs()
2597c478bd9Sstevel@tonic-gate {
260e11c3f44Smeem int i, nlifr;
2617c478bd9Sstevel@tonic-gate int af;
2627c478bd9Sstevel@tonic-gate char *cp;
2637c478bd9Sstevel@tonic-gate char *buf;
264e11c3f44Smeem int sockfd;
265e11c3f44Smeem uint64_t flags;
2667c478bd9Sstevel@tonic-gate struct lifnum lifn;
2677c478bd9Sstevel@tonic-gate struct lifconf lifc;
268e11c3f44Smeem struct lifreq lifreq;
2697c478bd9Sstevel@tonic-gate struct lifreq *lifr;
2707c478bd9Sstevel@tonic-gate struct logint *li;
2717c478bd9Sstevel@tonic-gate struct phyint_instance *pii;
2727c478bd9Sstevel@tonic-gate struct phyint_instance *next_pii;
273e11c3f44Smeem struct phyint_group *pg, *next_pg;
274e11c3f44Smeem char pi_name[LIFNAMSIZ + 1];
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate if (debug & D_PHYINT)
2777c478bd9Sstevel@tonic-gate logdebug("initifs: Scanning interfaces\n");
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate last_initifs_time = getcurrenttime();
2807c478bd9Sstevel@tonic-gate
28187e66ffcSrk /*
282e11c3f44Smeem * Free the existing local address list; we'll build a new list below.
28387e66ffcSrk */
284e11c3f44Smeem addrlist_free(&localaddrs);
28587e66ffcSrk
2867c478bd9Sstevel@tonic-gate /*
2877c478bd9Sstevel@tonic-gate * Mark the interfaces so that we can find phyints and logints
2887c478bd9Sstevel@tonic-gate * which have disappeared from the kernel. pii_process() and
2897c478bd9Sstevel@tonic-gate * logint_init_from_k() will set {pii,li}_in_use when they find
2907c478bd9Sstevel@tonic-gate * the interface in the kernel. Also, clear dupaddr bit on probe
2917c478bd9Sstevel@tonic-gate * logint. check_addr_unique() will set the dupaddr bit on the
2927c478bd9Sstevel@tonic-gate * probe logint, if the testaddress is not unique.
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate for (pii = phyint_instances; pii != NULL; pii = pii->pii_next) {
2957c478bd9Sstevel@tonic-gate pii->pii_in_use = 0;
2967c478bd9Sstevel@tonic-gate for (li = pii->pii_logint; li != NULL; li = li->li_next) {
2977c478bd9Sstevel@tonic-gate li->li_in_use = 0;
2987c478bd9Sstevel@tonic-gate if (pii->pii_probe_logint == li)
2997c478bd9Sstevel@tonic-gate li->li_dupaddr = 0;
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
303e11c3f44Smeem /*
304e11c3f44Smeem * As above, mark groups so that we can detect IPMP interfaces which
305e11c3f44Smeem * have been removed from the kernel. Also, delete the group address
306e11c3f44Smeem * list since we'll iteratively recreate it below.
307e11c3f44Smeem */
308e11c3f44Smeem for (pg = phyint_groups; pg != NULL; pg = pg->pg_next) {
309e11c3f44Smeem pg->pg_in_use = _B_FALSE;
310e11c3f44Smeem addrlist_free(&pg->pg_addrs);
311e11c3f44Smeem }
312e11c3f44Smeem
3137c478bd9Sstevel@tonic-gate lifn.lifn_family = AF_UNSPEC;
314e11c3f44Smeem lifn.lifn_flags = LIFC_ALLZONES | LIFC_UNDER_IPMP;
315e11c3f44Smeem again:
3167c478bd9Sstevel@tonic-gate if (ioctl(ifsock_v4, SIOCGLIFNUM, (char *)&lifn) < 0) {
317e11c3f44Smeem logperror("initifs: ioctl (get interface count)");
3187c478bd9Sstevel@tonic-gate return;
3197c478bd9Sstevel@tonic-gate }
320e11c3f44Smeem /*
321e11c3f44Smeem * Pad the interface count to detect when additional interfaces have
322e11c3f44Smeem * been configured between SIOCGLIFNUM and SIOCGLIFCONF.
323e11c3f44Smeem */
324e11c3f44Smeem lifn.lifn_count += 4;
3257c478bd9Sstevel@tonic-gate
326e11c3f44Smeem if ((buf = calloc(lifn.lifn_count, sizeof (struct lifreq))) == NULL) {
3277c478bd9Sstevel@tonic-gate logperror("initifs: calloc");
3287c478bd9Sstevel@tonic-gate return;
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate lifc.lifc_family = AF_UNSPEC;
332e11c3f44Smeem lifc.lifc_flags = LIFC_ALLZONES | LIFC_UNDER_IPMP;
333e11c3f44Smeem lifc.lifc_len = lifn.lifn_count * sizeof (struct lifreq);
3347c478bd9Sstevel@tonic-gate lifc.lifc_buf = buf;
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate if (ioctl(ifsock_v4, SIOCGLIFCONF, (char *)&lifc) < 0) {
337e11c3f44Smeem logperror("initifs: ioctl (get interface configuration)");
3387c478bd9Sstevel@tonic-gate free(buf);
3397c478bd9Sstevel@tonic-gate return;
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
343e11c3f44Smeem * If every lifr_req slot is taken, then additional interfaces must
344e11c3f44Smeem * have been plumbed between the SIOCGLIFNUM and the SIOCGLIFCONF.
345e11c3f44Smeem * Recalculate to make sure we didn't miss any interfaces.
3467c478bd9Sstevel@tonic-gate */
347e11c3f44Smeem nlifr = lifc.lifc_len / sizeof (struct lifreq);
348e11c3f44Smeem if (nlifr >= lifn.lifn_count) {
349e11c3f44Smeem free(buf);
350e11c3f44Smeem goto again;
351e11c3f44Smeem }
35287e66ffcSrk
353e11c3f44Smeem /*
354e11c3f44Smeem * Walk through the lifreqs returned by SIOGGLIFCONF, and refresh the
355e11c3f44Smeem * global list of addresses, phyint groups, phyints, and logints.
356e11c3f44Smeem */
357e11c3f44Smeem for (lifr = lifc.lifc_req, i = 0; i < nlifr; i++, lifr++) {
3587c478bd9Sstevel@tonic-gate af = lifr->lifr_addr.ss_family;
35987e66ffcSrk sockfd = (af == AF_INET) ? ifsock_v4 : ifsock_v6;
360e11c3f44Smeem (void) strlcpy(lifreq.lifr_name, lifr->lifr_name, LIFNAMSIZ);
36187e66ffcSrk
36287e66ffcSrk if (ioctl(sockfd, SIOCGLIFFLAGS, &lifreq) == -1) {
36387e66ffcSrk if (errno != ENXIO)
36487e66ffcSrk logperror("initifs: ioctl (SIOCGLIFFLAGS)");
36587e66ffcSrk continue;
36687e66ffcSrk }
367e11c3f44Smeem flags = lifreq.lifr_flags;
368e11c3f44Smeem
369e11c3f44Smeem /*
370e11c3f44Smeem * If the address is IFF_UP, add it to the local address list.
371e11c3f44Smeem * (We ignore addresses that aren't IFF_UP since another node
372e11c3f44Smeem * might legitimately have that address IFF_UP.)
373e11c3f44Smeem */
374e11c3f44Smeem if (flags & IFF_UP) {
375e11c3f44Smeem (void) addrlist_add(&localaddrs, lifr->lifr_name, flags,
376e11c3f44Smeem &lifr->lifr_addr);
377e11c3f44Smeem }
37887e66ffcSrk
37987e66ffcSrk /*
380e11c3f44Smeem * If this address is on an IPMP meta-interface, update our
381e11c3f44Smeem * phyint_group information (either by recording that group
382e11c3f44Smeem * still exists or creating a new group), and track what
383e11c3f44Smeem * group the address is part of.
38487e66ffcSrk */
385e11c3f44Smeem if (flags & IFF_IPMP) {
386e11c3f44Smeem if (ioctl(sockfd, SIOCGLIFGROUPNAME, &lifreq) == -1) {
387e11c3f44Smeem if (errno != ENXIO)
388e11c3f44Smeem logperror("initifs: ioctl "
389e11c3f44Smeem "(SIOCGLIFGROUPNAME)");
39087e66ffcSrk continue;
39187e66ffcSrk }
392e11c3f44Smeem
393e11c3f44Smeem pg = phyint_group_lookup(lifreq.lifr_groupname);
394e11c3f44Smeem if (pg == NULL) {
395e11c3f44Smeem pg = phyint_group_create(lifreq.lifr_groupname);
396e11c3f44Smeem if (pg == NULL) {
397e11c3f44Smeem logerr("initifs: cannot create group "
398