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
ipnet_bpf_open(const char * name,uintptr_t * mhandlep,zoneid_t zoneid)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
ipnet_bpf_close(uintptr_t mhandle)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 *
ipnet_bpf_name(uintptr_t mhandle)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
ipnet_bpf_type(uintptr_t mhandle)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
ipnet_bpf_sdu_get(uintptr_t mhandle,uint_t * mtup)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
ipnet_bpf_tx(uintptr_t chandle,mblk_t * pkt)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
ipnet_bpf_promisc_add(uintptr_t chandle,int how,void * arg,uintptr_t * promisc,int flags)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
ipnet_bpf_promisc_remove(uintptr_t phandle)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
ipnet_bpf_client_open(uintptr_t mhandle,uintptr_t * chandlep)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
ipnet_bpf_client_close(uintptr_t chandle)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 *
ipnet_bpf_client_name(uintptr_t chandle)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
ipnet_bpf_getlinkid(const char * name,datalink_id_t * idp,zoneid_t zoneid)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
ipnet_bpf_getzone(uintptr_t handle,zoneid_t * zip)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
ipnet_bpf_getdlt(uintptr_t handle,uint_t * dlp)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