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 5*e11c3f44Smeem * Common Development and Distribution License (the "License"). 6*e11c3f44Smeem * 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 20*e11c3f44Smeem * 21*e11c3f44Smeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 227c478bd9Sstevel@tonic-gate * Use is subject to license terms. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate /* 26*e11c3f44Smeem * IPMP query interfaces (see PSARC/2002/615 and PSARC/2007/272). 277c478bd9Sstevel@tonic-gate */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <assert.h> 307c478bd9Sstevel@tonic-gate #include <errno.h> 31*e11c3f44Smeem #include <libinetutil.h> 327c478bd9Sstevel@tonic-gate #include <string.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <unistd.h> 357c478bd9Sstevel@tonic-gate #include <sys/types.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include "ipmp_impl.h" 387c478bd9Sstevel@tonic-gate #include "ipmp_mpathd.h" 397c478bd9Sstevel@tonic-gate #include "ipmp_query_impl.h" 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate static ipmp_ifinfo_t *ipmp_ifinfo_clone(ipmp_ifinfo_t *); 42*e11c3f44Smeem static ipmp_addrinfo_t *ipmp_addrinfo_clone(ipmp_addrinfo_t *); 43*e11c3f44Smeem static ipmp_addrlist_t *ipmp_addrlist_clone(ipmp_addrlist_t *); 447c478bd9Sstevel@tonic-gate static ipmp_grouplist_t *ipmp_grouplist_clone(ipmp_grouplist_t *); 457c478bd9Sstevel@tonic-gate static ipmp_groupinfo_t *ipmp_groupinfo_clone(ipmp_groupinfo_t *); 46*e11c3f44Smeem static ipmp_iflist_t *ipmp_iflist_create(uint_t, char (*)[LIFNAMSIZ]); 47*e11c3f44Smeem static void ipmp_freeiflist(ipmp_iflist_t *); 48*e11c3f44Smeem static ipmp_addrlist_t *ipmp_addrlist_create(uint_t, struct sockaddr_storage *); 49*e11c3f44Smeem static void ipmp_freeaddrlist(ipmp_addrlist_t *); 507c478bd9Sstevel@tonic-gate static ipmp_groupinfo_t *ipmp_snap_getgroupinfo(ipmp_snap_t *, const char *); 517c478bd9Sstevel@tonic-gate static ipmp_ifinfo_t *ipmp_snap_getifinfo(ipmp_snap_t *, const char *); 52*e11c3f44Smeem static ipmp_addrinfo_t *ipmp_snap_getaddrinfo(ipmp_snap_t *, const char *, 53*e11c3f44Smeem struct sockaddr_storage *); 547c478bd9Sstevel@tonic-gate static int ipmp_snap_take(ipmp_state_t *, ipmp_snap_t **); 557c478bd9Sstevel@tonic-gate static boolean_t ipmp_checktlv(ipmp_infotype_t, size_t, void *); 567c478bd9Sstevel@tonic-gate static int ipmp_querydone(ipmp_state_t *, int); 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate /* 597c478bd9Sstevel@tonic-gate * Using `statep', send a query request for `type' to in.mpathd, and if 607c478bd9Sstevel@tonic-gate * necessary wait until at least `endtp' for a response. Returns an IPMP 617c478bd9Sstevel@tonic-gate * error code. If successful, the caller may then read additional query 627c478bd9Sstevel@tonic-gate * information through ipmp_readinfo(), and must eventually call 637c478bd9Sstevel@tonic-gate * ipmp_querydone() to complete the query operation. Only one query may be 647c478bd9Sstevel@tonic-gate * outstanding on a given `statep' at a time. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate static int 677c478bd9Sstevel@tonic-gate ipmp_sendquery(ipmp_state_t *statep, ipmp_infotype_t type, const char *name, 68*e11c3f44Smeem const void *addr, struct timeval *endtp) 697c478bd9Sstevel@tonic-gate { 707c478bd9Sstevel@tonic-gate mi_query_t query; 717c478bd9Sstevel@tonic-gate mi_result_t result; 727c478bd9Sstevel@tonic-gate int retval; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate query.miq_command = MI_QUERY; 757c478bd9Sstevel@tonic-gate query.miq_inforeq = type; 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate switch (type) { 78*e11c3f44Smeem case IPMP_ADDRINFO: 79*e11c3f44Smeem (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ); 80*e11c3f44Smeem query.miq_addr = *(struct sockaddr_storage *)addr; 81*e11c3f44Smeem break; 82*e11c3f44Smeem 837c478bd9Sstevel@tonic-gate case IPMP_GROUPINFO: 847c478bd9Sstevel@tonic-gate (void) strlcpy(query.miq_grname, name, LIFGRNAMSIZ); 857c478bd9Sstevel@tonic-gate break; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate case IPMP_IFINFO: 887c478bd9Sstevel@tonic-gate (void) strlcpy(query.miq_ifname, name, LIFNAMSIZ); 897c478bd9Sstevel@tonic-gate break; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate case IPMP_GROUPLIST: 927c478bd9Sstevel@tonic-gate case IPMP_SNAP: 937c478bd9Sstevel@tonic-gate break; 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate default: 967c478bd9Sstevel@tonic-gate assert(0); 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate if (gettimeofday(endtp, NULL) == -1) 1007c478bd9Sstevel@tonic-gate return (IPMP_FAILURE); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate endtp->tv_sec += IPMP_REQTIMEOUT; 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate assert(statep->st_fd == -1); 1057c478bd9Sstevel@tonic-gate retval = ipmp_connect(&statep->st_fd); 1067c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 1077c478bd9Sstevel@tonic-gate return (retval); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate retval = ipmp_write(statep->st_fd, &query, sizeof (query)); 1107c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 1117c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate retval = ipmp_read(statep->st_fd, &result, sizeof (result), endtp); 1147c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 1157c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate if (result.me_mpathd_error != IPMP_SUCCESS) 1187c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, result.me_mpathd_error)); 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate return (IPMP_SUCCESS); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Using `statep', read a query response of type `infotype' into a dynamically 1257c478bd9Sstevel@tonic-gate * allocated buffer pointed to by `*infop', before the current time becomes 1267c478bd9Sstevel@tonic-gate * `endtp'. Returns an IPMP error code. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate static int 1297c478bd9Sstevel@tonic-gate ipmp_readinfo(ipmp_state_t *statep, ipmp_infotype_t infotype, void **infop, 1307c478bd9Sstevel@tonic-gate const struct timeval *endtp) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate int retval; 1337c478bd9Sstevel@tonic-gate size_t len; 1347c478bd9Sstevel@tonic-gate ipmp_infotype_t type; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate retval = ipmp_readtlv(statep->st_fd, &type, &len, infop, endtp); 1377c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 1387c478bd9Sstevel@tonic-gate return (retval); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (type != infotype || !ipmp_checktlv(type, len, *infop)) { 1417c478bd9Sstevel@tonic-gate free(*infop); 1427c478bd9Sstevel@tonic-gate return (IPMP_EPROTO); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate return (IPMP_SUCCESS); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate /* 149*e11c3f44Smeem * Using `statep', read in the remaining IPMP group information TLVs from 150*e11c3f44Smeem * in.mpathd into `grinfop' before the current time becomes `endtp'. Returns 151*e11c3f44Smeem * an IPMP error code. On failure, `grinfop' will have its original contents. 152*e11c3f44Smeem */ 153*e11c3f44Smeem static int 154*e11c3f44Smeem ipmp_readgroupinfo_lists(ipmp_state_t *statep, ipmp_groupinfo_t *grinfop, 155*e11c3f44Smeem const struct timeval *endtp) 156*e11c3f44Smeem { 157*e11c3f44Smeem int retval; 158*e11c3f44Smeem ipmp_iflist_t *iflistp; 159*e11c3f44Smeem ipmp_addrlist_t *adlistp; 160*e11c3f44Smeem 161*e11c3f44Smeem retval = ipmp_readinfo(statep, IPMP_IFLIST, (void **)&iflistp, endtp); 162*e11c3f44Smeem if (retval != IPMP_SUCCESS) 163*e11c3f44Smeem return (retval); 164*e11c3f44Smeem 165*e11c3f44Smeem retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&adlistp, endtp); 166*e11c3f44Smeem if (retval != IPMP_SUCCESS) { 167*e11c3f44Smeem ipmp_freeiflist(iflistp); 168*e11c3f44Smeem return (retval); 169*e11c3f44Smeem } 170*e11c3f44Smeem 171*e11c3f44Smeem grinfop->gr_iflistp = iflistp; 172*e11c3f44Smeem grinfop->gr_adlistp = adlistp; 173*e11c3f44Smeem return (IPMP_SUCCESS); 174*e11c3f44Smeem } 175*e11c3f44Smeem 176*e11c3f44Smeem /* 177*e11c3f44Smeem * Using `statep', read in the remaining IPMP interface information TLVs from 178*e11c3f44Smeem * in.mpathd into `ifinfop' before the current time becomes `endtp'. Returns 179*e11c3f44Smeem * an IPMP error code. On failure, `ifinfop' will have its original contents. 180*e11c3f44Smeem */ 181*e11c3f44Smeem static int 182*e11c3f44Smeem ipmp_readifinfo_lists(ipmp_state_t *statep, ipmp_ifinfo_t *ifinfop, 183*e11c3f44Smeem const struct timeval *endtp) 184*e11c3f44Smeem { 185*e11c3f44Smeem int retval; 186*e11c3f44Smeem ipmp_addrlist_t *tlist4p, *tlist6p; 187*e11c3f44Smeem 188*e11c3f44Smeem retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist4p, endtp); 189*e11c3f44Smeem if (retval != IPMP_SUCCESS) 190*e11c3f44Smeem return (retval); 191*e11c3f44Smeem 192*e11c3f44Smeem retval = ipmp_readinfo(statep, IPMP_ADDRLIST, (void **)&tlist6p, endtp); 193*e11c3f44Smeem if (retval != IPMP_SUCCESS) { 194*e11c3f44Smeem ipmp_freeaddrlist(tlist4p); 195*e11c3f44Smeem return (retval); 196*e11c3f44Smeem } 197*e11c3f44Smeem 198*e11c3f44Smeem ifinfop->if_targinfo4.it_targlistp = tlist4p; 199*e11c3f44Smeem ifinfop->if_targinfo6.it_targlistp = tlist6p; 200*e11c3f44Smeem return (IPMP_SUCCESS); 201*e11c3f44Smeem } 202*e11c3f44Smeem 203*e11c3f44Smeem /* 2047c478bd9Sstevel@tonic-gate * Complete the query operation started in ipmp_sendquery(). The interface is 2057c478bd9Sstevel@tonic-gate * designed to be easy to use in the `return' statement of a function, and 2067c478bd9Sstevel@tonic-gate * thus returns the passed in `retval' and preserves `errno'. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate static int 2097c478bd9Sstevel@tonic-gate ipmp_querydone(ipmp_state_t *statep, int retval) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate int error = errno; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate (void) close(statep->st_fd); 2147c478bd9Sstevel@tonic-gate statep->st_fd = -1; 2157c478bd9Sstevel@tonic-gate errno = error; 2167c478bd9Sstevel@tonic-gate return (retval); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Using `handle', get the group list and store the results in a dynamically 2217c478bd9Sstevel@tonic-gate * allocated buffer pointed to by `*grlistpp'. Returns an IPMP error code. 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate int 2247c478bd9Sstevel@tonic-gate ipmp_getgrouplist(ipmp_handle_t handle, ipmp_grouplist_t **grlistpp) 2257c478bd9Sstevel@tonic-gate { 2267c478bd9Sstevel@tonic-gate ipmp_state_t *statep = handle; 2277c478bd9Sstevel@tonic-gate struct timeval end; 2287c478bd9Sstevel@tonic-gate int retval; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate if (statep->st_snap != NULL) { 2317c478bd9Sstevel@tonic-gate *grlistpp = ipmp_grouplist_clone(statep->st_snap->sn_grlistp); 2327c478bd9Sstevel@tonic-gate return (*grlistpp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 235*e11c3f44Smeem retval = ipmp_sendquery(statep, IPMP_GROUPLIST, NULL, NULL, &end); 2367c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 2377c478bd9Sstevel@tonic-gate return (retval); 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate retval = ipmp_readinfo(statep, IPMP_GROUPLIST, (void **)grlistpp, &end); 2407c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate /* 2447c478bd9Sstevel@tonic-gate * Free the group list pointed to by `grlistp'. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate void 2477c478bd9Sstevel@tonic-gate ipmp_freegrouplist(ipmp_grouplist_t *grlistp) 2487c478bd9Sstevel@tonic-gate { 2497c478bd9Sstevel@tonic-gate free(grlistp); 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate /* 2537c478bd9Sstevel@tonic-gate * Using `handle', get the group information associated with group `name' and 2547c478bd9Sstevel@tonic-gate * store the results in a dynamically allocated buffer pointed to by 2557c478bd9Sstevel@tonic-gate * `*grinfopp'. Returns an IPMP error code. 2567c478bd9Sstevel@tonic-gate */ 2577c478bd9Sstevel@tonic-gate int 2587c478bd9Sstevel@tonic-gate ipmp_getgroupinfo(ipmp_handle_t handle, const char *name, 2597c478bd9Sstevel@tonic-gate ipmp_groupinfo_t **grinfopp) 2607c478bd9Sstevel@tonic-gate { 2617c478bd9Sstevel@tonic-gate ipmp_state_t *statep = handle; 2627c478bd9Sstevel@tonic-gate int retval; 2637c478bd9Sstevel@tonic-gate struct timeval end; 2647c478bd9Sstevel@tonic-gate ipmp_groupinfo_t *grinfop; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate if (statep->st_snap != NULL) { 2677c478bd9Sstevel@tonic-gate grinfop = ipmp_snap_getgroupinfo(statep->st_snap, name); 2687c478bd9Sstevel@tonic-gate if (grinfop == NULL) 2697c478bd9Sstevel@tonic-gate return (IPMP_EUNKGROUP); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate *grinfopp = ipmp_groupinfo_clone(grinfop); 2727c478bd9Sstevel@tonic-gate return (*grinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate 275*e11c3f44Smeem retval = ipmp_sendquery(statep, IPMP_GROUPINFO, name, NULL, &end); 2767c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 2777c478bd9Sstevel@tonic-gate return (retval); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate retval = ipmp_readinfo(statep, IPMP_GROUPINFO, (void **)grinfopp, &end); 2807c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 2817c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 2827c478bd9Sstevel@tonic-gate 283*e11c3f44Smeem retval = ipmp_readgroupinfo_lists(statep, *grinfopp, &end); 2847c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 2857c478bd9Sstevel@tonic-gate free(*grinfopp); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* 2917c478bd9Sstevel@tonic-gate * Free the group information pointed to by `grinfop'. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate void 2947c478bd9Sstevel@tonic-gate ipmp_freegroupinfo(ipmp_groupinfo_t *grinfop) 2957c478bd9Sstevel@tonic-gate { 296*e11c3f44Smeem ipmp_freeaddrlist(grinfop->gr_adlistp); 297*e11c3f44Smeem ipmp_freeiflist(grinfop->gr_iflistp); 2987c478bd9Sstevel@tonic-gate free(grinfop); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Using `handle', get the interface information associated with interface 3037c478bd9Sstevel@tonic-gate * `name' and store the results in a dynamically allocated buffer pointed to 3047c478bd9Sstevel@tonic-gate * by `*ifinfopp'. Returns an IPMP error code. 3057c478bd9Sstevel@tonic-gate */ 3067c478bd9Sstevel@tonic-gate int 3077c478bd9Sstevel@tonic-gate ipmp_getifinfo(ipmp_handle_t handle, const char *name, ipmp_ifinfo_t **ifinfopp) 3087c478bd9Sstevel@tonic-gate { 3097c478bd9Sstevel@tonic-gate ipmp_state_t *statep = handle; 3107c478bd9Sstevel@tonic-gate ipmp_ifinfo_t *ifinfop; 3117c478bd9Sstevel@tonic-gate int retval; 3127c478bd9Sstevel@tonic-gate struct timeval end; 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if (statep->st_snap != NULL) { 3157c478bd9Sstevel@tonic-gate ifinfop = ipmp_snap_getifinfo(statep->st_snap, name); 3167c478bd9Sstevel@tonic-gate if (ifinfop == NULL) 3177c478bd9Sstevel@tonic-gate return (IPMP_EUNKIF); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate *ifinfopp = ipmp_ifinfo_clone(ifinfop); 3207c478bd9Sstevel@tonic-gate return (*ifinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 323*e11c3f44Smeem retval = ipmp_sendquery(statep, IPMP_IFINFO, name, NULL, &end); 3247c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 3257c478bd9Sstevel@tonic-gate return (retval); 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate retval = ipmp_readinfo(statep, IPMP_IFINFO, (void **)ifinfopp, &end); 328*e11c3f44Smeem if (retval != IPMP_SUCCESS) 329*e11c3f44Smeem return (ipmp_querydone(statep, retval)); 330*e11c3f44Smeem 331*e11c3f44Smeem retval = ipmp_readifinfo_lists(statep, *ifinfopp, &end); 332*e11c3f44Smeem if (retval != IPMP_SUCCESS) 333*e11c3f44Smeem free(*ifinfopp); 334*e11c3f44Smeem 3357c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate /* 3397c478bd9Sstevel@tonic-gate * Free the interface information pointed to by `ifinfop'. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate void 3427c478bd9Sstevel@tonic-gate ipmp_freeifinfo(ipmp_ifinfo_t *ifinfop) 3437c478bd9Sstevel@tonic-gate { 344*e11c3f44Smeem ipmp_freeaddrlist(ifinfop->if_targinfo4.it_targlistp); 345*e11c3f44Smeem ipmp_freeaddrlist(ifinfop->if_targinfo6.it_targlistp); 3467c478bd9Sstevel@tonic-gate free(ifinfop); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* 350*e11c3f44Smeem * Using `handle', get the address information associated with address `addrp' 351*e11c3f44Smeem * on group `grname' and store the results in a dynamically allocated buffer 352*e11c3f44Smeem * pointed to by `*adinfopp'. Returns an IPMP error code. 353*e11c3f44Smeem */ 354*e11c3f44Smeem int 355*e11c3f44Smeem ipmp_getaddrinfo(ipmp_handle_t handle, const char *grname, 356*e11c3f44Smeem struct sockaddr_storage *addrp, ipmp_addrinfo_t **adinfopp) 357*e11c3f44Smeem { 358*e11c3f44Smeem ipmp_state_t *statep = handle; 359*e11c3f44Smeem ipmp_addrinfo_t *adinfop; 360*e11c3f44Smeem int retval; 361*e11c3f44Smeem struct timeval end; 362*e11c3f44Smeem 363*e11c3f44Smeem if (statep->st_snap != NULL) { 364*e11c3f44Smeem adinfop = ipmp_snap_getaddrinfo(statep->st_snap, grname, addrp); 365*e11c3f44Smeem if (adinfop == NULL) 366*e11c3f44Smeem return (IPMP_EUNKADDR); 367*e11c3f44Smeem 368*e11c3f44Smeem *adinfopp = ipmp_addrinfo_clone(adinfop); 369*e11c3f44Smeem return (*adinfopp != NULL ? IPMP_SUCCESS : IPMP_ENOMEM); 370*e11c3f44Smeem } 371*e11c3f44Smeem 372*e11c3f44Smeem retval = ipmp_sendquery(statep, IPMP_ADDRINFO, grname, addrp, &end); 373*e11c3f44Smeem if (retval != IPMP_SUCCESS) 374*e11c3f44Smeem return (retval); 375*e11c3f44Smeem 376*e11c3f44Smeem retval = ipmp_readinfo(statep, IPMP_ADDRINFO, (void **)adinfopp, &end); 377*e11c3f44Smeem return (ipmp_querydone(statep, retval)); 378*e11c3f44Smeem } 379*e11c3f44Smeem 380*e11c3f44Smeem /* 381*e11c3f44Smeem * Free the address information pointed to by `adinfop'. 382*e11c3f44Smeem */ 383*e11c3f44Smeem void 384*e11c3f44Smeem ipmp_freeaddrinfo(ipmp_addrinfo_t *adinfop) 385*e11c3f44Smeem { 386*e11c3f44Smeem free(adinfop); 387*e11c3f44Smeem } 388*e11c3f44Smeem 389*e11c3f44Smeem /* 3907c478bd9Sstevel@tonic-gate * Check if `buf' has a NUL byte in its first `bufsize' bytes. 3917c478bd9Sstevel@tonic-gate */ 3927c478bd9Sstevel@tonic-gate static boolean_t 3937c478bd9Sstevel@tonic-gate hasnulbyte(const char *buf, size_t bufsize) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate while (bufsize-- > 0) { 3967c478bd9Sstevel@tonic-gate if (buf[bufsize] == '\0') 3977c478bd9Sstevel@tonic-gate return (B_TRUE); 3987c478bd9Sstevel@tonic-gate } 3997c478bd9Sstevel@tonic-gate return (B_FALSE); 4007c478bd9Sstevel@tonic-gate } 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate /* 4037c478bd9Sstevel@tonic-gate * Check that the TLV triplet named by `type', `len' and `value' is correctly 4047c478bd9Sstevel@tonic-gate * formed. 4057c478bd9Sstevel@tonic-gate */ 4067c478bd9Sstevel@tonic-gate static boolean_t 4077c478bd9Sstevel@tonic-gate ipmp_checktlv(ipmp_infotype_t type, size_t len, void *value) 4087c478bd9Sstevel@tonic-gate { 4097c478bd9Sstevel@tonic-gate ipmp_iflist_t *iflistp; 4107c478bd9Sstevel@tonic-gate ipmp_ifinfo_t *ifinfop; 4117c478bd9Sstevel@tonic-gate ipmp_grouplist_t *grlistp; 4127c478bd9Sstevel@tonic-gate ipmp_groupinfo_t *grinfop; 413*e11c3f44Smeem ipmp_addrlist_t *adlistp; 4147c478bd9Sstevel@tonic-gate unsigned int i; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate switch (type) { 417*e11c3f44Smeem case IPMP_ADDRINFO: 418*e11c3f44Smeem if (len != sizeof (ipmp_addrinfo_t)) 419*e11c3f44Smeem return (B_FALSE); 420*e11c3f44Smeem break; 421*e11c3f44Smeem 422*e11c3f44Smeem case IPMP_ADDRLIST: 423*e11c3f44Smeem adlistp = (ipmp_addrlist_t *)value; 424*e11c3f44Smeem if (len < IPMP_ADDRLIST_SIZE(0) || 425*e11c3f44Smeem len < IPMP_ADDRLIST_SIZE(adlistp->al_naddr)) 426*e11c3f44Smeem return (B_FALSE); 427*e11c3f44Smeem break; 428*e11c3f44Smeem 4297c478bd9Sstevel@tonic-gate case IPMP_IFLIST: 4307c478bd9Sstevel@tonic-gate iflistp = (ipmp_iflist_t *)value; 431*e11c3f44Smeem if (len < IPMP_IFLIST_SIZE(0) || 4327c478bd9Sstevel@tonic-gate len < IPMP_IFLIST_SIZE(iflistp->il_nif)) 4337c478bd9Sstevel@tonic-gate return (B_FALSE); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate for (i = 0; i < iflistp->il_nif; i++) 4367c478bd9Sstevel@tonic-gate if (!hasnulbyte(iflistp->il_ifs[i], LIFNAMSIZ)) 4377c478bd9Sstevel@tonic-gate return (B_FALSE); 4387c478bd9Sstevel@tonic-gate break; 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate case IPMP_IFINFO: 4417c478bd9Sstevel@tonic-gate ifinfop = (ipmp_ifinfo_t *)value; 4427c478bd9Sstevel@tonic-gate if (len != sizeof (ipmp_ifinfo_t)) 4437c478bd9Sstevel@tonic-gate return (B_FALSE); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate if (!hasnulbyte(ifinfop->if_name, LIFNAMSIZ) || 4467c478bd9Sstevel@tonic-gate !hasnulbyte(ifinfop->if_group, LIFGRNAMSIZ)) 4477c478bd9Sstevel@tonic-gate return (B_FALSE); 4487c478bd9Sstevel@tonic-gate break; 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate case IPMP_GROUPLIST: 4517c478bd9Sstevel@tonic-gate grlistp = (ipmp_grouplist_t *)value; 452*e11c3f44Smeem if (len < IPMP_GROUPLIST_SIZE(0) || 4537c478bd9Sstevel@tonic-gate len < IPMP_GROUPLIST_SIZE(grlistp->gl_ngroup)) 4547c478bd9Sstevel@tonic-gate return (B_FALSE); 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate for (i = 0; i < grlistp->gl_ngroup; i++) 4577c478bd9Sstevel@tonic-gate if (!hasnulbyte(grlistp->gl_groups[i], LIFGRNAMSIZ)) 4587c478bd9Sstevel@tonic-gate return (B_FALSE); 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate case IPMP_GROUPINFO: 4627c478bd9Sstevel@tonic-gate grinfop = (ipmp_groupinfo_t *)value; 4637c478bd9Sstevel@tonic-gate if (len != sizeof (ipmp_groupinfo_t)) 4647c478bd9Sstevel@tonic-gate return (B_FALSE); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (!hasnulbyte(grinfop->gr_name, LIFGRNAMSIZ)) 4677c478bd9Sstevel@tonic-gate return (B_FALSE); 4687c478bd9Sstevel@tonic-gate break; 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate case IPMP_SNAP: 4717c478bd9Sstevel@tonic-gate if (len != sizeof (ipmp_snap_t)) 4727c478bd9Sstevel@tonic-gate return (B_FALSE); 4737c478bd9Sstevel@tonic-gate break; 4747c478bd9Sstevel@tonic-gate 4757c478bd9Sstevel@tonic-gate default: 4767c478bd9Sstevel@tonic-gate return (B_FALSE); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate return (B_TRUE); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* 483*e11c3f44Smeem * Create a group list; arguments match ipmp_grouplist_t fields. Returns a 484*e11c3f44Smeem * pointer to the new group list on success, or NULL on failure. 4857c478bd9Sstevel@tonic-gate */ 4867c478bd9Sstevel@tonic-gate ipmp_grouplist_t * 4877c478bd9Sstevel@tonic-gate ipmp_grouplist_create(uint64_t sig, unsigned int ngroup, 4887c478bd9Sstevel@tonic-gate char (*groups)[LIFGRNAMSIZ]) 4897c478bd9Sstevel@tonic-gate { 4907c478bd9Sstevel@tonic-gate unsigned int i; 4917c478bd9Sstevel@tonic-gate ipmp_grouplist_t *grlistp; 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate grlistp = malloc(IPMP_GROUPLIST_SIZE(ngroup)); 4947c478bd9Sstevel@tonic-gate if (grlistp == NULL) 4957c478bd9Sstevel@tonic-gate return (NULL); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate grlistp->gl_sig = sig; 4987c478bd9Sstevel@tonic-gate grlistp->gl_ngroup = ngroup; 4997c478bd9Sstevel@tonic-gate for (i = 0; i < ngroup; i++) 5007c478bd9Sstevel@tonic-gate (void) strlcpy(grlistp->gl_groups[i], groups[i], LIFGRNAMSIZ); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate return (grlistp); 5037c478bd9Sstevel@tonic-gate } 5047c478bd9Sstevel@tonic-gate 5057c478bd9Sstevel@tonic-gate /* 5067c478bd9Sstevel@tonic-gate * Clone the group list named by `grlistp'. Returns a pointer to the clone on 5077c478bd9Sstevel@tonic-gate * success, or NULL on failure. 5087c478bd9Sstevel@tonic-gate */ 5097c478bd9Sstevel@tonic-gate ipmp_grouplist_t * 5107c478bd9Sstevel@tonic-gate ipmp_grouplist_clone(ipmp_grouplist_t *grlistp) 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate return (ipmp_grouplist_create(grlistp->gl_sig, grlistp->gl_ngroup, 5137c478bd9Sstevel@tonic-gate grlistp->gl_groups)); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 517*e11c3f44Smeem * Create target information; arguments match ipmp_targinfo_t fields. Returns 518*e11c3f44Smeem * a pointer to the new target info on success, or NULL on failure. 519*e11c3f44Smeem */ 520*e11c3f44Smeem ipmp_targinfo_t * 521*e11c3f44Smeem ipmp_targinfo_create(const char *name, struct sockaddr_storage *testaddrp, 522*e11c3f44Smeem ipmp_if_targmode_t targmode, uint_t ntarg, struct sockaddr_storage *targs) 523*e11c3f44Smeem { 524*e11c3f44Smeem ipmp_targinfo_t *targinfop; 525*e11c3f44Smeem 526*e11c3f44Smeem targinfop = malloc(sizeof (ipmp_targinfo_t)); 527*e11c3f44Smeem if (targinfop == NULL) 528*e11c3f44Smeem return (NULL); 529*e11c3f44Smeem 530*e11c3f44Smeem targinfop->it_testaddr = *testaddrp; 531*e11c3f44Smeem targinfop->it_targmode = targmode; 532*e11c3f44Smeem targinfop->it_targlistp = ipmp_addrlist_create(ntarg, targs); 533*e11c3f44Smeem if (targinfop->it_targlistp == NULL) { 534*e11c3f44Smeem ipmp_freetarginfo(targinfop); 535*e11c3f44Smeem return (NULL); 536*e11c3f44Smeem } 537*e11c3f44Smeem (void) strlcpy(targinfop->it_name, name, LIFNAMSIZ); 538*e11c3f44Smeem 539*e11c3f44Smeem return (targinfop); 540*e11c3f44Smeem } 541*e11c3f44Smeem 542*e11c3f44Smeem /* 543*e11c3f44Smeem * Free the target information pointed to by `targinfop'. 544*e11c3f44Smeem */ 545*e11c3f44Smeem void 546*e11c3f44Smeem ipmp_freetarginfo(ipmp_targinfo_t *targinfop) 547*e11c3f44Smeem { 548*e11c3f44Smeem free(targinfop->it_targlistp); 549*e11c3f44Smeem free(targinfop); 550*e11c3f44Smeem } 551*e11c3f44Smeem 552*e11c3f44Smeem /* 553*e11c3f44Smeem * Create an interface list; arguments match ipmp_iflist_t fields. Returns a 554*e11c3f44Smeem * pointer to the new interface list on success, or NULL on failure. 555*e11c3f44Smeem */ 556*e11c3f44Smeem static ipmp_iflist_t * 557*e11c3f44Smeem ipmp_iflist_create(uint_t nif, char (*ifs)[LIFNAMSIZ]) 558*e11c3f44Smeem { 559*e11c3f44Smeem unsigned int i; 560*e11c3f44Smeem ipmp_iflist_t *iflistp; 561*e11c3f44Smeem 562*e11c3f44Smeem iflistp = malloc(IPMP_IFLIST_SIZE(nif)); 563*e11c3f44Smeem if (iflistp == NULL) 564*e11c3f44Smeem return (NULL); 565*e11c3f44Smeem 566*e11c3f44Smeem iflistp->il_nif = nif; 567*e11c3f44Smeem for (i = 0; i < nif; i++) 568*e11c3f44Smeem (void) strlcpy(iflistp->il_ifs[i], ifs[i], LIFNAMSIZ); 569*e11c3f44Smeem 570*e11c3f44Smeem return (iflistp); 571*e11c3f44Smeem } 572*e11c3f44Smeem 573*e11c3f44Smeem /* 574*e11c3f44Smeem * Free the interface list pointed to by `iflistp'. 575*e11c3f44Smeem */ 576*e11c3f44Smeem static void 577*e11c3f44Smeem ipmp_freeiflist(ipmp_iflist_t *iflistp) 578*e11c3f44Smeem { 579*e11c3f44Smeem free(iflistp); 580*e11c3f44Smeem } 581*e11c3f44Smeem 582*e11c3f44Smeem /* 583*e11c3f44Smeem * Create an interface; arguments match ipmp_ifinfo_t fields. Returns a 584*e11c3f44Smeem * pointer to the new interface on success, or NULL on failure. 5857c478bd9Sstevel@tonic-gate */ 5867c478bd9Sstevel@tonic-gate ipmp_ifinfo_t * 5877c478bd9Sstevel@tonic-gate ipmp_ifinfo_create(const char *name, const char *group, ipmp_if_state_t state, 588*e11c3f44Smeem ipmp_if_type_t type, ipmp_if_linkstate_t linkstate, 589*e11c3f44Smeem ipmp_if_probestate_t probestate, ipmp_if_flags_t flags, 590*e11c3f44Smeem ipmp_targinfo_t *targinfo4p, ipmp_targinfo_t *targinfo6p) 5917c478bd9Sstevel@tonic-gate { 5927c478bd9Sstevel@tonic-gate ipmp_ifinfo_t *ifinfop; 5937c478bd9Sstevel@tonic-gate 5947c478bd9Sstevel@tonic-gate ifinfop = malloc(sizeof (ipmp_ifinfo_t)); 5957c478bd9Sstevel@tonic-gate if (ifinfop == NULL) 5967c478bd9Sstevel@tonic-gate return (NULL); 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate (void) strlcpy(ifinfop->if_name, name, LIFNAMSIZ); 5997c478bd9Sstevel@tonic-gate (void) strlcpy(ifinfop->if_group, group, LIFGRNAMSIZ); 600*e11c3f44Smeem 6017c478bd9Sstevel@tonic-gate ifinfop->if_state = state; 6027c478bd9Sstevel@tonic-gate ifinfop->if_type = type; 603*e11c3f44Smeem ifinfop->if_linkstate = linkstate; 604*e11c3f44Smeem ifinfop->if_probestate = probestate; 605*e11c3f44Smeem ifinfop->if_flags = flags; 606*e11c3f44Smeem ifinfop->if_targinfo4 = *targinfo4p; 607*e11c3f44Smeem ifinfop->if_targinfo6 = *targinfo6p; 608*e11c3f44Smeem 609*e11c3f44Smeem ifinfop->if_targinfo4.it_targlistp = 610*e11c3f44Smeem ipmp_addrlist_clone(targinfo4p->it_targlistp); 611*e11c3f44Smeem ifinfop->if_targinfo6.it_targlistp = 612*e11c3f44Smeem ipmp_addrlist_clone(targinfo6p->it_targlistp); 613*e11c3f44Smeem 614*e11c3f44Smeem if (ifinfop->if_targinfo4.it_targlistp == NULL || 615*e11c3f44Smeem ifinfop->if_targinfo6.it_targlistp == NULL) { 616*e11c3f44Smeem ipmp_freeifinfo(ifinfop); 617*e11c3f44Smeem return (NULL); 618*e11c3f44Smeem } 6197c478bd9Sstevel@tonic-gate 6207c478bd9Sstevel@tonic-gate return (ifinfop); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Clone the interface information named by `ifinfop'. Returns a pointer to 6257c478bd9Sstevel@tonic-gate * the clone on success, or NULL on failure. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate ipmp_ifinfo_t * 6287c478bd9Sstevel@tonic-gate ipmp_ifinfo_clone(ipmp_ifinfo_t *ifinfop) 6297c478bd9Sstevel@tonic-gate { 6307c478bd9Sstevel@tonic-gate return (ipmp_ifinfo_create(ifinfop->if_name, ifinfop->if_group, 631*e11c3f44Smeem ifinfop->if_state, ifinfop->if_type, ifinfop->if_linkstate, 632*e11c3f44Smeem ifinfop->if_probestate, ifinfop->if_flags, &ifinfop->if_targinfo4, 633*e11c3f44Smeem &ifinfop->if_targinfo6)); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* 637*e11c3f44Smeem * Create a group; arguments match ipmp_groupinfo_t fields. Returns a pointer 6387c478bd9Sstevel@tonic-gate * to the new group on success, or NULL on failure. 6397c478bd9Sstevel@tonic-gate */ 6407c478bd9Sstevel@tonic-gate ipmp_groupinfo_t * 641*e11c3f44Smeem ipmp_groupinfo_create(const char *name, uint64_t sig, uint_t fdt, 642*e11c3f44Smeem ipmp_group_state_t state, uint_t nif, char (*ifs)[LIFNAMSIZ], 643*e11c3f44Smeem const char *grifname, const char *m4ifname, const char *m6ifname, 644*e11c3f44Smeem const char *bcifname, uint_t naddr, struct sockaddr_storage *addrs) 6457c478bd9Sstevel@tonic-gate { 6467c478bd9Sstevel@tonic-gate ipmp_groupinfo_t *grinfop; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate grinfop = malloc(sizeof (ipmp_groupinfo_t)); 6497c478bd9Sstevel@tonic-gate if (grinfop == NULL) 6507c478bd9Sstevel@tonic-gate return (NULL); 6517c478bd9Sstevel@tonic-gate 652*e11c3f44Smeem grinfop->gr_sig = sig; 653*e11c3f44Smeem grinfop->gr_fdt = fdt; 654*e11c3f44Smeem grinfop->gr_state = state; 655*e11c3f44Smeem grinfop->gr_iflistp = ipmp_iflist_create(nif, ifs); 656*e11c3f44Smeem grinfop->gr_adlistp = ipmp_addrlist_create(naddr, addrs); 657*e11c3f44Smeem if (grinfop->gr_iflistp == NULL || grinfop->gr_adlistp == NULL) { 658*e11c3f44Smeem ipmp_freegroupinfo(grinfop); 6597c478bd9Sstevel@tonic-gate return (NULL); 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate (void) strlcpy(grinfop->gr_name, name, LIFGRNAMSIZ); 662*e11c3f44Smeem (void) strlcpy(grinfop->gr_ifname, grifname, LIFNAMSIZ); 663*e11c3f44Smeem (void) strlcpy(grinfop->gr_m4ifname, m4ifname, LIFNAMSIZ); 664*e11c3f44Smeem (void) strlcpy(grinfop->gr_m6ifname, m6ifname, LIFNAMSIZ); 665*e11c3f44Smeem (void) strlcpy(grinfop->gr_bcifname, bcifname, LIFNAMSIZ); 6667c478bd9Sstevel@tonic-gate 6677c478bd9Sstevel@tonic-gate return (grinfop); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * Clone the group information named by `grinfop'. Returns a pointer to 6727c478bd9Sstevel@tonic-gate * the clone on success, or NULL on failure. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate ipmp_groupinfo_t * 6757c478bd9Sstevel@tonic-gate ipmp_groupinfo_clone(ipmp_groupinfo_t *grinfop) 6767c478bd9Sstevel@tonic-gate { 677*e11c3f44Smeem ipmp_addrlist_t *adlistp = grinfop->gr_adlistp; 678*e11c3f44Smeem 6797c478bd9Sstevel@tonic-gate return (ipmp_groupinfo_create(grinfop->gr_name, grinfop->gr_sig, 680*e11c3f44Smeem grinfop->gr_fdt, grinfop->gr_state, grinfop->gr_iflistp->il_nif, 681*e11c3f44Smeem grinfop->gr_iflistp->il_ifs, grinfop->gr_ifname, 682*e11c3f44Smeem grinfop->gr_m4ifname, grinfop->gr_m6ifname, grinfop->gr_bcifname, 683*e11c3f44Smeem adlistp->al_naddr, adlistp->al_addrs)); 684*e11c3f44Smeem } 685*e11c3f44Smeem 686*e11c3f44Smeem /* 687*e11c3f44Smeem * Create an address list; arguments match ipmp_addrlist_t fields. Returns 688*e11c3f44Smeem * a pointer to the new address list on success, or NULL on failure. 689*e11c3f44Smeem */ 690*e11c3f44Smeem static ipmp_addrlist_t * 691*e11c3f44Smeem ipmp_addrlist_create(uint_t naddr, struct sockaddr_storage *addrs) 692*e11c3f44Smeem { 693*e11c3f44Smeem unsigned int i; 694*e11c3f44Smeem ipmp_addrlist_t *adlistp; 695*e11c3f44Smeem 696*e11c3f44Smeem adlistp = malloc(IPMP_ADDRLIST_SIZE(naddr)); 697*e11c3f44Smeem if (adlistp == NULL) 698*e11c3f44Smeem return (NULL); 699*e11c3f44Smeem 700*e11c3f44Smeem adlistp->al_naddr = naddr; 701*e11c3f44Smeem for (i = 0; i < naddr; i++) 702*e11c3f44Smeem adlistp->al_addrs[i] = addrs[i]; 703*e11c3f44Smeem 704*e11c3f44Smeem return (adlistp); 705*e11c3f44Smeem } 706*e11c3f44Smeem 707*e11c3f44Smeem /* 708*e11c3f44Smeem * Clone the address list named by `adlistp'. Returns a pointer to the clone 709*e11c3f44Smeem * on success, or NULL on failure. 710*e11c3f44Smeem */ 711*e11c3f44Smeem static ipmp_addrlist_t * 712*e11c3f44Smeem ipmp_addrlist_clone(ipmp_addrlist_t *adlistp) 713*e11c3f44Smeem { 714*e11c3f44Smeem return (ipmp_addrlist_create(adlistp->al_naddr, adlistp->al_addrs)); 715*e11c3f44Smeem } 716*e11c3f44Smeem 717*e11c3f44Smeem /* 718*e11c3f44Smeem * Free the address list pointed to by `adlistp'. 719*e11c3f44Smeem */ 720*e11c3f44Smeem static void 721*e11c3f44Smeem ipmp_freeaddrlist(ipmp_addrlist_t *adlistp) 722*e11c3f44Smeem { 723*e11c3f44Smeem free(adlistp); 724*e11c3f44Smeem } 725*e11c3f44Smeem 726*e11c3f44Smeem /* 727*e11c3f44Smeem * Create an address; arguments match ipmp_addrinfo_t fields. Returns a 728*e11c3f44Smeem * pointer to the new address on success, or NULL on failure. 729*e11c3f44Smeem */ 730*e11c3f44Smeem ipmp_addrinfo_t * 731*e11c3f44Smeem ipmp_addrinfo_create(struct sockaddr_storage *addrp, ipmp_addr_state_t state, 732*e11c3f44Smeem const char *group, const char *binding) 733*e11c3f44Smeem { 734*e11c3f44Smeem ipmp_addrinfo_t *adinfop; 735*e11c3f44Smeem 736*e11c3f44Smeem adinfop = malloc(sizeof (ipmp_addrinfo_t)); 737*e11c3f44Smeem if (adinfop == NULL) 738*e11c3f44Smeem return (NULL); 739*e11c3f44Smeem 740*e11c3f44Smeem adinfop->ad_addr = *addrp; 741*e11c3f44Smeem adinfop->ad_state = state; 742*e11c3f44Smeem (void) strlcpy(adinfop->ad_group, group, LIFGRNAMSIZ); 743*e11c3f44Smeem (void) strlcpy(adinfop->ad_binding, binding, LIFNAMSIZ); 744*e11c3f44Smeem 745*e11c3f44Smeem return (adinfop); 746*e11c3f44Smeem } 747*e11c3f44Smeem 748*e11c3f44Smeem /* 749*e11c3f44Smeem * Clone the address information named by `adinfop'. Returns a pointer to 750*e11c3f44Smeem * the clone on success, or NULL on failure. 751*e11c3f44Smeem */ 752*e11c3f44Smeem ipmp_addrinfo_t * 753*e11c3f44Smeem ipmp_addrinfo_clone(ipmp_addrinfo_t *adinfop) 754*e11c3f44Smeem { 755*e11c3f44Smeem return (ipmp_addrinfo_create(&adinfop->ad_addr, adinfop->ad_state, 756*e11c3f44Smeem adinfop->ad_group, adinfop->ad_binding)); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate 7597c478bd9Sstevel@tonic-gate /* 7607c478bd9Sstevel@tonic-gate * Set the query context associated with `handle' to `qcontext', which must be 7617c478bd9Sstevel@tonic-gate * either IPMP_QCONTEXT_LIVE or IPMP_QCONTEXT_SNAP. Upon success, any 7627c478bd9Sstevel@tonic-gate * previous snapshot associated with `handle' is discarded. Returns an IPMP 7637c478bd9Sstevel@tonic-gate * error code. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate int 7667c478bd9Sstevel@tonic-gate ipmp_setqcontext(ipmp_handle_t handle, ipmp_qcontext_t qcontext) 7677c478bd9Sstevel@tonic-gate { 7687c478bd9Sstevel@tonic-gate ipmp_state_t *statep = handle; 7697c478bd9Sstevel@tonic-gate ipmp_snap_t *snap; 7707c478bd9Sstevel@tonic-gate int retval; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate switch (qcontext) { 7737c478bd9Sstevel@tonic-gate case IPMP_QCONTEXT_LIVE: 7747c478bd9Sstevel@tonic-gate snap = NULL; 7757c478bd9Sstevel@tonic-gate break; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate case IPMP_QCONTEXT_SNAP: 7787c478bd9Sstevel@tonic-gate retval = ipmp_snap_take(statep, &snap); 7797c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 7807c478bd9Sstevel@tonic-gate return (retval); 7817c478bd9Sstevel@tonic-gate break; 7827c478bd9Sstevel@tonic-gate 7837c478bd9Sstevel@tonic-gate default: 7847c478bd9Sstevel@tonic-gate return (IPMP_EINVAL); 7857c478bd9Sstevel@tonic-gate } 7867c478bd9Sstevel@tonic-gate 7877c478bd9Sstevel@tonic-gate if (statep->st_snap != NULL) 7887c478bd9Sstevel@tonic-gate ipmp_snap_free(statep->st_snap); 7897c478bd9Sstevel@tonic-gate statep->st_snap = snap; 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate return (IPMP_SUCCESS); 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate 7947c478bd9Sstevel@tonic-gate /* 7957c478bd9Sstevel@tonic-gate * Create an empty snapshot. Returns a pointer to the snapshot on success, 7967c478bd9Sstevel@tonic-gate * or NULL on failure. 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate ipmp_snap_t * 7997c478bd9Sstevel@tonic-gate ipmp_snap_create(void) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate ipmp_snap_t *snap; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate snap = malloc(sizeof (ipmp_snap_t)); 8047c478bd9Sstevel@tonic-gate if (snap == NULL) 8057c478bd9Sstevel@tonic-gate return (NULL); 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate snap->sn_grlistp = NULL; 8087c478bd9Sstevel@tonic-gate snap->sn_grinfolistp = NULL; 8097c478bd9Sstevel@tonic-gate snap->sn_ifinfolistp = NULL; 810*e11c3f44Smeem snap->sn_adinfolistp = NULL; 8117c478bd9Sstevel@tonic-gate snap->sn_ngroup = 0; 8127c478bd9Sstevel@tonic-gate snap->sn_nif = 0; 813*e11c3f44Smeem snap->sn_naddr = 0; 8147c478bd9Sstevel@tonic-gate 8157c478bd9Sstevel@tonic-gate return (snap); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate /* 8197c478bd9Sstevel@tonic-gate * Free all of the resources associated with snapshot `snap'. 8207c478bd9Sstevel@tonic-gate */ 8217c478bd9Sstevel@tonic-gate void 8227c478bd9Sstevel@tonic-gate ipmp_snap_free(ipmp_snap_t *snap) 8237c478bd9Sstevel@tonic-gate { 8247c478bd9Sstevel@tonic-gate ipmp_ifinfolist_t *iflp, *ifnext; 825*e11c3f44Smeem ipmp_addrinfolist_t *adlp, *adnext; 8267c478bd9Sstevel@tonic-gate ipmp_groupinfolist_t *grlp, *grnext; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate ipmp_freegrouplist(snap->sn_grlistp); 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate for (grlp = snap->sn_grinfolistp; grlp != NULL; grlp = grnext) { 8317c478bd9Sstevel@tonic-gate grnext = grlp->grl_next; 8327c478bd9Sstevel@tonic-gate ipmp_freegroupinfo(grlp->grl_grinfop); 8337c478bd9Sstevel@tonic-gate free(grlp); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate for (iflp = snap->sn_ifinfolistp; iflp != NULL; iflp = ifnext) { 8377c478bd9Sstevel@tonic-gate ifnext = iflp->ifl_next; 8387c478bd9Sstevel@tonic-gate ipmp_freeifinfo(iflp->ifl_ifinfop); 8397c478bd9Sstevel@tonic-gate free(iflp); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 842*e11c3f44Smeem for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adnext) { 843*e11c3f44Smeem adnext = adlp->adl_next; 844*e11c3f44Smeem ipmp_freeaddrinfo(adlp->adl_adinfop); 845*e11c3f44Smeem free(adlp); 846*e11c3f44Smeem } 847*e11c3f44Smeem 8487c478bd9Sstevel@tonic-gate free(snap); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* 8527c478bd9Sstevel@tonic-gate * Add the group information in `grinfop' to the snapshot named by `snap'. 8537c478bd9Sstevel@tonic-gate * Returns an IPMP error code. 8547c478bd9Sstevel@tonic-gate */ 8557c478bd9Sstevel@tonic-gate int 8567c478bd9Sstevel@tonic-gate ipmp_snap_addgroupinfo(ipmp_snap_t *snap, ipmp_groupinfo_t *grinfop) 8577c478bd9Sstevel@tonic-gate { 8587c478bd9Sstevel@tonic-gate ipmp_groupinfolist_t *grlp; 8597c478bd9Sstevel@tonic-gate 8607c478bd9Sstevel@tonic-gate /* 8617c478bd9Sstevel@tonic-gate * If the information for this group is already in the snapshot, 8627c478bd9Sstevel@tonic-gate * in.mpathd is broken. 8637c478bd9Sstevel@tonic-gate */ 8647c478bd9Sstevel@tonic-gate if (ipmp_snap_getgroupinfo(snap, grinfop->gr_name) != NULL) 8657c478bd9Sstevel@tonic-gate return (IPMP_EPROTO); 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate grlp = malloc(sizeof (ipmp_groupinfolist_t)); 8687c478bd9Sstevel@tonic-gate if (grlp == NULL) 8697c478bd9Sstevel@tonic-gate return (IPMP_ENOMEM); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate grlp->grl_grinfop = grinfop; 8727c478bd9Sstevel@tonic-gate grlp->grl_next = snap->sn_grinfolistp; 8737c478bd9Sstevel@tonic-gate snap->sn_grinfolistp = grlp; 8747c478bd9Sstevel@tonic-gate snap->sn_ngroup++; 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate return (IPMP_SUCCESS); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate /* 8807c478bd9Sstevel@tonic-gate * Add the interface information in `ifinfop' to the snapshot named by `snap'. 8817c478bd9Sstevel@tonic-gate * Returns an IPMP error code. 8827c478bd9Sstevel@tonic-gate */ 8837c478bd9Sstevel@tonic-gate int 8847c478bd9Sstevel@tonic-gate ipmp_snap_addifinfo(ipmp_snap_t *snap, ipmp_ifinfo_t *ifinfop) 8857c478bd9Sstevel@tonic-gate { 8867c478bd9Sstevel@tonic-gate ipmp_ifinfolist_t *iflp; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate /* 8897c478bd9Sstevel@tonic-gate * If the information for this interface is already in the snapshot, 8907c478bd9Sstevel@tonic-gate * in.mpathd is broken. 8917c478bd9Sstevel@tonic-gate */ 8927c478bd9Sstevel@tonic-gate if (ipmp_snap_getifinfo(snap, ifinfop->if_name) != NULL) 8937c478bd9Sstevel@tonic-gate return (IPMP_EPROTO); 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate iflp = malloc(sizeof (ipmp_ifinfolist_t)); 8967c478bd9Sstevel@tonic-gate if (iflp == NULL) 8977c478bd9Sstevel@tonic-gate return (IPMP_ENOMEM); 8987c478bd9Sstevel@tonic-gate 8997c478bd9Sstevel@tonic-gate iflp->ifl_ifinfop = ifinfop; 9007c478bd9Sstevel@tonic-gate iflp->ifl_next = snap->sn_ifinfolistp; 9017c478bd9Sstevel@tonic-gate snap->sn_ifinfolistp = iflp; 9027c478bd9Sstevel@tonic-gate snap->sn_nif++; 9037c478bd9Sstevel@tonic-gate 9047c478bd9Sstevel@tonic-gate return (IPMP_SUCCESS); 9057c478bd9Sstevel@tonic-gate } 9067c478bd9Sstevel@tonic-gate 9077c478bd9Sstevel@tonic-gate /* 908*e11c3f44Smeem * Add the address information in `adinfop' to the snapshot named by `snap'. 909*e11c3f44Smeem * Returns an IPMP error code. 910*e11c3f44Smeem */ 911*e11c3f44Smeem int 912*e11c3f44Smeem ipmp_snap_addaddrinfo(ipmp_snap_t *snap, ipmp_addrinfo_t *adinfop) 913*e11c3f44Smeem { 914*e11c3f44Smeem ipmp_addrinfolist_t *adlp; 915*e11c3f44Smeem 916*e11c3f44Smeem /* 917*e11c3f44Smeem * Any duplicate addresses should've already been weeded by in.mpathd. 918*e11c3f44Smeem */ 919*e11c3f44Smeem if (ipmp_snap_getaddrinfo(snap, adinfop->ad_group, 920*e11c3f44Smeem &adinfop->ad_addr) != NULL) 921*e11c3f44Smeem return (IPMP_EPROTO); 922*e11c3f44Smeem 923*e11c3f44Smeem adlp = malloc(sizeof (ipmp_addrinfolist_t)); 924*e11c3f44Smeem if (adlp == NULL) 925*e11c3f44Smeem return (IPMP_ENOMEM); 926*e11c3f44Smeem 927*e11c3f44Smeem adlp->adl_adinfop = adinfop; 928*e11c3f44Smeem adlp->adl_next = snap->sn_adinfolistp; 929*e11c3f44Smeem snap->sn_adinfolistp = adlp; 930*e11c3f44Smeem snap->sn_naddr++; 931*e11c3f44Smeem 932*e11c3f44Smeem return (IPMP_SUCCESS); 933*e11c3f44Smeem } 934*e11c3f44Smeem 935*e11c3f44Smeem /* 9367c478bd9Sstevel@tonic-gate * Retrieve the information for the group `name' in snapshot `snap'. 9377c478bd9Sstevel@tonic-gate * Returns a pointer to the group information on success, or NULL on failure. 9387c478bd9Sstevel@tonic-gate */ 9397c478bd9Sstevel@tonic-gate static ipmp_groupinfo_t * 9407c478bd9Sstevel@tonic-gate ipmp_snap_getgroupinfo(ipmp_snap_t *snap, const char *name) 9417c478bd9Sstevel@tonic-gate { 9427c478bd9Sstevel@tonic-gate ipmp_groupinfolist_t *grlp; 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate for (grlp = snap->sn_grinfolistp; grlp != NULL; grlp = grlp->grl_next) { 9457c478bd9Sstevel@tonic-gate if (strcmp(grlp->grl_grinfop->gr_name, name) == 0) 9467c478bd9Sstevel@tonic-gate break; 9477c478bd9Sstevel@tonic-gate } 9487c478bd9Sstevel@tonic-gate 9497c478bd9Sstevel@tonic-gate return (grlp != NULL ? grlp->grl_grinfop : NULL); 9507c478bd9Sstevel@tonic-gate } 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate /* 9537c478bd9Sstevel@tonic-gate * Retrieve the information for the interface `name' in snapshot `snap'. 9547c478bd9Sstevel@tonic-gate * Returns a pointer to the interface information on success, or NULL on 9557c478bd9Sstevel@tonic-gate * failure. 9567c478bd9Sstevel@tonic-gate */ 9577c478bd9Sstevel@tonic-gate static ipmp_ifinfo_t * 9587c478bd9Sstevel@tonic-gate ipmp_snap_getifinfo(ipmp_snap_t *snap, const char *name) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate ipmp_ifinfolist_t *iflp; 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate for (iflp = snap->sn_ifinfolistp; iflp != NULL; iflp = iflp->ifl_next) { 9637c478bd9Sstevel@tonic-gate if (strcmp(iflp->ifl_ifinfop->if_name, name) == 0) 9647c478bd9Sstevel@tonic-gate break; 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate return (iflp != NULL ? iflp->ifl_ifinfop : NULL); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate /* 971*e11c3f44Smeem * Retrieve the information for the address `addrp' on group `grname' in 972*e11c3f44Smeem * snapshot `snap'. Returns a pointer to the address information on success, 973*e11c3f44Smeem * or NULL on failure. 974*e11c3f44Smeem */ 975*e11c3f44Smeem static ipmp_addrinfo_t * 976*e11c3f44Smeem ipmp_snap_getaddrinfo(ipmp_snap_t *snap, const char *grname, 977*e11c3f44Smeem struct sockaddr_storage *addrp) 978*e11c3f44Smeem { 979*e11c3f44Smeem ipmp_addrinfolist_t *adlp; 980*e11c3f44Smeem 981*e11c3f44Smeem for (adlp = snap->sn_adinfolistp; adlp != NULL; adlp = adlp->adl_next) { 982*e11c3f44Smeem if (strcmp(grname, adlp->adl_adinfop->ad_group) == 0 && 983*e11c3f44Smeem sockaddrcmp(addrp, &adlp->adl_adinfop->ad_addr)) 984*e11c3f44Smeem break; 985*e11c3f44Smeem } 986*e11c3f44Smeem 987*e11c3f44Smeem return (adlp != NULL ? adlp->adl_adinfop : NULL); 988*e11c3f44Smeem } 989*e11c3f44Smeem 990*e11c3f44Smeem /* 9917c478bd9Sstevel@tonic-gate * Using `statep', take a snapshot of the IPMP subsystem and if successful 9927c478bd9Sstevel@tonic-gate * return it in a dynamically allocated snapshot pointed to by `*snapp'. 9937c478bd9Sstevel@tonic-gate * Returns an IPMP error code. 9947c478bd9Sstevel@tonic-gate */ 9957c478bd9Sstevel@tonic-gate static int 9967c478bd9Sstevel@tonic-gate ipmp_snap_take(ipmp_state_t *statep, ipmp_snap_t **snapp) 9977c478bd9Sstevel@tonic-gate { 9987c478bd9Sstevel@tonic-gate ipmp_snap_t *snap, *osnap; 9997c478bd9Sstevel@tonic-gate ipmp_infotype_t type; 10007c478bd9Sstevel@tonic-gate int retval; 10017c478bd9Sstevel@tonic-gate size_t len; 10027c478bd9Sstevel@tonic-gate void *infop; 10037c478bd9Sstevel@tonic-gate struct timeval end; 10047c478bd9Sstevel@tonic-gate 10057c478bd9Sstevel@tonic-gate snap = ipmp_snap_create(); 10067c478bd9Sstevel@tonic-gate if (snap == NULL) 10077c478bd9Sstevel@tonic-gate return (IPMP_ENOMEM); 10087c478bd9Sstevel@tonic-gate 1009*e11c3f44Smeem retval = ipmp_sendquery(statep, IPMP_SNAP, NULL, NULL, &end); 10107c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) { 10117c478bd9Sstevel@tonic-gate ipmp_snap_free(snap); 10127c478bd9Sstevel@tonic-gate return (retval); 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate 10157c478bd9Sstevel@tonic-gate retval = ipmp_readinfo(statep, IPMP_SNAP, (void **)&osnap, &end); 10167c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) { 10177c478bd9Sstevel@tonic-gate ipmp_snap_free(snap); 10187c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate /* 1022*e11c3f44Smeem * Using the information in the `osnap' snapshot, build up our own 1023*e11c3f44Smeem * snapshot. We know there will always be at least one TLV (for 1024*e11c3f44Smeem * IPMP_GROUPLIST). If we receive anything illogical (e.g., more than 1025*e11c3f44Smeem * the expected number of interfaces), then bail out. However, to a 1026*e11c3f44Smeem * large extent we have to trust the information sent by in.mpathd. 10277c478bd9Sstevel@tonic-gate */ 10287c478bd9Sstevel@tonic-gate do { 10297c478bd9Sstevel@tonic-gate infop = NULL; 10307c478bd9Sstevel@tonic-gate retval = ipmp_readtlv(statep->st_fd, &type, &len, &infop, &end); 10317c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 10327c478bd9Sstevel@tonic-gate goto fail; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate if (!ipmp_checktlv(type, len, infop)) { 10357c478bd9Sstevel@tonic-gate retval = IPMP_EPROTO; 10367c478bd9Sstevel@tonic-gate goto fail; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate switch (type) { 10407c478bd9Sstevel@tonic-gate case IPMP_GROUPLIST: 10417c478bd9Sstevel@tonic-gate if (snap->sn_grlistp != NULL) { 10427c478bd9Sstevel@tonic-gate retval = IPMP_EPROTO; 10437c478bd9Sstevel@tonic-gate break; 10447c478bd9Sstevel@tonic-gate } 10457c478bd9Sstevel@tonic-gate snap->sn_grlistp = infop; 10467c478bd9Sstevel@tonic-gate break; 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate case IPMP_IFINFO: 10497c478bd9Sstevel@tonic-gate if (snap->sn_nif == osnap->sn_nif) { 10507c478bd9Sstevel@tonic-gate retval = IPMP_EPROTO; 10517c478bd9Sstevel@tonic-gate break; 10527c478bd9Sstevel@tonic-gate } 1053*e11c3f44Smeem 1054*e11c3f44Smeem /* 1055*e11c3f44Smeem * Read in V4 and V6 targlist TLVs that follow. 1056*e11c3f44Smeem */ 1057*e11c3f44Smeem retval = ipmp_readifinfo_lists(statep, infop, &end); 1058*e11c3f44Smeem if (retval != IPMP_SUCCESS) 1059*e11c3f44Smeem break; 1060*e11c3f44Smeem 10617c478bd9Sstevel@tonic-gate retval = ipmp_snap_addifinfo(snap, infop); 1062*e11c3f44Smeem if (retval != IPMP_SUCCESS) { 1063*e11c3f44Smeem ipmp_freeifinfo(infop); 1064*e11c3f44Smeem infop = NULL; 1065*e11c3f44Smeem } 1066*e11c3f44Smeem break; 1067*e11c3f44Smeem 1068*e11c3f44Smeem case IPMP_ADDRINFO: 1069*e11c3f44Smeem if (snap->sn_naddr == osnap->sn_naddr) { 1070*e11c3f44Smeem retval = IPMP_EPROTO; 1071*e11c3f44Smeem break; 1072*e11c3f44Smeem } 1073*e11c3f44Smeem 1074*e11c3f44Smeem retval = ipmp_snap_addaddrinfo(snap, infop); 1075*e11c3f44Smeem /* 1076*e11c3f44Smeem * NOTE: since we didn't call ipmp_read*info_lists(), 1077*e11c3f44Smeem * no need to use ipmp_freeaddrinfo() on failure. 1078*e11c3f44Smeem */ 10797c478bd9Sstevel@tonic-gate break; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate case IPMP_GROUPINFO: 10827c478bd9Sstevel@tonic-gate if (snap->sn_ngroup == osnap->sn_ngroup) { 10837c478bd9Sstevel@tonic-gate retval = IPMP_EPROTO; 10847c478bd9Sstevel@tonic-gate break; 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate 10877c478bd9Sstevel@tonic-gate /* 1088*e11c3f44Smeem * Read in IPMP groupinfo list TLVs that follow. 10897c478bd9Sstevel@tonic-gate */ 1090*e11c3f44Smeem retval = ipmp_readgroupinfo_lists(statep, infop, &end); 10917c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) 10927c478bd9Sstevel@tonic-gate break; 10937c478bd9Sstevel@tonic-gate 10947c478bd9Sstevel@tonic-gate retval = ipmp_snap_addgroupinfo(snap, infop); 1095*e11c3f44Smeem if (retval != IPMP_SUCCESS) { 1096*e11c3f44Smeem ipmp_freegroupinfo(infop); 1097*e11c3f44Smeem infop = NULL; 1098*e11c3f44Smeem } 10997c478bd9Sstevel@tonic-gate break; 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate default: 11027c478bd9Sstevel@tonic-gate retval = IPMP_EPROTO; 11037c478bd9Sstevel@tonic-gate break; 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate fail: 11067c478bd9Sstevel@tonic-gate if (retval != IPMP_SUCCESS) { 11077c478bd9Sstevel@tonic-gate free(infop); 11087c478bd9Sstevel@tonic-gate free(osnap); 11097c478bd9Sstevel@tonic-gate ipmp_snap_free(snap); 11107c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, retval)); 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate } while (snap->sn_grlistp == NULL || snap->sn_nif < osnap->sn_nif || 1113*e11c3f44Smeem snap->sn_ngroup < osnap->sn_ngroup || 1114*e11c3f44Smeem snap->sn_naddr < osnap->sn_naddr); 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate free(osnap); 11177c478bd9Sstevel@tonic-gate *snapp = snap; 11187c478bd9Sstevel@tonic-gate return (ipmp_querydone(statep, IPMP_SUCCESS)); 11197c478bd9Sstevel@tonic-gate } 1120