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_getlinkid(const char *, datalink_id_t *, zoneid_t); 44 static int ipnet_bpf_open(const char *, uintptr_t *, zoneid_t); 45 static uintptr_t ipnet_bpf_promisc_add(uintptr_t, int, void *, 46 uintptr_t *, int); 47 static void ipnet_bpf_promisc_remove(uintptr_t); 48 static void ipnet_bpf_sdu_get(uintptr_t, uint_t *); 49 static int ipnet_bpf_tx(uintptr_t, mblk_t *); 50 static int ipnet_bpf_type(uintptr_t); 51 52 bpf_provider_t bpf_ipnet = { 53 BPR_IPNET, 54 ipnet_bpf_open, 55 ipnet_bpf_close, 56 ipnet_bpf_name, 57 ipnet_bpf_type, 58 ipnet_bpf_sdu_get, 59 ipnet_bpf_tx, 60 ipnet_bpf_promisc_add, 61 ipnet_bpf_promisc_remove, 62 ipnet_bpf_getlinkid, 63 ipnet_bpf_client_close, 64 ipnet_bpf_client_name, 65 ipnet_bpf_client_open 66 }; 67 68 /*ARGSUSED*/ 69 static int 70 ipnet_bpf_open(const char *name, uintptr_t *mhandlep, zoneid_t zoneid) 71 { 72 return (ipnet_open_byname(name, (ipnetif_t **)mhandlep, zoneid)); 73 } 74 75 /*ARGSUSED*/ 76 static void 77 ipnet_bpf_close(uintptr_t mhandle) 78 { 79 ipnet_close_byhandle((ipnetif_t *)mhandle); 80 } 81 82 static const char * 83 ipnet_bpf_name(uintptr_t mhandle) 84 { 85 return (ipnet_name((ipnetif_t *)mhandle)); 86 } 87 88 /*ARGSUSED*/ 89 static int 90 ipnet_bpf_type(uintptr_t mhandle) 91 { 92 return (DL_IPNET); 93 } 94 95 /*ARGSUSED*/ 96 static void 97 ipnet_bpf_sdu_get(uintptr_t mhandle, uint_t *mtup) 98 { 99 /* 100 * The choice of 65535 is arbitrary, it could be any smaller number 101 * but it does matche the current default choice of libpcap as the 102 * packet snap size. 103 */ 104 *mtup = 65535; 105 } 106 107 /*ARGSUSED*/ 108 static int 109 ipnet_bpf_tx(uintptr_t chandle, mblk_t *pkt) 110 { 111 /* 112 * It is not clear what it would mean to send an ipnet packet, 113 * especially since the ipnet device has been implemented to be 114 * an observation (read-only) instrument. Thus a call to send a 115 * packet using ipnet results in the packet being free'd and an 116 * error returned. 117 */ 118 freemsg(pkt); 119 120 return (EBADF); 121 } 122 123 /* 124 * BPF does not provide the means to select which SAP is being sniffed, 125 * so for the purpose of ipnet, all BPF clients are in SAP promiscuous 126 * mode. 127 */ 128 static uintptr_t 129 ipnet_bpf_promisc_add(uintptr_t chandle, int how, void *arg, 130 uintptr_t *promisc, int flags) 131 { 132 int newhow; 133 134 /* 135 * Map the mac values into ipnet values. 136 */ 137 switch (how) { 138 case MAC_CLIENT_PROMISC_ALL : 139 newhow = DL_PROMISC_PHYS; 140 flags = IPNET_PROMISC_PHYS|IPNET_PROMISC_SAP; 141 break; 142 case MAC_CLIENT_PROMISC_MULTI : 143 newhow = DL_PROMISC_MULTI; 144 flags = IPNET_PROMISC_MULTI|IPNET_PROMISC_SAP; 145 break; 146 default : 147 newhow = 0; 148 break; 149 } 150 151 return (ipnet_promisc_add((void *)chandle, newhow, 152 arg, promisc, flags)); 153 } 154 155 static void 156 ipnet_bpf_promisc_remove(uintptr_t phandle) 157 { 158 ipnet_promisc_remove((void *)phandle); 159 } 160 161 static int 162 ipnet_bpf_client_open(uintptr_t mhandle, uintptr_t *chandlep) 163 { 164 165 return (ipnet_client_open((ipnetif_t *)mhandle, 166 (ipnetif_t **)chandlep)); 167 } 168 169 /*ARGSUSED*/ 170 static void 171 ipnet_bpf_client_close(uintptr_t chandle) 172 { 173 ipnet_client_close((ipnetif_t *)chandle); 174 } 175 176 static const char * 177 ipnet_bpf_client_name(uintptr_t chandle) 178 { 179 return (ipnet_bpf_name(chandle)); 180 } 181 182 static int 183 ipnet_bpf_getlinkid(const char *name, datalink_id_t *idp, zoneid_t zoneid) 184 { 185 uint_t index; 186 int error; 187 188 index = 0; 189 error = ipnet_get_linkid_byname(name, &index, zoneid); 190 if (error == 0) 191 *idp = (datalink_id_t)index; 192 return (error); 193 } 194