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 2009 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 (void) strlcpy(fi.fi_flowname, finfo->fi_flow_name, 78 sizeof (fi.fi_flowname)); 79 fi.fi_linkid = finfo->fi_link_id; 80 fi.fi_flow_desc = finfo->fi_flow_desc; 81 fi.fi_resource_props = finfo->fi_resource_props; 82 83 if (copyout(&fi, statep->fi_fl, sizeof (fi)) != 0) { 84 return (EFAULT); 85 } 86 statep->fi_nflows++; 87 statep->fi_bufsize -= sizeof (dld_flowinfo_t); 88 statep->fi_fl += sizeof (dld_flowinfo_t); 89 return (0); 90 } 91 92 /* 93 * Implements flow walk ioctl. 94 * Retrieves a specific flow or a list of flows from the specified link. 95 * ENOSPC is returned a bigger buffer is needed. 96 */ 97 int 98 dld_walk_flow(dld_ioc_walkflow_t *wf, intptr_t uaddr, cred_t *credp) 99 { 100 flowinfo_state_t state; 101 mac_flowinfo_t finfo; 102 int err = 0; 103 104 /* For now, one can only view flows from the global zone. */ 105 if (crgetzoneid(credp) != GLOBAL_ZONEID) 106 return (EPERM); 107 108 state.fi_bufsize = wf->wf_len; 109 state.fi_fl = (uchar_t *)uaddr + sizeof (*wf); 110 state.fi_nflows = 0; 111 112 if (wf->wf_name[0] == '\0') { 113 err = mac_link_flow_walk(wf->wf_linkid, dld_walk_flow_cb, 114 &state); 115 } else { 116 err = mac_link_flow_info(wf->wf_name, &finfo); 117 if (err != 0) 118 return (err); 119 120 err = dld_walk_flow_cb(&finfo, &state); 121 } 122 wf->wf_nflows = state.fi_nflows; 123 return (err); 124 } 125