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 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/stream.h> 29 #include <net/bpf.h> 30 #include <net/bpfdesc.h> 31 #include <inet/ipnet.h> 32 33 /* 34 * This file implements the function calls for ipnet that translate the 35 * calls from BPF into the correct arguments and functions inside of the 36 * ipnet device. 37 */ 38 static const char *ipnet_bpf_name(uintptr_t); 39 static void ipnet_bpf_client_close(uintptr_t); 40 static const char *ipnet_bpf_client_name(uintptr_t); 41 static int ipnet_bpf_client_open(uintptr_t, uintptr_t *); 42 static void ipnet_bpf_close(uintptr_t); 43 static int ipnet_bpf_getdlt(uintptr_t, uint_t *); 44 static int ipnet_bpf_getlinkid(const char *, datalink_id_t *, zoneid_t); 45 static int ipnet_bpf_getzone(uintptr_t, zoneid_t *); 46 static int ipnet_bpf_open(const char *, uintptr_t *, zoneid_t); 47 static uintptr_t ipnet_bpf_promisc_add(uintptr_t, int, void *, 48 uintptr_t *, int); 49 static void ipnet_bpf_promisc_remove(uintptr_t); 50 static void ipnet_bpf_sdu_get(uintptr_t, uint_t *); 51 static int ipnet_bpf_tx(uintptr_t, mblk_t *); 52 static int ipnet_bpf_type(uintptr_t); 53 54 bpf_provider_t bpf_ipnet = { 55 BPR_IPNET, 56 ipnet_bpf_open, 57 ipnet_bpf_close, 58 ipnet_bpf_name, 59 ipnet_bpf_type, 60 ipnet_bpf_sdu_get, 61 ipnet_bpf_tx, 62 ipnet_bpf_promisc_add, 63 ipnet_bpf_promisc_remove, 64 ipnet_bpf_getlinkid, 65 ipnet_bpf_client_close, 66 ipnet_bpf_client_name, 67 ipnet_bpf_client_open, 68 ipnet_bpf_getzone, 69 ipnet_bpf_getdlt, 70 }; 71 72 /*ARGSUSED*/ 73 static int 74 ipnet_bpf_open(const char *name, uintptr_t *mhandlep, zoneid_t zoneid) 75 { 76 if (zoneid == ALL_ZONES) 77 zoneid = GLOBAL_ZONEID; 78 return (ipnet_open_byname(name, (ipnetif_t **)mhandlep, zoneid)); 79 } 80 81 /*ARGSUSED*/ 82 static void 83 ipnet_bpf_close(uintptr_t mhandle) 84 { 85 ipnet_close_byhandle((ipnetif_t *)mhandle); 86 } 87 88 static const char * 89 ipnet_bpf_name(uintptr_t mhandle) 90 { 91 return (ipnet_name((ipnetif_t *)mhandle)); 92 } 93 94 /*ARGSUSED*/ 95 static int 96 ipnet_bpf_type(uintptr_t mhandle) 97 { 98 return (DL_IPNET); 99 } 100 101 /*ARGSUSED*/ 102 static void 103 ipnet_bpf_sdu_get(uintptr_t mhandle, uint_t *mtup) 104 { 105 /* 106 * The choice of 65535 is arbitrary, it could be any smaller number 107 * but it does matche the current default choice of libpcap as the 108 * packet snap size. 109 */ 110 *mtup = 65535; 111 } 112 113 /*ARGSUSED*/ 114 static int 115 ipnet_bpf_tx(uintptr_t chandle, mblk_t *pkt) 116 { 117 /* 118 * It is not clear what it would mean to send an ipnet packet, 119 * especially since the ipnet device has been implemented to be 120 * an observation (read-only) instrument. Thus a call to send a 121 * packet using ipnet results in the packet being free'd and an 122 * error returned. 123 */ 124 freemsg(pkt); 125 126 return (EBADF); 127 } 128 129 /* 130 * BPF does not provide the means to select which SAP is being sniffed, 131 * so for the purpose of ipnet, all BPF clients are in SAP promiscuous 132 * mode. 133 */ 134 static uintptr_t 135 ipnet_bpf_promisc_add(uintptr_t chandle, int how, void *arg, 136 uintptr_t *promisc, int flags) 137 { 138 int newhow; 139 140 /* 141 * Map the mac values into ipnet values. 142 */ 143 switch (how) { 144 case MAC_CLIENT_PROMISC_ALL : 145 newhow = DL_PROMISC_PHYS; 146 flags = IPNET_PROMISC_PHYS|IPNET_PROMISC_SAP; 147 break; 148 case MAC_CLIENT_PROMISC_MULTI : 149 newhow = DL_PROMISC_MULTI; 150 flags = IPNET_PROMISC_MULTI|IPNET_PROMISC_SAP; 151 break; 152 default : 153 newhow = 0; 154 break; 155 } 156 157 return (ipnet_promisc_add((void *)chandle, newhow, 158 arg, promisc, flags)); 159 } 160 161 static void 162 ipnet_bpf_promisc_remove(uintptr_t phandle) 163 { 164 ipnet_promisc_remove((void *)phandle); 165 } 166 167 static int 168 ipnet_bpf_client_open(uintptr_t mhandle, uintptr_t *chandlep) 169 { 170 171 return (ipnet_client_open((ipnetif_t *)mhandle, 172 (ipnetif_t **)chandlep)); 173 } 174 175 /*ARGSUSED*/ 176 static void 177 ipnet_bpf_client_close(uintptr_t chandle) 178 { 179 ipnet_client_close((ipnetif_t *)chandle); 180 } 181 182 static const char * 183 ipnet_bpf_client_name(uintptr_t chandle) 184 { 185 return (ipnet_bpf_name(chandle)); 186 } 187 188 static int 189 ipnet_bpf_getlinkid(const char *name, datalink_id_t *idp, zoneid_t zoneid) 190 { 191 uint_t index; 192 int error; 193 ipnet_stack_t *ips; 194 195 VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL); 196 197 index = 0; 198 mutex_enter(&ips->ips_event_lock); 199 error = ipnet_get_linkid_byname(name, &index, zoneid); 200 mutex_exit(&ips->ips_event_lock); 201 if (error == 0) 202 *idp = (datalink_id_t)index; 203 ipnet_rele(ips); 204 return (error); 205 } 206 207 static int 208 ipnet_bpf_getzone(uintptr_t handle, zoneid_t *zip) 209 { 210 ipnetif_t *ipnetif; 211 212 ipnetif = (ipnetif_t *)handle; 213 *zip = ipnetif->if_zoneid; 214 return (0); 215 } 216 217 /*ARGSUSED*/ 218 static int 219 ipnet_bpf_getdlt(uintptr_t handle, uint_t *dlp) 220 { 221 *dlp = DL_IPNET; 222 return (0); 223 } 224