11cb875aeSCathy Zhou /* 21cb875aeSCathy Zhou * CDDL HEADER START 31cb875aeSCathy Zhou * 41cb875aeSCathy Zhou * The contents of this file are subject to the terms of the 51cb875aeSCathy Zhou * Common Development and Distribution License (the "License"). 61cb875aeSCathy Zhou * You may not use this file except in compliance with the License. 71cb875aeSCathy Zhou * 81cb875aeSCathy Zhou * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91cb875aeSCathy Zhou * or http://www.opensolaris.org/os/licensing. 101cb875aeSCathy Zhou * See the License for the specific language governing permissions 111cb875aeSCathy Zhou * and limitations under the License. 121cb875aeSCathy Zhou * 131cb875aeSCathy Zhou * When distributing Covered Code, include this CDDL HEADER in each 141cb875aeSCathy Zhou * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151cb875aeSCathy Zhou * If applicable, add the following below this CDDL HEADER, with the 161cb875aeSCathy Zhou * fields enclosed by brackets "[]" replaced with your own identifying 171cb875aeSCathy Zhou * information: Portions Copyright [yyyy] [name of copyright owner] 181cb875aeSCathy Zhou * 191cb875aeSCathy Zhou * CDDL HEADER END 201cb875aeSCathy Zhou */ 211cb875aeSCathy Zhou 221cb875aeSCathy Zhou /* 23*c5e0ece0SCathy Zhou * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 241cb875aeSCathy Zhou * Use is subject to license terms. 251cb875aeSCathy Zhou */ 261cb875aeSCathy Zhou 271cb875aeSCathy Zhou #include <sys/types.h> 281cb875aeSCathy Zhou #include <sys/stat.h> 291cb875aeSCathy Zhou #include <sys/socket.h> 301cb875aeSCathy Zhou #include <sys/mman.h> 311cb875aeSCathy Zhou #include <sys/varargs.h> 321cb875aeSCathy Zhou #include <sys/vlan.h> 331cb875aeSCathy Zhou #include <errno.h> 341cb875aeSCathy Zhou #include <ctype.h> 351cb875aeSCathy Zhou #include <fcntl.h> 361cb875aeSCathy Zhou #include <unistd.h> 371cb875aeSCathy Zhou #include <stdio.h> 381cb875aeSCathy Zhou #include <stdlib.h> 391cb875aeSCathy Zhou #include <string.h> 401cb875aeSCathy Zhou #include <netinet/in.h> 411cb875aeSCathy Zhou #include <arpa/inet.h> 421cb875aeSCathy Zhou #include <net/if.h> /* LIFNAMSIZ */ 431cb875aeSCathy Zhou #include <netinet/vrrp.h> 441cb875aeSCathy Zhou #include <libdladm.h> 451cb875aeSCathy Zhou #include <libdlvnic.h> 461cb875aeSCathy Zhou #include <libdlvlan.h> 471cb875aeSCathy Zhou #include <libdllink.h> 481cb875aeSCathy Zhou #include <libintl.h> 49*c5e0ece0SCathy Zhou #include <libscf.h> 501cb875aeSCathy Zhou #include <libvrrpadm.h> 511cb875aeSCathy Zhou 52*c5e0ece0SCathy Zhou #define VRRP_SERVICE "network/vrrp:default" 53*c5e0ece0SCathy Zhou 541cb875aeSCathy Zhou typedef vrrp_err_t vrrp_cmd_func_t(int, void *); 551cb875aeSCathy Zhou 56*c5e0ece0SCathy Zhou static boolean_t 57*c5e0ece0SCathy Zhou vrrp_svc_isonline(char *svc_name) 58*c5e0ece0SCathy Zhou { 59*c5e0ece0SCathy Zhou char *s; 60*c5e0ece0SCathy Zhou boolean_t isonline = B_FALSE; 61*c5e0ece0SCathy Zhou 62*c5e0ece0SCathy Zhou if ((s = smf_get_state(svc_name)) != NULL) { 63*c5e0ece0SCathy Zhou if (strcmp(s, SCF_STATE_STRING_ONLINE) == 0) 64*c5e0ece0SCathy Zhou isonline = B_TRUE; 65*c5e0ece0SCathy Zhou free(s); 66*c5e0ece0SCathy Zhou } 67*c5e0ece0SCathy Zhou 68*c5e0ece0SCathy Zhou return (isonline); 69*c5e0ece0SCathy Zhou } 70*c5e0ece0SCathy Zhou 71*c5e0ece0SCathy Zhou #define MAX_WAIT_TIME 15 72*c5e0ece0SCathy Zhou 73*c5e0ece0SCathy Zhou static vrrp_err_t 74*c5e0ece0SCathy Zhou vrrp_enable_service() 75*c5e0ece0SCathy Zhou { 76*c5e0ece0SCathy Zhou int i; 77*c5e0ece0SCathy Zhou 78*c5e0ece0SCathy Zhou if (vrrp_svc_isonline(VRRP_SERVICE)) 79*c5e0ece0SCathy Zhou return (VRRP_SUCCESS); 80*c5e0ece0SCathy Zhou 81*c5e0ece0SCathy Zhou if (smf_enable_instance(VRRP_SERVICE, 0) == -1) { 82*c5e0ece0SCathy Zhou if (scf_error() == SCF_ERROR_PERMISSION_DENIED) 83*c5e0ece0SCathy Zhou return (VRRP_EPERM); 84*c5e0ece0SCathy Zhou else 85*c5e0ece0SCathy Zhou return (VRRP_ENOSVC); 86*c5e0ece0SCathy Zhou } 87*c5e0ece0SCathy Zhou 88*c5e0ece0SCathy Zhou /* 89*c5e0ece0SCathy Zhou * Wait up to MAX_WAIT_TIME seconds for the VRRP service being brought 90*c5e0ece0SCathy Zhou * up online 91*c5e0ece0SCathy Zhou */ 92*c5e0ece0SCathy Zhou for (i = 0; i < MAX_WAIT_TIME; i++) { 93*c5e0ece0SCathy Zhou if (vrrp_svc_isonline(VRRP_SERVICE)) 94*c5e0ece0SCathy Zhou break; 95*c5e0ece0SCathy Zhou (void) sleep(1); 96*c5e0ece0SCathy Zhou } 97*c5e0ece0SCathy Zhou if (i == MAX_WAIT_TIME) 98*c5e0ece0SCathy Zhou return (VRRP_ENOSVC); 99*c5e0ece0SCathy Zhou 100*c5e0ece0SCathy Zhou return (VRRP_SUCCESS); 101*c5e0ece0SCathy Zhou } 102*c5e0ece0SCathy Zhou 103*c5e0ece0SCathy Zhou /* 104*c5e0ece0SCathy Zhou * Disable the VRRP service if there is no VRRP router left. 105*c5e0ece0SCathy Zhou */ 106*c5e0ece0SCathy Zhou static void 107*c5e0ece0SCathy Zhou vrrp_disable_service_when_no_router() 108*c5e0ece0SCathy Zhou { 109*c5e0ece0SCathy Zhou uint32_t cnt = 0; 110*c5e0ece0SCathy Zhou 111*c5e0ece0SCathy Zhou /* 112*c5e0ece0SCathy Zhou * Get the number of the existing routers. If there is no routers 113*c5e0ece0SCathy Zhou * left, disable the service. 114*c5e0ece0SCathy Zhou */ 115*c5e0ece0SCathy Zhou if (vrrp_list(NULL, VRRP_VRID_NONE, NULL, AF_UNSPEC, &cnt, 116*c5e0ece0SCathy Zhou NULL) == VRRP_SUCCESS && cnt == 0) { 117*c5e0ece0SCathy Zhou (void) smf_disable_instance(VRRP_SERVICE, 0); 118*c5e0ece0SCathy Zhou } 119*c5e0ece0SCathy Zhou } 120*c5e0ece0SCathy Zhou 1211cb875aeSCathy Zhou static vrrp_err_t 1221cb875aeSCathy Zhou vrrp_cmd_request(void *cmd, size_t csize, vrrp_cmd_func_t func, void *arg) 1231cb875aeSCathy Zhou { 1241cb875aeSCathy Zhou struct sockaddr_un to; 1251cb875aeSCathy Zhou int sock, flags; 1261cb875aeSCathy Zhou size_t len, cur_size = 0; 1271cb875aeSCathy Zhou vrrp_ret_t ret; 1281cb875aeSCathy Zhou vrrp_err_t err; 1291cb875aeSCathy Zhou 1301cb875aeSCathy Zhou if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 131*c5e0ece0SCathy Zhou return (VRRP_ESYS); 1321cb875aeSCathy Zhou 1331cb875aeSCathy Zhou /* 1341cb875aeSCathy Zhou * Set it to be non-blocking. 1351cb875aeSCathy Zhou */ 1361cb875aeSCathy Zhou flags = fcntl(sock, F_GETFL, 0); 1371cb875aeSCathy Zhou (void) fcntl(sock, F_SETFL, (flags | O_NONBLOCK)); 1381cb875aeSCathy Zhou 1391cb875aeSCathy Zhou (void) memset(&to, 0, sizeof (to)); 1401cb875aeSCathy Zhou to.sun_family = AF_UNIX; 1411cb875aeSCathy Zhou (void) strlcpy(to.sun_path, VRRPD_SOCKET, sizeof (to.sun_path)); 1421cb875aeSCathy Zhou 1431cb875aeSCathy Zhou /* 1441cb875aeSCathy Zhou * Connect to vrrpd 1451cb875aeSCathy Zhou */ 1461cb875aeSCathy Zhou if (connect(sock, (const struct sockaddr *)&to, sizeof (to)) < 0) { 1471cb875aeSCathy Zhou (void) close(sock); 148*c5e0ece0SCathy Zhou return (VRRP_ENOSVC); 1491cb875aeSCathy Zhou } 1501cb875aeSCathy Zhou 1511cb875aeSCathy Zhou /* 1521cb875aeSCathy Zhou * Send the request 1531cb875aeSCathy Zhou */ 1541cb875aeSCathy Zhou while (cur_size < csize) { 1551cb875aeSCathy Zhou len = write(sock, (char *)cmd + cur_size, csize - cur_size); 1561cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 1571cb875aeSCathy Zhou continue; 1581cb875aeSCathy Zhou } else if (len > 0) { 1591cb875aeSCathy Zhou cur_size += len; 1601cb875aeSCathy Zhou continue; 1611cb875aeSCathy Zhou } 1621cb875aeSCathy Zhou (void) close(sock); 163*c5e0ece0SCathy Zhou return (VRRP_ENOSVC); 1641cb875aeSCathy Zhou } 1651cb875aeSCathy Zhou 1661cb875aeSCathy Zhou /* 1671cb875aeSCathy Zhou * Expect the ack, first get the error code. 1681cb875aeSCathy Zhou */ 1691cb875aeSCathy Zhou cur_size = 0; 1701cb875aeSCathy Zhou while (cur_size < sizeof (vrrp_err_t)) { 1711cb875aeSCathy Zhou len = read(sock, (char *)&ret + cur_size, 1721cb875aeSCathy Zhou sizeof (vrrp_err_t) - cur_size); 1731cb875aeSCathy Zhou 1741cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 1751cb875aeSCathy Zhou continue; 1761cb875aeSCathy Zhou } else if (len > 0) { 1771cb875aeSCathy Zhou cur_size += len; 1781cb875aeSCathy Zhou continue; 1791cb875aeSCathy Zhou } 1801cb875aeSCathy Zhou (void) close(sock); 181*c5e0ece0SCathy Zhou return (VRRP_ESYS); 1821cb875aeSCathy Zhou } 1831cb875aeSCathy Zhou 1841cb875aeSCathy Zhou if ((err = ret.vr_err) != VRRP_SUCCESS) 1851cb875aeSCathy Zhou goto done; 1861cb875aeSCathy Zhou 1871cb875aeSCathy Zhou /* 1881cb875aeSCathy Zhou * The specific callback gets the rest of the information. 1891cb875aeSCathy Zhou */ 1901cb875aeSCathy Zhou if (func != NULL) 1911cb875aeSCathy Zhou err = func(sock, arg); 1921cb875aeSCathy Zhou 1931cb875aeSCathy Zhou done: 1941cb875aeSCathy Zhou (void) close(sock); 1951cb875aeSCathy Zhou return (err); 1961cb875aeSCathy Zhou } 1971cb875aeSCathy Zhou 1981cb875aeSCathy Zhou /* 1991cb875aeSCathy Zhou * public APIs 2001cb875aeSCathy Zhou */ 2011cb875aeSCathy Zhou const char * 2021cb875aeSCathy Zhou vrrp_err2str(vrrp_err_t err) 2031cb875aeSCathy Zhou { 2041cb875aeSCathy Zhou switch (err) { 2051cb875aeSCathy Zhou case VRRP_SUCCESS: 2061cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "success")); 2071cb875aeSCathy Zhou case VRRP_ENOMEM: 2081cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "not enough memory")); 2091cb875aeSCathy Zhou case VRRP_EINVALVRNAME: 2101cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid router name")); 2111cb875aeSCathy Zhou case VRRP_ENOPRIM: 2121cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "no primary IP")); 2131cb875aeSCathy Zhou case VRRP_EEXIST: 2141cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "already exists")); 2151cb875aeSCathy Zhou case VRRP_ENOVIRT: 2161cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "no virtual IPs")); 2171cb875aeSCathy Zhou case VRRP_EIPADM: 2181cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "ip configuration failure")); 2191cb875aeSCathy Zhou case VRRP_EDLADM: 2201cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "data-link configuration " 2211cb875aeSCathy Zhou "failure")); 2221cb875aeSCathy Zhou case VRRP_EDB: 2231cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "configuration update error")); 2241cb875aeSCathy Zhou case VRRP_EBADSTATE: 2251cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid state")); 2261cb875aeSCathy Zhou case VRRP_EVREXIST: 2271cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "VRRP router already exists")); 2281cb875aeSCathy Zhou case VRRP_ETOOSMALL: 2291cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "not enough space")); 2301cb875aeSCathy Zhou case VRRP_EINSTEXIST: 2311cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "router name already exists")); 2321cb875aeSCathy Zhou case VRRP_ENOTFOUND: 2331cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "VRRP router not found")); 2341cb875aeSCathy Zhou case VRRP_EINVALADDR: 2351cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid IP address")); 2361cb875aeSCathy Zhou case VRRP_EINVALAF: 2371cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid IP address family")); 2381cb875aeSCathy Zhou case VRRP_EINVALLINK: 2391cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid data-link")); 2401cb875aeSCathy Zhou case VRRP_EPERM: 2411cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "permission denied")); 2421cb875aeSCathy Zhou case VRRP_ESYS: 2431cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "system error")); 2441cb875aeSCathy Zhou case VRRP_EAGAIN: 2451cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "try again")); 2461cb875aeSCathy Zhou case VRRP_EALREADY: 2471cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "operation already in progress")); 2481cb875aeSCathy Zhou case VRRP_ENOVNIC: 2491cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "VRRP VNIC has not been " 2501cb875aeSCathy Zhou "created")); 2511cb875aeSCathy Zhou case VRRP_ENOLINK: 2521cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "the data-link does not exist")); 253*c5e0ece0SCathy Zhou case VRRP_ENOSVC: 254*c5e0ece0SCathy Zhou return (dgettext(TEXT_DOMAIN, "the VRRP service cannot " 255*c5e0ece0SCathy Zhou "be enabled")); 2561cb875aeSCathy Zhou case VRRP_EINVAL: 2571cb875aeSCathy Zhou default: 2581cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "invalid argument")); 2591cb875aeSCathy Zhou } 2601cb875aeSCathy Zhou } 2611cb875aeSCathy Zhou 2621cb875aeSCathy Zhou const char * 2631cb875aeSCathy Zhou vrrp_state2str(vrrp_state_t state) 2641cb875aeSCathy Zhou { 2651cb875aeSCathy Zhou switch (state) { 2661cb875aeSCathy Zhou case VRRP_STATE_NONE: 2671cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "NONE")); 2681cb875aeSCathy Zhou case VRRP_STATE_INIT: 2691cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "INIT")); 2701cb875aeSCathy Zhou case VRRP_STATE_MASTER: 2711cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "MASTER")); 2721cb875aeSCathy Zhou case VRRP_STATE_BACKUP: 2731cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "BACKUP")); 2741cb875aeSCathy Zhou default: 2751cb875aeSCathy Zhou return (dgettext(TEXT_DOMAIN, "INVALID")); 2761cb875aeSCathy Zhou } 2771cb875aeSCathy Zhou } 2781cb875aeSCathy Zhou 2791cb875aeSCathy Zhou vrrp_err_t 2801cb875aeSCathy Zhou vrrp_open(vrrp_handle_t *vh) 2811cb875aeSCathy Zhou { 2821cb875aeSCathy Zhou dladm_handle_t dh; 2831cb875aeSCathy Zhou 2841cb875aeSCathy Zhou if (dladm_open(&dh) != DLADM_STATUS_OK) 2851cb875aeSCathy Zhou return (VRRP_EDLADM); 2861cb875aeSCathy Zhou 2871cb875aeSCathy Zhou if ((*vh = malloc(sizeof (struct vrrp_handle))) == NULL) { 2881cb875aeSCathy Zhou dladm_close(dh); 2891cb875aeSCathy Zhou return (VRRP_ENOMEM); 2901cb875aeSCathy Zhou } 2911cb875aeSCathy Zhou (*vh)->vh_dh = dh; 2921cb875aeSCathy Zhou return (VRRP_SUCCESS); 2931cb875aeSCathy Zhou } 2941cb875aeSCathy Zhou 2951cb875aeSCathy Zhou void 2961cb875aeSCathy Zhou vrrp_close(vrrp_handle_t vh) 2971cb875aeSCathy Zhou { 2981cb875aeSCathy Zhou if (vh != NULL) { 2991cb875aeSCathy Zhou dladm_close(vh->vh_dh); 3001cb875aeSCathy Zhou free(vh); 3011cb875aeSCathy Zhou } 3021cb875aeSCathy Zhou } 3031cb875aeSCathy Zhou 3041cb875aeSCathy Zhou boolean_t 3051cb875aeSCathy Zhou vrrp_valid_name(const char *name) 3061cb875aeSCathy Zhou { 3071cb875aeSCathy Zhou const char *c; 3081cb875aeSCathy Zhou 3091cb875aeSCathy Zhou /* 3101cb875aeSCathy Zhou * The legal characters in a valid router name are: 3111cb875aeSCathy Zhou * alphanumeric (a-z, A-Z, 0-9), underscore ('_'), and '.'. 3121cb875aeSCathy Zhou */ 3131cb875aeSCathy Zhou for (c = name; *c != '\0'; c++) { 3141cb875aeSCathy Zhou if ((isalnum(*c) == 0) && (*c != '_')) 3151cb875aeSCathy Zhou return (B_FALSE); 3161cb875aeSCathy Zhou } 3171cb875aeSCathy Zhou 3181cb875aeSCathy Zhou return (B_TRUE); 3191cb875aeSCathy Zhou } 3201cb875aeSCathy Zhou 3211cb875aeSCathy Zhou /*ARGSUSED*/ 3221cb875aeSCathy Zhou vrrp_err_t 3231cb875aeSCathy Zhou vrrp_create(vrrp_handle_t vh, vrrp_vr_conf_t *conf) 3241cb875aeSCathy Zhou { 3251cb875aeSCathy Zhou vrrp_cmd_create_t cmd; 3261cb875aeSCathy Zhou vrrp_err_t err; 3271cb875aeSCathy Zhou 328*c5e0ece0SCathy Zhou again: 329*c5e0ece0SCathy Zhou /* 330*c5e0ece0SCathy Zhou * Enable the VRRP service if it is not already enabled. 331*c5e0ece0SCathy Zhou */ 332*c5e0ece0SCathy Zhou if ((err = vrrp_enable_service()) != VRRP_SUCCESS) 333*c5e0ece0SCathy Zhou return (err); 334*c5e0ece0SCathy Zhou 3351cb875aeSCathy Zhou cmd.vcc_cmd = VRRP_CMD_CREATE; 3361cb875aeSCathy Zhou (void) memcpy(&cmd.vcc_conf, conf, sizeof (vrrp_vr_conf_t)); 3371cb875aeSCathy Zhou 3381cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 339*c5e0ece0SCathy Zhou if (err == VRRP_ENOSVC) { 340*c5e0ece0SCathy Zhou /* 341*c5e0ece0SCathy Zhou * This may be due to another process is deleting the last 342*c5e0ece0SCathy Zhou * router and disabled the VRRP service, try again. 343*c5e0ece0SCathy Zhou */ 344*c5e0ece0SCathy Zhou goto again; 345*c5e0ece0SCathy Zhou } else if (err != VRRP_SUCCESS) { 346*c5e0ece0SCathy Zhou /* 347*c5e0ece0SCathy Zhou * If router cannot be created, check if the VRRP service 348*c5e0ece0SCathy Zhou * should be disabled, and disable if needed. 349*c5e0ece0SCathy Zhou */ 350*c5e0ece0SCathy Zhou vrrp_disable_service_when_no_router(); 351*c5e0ece0SCathy Zhou } 352*c5e0ece0SCathy Zhou 3531cb875aeSCathy Zhou return (err); 3541cb875aeSCathy Zhou } 3551cb875aeSCathy Zhou 3561cb875aeSCathy Zhou /*ARGSUSED*/ 3571cb875aeSCathy Zhou vrrp_err_t 3581cb875aeSCathy Zhou vrrp_delete(vrrp_handle_t vh, const char *vn) 3591cb875aeSCathy Zhou { 3601cb875aeSCathy Zhou vrrp_cmd_delete_t cmd; 3611cb875aeSCathy Zhou vrrp_err_t err; 3621cb875aeSCathy Zhou 363*c5e0ece0SCathy Zhou /* 364*c5e0ece0SCathy Zhou * If the VRRP service is not enabled, we assume there is no router 365*c5e0ece0SCathy Zhou * configured. 366*c5e0ece0SCathy Zhou */ 367*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) 368*c5e0ece0SCathy Zhou return (VRRP_ENOTFOUND); 369*c5e0ece0SCathy Zhou 3701cb875aeSCathy Zhou cmd.vcd_cmd = VRRP_CMD_DELETE; 3711cb875aeSCathy Zhou if (strlcpy(cmd.vcd_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 3721cb875aeSCathy Zhou return (VRRP_EINVAL); 3731cb875aeSCathy Zhou 3741cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 375*c5e0ece0SCathy Zhou if (err == VRRP_SUCCESS) 376*c5e0ece0SCathy Zhou vrrp_disable_service_when_no_router(); 3771cb875aeSCathy Zhou return (err); 3781cb875aeSCathy Zhou } 3791cb875aeSCathy Zhou 3801cb875aeSCathy Zhou /*ARGSUSED*/ 3811cb875aeSCathy Zhou vrrp_err_t 3821cb875aeSCathy Zhou vrrp_enable(vrrp_handle_t vh, const char *vn) 3831cb875aeSCathy Zhou { 3841cb875aeSCathy Zhou vrrp_cmd_enable_t cmd; 3851cb875aeSCathy Zhou vrrp_err_t err; 3861cb875aeSCathy Zhou 387*c5e0ece0SCathy Zhou /* 388*c5e0ece0SCathy Zhou * If the VRRP service is not enabled, we assume there is no router 389*c5e0ece0SCathy Zhou * configured. 390*c5e0ece0SCathy Zhou */ 391*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) 392*c5e0ece0SCathy Zhou return (VRRP_ENOTFOUND); 393*c5e0ece0SCathy Zhou 3941cb875aeSCathy Zhou cmd.vcs_cmd = VRRP_CMD_ENABLE; 3951cb875aeSCathy Zhou if (strlcpy(cmd.vcs_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 3961cb875aeSCathy Zhou return (VRRP_EINVAL); 3971cb875aeSCathy Zhou 3981cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 3991cb875aeSCathy Zhou return (err); 4001cb875aeSCathy Zhou } 4011cb875aeSCathy Zhou 4021cb875aeSCathy Zhou /*ARGSUSED*/ 4031cb875aeSCathy Zhou vrrp_err_t 4041cb875aeSCathy Zhou vrrp_disable(vrrp_handle_t vh, const char *vn) 4051cb875aeSCathy Zhou { 4061cb875aeSCathy Zhou vrrp_cmd_disable_t cmd; 4071cb875aeSCathy Zhou vrrp_err_t err; 4081cb875aeSCathy Zhou 409*c5e0ece0SCathy Zhou /* 410*c5e0ece0SCathy Zhou * If the VRRP service is not enabled, we assume there is no router 411*c5e0ece0SCathy Zhou * configured. 412*c5e0ece0SCathy Zhou */ 413*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) 414*c5e0ece0SCathy Zhou return (VRRP_ENOTFOUND); 415*c5e0ece0SCathy Zhou 4161cb875aeSCathy Zhou cmd.vcx_cmd = VRRP_CMD_DISABLE; 4171cb875aeSCathy Zhou if (strlcpy(cmd.vcx_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 4181cb875aeSCathy Zhou return (VRRP_EINVAL); 4191cb875aeSCathy Zhou 4201cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 4211cb875aeSCathy Zhou return (err); 4221cb875aeSCathy Zhou } 4231cb875aeSCathy Zhou 4241cb875aeSCathy Zhou /*ARGSUSED*/ 4251cb875aeSCathy Zhou vrrp_err_t 4261cb875aeSCathy Zhou vrrp_modify(vrrp_handle_t vh, vrrp_vr_conf_t *conf, uint32_t mask) 4271cb875aeSCathy Zhou { 4281cb875aeSCathy Zhou vrrp_cmd_modify_t cmd; 4291cb875aeSCathy Zhou vrrp_err_t err; 4301cb875aeSCathy Zhou 431*c5e0ece0SCathy Zhou /* 432*c5e0ece0SCathy Zhou * If the VRRP service is not enabled, we assume there is no router 433*c5e0ece0SCathy Zhou * configured. 434*c5e0ece0SCathy Zhou */ 435*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) 436*c5e0ece0SCathy Zhou return (VRRP_ENOTFOUND); 437*c5e0ece0SCathy Zhou 4381cb875aeSCathy Zhou cmd.vcm_cmd = VRRP_CMD_MODIFY; 4391cb875aeSCathy Zhou cmd.vcm_mask = mask; 4401cb875aeSCathy Zhou (void) memcpy(&cmd.vcm_conf, conf, sizeof (vrrp_vr_conf_t)); 4411cb875aeSCathy Zhou 4421cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 4431cb875aeSCathy Zhou return (err); 4441cb875aeSCathy Zhou } 4451cb875aeSCathy Zhou 4461cb875aeSCathy Zhou typedef struct vrrp_cmd_list_arg { 4471cb875aeSCathy Zhou uint32_t *vfl_cnt; 4481cb875aeSCathy Zhou char *vfl_names; 4491cb875aeSCathy Zhou } vrrp_cmd_list_arg_t; 4501cb875aeSCathy Zhou 4511cb875aeSCathy Zhou static vrrp_err_t 4521cb875aeSCathy Zhou vrrp_list_func(int sock, void *arg) 4531cb875aeSCathy Zhou { 4541cb875aeSCathy Zhou vrrp_cmd_list_arg_t *list_arg = arg; 4551cb875aeSCathy Zhou uint32_t in_cnt = *(list_arg->vfl_cnt); 4561cb875aeSCathy Zhou uint32_t out_cnt; 4571cb875aeSCathy Zhou vrrp_ret_list_t ret; 4581cb875aeSCathy Zhou size_t len, cur_size = 0; 4591cb875aeSCathy Zhou 4601cb875aeSCathy Zhou /* 4611cb875aeSCathy Zhou * Get the rest of vrrp_ret_list_t besides the error code. 4621cb875aeSCathy Zhou */ 4631cb875aeSCathy Zhou cur_size = sizeof (vrrp_err_t); 4641cb875aeSCathy Zhou while (cur_size < sizeof (vrrp_ret_list_t)) { 4651cb875aeSCathy Zhou len = read(sock, (char *)&ret + cur_size, 4661cb875aeSCathy Zhou sizeof (vrrp_ret_list_t) - cur_size); 4671cb875aeSCathy Zhou 4681cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 4691cb875aeSCathy Zhou continue; 4701cb875aeSCathy Zhou } else if (len > 0) { 4711cb875aeSCathy Zhou cur_size += len; 4721cb875aeSCathy Zhou continue; 4731cb875aeSCathy Zhou } 474*c5e0ece0SCathy Zhou return (VRRP_ESYS); 4751cb875aeSCathy Zhou } 4761cb875aeSCathy Zhou 4771cb875aeSCathy Zhou *(list_arg->vfl_cnt) = out_cnt = ret.vrl_cnt; 4781cb875aeSCathy Zhou out_cnt = (in_cnt <= out_cnt) ? in_cnt : out_cnt; 4791cb875aeSCathy Zhou cur_size = 0; 4801cb875aeSCathy Zhou 4811cb875aeSCathy Zhou while (cur_size < VRRP_NAME_MAX * out_cnt) { 4821cb875aeSCathy Zhou len = read(sock, (char *)list_arg->vfl_names + cur_size, 4831cb875aeSCathy Zhou VRRP_NAME_MAX * out_cnt - cur_size); 4841cb875aeSCathy Zhou 4851cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 4861cb875aeSCathy Zhou continue; 4871cb875aeSCathy Zhou } else if (len > 0) { 4881cb875aeSCathy Zhou cur_size += len; 4891cb875aeSCathy Zhou continue; 4901cb875aeSCathy Zhou } 491*c5e0ece0SCathy Zhou return (VRRP_ESYS); 4921cb875aeSCathy Zhou } 4931cb875aeSCathy Zhou return (VRRP_SUCCESS); 4941cb875aeSCathy Zhou } 4951cb875aeSCathy Zhou 4961cb875aeSCathy Zhou /* 4971cb875aeSCathy Zhou * Looks up the vrrp instances that matches the given variable. 4981cb875aeSCathy Zhou * 4991cb875aeSCathy Zhou * If the given cnt is 0, names should be set to NULL. In this case, only 5001cb875aeSCathy Zhou * the count of the matched instances is returned. 5011cb875aeSCathy Zhou * 5021cb875aeSCathy Zhou * If the given cnt is non-zero, caller must allocate "names" whose size 5031cb875aeSCathy Zhou * is (cnt * VRRP_NAME_MAX). 5041cb875aeSCathy Zhou * 5051cb875aeSCathy Zhou * Return value: the current count of matched instances, and names will be 5061cb875aeSCathy Zhou * points to the list of the current vrrp instances names. Note that 5071cb875aeSCathy Zhou * only MIN(in_cnt, out_cnt) number of names will be returned. 5081cb875aeSCathy Zhou */ 5091cb875aeSCathy Zhou /*ARGSUSED*/ 5101cb875aeSCathy Zhou vrrp_err_t 5111cb875aeSCathy Zhou vrrp_list(vrrp_handle_t vh, vrid_t vrid, const char *intf, int af, 5121cb875aeSCathy Zhou uint32_t *cnt, char *names) 5131cb875aeSCathy Zhou { 5141cb875aeSCathy Zhou vrrp_cmd_list_t cmd; 5151cb875aeSCathy Zhou vrrp_err_t err; 5161cb875aeSCathy Zhou vrrp_cmd_list_arg_t list_arg; 5171cb875aeSCathy Zhou 5181cb875aeSCathy Zhou if ((cnt == NULL) || (*cnt != 0 && names == NULL)) 5191cb875aeSCathy Zhou return (VRRP_EINVAL); 5201cb875aeSCathy Zhou 5211cb875aeSCathy Zhou cmd.vcl_ifname[0] = '\0'; 5221cb875aeSCathy Zhou if (intf != NULL && (strlcpy(cmd.vcl_ifname, intf, 5231cb875aeSCathy Zhou LIFNAMSIZ) >= LIFNAMSIZ)) { 5241cb875aeSCathy Zhou return (VRRP_EINVAL); 5251cb875aeSCathy Zhou } 5261cb875aeSCathy Zhou 527*c5e0ece0SCathy Zhou /* 528*c5e0ece0SCathy Zhou * If the service is not online, we assume there is no router 529*c5e0ece0SCathy Zhou * configured. 530*c5e0ece0SCathy Zhou */ 531*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) { 532*c5e0ece0SCathy Zhou *cnt = 0; 533*c5e0ece0SCathy Zhou return (VRRP_SUCCESS); 534*c5e0ece0SCathy Zhou } 535*c5e0ece0SCathy Zhou 5361cb875aeSCathy Zhou cmd.vcl_cmd = VRRP_CMD_LIST; 5371cb875aeSCathy Zhou cmd.vcl_vrid = vrid; 5381cb875aeSCathy Zhou cmd.vcl_af = af; 5391cb875aeSCathy Zhou 5401cb875aeSCathy Zhou list_arg.vfl_cnt = cnt; 5411cb875aeSCathy Zhou list_arg.vfl_names = names; 5421cb875aeSCathy Zhou 5431cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_list_func, &list_arg); 5441cb875aeSCathy Zhou return (err); 5451cb875aeSCathy Zhou } 5461cb875aeSCathy Zhou 5471cb875aeSCathy Zhou static vrrp_err_t 5481cb875aeSCathy Zhou vrrp_query_func(int sock, void *arg) 5491cb875aeSCathy Zhou { 5501cb875aeSCathy Zhou vrrp_queryinfo_t *qinfo = arg; 5511cb875aeSCathy Zhou size_t len, cur_size = 0, total; 5521cb875aeSCathy Zhou uint32_t in_cnt = qinfo->show_va.va_vipcnt; 5531cb875aeSCathy Zhou uint32_t out_cnt; 5541cb875aeSCathy Zhou 5551cb875aeSCathy Zhou /* 5561cb875aeSCathy Zhou * Expect the ack, first get the vrrp_ret_t. 5571cb875aeSCathy Zhou */ 5581cb875aeSCathy Zhou total = sizeof (vrrp_queryinfo_t); 5591cb875aeSCathy Zhou while (cur_size < total) { 5601cb875aeSCathy Zhou len = read(sock, (char *)qinfo + cur_size, total - cur_size); 5611cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 5621cb875aeSCathy Zhou continue; 5631cb875aeSCathy Zhou } else if (len > 0) { 5641cb875aeSCathy Zhou cur_size += len; 5651cb875aeSCathy Zhou continue; 5661cb875aeSCathy Zhou } 567*c5e0ece0SCathy Zhou return (VRRP_ESYS); 5681cb875aeSCathy Zhou } 5691cb875aeSCathy Zhou 5701cb875aeSCathy Zhou out_cnt = qinfo->show_va.va_vipcnt; 5711cb875aeSCathy Zhou 5721cb875aeSCathy Zhou /* 5731cb875aeSCathy Zhou * Even if there is no IP virtual IP address, there is always 5741cb875aeSCathy Zhou * space in the vrrp_queryinfo_t structure for one virtual 5751cb875aeSCathy Zhou * IP address. 5761cb875aeSCathy Zhou */ 5771cb875aeSCathy Zhou out_cnt = (out_cnt == 0) ? 1 : out_cnt; 5781cb875aeSCathy Zhou out_cnt = (in_cnt < out_cnt ? in_cnt : out_cnt) - 1; 5791cb875aeSCathy Zhou total += out_cnt * sizeof (vrrp_addr_t); 5801cb875aeSCathy Zhou 5811cb875aeSCathy Zhou while (cur_size < total) { 5821cb875aeSCathy Zhou len = read(sock, (char *)qinfo + cur_size, total - cur_size); 5831cb875aeSCathy Zhou if (len == (size_t)-1 && errno == EAGAIN) { 5841cb875aeSCathy Zhou continue; 5851cb875aeSCathy Zhou } else if (len > 0) { 5861cb875aeSCathy Zhou cur_size += len; 5871cb875aeSCathy Zhou continue; 5881cb875aeSCathy Zhou } 589*c5e0ece0SCathy Zhou return (VRRP_ESYS); 5901cb875aeSCathy Zhou } 5911cb875aeSCathy Zhou return (VRRP_SUCCESS); 5921cb875aeSCathy Zhou } 5931cb875aeSCathy Zhou 5941cb875aeSCathy Zhou /* 5951cb875aeSCathy Zhou * *vqp is allocated inside this function and must be freed by the caller. 5961cb875aeSCathy Zhou */ 5971cb875aeSCathy Zhou /*ARGSUSED*/ 5981cb875aeSCathy Zhou vrrp_err_t 5991cb875aeSCathy Zhou vrrp_query(vrrp_handle_t vh, const char *vn, vrrp_queryinfo_t **vqp) 6001cb875aeSCathy Zhou { 6011cb875aeSCathy Zhou vrrp_cmd_query_t cmd; 6021cb875aeSCathy Zhou vrrp_queryinfo_t *qinfo; 6031cb875aeSCathy Zhou vrrp_err_t err; 6041cb875aeSCathy Zhou size_t size; 6051cb875aeSCathy Zhou uint32_t vipcnt = 1; 6061cb875aeSCathy Zhou 6071cb875aeSCathy Zhou if (strlcpy(cmd.vcq_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 6081cb875aeSCathy Zhou return (VRRP_EINVAL); 6091cb875aeSCathy Zhou 610*c5e0ece0SCathy Zhou /* 611*c5e0ece0SCathy Zhou * If the service is not online, we assume there is no router 612*c5e0ece0SCathy Zhou * configured. 613*c5e0ece0SCathy Zhou */ 614*c5e0ece0SCathy Zhou if (!vrrp_svc_isonline(VRRP_SERVICE)) 615*c5e0ece0SCathy Zhou return (VRRP_ENOTFOUND); 616*c5e0ece0SCathy Zhou 6171cb875aeSCathy Zhou cmd.vcq_cmd = VRRP_CMD_QUERY; 6181cb875aeSCathy Zhou 6191cb875aeSCathy Zhou /* 6201cb875aeSCathy Zhou * Allocate enough room for virtual IPs. 6211cb875aeSCathy Zhou */ 6221cb875aeSCathy Zhou again: 6231cb875aeSCathy Zhou size = sizeof (vrrp_queryinfo_t); 6241cb875aeSCathy Zhou size += (vipcnt == 0) ? 0 : (vipcnt - 1) * sizeof (vrrp_addr_t); 6251cb875aeSCathy Zhou if ((qinfo = malloc(size)) == NULL) { 6261cb875aeSCathy Zhou err = VRRP_ENOMEM; 6271cb875aeSCathy Zhou goto done; 6281cb875aeSCathy Zhou } 6291cb875aeSCathy Zhou 6301cb875aeSCathy Zhou qinfo->show_va.va_vipcnt = vipcnt; 6311cb875aeSCathy Zhou err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_query_func, qinfo); 6321cb875aeSCathy Zhou if (err != VRRP_SUCCESS) { 6331cb875aeSCathy Zhou free(qinfo); 6341cb875aeSCathy Zhou goto done; 6351cb875aeSCathy Zhou } 6361cb875aeSCathy Zhou 6371cb875aeSCathy Zhou /* 6381cb875aeSCathy Zhou * If the returned number of virtual IPs is greater than we expected, 6391cb875aeSCathy Zhou * allocate more room and try again. 6401cb875aeSCathy Zhou */ 6411cb875aeSCathy Zhou if (qinfo->show_va.va_vipcnt > vipcnt) { 6421cb875aeSCathy Zhou vipcnt = qinfo->show_va.va_vipcnt; 6431cb875aeSCathy Zhou free(qinfo); 6441cb875aeSCathy Zhou goto again; 6451cb875aeSCathy Zhou } 6461cb875aeSCathy Zhou 6471cb875aeSCathy Zhou *vqp = qinfo; 6481cb875aeSCathy Zhou 6491cb875aeSCathy Zhou done: 6501cb875aeSCathy Zhou return (err); 6511cb875aeSCathy Zhou } 6521cb875aeSCathy Zhou 6531cb875aeSCathy Zhou struct lookup_vnic_arg { 6541cb875aeSCathy Zhou vrid_t lva_vrid; 6551cb875aeSCathy Zhou datalink_id_t lva_linkid; 6561cb875aeSCathy Zhou int lva_af; 6571cb875aeSCathy Zhou uint16_t lva_vid; 6581cb875aeSCathy Zhou vrrp_handle_t lva_vh; 6591cb875aeSCathy Zhou char lva_vnic[MAXLINKNAMELEN]; 6601cb875aeSCathy Zhou }; 6611cb875aeSCathy Zhou 6621cb875aeSCathy Zhou /* 6631cb875aeSCathy Zhou * Is this a special VNIC interface created for VRRP? If so, return 6641cb875aeSCathy Zhou * the linkid the VNIC was created on, the VRRP ID and address family. 6651cb875aeSCathy Zhou */ 6661cb875aeSCathy Zhou boolean_t 6671cb875aeSCathy Zhou vrrp_is_vrrp_vnic(vrrp_handle_t vh, datalink_id_t vnicid, 6681cb875aeSCathy Zhou datalink_id_t *linkidp, uint16_t *vidp, vrid_t *vridp, int *afp) 6691cb875aeSCathy Zhou { 6701cb875aeSCathy Zhou dladm_vnic_attr_t vattr; 6711cb875aeSCathy Zhou 6721cb875aeSCathy Zhou if (dladm_vnic_info(vh->vh_dh, vnicid, &vattr, DLADM_OPT_ACTIVE) != 6731cb875aeSCathy Zhou DLADM_STATUS_OK) { 6741cb875aeSCathy Zhou return (B_FALSE); 6751cb875aeSCathy Zhou } 6761cb875aeSCathy Zhou 6771cb875aeSCathy Zhou *vridp = vattr.va_vrid; 6781cb875aeSCathy Zhou *vidp = vattr.va_vid; 6791cb875aeSCathy Zhou *afp = vattr.va_af; 6801cb875aeSCathy Zhou *linkidp = vattr.va_link_id; 6811cb875aeSCathy Zhou return (vattr.va_vrid != VRRP_VRID_NONE); 6821cb875aeSCathy Zhou } 6831cb875aeSCathy Zhou 6841cb875aeSCathy Zhou static int 6851cb875aeSCathy Zhou lookup_vnic(dladm_handle_t dh, datalink_id_t vnicid, void *arg) 6861cb875aeSCathy Zhou { 6871cb875aeSCathy Zhou vrid_t vrid; 6881cb875aeSCathy Zhou uint16_t vid; 6891cb875aeSCathy Zhou datalink_id_t linkid; 6901cb875aeSCathy Zhou int af; 6911cb875aeSCathy Zhou struct lookup_vnic_arg *lva = arg; 6921cb875aeSCathy Zhou 6931cb875aeSCathy Zhou if (vrrp_is_vrrp_vnic(lva->lva_vh, vnicid, &linkid, &vid, &vrid, 6941cb875aeSCathy Zhou &af) && lva->lva_vrid == vrid && lva->lva_linkid == linkid && 6951cb875aeSCathy Zhou lva->lva_vid == vid && lva->lva_af == af) { 6961cb875aeSCathy Zhou if (dladm_datalink_id2info(dh, vnicid, NULL, NULL, NULL, 6971cb875aeSCathy Zhou lva->lva_vnic, sizeof (lva->lva_vnic)) == DLADM_STATUS_OK) { 6981cb875aeSCathy Zhou return (DLADM_WALK_TERMINATE); 6991cb875aeSCathy Zhou } 7001cb875aeSCathy Zhou } 7011cb875aeSCathy Zhou return (DLADM_WALK_CONTINUE); 7021cb875aeSCathy Zhou } 7031cb875aeSCathy Zhou 7041cb875aeSCathy Zhou /* 7051cb875aeSCathy Zhou * Given the primary link name, find the assoicated VRRP vnic name, if 7061cb875aeSCathy Zhou * the vnic does not exist yet, return the linkid, vid of the primary link. 7071cb875aeSCathy Zhou */ 7081cb875aeSCathy Zhou vrrp_err_t 7091cb875aeSCathy Zhou vrrp_get_vnicname(vrrp_handle_t vh, vrid_t vrid, int af, char *link, 7101cb875aeSCathy Zhou datalink_id_t *linkidp, uint16_t *vidp, char *vnic, size_t len) 7111cb875aeSCathy Zhou { 7121cb875aeSCathy Zhou datalink_id_t linkid; 7131cb875aeSCathy Zhou uint32_t flags; 7141cb875aeSCathy Zhou uint16_t vid = VLAN_ID_NONE; 7151cb875aeSCathy Zhou datalink_class_t class; 7161cb875aeSCathy Zhou dladm_vlan_attr_t vlan_attr; 7171cb875aeSCathy Zhou struct lookup_vnic_arg lva; 7181cb875aeSCathy Zhou uint32_t media; 7191cb875aeSCathy Zhou 7201cb875aeSCathy Zhou if ((strlen(link) == 0) || dladm_name2info(vh->vh_dh, 7211cb875aeSCathy Zhou link, &linkid, &flags, &class, &media) != 7221cb875aeSCathy Zhou DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) { 7231cb875aeSCathy Zhou return (VRRP_EINVAL); 7241cb875aeSCathy Zhou } 7251cb875aeSCathy Zhou 7261cb875aeSCathy Zhou if (class == DATALINK_CLASS_VLAN) { 7271cb875aeSCathy Zhou if (dladm_vlan_info(vh->vh_dh, linkid, &vlan_attr, 7281cb875aeSCathy Zhou DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { 7291cb875aeSCathy Zhou return (VRRP_EINVAL); 7301cb875aeSCathy Zhou } 7311cb875aeSCathy Zhou linkid = vlan_attr.dv_linkid; 7321cb875aeSCathy Zhou vid = vlan_attr.dv_vid; 7331cb875aeSCathy Zhou if ((dladm_datalink_id2info(vh->vh_dh, linkid, NULL, 7341cb875aeSCathy Zhou &class, &media, NULL, 0)) != DLADM_STATUS_OK) { 7351cb875aeSCathy Zhou return (VRRP_EINVAL); 7361cb875aeSCathy Zhou } 7371cb875aeSCathy Zhou } 7381cb875aeSCathy Zhou 7391cb875aeSCathy Zhou /* 7401cb875aeSCathy Zhou * For now, Only VRRP over aggr and physical ethernet links is supported 7411cb875aeSCathy Zhou */ 7421cb875aeSCathy Zhou if ((class != DATALINK_CLASS_PHYS && class != DATALINK_CLASS_AGGR) || 7431cb875aeSCathy Zhou media != DL_ETHER) { 7441cb875aeSCathy Zhou return (VRRP_EINVAL); 7451cb875aeSCathy Zhou } 7461cb875aeSCathy Zhou 7471cb875aeSCathy Zhou if (linkidp != NULL) 7481cb875aeSCathy Zhou *linkidp = linkid; 7491cb875aeSCathy Zhou if (vidp != NULL) 7501cb875aeSCathy Zhou *vidp = vid; 7511cb875aeSCathy Zhou 7521cb875aeSCathy Zhou /* 7531cb875aeSCathy Zhou * Find the assoicated vnic with the given vrid/vid/af/linkid 7541cb875aeSCathy Zhou */ 7551cb875aeSCathy Zhou lva.lva_vrid = vrid; 7561cb875aeSCathy Zhou lva.lva_vid = vid; 7571cb875aeSCathy Zhou lva.lva_af = af; 7581cb875aeSCathy Zhou lva.lva_linkid = linkid; 7591cb875aeSCathy Zhou lva.lva_vh = vh; 7601cb875aeSCathy Zhou lva.lva_vnic[0] = '\0'; 7611cb875aeSCathy Zhou 7621cb875aeSCathy Zhou (void) dladm_walk_datalink_id(lookup_vnic, vh->vh_dh, &lva, 7631cb875aeSCathy Zhou DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 7641cb875aeSCathy Zhou if (strlen(lva.lva_vnic) != 0) { 7651cb875aeSCathy Zhou (void) strlcpy(vnic, lva.lva_vnic, len); 7661cb875aeSCathy Zhou return (VRRP_SUCCESS); 7671cb875aeSCathy Zhou } 7681cb875aeSCathy Zhou 7691cb875aeSCathy Zhou return (VRRP_ENOVNIC); 7701cb875aeSCathy Zhou } 771