1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26/* 27 * Flows ioctls implementation. 28 */ 29 30#include <sys/cred.h> 31#include <sys/dld.h> 32#include <sys/mac_provider.h> 33#include <sys/mac_client.h> 34#include <sys/mac_client_priv.h> 35 36/* 37 * Implements flow add, remove, modify ioctls. 38 */ 39int 40dld_add_flow(datalink_id_t linkid, char *flow_name, flow_desc_t *flow_desc, 41 mac_resource_props_t *mrp) 42{ 43 return (mac_link_flow_add(linkid, flow_name, flow_desc, mrp)); 44} 45 46int 47dld_remove_flow(char *flow_name) 48{ 49 return (mac_link_flow_remove(flow_name)); 50} 51 52int 53dld_modify_flow(char *flow_name, mac_resource_props_t *mrp) 54{ 55 return (mac_link_flow_modify(flow_name, mrp)); 56} 57 58 59/* 60 * Callback function and structure used by dld_walk_flow(). 61 */ 62typedef struct flowinfo_state_s { 63 int fi_bufsize; 64 int fi_nflows; 65 uchar_t *fi_fl; 66} flowinfo_state_t; 67 68static int 69dld_walk_flow_cb(mac_flowinfo_t *finfo, void *arg) 70{ 71 flowinfo_state_t *statep = arg; 72 dld_flowinfo_t *fi; 73 74 if (statep->fi_bufsize < sizeof (dld_flowinfo_t)) 75 return (ENOSPC); 76 77 fi = kmem_zalloc(sizeof (*fi), KM_SLEEP); 78 (void) strlcpy(fi->fi_flowname, finfo->fi_flow_name, 79 sizeof (fi->fi_flowname)); 80 fi->fi_linkid = finfo->fi_link_id; 81 fi->fi_flow_desc = finfo->fi_flow_desc; 82 fi->fi_resource_props = finfo->fi_resource_props; 83 84 if (copyout(fi, statep->fi_fl, sizeof (*fi)) != 0) { 85 kmem_free(fi, sizeof (*fi)); 86 return (EFAULT); 87 } 88 kmem_free(fi, sizeof (*fi)); 89 statep->fi_nflows++; 90 statep->fi_bufsize -= sizeof (dld_flowinfo_t); 91 statep->fi_fl += sizeof (dld_flowinfo_t); 92 return (0); 93} 94 95/* 96 * Implements flow walk ioctl. 97 * Retrieves a specific flow or a list of flows from the specified link. 98 * ENOSPC is returned a bigger buffer is needed. 99 */ 100int 101dld_walk_flow(dld_ioc_walkflow_t *wf, intptr_t uaddr, cred_t *credp) 102{ 103 flowinfo_state_t state; 104 mac_flowinfo_t *finfo; 105 int err = 0; 106 107 /* For now, one can only view flows from the global zone. */ 108 if (crgetzoneid(credp) != GLOBAL_ZONEID) 109 return (EPERM); 110 111 finfo = kmem_zalloc(sizeof (*finfo), KM_SLEEP); 112 state.fi_bufsize = wf->wf_len; 113 state.fi_fl = (uchar_t *)uaddr + sizeof (*wf); 114 state.fi_nflows = 0; 115 116 if (wf->wf_name[0] == '\0') { 117 err = mac_link_flow_walk(wf->wf_linkid, dld_walk_flow_cb, 118 &state); 119 } else { 120 err = mac_link_flow_info(wf->wf_name, finfo); 121 if (err != 0) { 122 kmem_free(finfo, sizeof (*finfo)); 123 return (err); 124 } 125 err = dld_walk_flow_cb(finfo, &state); 126 } 127 kmem_free(finfo, sizeof (*finfo)); 128 wf->wf_nflows = state.fi_nflows; 129 return (err); 130} 131