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 */ 39 int 40 dld_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 46 int 47 dld_remove_flow(char *flow_name) 48 { 49 return (mac_link_flow_remove(flow_name)); 50 } 51 52 int 53 dld_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 */ 62 typedef struct flowinfo_state_s { 63 int fi_bufsize; 64 int fi_nflows; 65 uchar_t *fi_fl; 66 } flowinfo_state_t; 67 68 static int 69 dld_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 */ 100 int 101 dld_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