1*11076SCathy.Zhou@Sun.COM /* 2*11076SCathy.Zhou@Sun.COM * CDDL HEADER START 3*11076SCathy.Zhou@Sun.COM * 4*11076SCathy.Zhou@Sun.COM * The contents of this file are subject to the terms of the 5*11076SCathy.Zhou@Sun.COM * Common Development and Distribution License (the "License"). 6*11076SCathy.Zhou@Sun.COM * You may not use this file except in compliance with the License. 7*11076SCathy.Zhou@Sun.COM * 8*11076SCathy.Zhou@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*11076SCathy.Zhou@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*11076SCathy.Zhou@Sun.COM * See the License for the specific language governing permissions 11*11076SCathy.Zhou@Sun.COM * and limitations under the License. 12*11076SCathy.Zhou@Sun.COM * 13*11076SCathy.Zhou@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*11076SCathy.Zhou@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*11076SCathy.Zhou@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*11076SCathy.Zhou@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*11076SCathy.Zhou@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*11076SCathy.Zhou@Sun.COM * 19*11076SCathy.Zhou@Sun.COM * CDDL HEADER END 20*11076SCathy.Zhou@Sun.COM */ 21*11076SCathy.Zhou@Sun.COM 22*11076SCathy.Zhou@Sun.COM /* 23*11076SCathy.Zhou@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24*11076SCathy.Zhou@Sun.COM * Use is subject to license terms. 25*11076SCathy.Zhou@Sun.COM */ 26*11076SCathy.Zhou@Sun.COM 27*11076SCathy.Zhou@Sun.COM #include <sys/types.h> 28*11076SCathy.Zhou@Sun.COM #include <sys/stat.h> 29*11076SCathy.Zhou@Sun.COM #include <sys/socket.h> 30*11076SCathy.Zhou@Sun.COM #include <sys/mman.h> 31*11076SCathy.Zhou@Sun.COM #include <sys/varargs.h> 32*11076SCathy.Zhou@Sun.COM #include <sys/vlan.h> 33*11076SCathy.Zhou@Sun.COM #include <errno.h> 34*11076SCathy.Zhou@Sun.COM #include <ctype.h> 35*11076SCathy.Zhou@Sun.COM #include <fcntl.h> 36*11076SCathy.Zhou@Sun.COM #include <unistd.h> 37*11076SCathy.Zhou@Sun.COM #include <stdio.h> 38*11076SCathy.Zhou@Sun.COM #include <stdlib.h> 39*11076SCathy.Zhou@Sun.COM #include <string.h> 40*11076SCathy.Zhou@Sun.COM #include <netinet/in.h> 41*11076SCathy.Zhou@Sun.COM #include <arpa/inet.h> 42*11076SCathy.Zhou@Sun.COM #include <net/if.h> /* LIFNAMSIZ */ 43*11076SCathy.Zhou@Sun.COM #include <netinet/vrrp.h> 44*11076SCathy.Zhou@Sun.COM #include <libdladm.h> 45*11076SCathy.Zhou@Sun.COM #include <libdlvnic.h> 46*11076SCathy.Zhou@Sun.COM #include <libdlvlan.h> 47*11076SCathy.Zhou@Sun.COM #include <libdllink.h> 48*11076SCathy.Zhou@Sun.COM #include <libintl.h> 49*11076SCathy.Zhou@Sun.COM #include <libvrrpadm.h> 50*11076SCathy.Zhou@Sun.COM 51*11076SCathy.Zhou@Sun.COM typedef vrrp_err_t vrrp_cmd_func_t(int, void *); 52*11076SCathy.Zhou@Sun.COM 53*11076SCathy.Zhou@Sun.COM static vrrp_err_t 54*11076SCathy.Zhou@Sun.COM vrrp_cmd_request(void *cmd, size_t csize, vrrp_cmd_func_t func, void *arg) 55*11076SCathy.Zhou@Sun.COM { 56*11076SCathy.Zhou@Sun.COM struct sockaddr_un to; 57*11076SCathy.Zhou@Sun.COM int sock, flags; 58*11076SCathy.Zhou@Sun.COM size_t len, cur_size = 0; 59*11076SCathy.Zhou@Sun.COM vrrp_ret_t ret; 60*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 61*11076SCathy.Zhou@Sun.COM 62*11076SCathy.Zhou@Sun.COM if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) 63*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 64*11076SCathy.Zhou@Sun.COM 65*11076SCathy.Zhou@Sun.COM /* 66*11076SCathy.Zhou@Sun.COM * Set it to be non-blocking. 67*11076SCathy.Zhou@Sun.COM */ 68*11076SCathy.Zhou@Sun.COM flags = fcntl(sock, F_GETFL, 0); 69*11076SCathy.Zhou@Sun.COM (void) fcntl(sock, F_SETFL, (flags | O_NONBLOCK)); 70*11076SCathy.Zhou@Sun.COM 71*11076SCathy.Zhou@Sun.COM (void) memset(&to, 0, sizeof (to)); 72*11076SCathy.Zhou@Sun.COM to.sun_family = AF_UNIX; 73*11076SCathy.Zhou@Sun.COM (void) strlcpy(to.sun_path, VRRPD_SOCKET, sizeof (to.sun_path)); 74*11076SCathy.Zhou@Sun.COM 75*11076SCathy.Zhou@Sun.COM /* 76*11076SCathy.Zhou@Sun.COM * Connect to vrrpd 77*11076SCathy.Zhou@Sun.COM */ 78*11076SCathy.Zhou@Sun.COM if (connect(sock, (const struct sockaddr *)&to, sizeof (to)) < 0) { 79*11076SCathy.Zhou@Sun.COM (void) close(sock); 80*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 81*11076SCathy.Zhou@Sun.COM } 82*11076SCathy.Zhou@Sun.COM 83*11076SCathy.Zhou@Sun.COM /* 84*11076SCathy.Zhou@Sun.COM * Send the request 85*11076SCathy.Zhou@Sun.COM */ 86*11076SCathy.Zhou@Sun.COM while (cur_size < csize) { 87*11076SCathy.Zhou@Sun.COM len = write(sock, (char *)cmd + cur_size, csize - cur_size); 88*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 89*11076SCathy.Zhou@Sun.COM continue; 90*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 91*11076SCathy.Zhou@Sun.COM cur_size += len; 92*11076SCathy.Zhou@Sun.COM continue; 93*11076SCathy.Zhou@Sun.COM } 94*11076SCathy.Zhou@Sun.COM (void) close(sock); 95*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 96*11076SCathy.Zhou@Sun.COM } 97*11076SCathy.Zhou@Sun.COM 98*11076SCathy.Zhou@Sun.COM /* 99*11076SCathy.Zhou@Sun.COM * Expect the ack, first get the error code. 100*11076SCathy.Zhou@Sun.COM */ 101*11076SCathy.Zhou@Sun.COM cur_size = 0; 102*11076SCathy.Zhou@Sun.COM while (cur_size < sizeof (vrrp_err_t)) { 103*11076SCathy.Zhou@Sun.COM len = read(sock, (char *)&ret + cur_size, 104*11076SCathy.Zhou@Sun.COM sizeof (vrrp_err_t) - cur_size); 105*11076SCathy.Zhou@Sun.COM 106*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 107*11076SCathy.Zhou@Sun.COM continue; 108*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 109*11076SCathy.Zhou@Sun.COM cur_size += len; 110*11076SCathy.Zhou@Sun.COM continue; 111*11076SCathy.Zhou@Sun.COM } 112*11076SCathy.Zhou@Sun.COM (void) close(sock); 113*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 114*11076SCathy.Zhou@Sun.COM } 115*11076SCathy.Zhou@Sun.COM 116*11076SCathy.Zhou@Sun.COM if ((err = ret.vr_err) != VRRP_SUCCESS) 117*11076SCathy.Zhou@Sun.COM goto done; 118*11076SCathy.Zhou@Sun.COM 119*11076SCathy.Zhou@Sun.COM /* 120*11076SCathy.Zhou@Sun.COM * The specific callback gets the rest of the information. 121*11076SCathy.Zhou@Sun.COM */ 122*11076SCathy.Zhou@Sun.COM if (func != NULL) 123*11076SCathy.Zhou@Sun.COM err = func(sock, arg); 124*11076SCathy.Zhou@Sun.COM 125*11076SCathy.Zhou@Sun.COM done: 126*11076SCathy.Zhou@Sun.COM (void) close(sock); 127*11076SCathy.Zhou@Sun.COM return (err); 128*11076SCathy.Zhou@Sun.COM } 129*11076SCathy.Zhou@Sun.COM 130*11076SCathy.Zhou@Sun.COM /* 131*11076SCathy.Zhou@Sun.COM * public APIs 132*11076SCathy.Zhou@Sun.COM */ 133*11076SCathy.Zhou@Sun.COM const char * 134*11076SCathy.Zhou@Sun.COM vrrp_err2str(vrrp_err_t err) 135*11076SCathy.Zhou@Sun.COM { 136*11076SCathy.Zhou@Sun.COM switch (err) { 137*11076SCathy.Zhou@Sun.COM case VRRP_SUCCESS: 138*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "success")); 139*11076SCathy.Zhou@Sun.COM case VRRP_ENOMEM: 140*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "not enough memory")); 141*11076SCathy.Zhou@Sun.COM case VRRP_EINVALVRNAME: 142*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid router name")); 143*11076SCathy.Zhou@Sun.COM case VRRP_ENOPRIM: 144*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "no primary IP")); 145*11076SCathy.Zhou@Sun.COM case VRRP_EEXIST: 146*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "already exists")); 147*11076SCathy.Zhou@Sun.COM case VRRP_ENOVIRT: 148*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "no virtual IPs")); 149*11076SCathy.Zhou@Sun.COM case VRRP_EIPADM: 150*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "ip configuration failure")); 151*11076SCathy.Zhou@Sun.COM case VRRP_EDLADM: 152*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "data-link configuration " 153*11076SCathy.Zhou@Sun.COM "failure")); 154*11076SCathy.Zhou@Sun.COM case VRRP_EDB: 155*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "configuration update error")); 156*11076SCathy.Zhou@Sun.COM case VRRP_EBADSTATE: 157*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid state")); 158*11076SCathy.Zhou@Sun.COM case VRRP_EVREXIST: 159*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "VRRP router already exists")); 160*11076SCathy.Zhou@Sun.COM case VRRP_ETOOSMALL: 161*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "not enough space")); 162*11076SCathy.Zhou@Sun.COM case VRRP_EINSTEXIST: 163*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "router name already exists")); 164*11076SCathy.Zhou@Sun.COM case VRRP_ENOTFOUND: 165*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "VRRP router not found")); 166*11076SCathy.Zhou@Sun.COM case VRRP_ECMD: 167*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "failed to communicate to " 168*11076SCathy.Zhou@Sun.COM "vrrpd")); 169*11076SCathy.Zhou@Sun.COM case VRRP_EINVALADDR: 170*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid IP address")); 171*11076SCathy.Zhou@Sun.COM case VRRP_EINVALAF: 172*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid IP address family")); 173*11076SCathy.Zhou@Sun.COM case VRRP_EINVALLINK: 174*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid data-link")); 175*11076SCathy.Zhou@Sun.COM case VRRP_EPERM: 176*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "permission denied")); 177*11076SCathy.Zhou@Sun.COM case VRRP_ESYS: 178*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "system error")); 179*11076SCathy.Zhou@Sun.COM case VRRP_EAGAIN: 180*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "try again")); 181*11076SCathy.Zhou@Sun.COM case VRRP_EALREADY: 182*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "operation already in progress")); 183*11076SCathy.Zhou@Sun.COM case VRRP_ENOVNIC: 184*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "VRRP VNIC has not been " 185*11076SCathy.Zhou@Sun.COM "created")); 186*11076SCathy.Zhou@Sun.COM case VRRP_ENOLINK: 187*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "the data-link does not exist")); 188*11076SCathy.Zhou@Sun.COM case VRRP_EINVAL: 189*11076SCathy.Zhou@Sun.COM default: 190*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "invalid argument")); 191*11076SCathy.Zhou@Sun.COM } 192*11076SCathy.Zhou@Sun.COM } 193*11076SCathy.Zhou@Sun.COM 194*11076SCathy.Zhou@Sun.COM const char * 195*11076SCathy.Zhou@Sun.COM vrrp_state2str(vrrp_state_t state) 196*11076SCathy.Zhou@Sun.COM { 197*11076SCathy.Zhou@Sun.COM switch (state) { 198*11076SCathy.Zhou@Sun.COM case VRRP_STATE_NONE: 199*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "NONE")); 200*11076SCathy.Zhou@Sun.COM case VRRP_STATE_INIT: 201*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "INIT")); 202*11076SCathy.Zhou@Sun.COM case VRRP_STATE_MASTER: 203*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "MASTER")); 204*11076SCathy.Zhou@Sun.COM case VRRP_STATE_BACKUP: 205*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "BACKUP")); 206*11076SCathy.Zhou@Sun.COM default: 207*11076SCathy.Zhou@Sun.COM return (dgettext(TEXT_DOMAIN, "INVALID")); 208*11076SCathy.Zhou@Sun.COM } 209*11076SCathy.Zhou@Sun.COM } 210*11076SCathy.Zhou@Sun.COM 211*11076SCathy.Zhou@Sun.COM vrrp_err_t 212*11076SCathy.Zhou@Sun.COM vrrp_open(vrrp_handle_t *vh) 213*11076SCathy.Zhou@Sun.COM { 214*11076SCathy.Zhou@Sun.COM dladm_handle_t dh; 215*11076SCathy.Zhou@Sun.COM 216*11076SCathy.Zhou@Sun.COM if (dladm_open(&dh) != DLADM_STATUS_OK) 217*11076SCathy.Zhou@Sun.COM return (VRRP_EDLADM); 218*11076SCathy.Zhou@Sun.COM 219*11076SCathy.Zhou@Sun.COM if ((*vh = malloc(sizeof (struct vrrp_handle))) == NULL) { 220*11076SCathy.Zhou@Sun.COM dladm_close(dh); 221*11076SCathy.Zhou@Sun.COM return (VRRP_ENOMEM); 222*11076SCathy.Zhou@Sun.COM } 223*11076SCathy.Zhou@Sun.COM (*vh)->vh_dh = dh; 224*11076SCathy.Zhou@Sun.COM return (VRRP_SUCCESS); 225*11076SCathy.Zhou@Sun.COM } 226*11076SCathy.Zhou@Sun.COM 227*11076SCathy.Zhou@Sun.COM void 228*11076SCathy.Zhou@Sun.COM vrrp_close(vrrp_handle_t vh) 229*11076SCathy.Zhou@Sun.COM { 230*11076SCathy.Zhou@Sun.COM if (vh != NULL) { 231*11076SCathy.Zhou@Sun.COM dladm_close(vh->vh_dh); 232*11076SCathy.Zhou@Sun.COM free(vh); 233*11076SCathy.Zhou@Sun.COM } 234*11076SCathy.Zhou@Sun.COM } 235*11076SCathy.Zhou@Sun.COM 236*11076SCathy.Zhou@Sun.COM boolean_t 237*11076SCathy.Zhou@Sun.COM vrrp_valid_name(const char *name) 238*11076SCathy.Zhou@Sun.COM { 239*11076SCathy.Zhou@Sun.COM const char *c; 240*11076SCathy.Zhou@Sun.COM 241*11076SCathy.Zhou@Sun.COM /* 242*11076SCathy.Zhou@Sun.COM * The legal characters in a valid router name are: 243*11076SCathy.Zhou@Sun.COM * alphanumeric (a-z, A-Z, 0-9), underscore ('_'), and '.'. 244*11076SCathy.Zhou@Sun.COM */ 245*11076SCathy.Zhou@Sun.COM for (c = name; *c != '\0'; c++) { 246*11076SCathy.Zhou@Sun.COM if ((isalnum(*c) == 0) && (*c != '_')) 247*11076SCathy.Zhou@Sun.COM return (B_FALSE); 248*11076SCathy.Zhou@Sun.COM } 249*11076SCathy.Zhou@Sun.COM 250*11076SCathy.Zhou@Sun.COM return (B_TRUE); 251*11076SCathy.Zhou@Sun.COM } 252*11076SCathy.Zhou@Sun.COM 253*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 254*11076SCathy.Zhou@Sun.COM vrrp_err_t 255*11076SCathy.Zhou@Sun.COM vrrp_create(vrrp_handle_t vh, vrrp_vr_conf_t *conf) 256*11076SCathy.Zhou@Sun.COM { 257*11076SCathy.Zhou@Sun.COM vrrp_cmd_create_t cmd; 258*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 259*11076SCathy.Zhou@Sun.COM 260*11076SCathy.Zhou@Sun.COM cmd.vcc_cmd = VRRP_CMD_CREATE; 261*11076SCathy.Zhou@Sun.COM (void) memcpy(&cmd.vcc_conf, conf, sizeof (vrrp_vr_conf_t)); 262*11076SCathy.Zhou@Sun.COM 263*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 264*11076SCathy.Zhou@Sun.COM return (err); 265*11076SCathy.Zhou@Sun.COM } 266*11076SCathy.Zhou@Sun.COM 267*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 268*11076SCathy.Zhou@Sun.COM vrrp_err_t 269*11076SCathy.Zhou@Sun.COM vrrp_delete(vrrp_handle_t vh, const char *vn) 270*11076SCathy.Zhou@Sun.COM { 271*11076SCathy.Zhou@Sun.COM vrrp_cmd_delete_t cmd; 272*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 273*11076SCathy.Zhou@Sun.COM 274*11076SCathy.Zhou@Sun.COM cmd.vcd_cmd = VRRP_CMD_DELETE; 275*11076SCathy.Zhou@Sun.COM if (strlcpy(cmd.vcd_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 276*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 277*11076SCathy.Zhou@Sun.COM 278*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 279*11076SCathy.Zhou@Sun.COM return (err); 280*11076SCathy.Zhou@Sun.COM } 281*11076SCathy.Zhou@Sun.COM 282*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 283*11076SCathy.Zhou@Sun.COM vrrp_err_t 284*11076SCathy.Zhou@Sun.COM vrrp_enable(vrrp_handle_t vh, const char *vn) 285*11076SCathy.Zhou@Sun.COM { 286*11076SCathy.Zhou@Sun.COM vrrp_cmd_enable_t cmd; 287*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 288*11076SCathy.Zhou@Sun.COM 289*11076SCathy.Zhou@Sun.COM cmd.vcs_cmd = VRRP_CMD_ENABLE; 290*11076SCathy.Zhou@Sun.COM if (strlcpy(cmd.vcs_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 291*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 292*11076SCathy.Zhou@Sun.COM 293*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 294*11076SCathy.Zhou@Sun.COM return (err); 295*11076SCathy.Zhou@Sun.COM } 296*11076SCathy.Zhou@Sun.COM 297*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 298*11076SCathy.Zhou@Sun.COM vrrp_err_t 299*11076SCathy.Zhou@Sun.COM vrrp_disable(vrrp_handle_t vh, const char *vn) 300*11076SCathy.Zhou@Sun.COM { 301*11076SCathy.Zhou@Sun.COM vrrp_cmd_disable_t cmd; 302*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 303*11076SCathy.Zhou@Sun.COM 304*11076SCathy.Zhou@Sun.COM cmd.vcx_cmd = VRRP_CMD_DISABLE; 305*11076SCathy.Zhou@Sun.COM if (strlcpy(cmd.vcx_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 306*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 307*11076SCathy.Zhou@Sun.COM 308*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 309*11076SCathy.Zhou@Sun.COM return (err); 310*11076SCathy.Zhou@Sun.COM } 311*11076SCathy.Zhou@Sun.COM 312*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 313*11076SCathy.Zhou@Sun.COM vrrp_err_t 314*11076SCathy.Zhou@Sun.COM vrrp_modify(vrrp_handle_t vh, vrrp_vr_conf_t *conf, uint32_t mask) 315*11076SCathy.Zhou@Sun.COM { 316*11076SCathy.Zhou@Sun.COM vrrp_cmd_modify_t cmd; 317*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 318*11076SCathy.Zhou@Sun.COM 319*11076SCathy.Zhou@Sun.COM cmd.vcm_cmd = VRRP_CMD_MODIFY; 320*11076SCathy.Zhou@Sun.COM cmd.vcm_mask = mask; 321*11076SCathy.Zhou@Sun.COM (void) memcpy(&cmd.vcm_conf, conf, sizeof (vrrp_vr_conf_t)); 322*11076SCathy.Zhou@Sun.COM 323*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), NULL, NULL); 324*11076SCathy.Zhou@Sun.COM return (err); 325*11076SCathy.Zhou@Sun.COM } 326*11076SCathy.Zhou@Sun.COM 327*11076SCathy.Zhou@Sun.COM typedef struct vrrp_cmd_list_arg { 328*11076SCathy.Zhou@Sun.COM uint32_t *vfl_cnt; 329*11076SCathy.Zhou@Sun.COM char *vfl_names; 330*11076SCathy.Zhou@Sun.COM } vrrp_cmd_list_arg_t; 331*11076SCathy.Zhou@Sun.COM 332*11076SCathy.Zhou@Sun.COM static vrrp_err_t 333*11076SCathy.Zhou@Sun.COM vrrp_list_func(int sock, void *arg) 334*11076SCathy.Zhou@Sun.COM { 335*11076SCathy.Zhou@Sun.COM vrrp_cmd_list_arg_t *list_arg = arg; 336*11076SCathy.Zhou@Sun.COM uint32_t in_cnt = *(list_arg->vfl_cnt); 337*11076SCathy.Zhou@Sun.COM uint32_t out_cnt; 338*11076SCathy.Zhou@Sun.COM vrrp_ret_list_t ret; 339*11076SCathy.Zhou@Sun.COM size_t len, cur_size = 0; 340*11076SCathy.Zhou@Sun.COM 341*11076SCathy.Zhou@Sun.COM /* 342*11076SCathy.Zhou@Sun.COM * Get the rest of vrrp_ret_list_t besides the error code. 343*11076SCathy.Zhou@Sun.COM */ 344*11076SCathy.Zhou@Sun.COM cur_size = sizeof (vrrp_err_t); 345*11076SCathy.Zhou@Sun.COM while (cur_size < sizeof (vrrp_ret_list_t)) { 346*11076SCathy.Zhou@Sun.COM len = read(sock, (char *)&ret + cur_size, 347*11076SCathy.Zhou@Sun.COM sizeof (vrrp_ret_list_t) - cur_size); 348*11076SCathy.Zhou@Sun.COM 349*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 350*11076SCathy.Zhou@Sun.COM continue; 351*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 352*11076SCathy.Zhou@Sun.COM cur_size += len; 353*11076SCathy.Zhou@Sun.COM continue; 354*11076SCathy.Zhou@Sun.COM } 355*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 356*11076SCathy.Zhou@Sun.COM } 357*11076SCathy.Zhou@Sun.COM 358*11076SCathy.Zhou@Sun.COM *(list_arg->vfl_cnt) = out_cnt = ret.vrl_cnt; 359*11076SCathy.Zhou@Sun.COM out_cnt = (in_cnt <= out_cnt) ? in_cnt : out_cnt; 360*11076SCathy.Zhou@Sun.COM cur_size = 0; 361*11076SCathy.Zhou@Sun.COM 362*11076SCathy.Zhou@Sun.COM while (cur_size < VRRP_NAME_MAX * out_cnt) { 363*11076SCathy.Zhou@Sun.COM len = read(sock, (char *)list_arg->vfl_names + cur_size, 364*11076SCathy.Zhou@Sun.COM VRRP_NAME_MAX * out_cnt - cur_size); 365*11076SCathy.Zhou@Sun.COM 366*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 367*11076SCathy.Zhou@Sun.COM continue; 368*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 369*11076SCathy.Zhou@Sun.COM cur_size += len; 370*11076SCathy.Zhou@Sun.COM continue; 371*11076SCathy.Zhou@Sun.COM } 372*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 373*11076SCathy.Zhou@Sun.COM } 374*11076SCathy.Zhou@Sun.COM return (VRRP_SUCCESS); 375*11076SCathy.Zhou@Sun.COM } 376*11076SCathy.Zhou@Sun.COM 377*11076SCathy.Zhou@Sun.COM /* 378*11076SCathy.Zhou@Sun.COM * Looks up the vrrp instances that matches the given variable. 379*11076SCathy.Zhou@Sun.COM * 380*11076SCathy.Zhou@Sun.COM * If the given cnt is 0, names should be set to NULL. In this case, only 381*11076SCathy.Zhou@Sun.COM * the count of the matched instances is returned. 382*11076SCathy.Zhou@Sun.COM * 383*11076SCathy.Zhou@Sun.COM * If the given cnt is non-zero, caller must allocate "names" whose size 384*11076SCathy.Zhou@Sun.COM * is (cnt * VRRP_NAME_MAX). 385*11076SCathy.Zhou@Sun.COM * 386*11076SCathy.Zhou@Sun.COM * Return value: the current count of matched instances, and names will be 387*11076SCathy.Zhou@Sun.COM * points to the list of the current vrrp instances names. Note that 388*11076SCathy.Zhou@Sun.COM * only MIN(in_cnt, out_cnt) number of names will be returned. 389*11076SCathy.Zhou@Sun.COM */ 390*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 391*11076SCathy.Zhou@Sun.COM vrrp_err_t 392*11076SCathy.Zhou@Sun.COM vrrp_list(vrrp_handle_t vh, vrid_t vrid, const char *intf, int af, 393*11076SCathy.Zhou@Sun.COM uint32_t *cnt, char *names) 394*11076SCathy.Zhou@Sun.COM { 395*11076SCathy.Zhou@Sun.COM vrrp_cmd_list_t cmd; 396*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 397*11076SCathy.Zhou@Sun.COM vrrp_cmd_list_arg_t list_arg; 398*11076SCathy.Zhou@Sun.COM 399*11076SCathy.Zhou@Sun.COM if ((cnt == NULL) || (*cnt != 0 && names == NULL)) 400*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 401*11076SCathy.Zhou@Sun.COM 402*11076SCathy.Zhou@Sun.COM cmd.vcl_ifname[0] = '\0'; 403*11076SCathy.Zhou@Sun.COM if (intf != NULL && (strlcpy(cmd.vcl_ifname, intf, 404*11076SCathy.Zhou@Sun.COM LIFNAMSIZ) >= LIFNAMSIZ)) { 405*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 406*11076SCathy.Zhou@Sun.COM } 407*11076SCathy.Zhou@Sun.COM 408*11076SCathy.Zhou@Sun.COM cmd.vcl_cmd = VRRP_CMD_LIST; 409*11076SCathy.Zhou@Sun.COM cmd.vcl_vrid = vrid; 410*11076SCathy.Zhou@Sun.COM cmd.vcl_af = af; 411*11076SCathy.Zhou@Sun.COM 412*11076SCathy.Zhou@Sun.COM list_arg.vfl_cnt = cnt; 413*11076SCathy.Zhou@Sun.COM list_arg.vfl_names = names; 414*11076SCathy.Zhou@Sun.COM 415*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_list_func, &list_arg); 416*11076SCathy.Zhou@Sun.COM return (err); 417*11076SCathy.Zhou@Sun.COM } 418*11076SCathy.Zhou@Sun.COM 419*11076SCathy.Zhou@Sun.COM static vrrp_err_t 420*11076SCathy.Zhou@Sun.COM vrrp_query_func(int sock, void *arg) 421*11076SCathy.Zhou@Sun.COM { 422*11076SCathy.Zhou@Sun.COM vrrp_queryinfo_t *qinfo = arg; 423*11076SCathy.Zhou@Sun.COM size_t len, cur_size = 0, total; 424*11076SCathy.Zhou@Sun.COM uint32_t in_cnt = qinfo->show_va.va_vipcnt; 425*11076SCathy.Zhou@Sun.COM uint32_t out_cnt; 426*11076SCathy.Zhou@Sun.COM 427*11076SCathy.Zhou@Sun.COM /* 428*11076SCathy.Zhou@Sun.COM * Expect the ack, first get the vrrp_ret_t. 429*11076SCathy.Zhou@Sun.COM */ 430*11076SCathy.Zhou@Sun.COM total = sizeof (vrrp_queryinfo_t); 431*11076SCathy.Zhou@Sun.COM while (cur_size < total) { 432*11076SCathy.Zhou@Sun.COM len = read(sock, (char *)qinfo + cur_size, total - cur_size); 433*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 434*11076SCathy.Zhou@Sun.COM continue; 435*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 436*11076SCathy.Zhou@Sun.COM cur_size += len; 437*11076SCathy.Zhou@Sun.COM continue; 438*11076SCathy.Zhou@Sun.COM } 439*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 440*11076SCathy.Zhou@Sun.COM } 441*11076SCathy.Zhou@Sun.COM 442*11076SCathy.Zhou@Sun.COM out_cnt = qinfo->show_va.va_vipcnt; 443*11076SCathy.Zhou@Sun.COM 444*11076SCathy.Zhou@Sun.COM /* 445*11076SCathy.Zhou@Sun.COM * Even if there is no IP virtual IP address, there is always 446*11076SCathy.Zhou@Sun.COM * space in the vrrp_queryinfo_t structure for one virtual 447*11076SCathy.Zhou@Sun.COM * IP address. 448*11076SCathy.Zhou@Sun.COM */ 449*11076SCathy.Zhou@Sun.COM out_cnt = (out_cnt == 0) ? 1 : out_cnt; 450*11076SCathy.Zhou@Sun.COM out_cnt = (in_cnt < out_cnt ? in_cnt : out_cnt) - 1; 451*11076SCathy.Zhou@Sun.COM total += out_cnt * sizeof (vrrp_addr_t); 452*11076SCathy.Zhou@Sun.COM 453*11076SCathy.Zhou@Sun.COM while (cur_size < total) { 454*11076SCathy.Zhou@Sun.COM len = read(sock, (char *)qinfo + cur_size, total - cur_size); 455*11076SCathy.Zhou@Sun.COM if (len == (size_t)-1 && errno == EAGAIN) { 456*11076SCathy.Zhou@Sun.COM continue; 457*11076SCathy.Zhou@Sun.COM } else if (len > 0) { 458*11076SCathy.Zhou@Sun.COM cur_size += len; 459*11076SCathy.Zhou@Sun.COM continue; 460*11076SCathy.Zhou@Sun.COM } 461*11076SCathy.Zhou@Sun.COM return (VRRP_ECMD); 462*11076SCathy.Zhou@Sun.COM } 463*11076SCathy.Zhou@Sun.COM return (VRRP_SUCCESS); 464*11076SCathy.Zhou@Sun.COM } 465*11076SCathy.Zhou@Sun.COM 466*11076SCathy.Zhou@Sun.COM /* 467*11076SCathy.Zhou@Sun.COM * *vqp is allocated inside this function and must be freed by the caller. 468*11076SCathy.Zhou@Sun.COM */ 469*11076SCathy.Zhou@Sun.COM /*ARGSUSED*/ 470*11076SCathy.Zhou@Sun.COM vrrp_err_t 471*11076SCathy.Zhou@Sun.COM vrrp_query(vrrp_handle_t vh, const char *vn, vrrp_queryinfo_t **vqp) 472*11076SCathy.Zhou@Sun.COM { 473*11076SCathy.Zhou@Sun.COM vrrp_cmd_query_t cmd; 474*11076SCathy.Zhou@Sun.COM vrrp_queryinfo_t *qinfo; 475*11076SCathy.Zhou@Sun.COM vrrp_err_t err; 476*11076SCathy.Zhou@Sun.COM size_t size; 477*11076SCathy.Zhou@Sun.COM uint32_t vipcnt = 1; 478*11076SCathy.Zhou@Sun.COM 479*11076SCathy.Zhou@Sun.COM if (strlcpy(cmd.vcq_name, vn, VRRP_NAME_MAX) >= VRRP_NAME_MAX) 480*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 481*11076SCathy.Zhou@Sun.COM 482*11076SCathy.Zhou@Sun.COM cmd.vcq_cmd = VRRP_CMD_QUERY; 483*11076SCathy.Zhou@Sun.COM 484*11076SCathy.Zhou@Sun.COM /* 485*11076SCathy.Zhou@Sun.COM * Allocate enough room for virtual IPs. 486*11076SCathy.Zhou@Sun.COM */ 487*11076SCathy.Zhou@Sun.COM again: 488*11076SCathy.Zhou@Sun.COM size = sizeof (vrrp_queryinfo_t); 489*11076SCathy.Zhou@Sun.COM size += (vipcnt == 0) ? 0 : (vipcnt - 1) * sizeof (vrrp_addr_t); 490*11076SCathy.Zhou@Sun.COM if ((qinfo = malloc(size)) == NULL) { 491*11076SCathy.Zhou@Sun.COM err = VRRP_ENOMEM; 492*11076SCathy.Zhou@Sun.COM goto done; 493*11076SCathy.Zhou@Sun.COM } 494*11076SCathy.Zhou@Sun.COM 495*11076SCathy.Zhou@Sun.COM qinfo->show_va.va_vipcnt = vipcnt; 496*11076SCathy.Zhou@Sun.COM err = vrrp_cmd_request(&cmd, sizeof (cmd), vrrp_query_func, qinfo); 497*11076SCathy.Zhou@Sun.COM if (err != VRRP_SUCCESS) { 498*11076SCathy.Zhou@Sun.COM free(qinfo); 499*11076SCathy.Zhou@Sun.COM goto done; 500*11076SCathy.Zhou@Sun.COM } 501*11076SCathy.Zhou@Sun.COM 502*11076SCathy.Zhou@Sun.COM /* 503*11076SCathy.Zhou@Sun.COM * If the returned number of virtual IPs is greater than we expected, 504*11076SCathy.Zhou@Sun.COM * allocate more room and try again. 505*11076SCathy.Zhou@Sun.COM */ 506*11076SCathy.Zhou@Sun.COM if (qinfo->show_va.va_vipcnt > vipcnt) { 507*11076SCathy.Zhou@Sun.COM vipcnt = qinfo->show_va.va_vipcnt; 508*11076SCathy.Zhou@Sun.COM free(qinfo); 509*11076SCathy.Zhou@Sun.COM goto again; 510*11076SCathy.Zhou@Sun.COM } 511*11076SCathy.Zhou@Sun.COM 512*11076SCathy.Zhou@Sun.COM *vqp = qinfo; 513*11076SCathy.Zhou@Sun.COM 514*11076SCathy.Zhou@Sun.COM done: 515*11076SCathy.Zhou@Sun.COM return (err); 516*11076SCathy.Zhou@Sun.COM } 517*11076SCathy.Zhou@Sun.COM 518*11076SCathy.Zhou@Sun.COM struct lookup_vnic_arg { 519*11076SCathy.Zhou@Sun.COM vrid_t lva_vrid; 520*11076SCathy.Zhou@Sun.COM datalink_id_t lva_linkid; 521*11076SCathy.Zhou@Sun.COM int lva_af; 522*11076SCathy.Zhou@Sun.COM uint16_t lva_vid; 523*11076SCathy.Zhou@Sun.COM vrrp_handle_t lva_vh; 524*11076SCathy.Zhou@Sun.COM char lva_vnic[MAXLINKNAMELEN]; 525*11076SCathy.Zhou@Sun.COM }; 526*11076SCathy.Zhou@Sun.COM 527*11076SCathy.Zhou@Sun.COM /* 528*11076SCathy.Zhou@Sun.COM * Is this a special VNIC interface created for VRRP? If so, return 529*11076SCathy.Zhou@Sun.COM * the linkid the VNIC was created on, the VRRP ID and address family. 530*11076SCathy.Zhou@Sun.COM */ 531*11076SCathy.Zhou@Sun.COM boolean_t 532*11076SCathy.Zhou@Sun.COM vrrp_is_vrrp_vnic(vrrp_handle_t vh, datalink_id_t vnicid, 533*11076SCathy.Zhou@Sun.COM datalink_id_t *linkidp, uint16_t *vidp, vrid_t *vridp, int *afp) 534*11076SCathy.Zhou@Sun.COM { 535*11076SCathy.Zhou@Sun.COM dladm_vnic_attr_t vattr; 536*11076SCathy.Zhou@Sun.COM 537*11076SCathy.Zhou@Sun.COM if (dladm_vnic_info(vh->vh_dh, vnicid, &vattr, DLADM_OPT_ACTIVE) != 538*11076SCathy.Zhou@Sun.COM DLADM_STATUS_OK) { 539*11076SCathy.Zhou@Sun.COM return (B_FALSE); 540*11076SCathy.Zhou@Sun.COM } 541*11076SCathy.Zhou@Sun.COM 542*11076SCathy.Zhou@Sun.COM *vridp = vattr.va_vrid; 543*11076SCathy.Zhou@Sun.COM *vidp = vattr.va_vid; 544*11076SCathy.Zhou@Sun.COM *afp = vattr.va_af; 545*11076SCathy.Zhou@Sun.COM *linkidp = vattr.va_link_id; 546*11076SCathy.Zhou@Sun.COM return (vattr.va_vrid != VRRP_VRID_NONE); 547*11076SCathy.Zhou@Sun.COM } 548*11076SCathy.Zhou@Sun.COM 549*11076SCathy.Zhou@Sun.COM static int 550*11076SCathy.Zhou@Sun.COM lookup_vnic(dladm_handle_t dh, datalink_id_t vnicid, void *arg) 551*11076SCathy.Zhou@Sun.COM { 552*11076SCathy.Zhou@Sun.COM vrid_t vrid; 553*11076SCathy.Zhou@Sun.COM uint16_t vid; 554*11076SCathy.Zhou@Sun.COM datalink_id_t linkid; 555*11076SCathy.Zhou@Sun.COM int af; 556*11076SCathy.Zhou@Sun.COM struct lookup_vnic_arg *lva = arg; 557*11076SCathy.Zhou@Sun.COM 558*11076SCathy.Zhou@Sun.COM if (vrrp_is_vrrp_vnic(lva->lva_vh, vnicid, &linkid, &vid, &vrid, 559*11076SCathy.Zhou@Sun.COM &af) && lva->lva_vrid == vrid && lva->lva_linkid == linkid && 560*11076SCathy.Zhou@Sun.COM lva->lva_vid == vid && lva->lva_af == af) { 561*11076SCathy.Zhou@Sun.COM if (dladm_datalink_id2info(dh, vnicid, NULL, NULL, NULL, 562*11076SCathy.Zhou@Sun.COM lva->lva_vnic, sizeof (lva->lva_vnic)) == DLADM_STATUS_OK) { 563*11076SCathy.Zhou@Sun.COM return (DLADM_WALK_TERMINATE); 564*11076SCathy.Zhou@Sun.COM } 565*11076SCathy.Zhou@Sun.COM } 566*11076SCathy.Zhou@Sun.COM return (DLADM_WALK_CONTINUE); 567*11076SCathy.Zhou@Sun.COM } 568*11076SCathy.Zhou@Sun.COM 569*11076SCathy.Zhou@Sun.COM /* 570*11076SCathy.Zhou@Sun.COM * Given the primary link name, find the assoicated VRRP vnic name, if 571*11076SCathy.Zhou@Sun.COM * the vnic does not exist yet, return the linkid, vid of the primary link. 572*11076SCathy.Zhou@Sun.COM */ 573*11076SCathy.Zhou@Sun.COM vrrp_err_t 574*11076SCathy.Zhou@Sun.COM vrrp_get_vnicname(vrrp_handle_t vh, vrid_t vrid, int af, char *link, 575*11076SCathy.Zhou@Sun.COM datalink_id_t *linkidp, uint16_t *vidp, char *vnic, size_t len) 576*11076SCathy.Zhou@Sun.COM { 577*11076SCathy.Zhou@Sun.COM datalink_id_t linkid; 578*11076SCathy.Zhou@Sun.COM uint32_t flags; 579*11076SCathy.Zhou@Sun.COM uint16_t vid = VLAN_ID_NONE; 580*11076SCathy.Zhou@Sun.COM datalink_class_t class; 581*11076SCathy.Zhou@Sun.COM dladm_vlan_attr_t vlan_attr; 582*11076SCathy.Zhou@Sun.COM struct lookup_vnic_arg lva; 583*11076SCathy.Zhou@Sun.COM uint32_t media; 584*11076SCathy.Zhou@Sun.COM 585*11076SCathy.Zhou@Sun.COM if ((strlen(link) == 0) || dladm_name2info(vh->vh_dh, 586*11076SCathy.Zhou@Sun.COM link, &linkid, &flags, &class, &media) != 587*11076SCathy.Zhou@Sun.COM DLADM_STATUS_OK || !(flags & DLADM_OPT_ACTIVE)) { 588*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 589*11076SCathy.Zhou@Sun.COM } 590*11076SCathy.Zhou@Sun.COM 591*11076SCathy.Zhou@Sun.COM if (class == DATALINK_CLASS_VLAN) { 592*11076SCathy.Zhou@Sun.COM if (dladm_vlan_info(vh->vh_dh, linkid, &vlan_attr, 593*11076SCathy.Zhou@Sun.COM DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { 594*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 595*11076SCathy.Zhou@Sun.COM } 596*11076SCathy.Zhou@Sun.COM linkid = vlan_attr.dv_linkid; 597*11076SCathy.Zhou@Sun.COM vid = vlan_attr.dv_vid; 598*11076SCathy.Zhou@Sun.COM if ((dladm_datalink_id2info(vh->vh_dh, linkid, NULL, 599*11076SCathy.Zhou@Sun.COM &class, &media, NULL, 0)) != DLADM_STATUS_OK) { 600*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 601*11076SCathy.Zhou@Sun.COM } 602*11076SCathy.Zhou@Sun.COM } 603*11076SCathy.Zhou@Sun.COM 604*11076SCathy.Zhou@Sun.COM /* 605*11076SCathy.Zhou@Sun.COM * For now, Only VRRP over aggr and physical ethernet links is supported 606*11076SCathy.Zhou@Sun.COM */ 607*11076SCathy.Zhou@Sun.COM if ((class != DATALINK_CLASS_PHYS && class != DATALINK_CLASS_AGGR) || 608*11076SCathy.Zhou@Sun.COM media != DL_ETHER) { 609*11076SCathy.Zhou@Sun.COM return (VRRP_EINVAL); 610*11076SCathy.Zhou@Sun.COM } 611*11076SCathy.Zhou@Sun.COM 612*11076SCathy.Zhou@Sun.COM if (linkidp != NULL) 613*11076SCathy.Zhou@Sun.COM *linkidp = linkid; 614*11076SCathy.Zhou@Sun.COM if (vidp != NULL) 615*11076SCathy.Zhou@Sun.COM *vidp = vid; 616*11076SCathy.Zhou@Sun.COM 617*11076SCathy.Zhou@Sun.COM /* 618*11076SCathy.Zhou@Sun.COM * Find the assoicated vnic with the given vrid/vid/af/linkid 619*11076SCathy.Zhou@Sun.COM */ 620*11076SCathy.Zhou@Sun.COM lva.lva_vrid = vrid; 621*11076SCathy.Zhou@Sun.COM lva.lva_vid = vid; 622*11076SCathy.Zhou@Sun.COM lva.lva_af = af; 623*11076SCathy.Zhou@Sun.COM lva.lva_linkid = linkid; 624*11076SCathy.Zhou@Sun.COM lva.lva_vh = vh; 625*11076SCathy.Zhou@Sun.COM lva.lva_vnic[0] = '\0'; 626*11076SCathy.Zhou@Sun.COM 627*11076SCathy.Zhou@Sun.COM (void) dladm_walk_datalink_id(lookup_vnic, vh->vh_dh, &lva, 628*11076SCathy.Zhou@Sun.COM DATALINK_CLASS_VNIC, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); 629*11076SCathy.Zhou@Sun.COM if (strlen(lva.lva_vnic) != 0) { 630*11076SCathy.Zhou@Sun.COM (void) strlcpy(vnic, lva.lva_vnic, len); 631*11076SCathy.Zhou@Sun.COM return (VRRP_SUCCESS); 632*11076SCathy.Zhou@Sun.COM } 633*11076SCathy.Zhou@Sun.COM 634*11076SCathy.Zhou@Sun.COM return (VRRP_ENOVNIC); 635*11076SCathy.Zhou@Sun.COM } 636