10a0e9771SDarren Reed /* 20a0e9771SDarren Reed * CDDL HEADER START 30a0e9771SDarren Reed * 40a0e9771SDarren Reed * The contents of this file are subject to the terms of the 50a0e9771SDarren Reed * Common Development and Distribution License (the "License"). 60a0e9771SDarren Reed * You may not use this file except in compliance with the License. 70a0e9771SDarren Reed * 80a0e9771SDarren Reed * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90a0e9771SDarren Reed * or http://www.opensolaris.org/os/licensing. 100a0e9771SDarren Reed * See the License for the specific language governing permissions 110a0e9771SDarren Reed * and limitations under the License. 120a0e9771SDarren Reed * 130a0e9771SDarren Reed * When distributing Covered Code, include this CDDL HEADER in each 140a0e9771SDarren Reed * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150a0e9771SDarren Reed * If applicable, add the following below this CDDL HEADER, with the 160a0e9771SDarren Reed * fields enclosed by brackets "[]" replaced with your own identifying 170a0e9771SDarren Reed * information: Portions Copyright [yyyy] [name of copyright owner] 180a0e9771SDarren Reed * 190a0e9771SDarren Reed * CDDL HEADER END 200a0e9771SDarren Reed */ 210a0e9771SDarren Reed 220a0e9771SDarren Reed /* 230a0e9771SDarren Reed * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240a0e9771SDarren Reed * Use is subject to license terms. 250a0e9771SDarren Reed */ 260a0e9771SDarren Reed 270a0e9771SDarren Reed #include <sys/types.h> 280a0e9771SDarren Reed #include <sys/stream.h> 290a0e9771SDarren Reed #include <net/bpf.h> 300a0e9771SDarren Reed #include <net/bpfdesc.h> 310a0e9771SDarren Reed #include <inet/ipnet.h> 320a0e9771SDarren Reed 330a0e9771SDarren Reed /* 340a0e9771SDarren Reed * This file implements the function calls for ipnet that translate the 350a0e9771SDarren Reed * calls from BPF into the correct arguments and functions inside of the 360a0e9771SDarren Reed * ipnet device. 370a0e9771SDarren Reed */ 380a0e9771SDarren Reed static const char *ipnet_bpf_name(uintptr_t); 390a0e9771SDarren Reed static void ipnet_bpf_client_close(uintptr_t); 400a0e9771SDarren Reed static const char *ipnet_bpf_client_name(uintptr_t); 410a0e9771SDarren Reed static int ipnet_bpf_client_open(uintptr_t, uintptr_t *); 420a0e9771SDarren Reed static void ipnet_bpf_close(uintptr_t); 43*b7ea883bSDarren Reed static int ipnet_bpf_getdlt(uintptr_t, uint_t *); 440a0e9771SDarren Reed static int ipnet_bpf_getlinkid(const char *, datalink_id_t *, zoneid_t); 45*b7ea883bSDarren Reed static int ipnet_bpf_getzone(uintptr_t, zoneid_t *); 460a0e9771SDarren Reed static int ipnet_bpf_open(const char *, uintptr_t *, zoneid_t); 470a0e9771SDarren Reed static uintptr_t ipnet_bpf_promisc_add(uintptr_t, int, void *, 480a0e9771SDarren Reed uintptr_t *, int); 490a0e9771SDarren Reed static void ipnet_bpf_promisc_remove(uintptr_t); 500a0e9771SDarren Reed static void ipnet_bpf_sdu_get(uintptr_t, uint_t *); 510a0e9771SDarren Reed static int ipnet_bpf_tx(uintptr_t, mblk_t *); 520a0e9771SDarren Reed static int ipnet_bpf_type(uintptr_t); 530a0e9771SDarren Reed 540a0e9771SDarren Reed bpf_provider_t bpf_ipnet = { 550a0e9771SDarren Reed BPR_IPNET, 560a0e9771SDarren Reed ipnet_bpf_open, 570a0e9771SDarren Reed ipnet_bpf_close, 580a0e9771SDarren Reed ipnet_bpf_name, 590a0e9771SDarren Reed ipnet_bpf_type, 600a0e9771SDarren Reed ipnet_bpf_sdu_get, 610a0e9771SDarren Reed ipnet_bpf_tx, 620a0e9771SDarren Reed ipnet_bpf_promisc_add, 630a0e9771SDarren Reed ipnet_bpf_promisc_remove, 640a0e9771SDarren Reed ipnet_bpf_getlinkid, 650a0e9771SDarren Reed ipnet_bpf_client_close, 660a0e9771SDarren Reed ipnet_bpf_client_name, 67*b7ea883bSDarren Reed ipnet_bpf_client_open, 68*b7ea883bSDarren Reed ipnet_bpf_getzone, 69*b7ea883bSDarren Reed ipnet_bpf_getdlt, 700a0e9771SDarren Reed }; 710a0e9771SDarren Reed 720a0e9771SDarren Reed /*ARGSUSED*/ 730a0e9771SDarren Reed static int 740a0e9771SDarren Reed ipnet_bpf_open(const char *name, uintptr_t *mhandlep, zoneid_t zoneid) 750a0e9771SDarren Reed { 76*b7ea883bSDarren Reed if (zoneid == ALL_ZONES) 77*b7ea883bSDarren Reed zoneid = GLOBAL_ZONEID; 780a0e9771SDarren Reed return (ipnet_open_byname(name, (ipnetif_t **)mhandlep, zoneid)); 790a0e9771SDarren Reed } 800a0e9771SDarren Reed 810a0e9771SDarren Reed /*ARGSUSED*/ 820a0e9771SDarren Reed static void 830a0e9771SDarren Reed ipnet_bpf_close(uintptr_t mhandle) 840a0e9771SDarren Reed { 850a0e9771SDarren Reed ipnet_close_byhandle((ipnetif_t *)mhandle); 860a0e9771SDarren Reed } 870a0e9771SDarren Reed 880a0e9771SDarren Reed static const char * 890a0e9771SDarren Reed ipnet_bpf_name(uintptr_t mhandle) 900a0e9771SDarren Reed { 910a0e9771SDarren Reed return (ipnet_name((ipnetif_t *)mhandle)); 920a0e9771SDarren Reed } 930a0e9771SDarren Reed 940a0e9771SDarren Reed /*ARGSUSED*/ 950a0e9771SDarren Reed static int 960a0e9771SDarren Reed ipnet_bpf_type(uintptr_t mhandle) 970a0e9771SDarren Reed { 980a0e9771SDarren Reed return (DL_IPNET); 990a0e9771SDarren Reed } 1000a0e9771SDarren Reed 1010a0e9771SDarren Reed /*ARGSUSED*/ 1020a0e9771SDarren Reed static void 1030a0e9771SDarren Reed ipnet_bpf_sdu_get(uintptr_t mhandle, uint_t *mtup) 1040a0e9771SDarren Reed { 1050a0e9771SDarren Reed /* 1060a0e9771SDarren Reed * The choice of 65535 is arbitrary, it could be any smaller number 1070a0e9771SDarren Reed * but it does matche the current default choice of libpcap as the 1080a0e9771SDarren Reed * packet snap size. 1090a0e9771SDarren Reed */ 1100a0e9771SDarren Reed *mtup = 65535; 1110a0e9771SDarren Reed } 1120a0e9771SDarren Reed 1130a0e9771SDarren Reed /*ARGSUSED*/ 1140a0e9771SDarren Reed static int 1150a0e9771SDarren Reed ipnet_bpf_tx(uintptr_t chandle, mblk_t *pkt) 1160a0e9771SDarren Reed { 1170a0e9771SDarren Reed /* 1180a0e9771SDarren Reed * It is not clear what it would mean to send an ipnet packet, 1190a0e9771SDarren Reed * especially since the ipnet device has been implemented to be 1200a0e9771SDarren Reed * an observation (read-only) instrument. Thus a call to send a 1210a0e9771SDarren Reed * packet using ipnet results in the packet being free'd and an 1220a0e9771SDarren Reed * error returned. 1230a0e9771SDarren Reed */ 1240a0e9771SDarren Reed freemsg(pkt); 1250a0e9771SDarren Reed 1260a0e9771SDarren Reed return (EBADF); 1270a0e9771SDarren Reed } 1280a0e9771SDarren Reed 1290a0e9771SDarren Reed /* 1300a0e9771SDarren Reed * BPF does not provide the means to select which SAP is being sniffed, 1310a0e9771SDarren Reed * so for the purpose of ipnet, all BPF clients are in SAP promiscuous 1320a0e9771SDarren Reed * mode. 1330a0e9771SDarren Reed */ 1340a0e9771SDarren Reed static uintptr_t 1350a0e9771SDarren Reed ipnet_bpf_promisc_add(uintptr_t chandle, int how, void *arg, 1360a0e9771SDarren Reed uintptr_t *promisc, int flags) 1370a0e9771SDarren Reed { 1380a0e9771SDarren Reed int newhow; 1390a0e9771SDarren Reed 1400a0e9771SDarren Reed /* 1410a0e9771SDarren Reed * Map the mac values into ipnet values. 1420a0e9771SDarren Reed */ 1430a0e9771SDarren Reed switch (how) { 1440a0e9771SDarren Reed case MAC_CLIENT_PROMISC_ALL : 1450a0e9771SDarren Reed newhow = DL_PROMISC_PHYS; 1460a0e9771SDarren Reed flags = IPNET_PROMISC_PHYS|IPNET_PROMISC_SAP; 1470a0e9771SDarren Reed break; 1480a0e9771SDarren Reed case MAC_CLIENT_PROMISC_MULTI : 1490a0e9771SDarren Reed newhow = DL_PROMISC_MULTI; 1500a0e9771SDarren Reed flags = IPNET_PROMISC_MULTI|IPNET_PROMISC_SAP; 1510a0e9771SDarren Reed break; 1520a0e9771SDarren Reed default : 1530a0e9771SDarren Reed newhow = 0; 1540a0e9771SDarren Reed break; 1550a0e9771SDarren Reed } 1560a0e9771SDarren Reed 1570a0e9771SDarren Reed return (ipnet_promisc_add((void *)chandle, newhow, 1580a0e9771SDarren Reed arg, promisc, flags)); 1590a0e9771SDarren Reed } 1600a0e9771SDarren Reed 1610a0e9771SDarren Reed static void 1620a0e9771SDarren Reed ipnet_bpf_promisc_remove(uintptr_t phandle) 1630a0e9771SDarren Reed { 1640a0e9771SDarren Reed ipnet_promisc_remove((void *)phandle); 1650a0e9771SDarren Reed } 1660a0e9771SDarren Reed 1670a0e9771SDarren Reed static int 1680a0e9771SDarren Reed ipnet_bpf_client_open(uintptr_t mhandle, uintptr_t *chandlep) 1690a0e9771SDarren Reed { 1700a0e9771SDarren Reed 1710a0e9771SDarren Reed return (ipnet_client_open((ipnetif_t *)mhandle, 1720a0e9771SDarren Reed (ipnetif_t **)chandlep)); 1730a0e9771SDarren Reed } 1740a0e9771SDarren Reed 1750a0e9771SDarren Reed /*ARGSUSED*/ 1760a0e9771SDarren Reed static void 1770a0e9771SDarren Reed ipnet_bpf_client_close(uintptr_t chandle) 1780a0e9771SDarren Reed { 1790a0e9771SDarren Reed ipnet_client_close((ipnetif_t *)chandle); 1800a0e9771SDarren Reed } 1810a0e9771SDarren Reed 1820a0e9771SDarren Reed static const char * 1830a0e9771SDarren Reed ipnet_bpf_client_name(uintptr_t chandle) 1840a0e9771SDarren Reed { 1850a0e9771SDarren Reed return (ipnet_bpf_name(chandle)); 1860a0e9771SDarren Reed } 1870a0e9771SDarren Reed 1880a0e9771SDarren Reed static int 1890a0e9771SDarren Reed ipnet_bpf_getlinkid(const char *name, datalink_id_t *idp, zoneid_t zoneid) 1900a0e9771SDarren Reed { 1910a0e9771SDarren Reed uint_t index; 1920a0e9771SDarren Reed int error; 193*b7ea883bSDarren Reed ipnet_stack_t *ips; 194*b7ea883bSDarren Reed 195*b7ea883bSDarren Reed VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL); 1960a0e9771SDarren Reed 1970a0e9771SDarren Reed index = 0; 198*b7ea883bSDarren Reed mutex_enter(&ips->ips_event_lock); 1990a0e9771SDarren Reed error = ipnet_get_linkid_byname(name, &index, zoneid); 200*b7ea883bSDarren Reed mutex_exit(&ips->ips_event_lock); 2010a0e9771SDarren Reed if (error == 0) 2020a0e9771SDarren Reed *idp = (datalink_id_t)index; 203*b7ea883bSDarren Reed ipnet_rele(ips); 2040a0e9771SDarren Reed return (error); 2050a0e9771SDarren Reed } 206*b7ea883bSDarren Reed 207*b7ea883bSDarren Reed static int 208*b7ea883bSDarren Reed ipnet_bpf_getzone(uintptr_t handle, zoneid_t *zip) 209*b7ea883bSDarren Reed { 210*b7ea883bSDarren Reed ipnetif_t *ipnetif; 211*b7ea883bSDarren Reed 212*b7ea883bSDarren Reed ipnetif = (ipnetif_t *)handle; 213*b7ea883bSDarren Reed *zip = ipnetif->if_zoneid; 214*b7ea883bSDarren Reed return (0); 215*b7ea883bSDarren Reed } 216*b7ea883bSDarren Reed 217*b7ea883bSDarren Reed /*ARGSUSED*/ 218*b7ea883bSDarren Reed static int 219*b7ea883bSDarren Reed ipnet_bpf_getdlt(uintptr_t handle, uint_t *dlp) 220*b7ea883bSDarren Reed { 221*b7ea883bSDarren Reed *dlp = DL_IPNET; 222*b7ea883bSDarren Reed return (0); 223*b7ea883bSDarren Reed } 224