xref: /titanic_44/usr/src/uts/common/inet/ipnet/ipnet_bpf.c (revision b7ea883b48e925772db7fa37388112c84c6d5f5b)
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