10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*2311Sseb * Common Development and Distribution License (the "License"). 6*2311Sseb * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*2311Sseb * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate #include <stdio.h> 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <string.h> 310Sstevel@tonic-gate #include <fcntl.h> 320Sstevel@tonic-gate #include <unistd.h> 330Sstevel@tonic-gate #include <stropts.h> 340Sstevel@tonic-gate #include <stdlib.h> 350Sstevel@tonic-gate #include <errno.h> 360Sstevel@tonic-gate #include <libdevinfo.h> 370Sstevel@tonic-gate #include <libdlpi.h> 380Sstevel@tonic-gate #include <libdladm.h> 390Sstevel@tonic-gate #include <sys/dld.h> 400Sstevel@tonic-gate #include <net/if.h> 410Sstevel@tonic-gate 42733Skrgopi typedef struct dladm_dev { 43733Skrgopi char dd_name[IFNAMSIZ]; 44733Skrgopi struct dladm_dev *dd_next; 45733Skrgopi } dladm_dev_t; 46733Skrgopi 47733Skrgopi typedef struct dladm_walk { 48733Skrgopi dladm_dev_t *dw_dev_list; 49733Skrgopi } dladm_walk_t; 50733Skrgopi 510Sstevel@tonic-gate /* 520Sstevel@tonic-gate * Issue an ioctl to the specified file descriptor attached to the 530Sstevel@tonic-gate * DLD control driver interface. 540Sstevel@tonic-gate */ 550Sstevel@tonic-gate static int 56269Sericheng i_dladm_ioctl(int fd, int ic_cmd, void *ic_dp, int ic_len) 570Sstevel@tonic-gate { 580Sstevel@tonic-gate struct strioctl iocb; 590Sstevel@tonic-gate 600Sstevel@tonic-gate iocb.ic_cmd = ic_cmd; 610Sstevel@tonic-gate iocb.ic_timout = 0; 620Sstevel@tonic-gate iocb.ic_len = ic_len; 63269Sericheng iocb.ic_dp = (char *)ic_dp; 640Sstevel@tonic-gate 650Sstevel@tonic-gate return (ioctl(fd, I_STR, &iocb)); 660Sstevel@tonic-gate } 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * Return the attributes of the specified datalink from the DLD driver. 700Sstevel@tonic-gate */ 710Sstevel@tonic-gate static int 720Sstevel@tonic-gate i_dladm_info(int fd, const char *name, dladm_attr_t *dap) 730Sstevel@tonic-gate { 740Sstevel@tonic-gate dld_ioc_attr_t dia; 750Sstevel@tonic-gate 760Sstevel@tonic-gate if (strlen(name) >= IFNAMSIZ) { 770Sstevel@tonic-gate errno = EINVAL; 780Sstevel@tonic-gate return (-1); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate 810Sstevel@tonic-gate (void) strlcpy(dia.dia_name, name, IFNAMSIZ); 820Sstevel@tonic-gate 83269Sericheng if (i_dladm_ioctl(fd, DLDIOCATTR, &dia, sizeof (dia)) < 0) 840Sstevel@tonic-gate return (-1); 850Sstevel@tonic-gate 860Sstevel@tonic-gate (void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN); 87269Sericheng dap->da_max_sdu = dia.dia_max_sdu; 880Sstevel@tonic-gate dap->da_vid = dia.dia_vid; 890Sstevel@tonic-gate 900Sstevel@tonic-gate return (0); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * Adds a datalink to the array corresponding to arg. 950Sstevel@tonic-gate */ 960Sstevel@tonic-gate static void 970Sstevel@tonic-gate i_dladm_nt_net_add(void *arg, char *name) 980Sstevel@tonic-gate { 99733Skrgopi dladm_walk_t *dwp = arg; 100733Skrgopi dladm_dev_t *ddp = dwp->dw_dev_list; 101733Skrgopi dladm_dev_t **lastp = &dwp->dw_dev_list; 1020Sstevel@tonic-gate 103733Skrgopi while (ddp) { 104733Skrgopi /* 105733Skrgopi * Skip duplicates. 106733Skrgopi */ 107733Skrgopi if (strcmp(ddp->dd_name, name) == 0) 1080Sstevel@tonic-gate return; 109733Skrgopi 110733Skrgopi lastp = &ddp->dd_next; 111733Skrgopi ddp = ddp->dd_next; 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 114733Skrgopi if ((ddp = malloc(sizeof (*ddp))) == NULL) 115733Skrgopi return; 116733Skrgopi 117733Skrgopi (void) strlcpy(ddp->dd_name, name, IFNAMSIZ); 118733Skrgopi ddp->dd_next = NULL; 119733Skrgopi *lastp = ddp; 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate /* 1230Sstevel@tonic-gate * Walker callback invoked for each DDI_NT_NET node. 1240Sstevel@tonic-gate */ 1250Sstevel@tonic-gate static int 1260Sstevel@tonic-gate i_dladm_nt_net_walk(di_node_t node, di_minor_t minor, void *arg) 1270Sstevel@tonic-gate { 1280Sstevel@tonic-gate dl_info_ack_t dlia; 1290Sstevel@tonic-gate char name[IFNAMSIZ]; 1300Sstevel@tonic-gate int fd; 1310Sstevel@tonic-gate char *provider; 1320Sstevel@tonic-gate uint_t ppa; 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate provider = di_minor_name(minor); 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate if ((fd = dlpi_open(provider)) < 0) 1370Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate if (dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) < 0) { 1400Sstevel@tonic-gate (void) dlpi_close(fd); 1410Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1420Sstevel@tonic-gate } 1430Sstevel@tonic-gate 1440Sstevel@tonic-gate if (dlia.dl_provider_style == DL_STYLE1) { 1450Sstevel@tonic-gate i_dladm_nt_net_add(arg, provider); 1460Sstevel@tonic-gate (void) dlpi_close(fd); 1470Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1480Sstevel@tonic-gate } 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate ppa = di_instance(node); 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate if (dlpi_attach(fd, -1, ppa) < 0) { 1530Sstevel@tonic-gate (void) dlpi_close(fd); 1540Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1550Sstevel@tonic-gate } 1560Sstevel@tonic-gate (void) snprintf(name, IFNAMSIZ - 1, "%s%d", provider, ppa); 1570Sstevel@tonic-gate i_dladm_nt_net_add(arg, name); 1580Sstevel@tonic-gate (void) dlpi_close(fd); 1590Sstevel@tonic-gate return (DI_WALK_CONTINUE); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* 1630Sstevel@tonic-gate * Invoke the specified callback function for each active DDI_NT_NET 1640Sstevel@tonic-gate * node. 1650Sstevel@tonic-gate */ 1660Sstevel@tonic-gate int 1670Sstevel@tonic-gate dladm_walk(void (*fn)(void *, const char *), void *arg) 1680Sstevel@tonic-gate { 1690Sstevel@tonic-gate di_node_t root; 170733Skrgopi dladm_walk_t dw; 171733Skrgopi dladm_dev_t *ddp, *last_ddp; 1720Sstevel@tonic-gate 1730Sstevel@tonic-gate if ((root = di_init("/", DINFOCACHE)) == DI_NODE_NIL) { 1740Sstevel@tonic-gate errno = EFAULT; 1750Sstevel@tonic-gate return (-1); 1760Sstevel@tonic-gate } 177733Skrgopi dw.dw_dev_list = NULL; 1780Sstevel@tonic-gate 179733Skrgopi (void) di_walk_minor(root, DDI_NT_NET, DI_CHECK_ALIAS, &dw, 180733Skrgopi i_dladm_nt_net_walk); 1810Sstevel@tonic-gate 182733Skrgopi di_fini(root); 1830Sstevel@tonic-gate 184733Skrgopi ddp = dw.dw_dev_list; 185733Skrgopi while (ddp) { 186733Skrgopi fn(arg, ddp->dd_name); 187737Skrgopi (void) dladm_walk_vlan(fn, arg, ddp->dd_name); 188733Skrgopi last_ddp = ddp; 189733Skrgopi ddp = ddp->dd_next; 190733Skrgopi free(last_ddp); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 193733Skrgopi return (0); 1940Sstevel@tonic-gate } 1950Sstevel@tonic-gate 1960Sstevel@tonic-gate /* 197269Sericheng * Invoke the specified callback function for each vlan managed by dld 1980Sstevel@tonic-gate */ 1990Sstevel@tonic-gate int 200733Skrgopi dladm_walk_vlan(void (*fn)(void *, const char *), void *arg, const char *name) 2010Sstevel@tonic-gate { 202733Skrgopi int fd, bufsize, i; 203733Skrgopi int nvlan = 4094; 204269Sericheng dld_ioc_vlan_t *iocp = NULL; 205269Sericheng dld_vlan_info_t *dvip; 206269Sericheng 207269Sericheng if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 208269Sericheng return (-1); 209269Sericheng 210733Skrgopi bufsize = sizeof (dld_ioc_vlan_t) + nvlan * sizeof (dld_vlan_info_t); 2110Sstevel@tonic-gate 212733Skrgopi if ((iocp = (dld_ioc_vlan_t *)calloc(1, bufsize)) == NULL) 213733Skrgopi return (-1); 214269Sericheng 215*2311Sseb (void) strlcpy((char *)iocp->div_name, name, IFNAMSIZ); 216733Skrgopi if (i_dladm_ioctl(fd, DLDIOCVLAN, iocp, bufsize) == 0) { 217733Skrgopi dvip = (dld_vlan_info_t *)(iocp + 1); 218733Skrgopi for (i = 0; i < iocp->div_count; i++) 219269Sericheng (*fn)(arg, dvip[i].dvi_name); 2200Sstevel@tonic-gate } 221733Skrgopi /* 222733Skrgopi * Note: Callers of dladm_walk_vlan() ignore the return 223733Skrgopi * value of this routine. So ignoring ioctl failure case 224733Skrgopi * and just returning 0. 225733Skrgopi */ 226269Sericheng free(iocp); 227269Sericheng (void) close(fd); 2280Sstevel@tonic-gate return (0); 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate /* 2330Sstevel@tonic-gate * Returns the current attributes of the specified datalink. 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate int 2360Sstevel@tonic-gate dladm_info(const char *name, dladm_attr_t *dap) 2370Sstevel@tonic-gate { 2380Sstevel@tonic-gate int fd; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) 2410Sstevel@tonic-gate return (-1); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate if (i_dladm_info(fd, name, dap) < 0) 2440Sstevel@tonic-gate goto failed; 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate (void) close(fd); 2470Sstevel@tonic-gate return (0); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate failed: 2500Sstevel@tonic-gate (void) close(fd); 2510Sstevel@tonic-gate return (-1); 2520Sstevel@tonic-gate } 253