110639SDarren.Reed@Sun.COM /*
210639SDarren.Reed@Sun.COM * CDDL HEADER START
310639SDarren.Reed@Sun.COM *
410639SDarren.Reed@Sun.COM * The contents of this file are subject to the terms of the
510639SDarren.Reed@Sun.COM * Common Development and Distribution License (the "License").
610639SDarren.Reed@Sun.COM * You may not use this file except in compliance with the License.
710639SDarren.Reed@Sun.COM *
810639SDarren.Reed@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910639SDarren.Reed@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010639SDarren.Reed@Sun.COM * See the License for the specific language governing permissions
1110639SDarren.Reed@Sun.COM * and limitations under the License.
1210639SDarren.Reed@Sun.COM *
1310639SDarren.Reed@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410639SDarren.Reed@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510639SDarren.Reed@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610639SDarren.Reed@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710639SDarren.Reed@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810639SDarren.Reed@Sun.COM *
1910639SDarren.Reed@Sun.COM * CDDL HEADER END
2010639SDarren.Reed@Sun.COM */
2110639SDarren.Reed@Sun.COM
2210639SDarren.Reed@Sun.COM /*
2310639SDarren.Reed@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
2410639SDarren.Reed@Sun.COM * Use is subject to license terms.
2510639SDarren.Reed@Sun.COM */
2610639SDarren.Reed@Sun.COM
2710639SDarren.Reed@Sun.COM #include <sys/types.h>
2810639SDarren.Reed@Sun.COM #include <sys/param.h>
2910639SDarren.Reed@Sun.COM #include <sys/stat.h>
3010639SDarren.Reed@Sun.COM #include <sys/errno.h>
3110639SDarren.Reed@Sun.COM #include <sys/uio.h>
3210639SDarren.Reed@Sun.COM #include <sys/buf.h>
3310639SDarren.Reed@Sun.COM #include <sys/modctl.h>
3410639SDarren.Reed@Sun.COM #include <sys/open.h>
3510639SDarren.Reed@Sun.COM #include <sys/kmem.h>
3610639SDarren.Reed@Sun.COM #include <sys/conf.h>
3710639SDarren.Reed@Sun.COM #include <sys/cmn_err.h>
3810639SDarren.Reed@Sun.COM #include <sys/cred.h>
3910639SDarren.Reed@Sun.COM #include <sys/sunddi.h>
4010639SDarren.Reed@Sun.COM #include <sys/mac_provider.h>
4110639SDarren.Reed@Sun.COM #include <sys/dls_impl.h>
4210639SDarren.Reed@Sun.COM #include <inet/ipnet.h>
4310639SDarren.Reed@Sun.COM
4410639SDarren.Reed@Sun.COM extern int bpfopen(dev_t *devp, int flag, int otyp, cred_t *cred);
4510639SDarren.Reed@Sun.COM extern int bpfclose(dev_t dev, int flag, int otyp, cred_t *cred);
4610639SDarren.Reed@Sun.COM extern int bpfread(dev_t dev, struct uio *uio_p, cred_t *cred_p);
4710639SDarren.Reed@Sun.COM extern int bpfwrite(dev_t dev, struct uio *uio, cred_t *cred);
4810639SDarren.Reed@Sun.COM extern int bpfchpoll(dev_t, short, int, short *, struct pollhead **);
4910639SDarren.Reed@Sun.COM extern int bpfioctl(dev_t, int, intptr_t, int, cred_t *, int *);
5010639SDarren.Reed@Sun.COM extern int bpfilterattach(void);
5110639SDarren.Reed@Sun.COM extern int bpfilterdetach(void);
5210639SDarren.Reed@Sun.COM
5310639SDarren.Reed@Sun.COM extern bpf_provider_t bpf_mac;
5410639SDarren.Reed@Sun.COM extern bpf_provider_t bpf_ipnet;
5510639SDarren.Reed@Sun.COM
5610639SDarren.Reed@Sun.COM static int bpf_attach(dev_info_t *, ddi_attach_cmd_t);
5710639SDarren.Reed@Sun.COM static void *bpf_create_inst(const netid_t);
5810639SDarren.Reed@Sun.COM static void bpf_destroy_inst(const netid_t, void *);
5910639SDarren.Reed@Sun.COM static int bpf_detach(dev_info_t *, ddi_detach_cmd_t);
6010639SDarren.Reed@Sun.COM static int bpf_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
6110639SDarren.Reed@Sun.COM static int bpf_provider_add(bpf_provider_t *);
6210639SDarren.Reed@Sun.COM static int bpf_provider_remove(bpf_provider_t *);
6310639SDarren.Reed@Sun.COM static void bpf_shutdown_inst(const netid_t, void *);
6410639SDarren.Reed@Sun.COM
6510639SDarren.Reed@Sun.COM extern void bpfdetach(uintptr_t);
6610639SDarren.Reed@Sun.COM extern int bpf_bufsize;
6710639SDarren.Reed@Sun.COM extern int bpf_maxbufsize;
6810639SDarren.Reed@Sun.COM
69*11179SDarren.Reed@Sun.COM bpf_provider_head_t bpf_providers;
7010639SDarren.Reed@Sun.COM
7110639SDarren.Reed@Sun.COM static struct cb_ops bpf_cb_ops = {
7210639SDarren.Reed@Sun.COM bpfopen,
7310639SDarren.Reed@Sun.COM bpfclose,
7410639SDarren.Reed@Sun.COM nodev, /* strategy */
7510639SDarren.Reed@Sun.COM nodev, /* print */
7610639SDarren.Reed@Sun.COM nodev, /* dump */
7710639SDarren.Reed@Sun.COM bpfread,
7810639SDarren.Reed@Sun.COM bpfwrite, /* write */
7910639SDarren.Reed@Sun.COM bpfioctl, /* ioctl */
8010639SDarren.Reed@Sun.COM nodev, /* devmap */
8110639SDarren.Reed@Sun.COM nodev, /* mmap */
8210639SDarren.Reed@Sun.COM nodev, /* segmap */
8310639SDarren.Reed@Sun.COM bpfchpoll, /* poll */
8410639SDarren.Reed@Sun.COM ddi_prop_op,
8510639SDarren.Reed@Sun.COM NULL,
8610639SDarren.Reed@Sun.COM D_MTSAFE,
8710639SDarren.Reed@Sun.COM CB_REV,
8810639SDarren.Reed@Sun.COM nodev, /* aread */
8910639SDarren.Reed@Sun.COM nodev, /* awrite */
9010639SDarren.Reed@Sun.COM };
9110639SDarren.Reed@Sun.COM
9210639SDarren.Reed@Sun.COM static struct dev_ops bpf_ops = {
9310639SDarren.Reed@Sun.COM DEVO_REV,
9410639SDarren.Reed@Sun.COM 0,
9510639SDarren.Reed@Sun.COM bpf_getinfo,
9610639SDarren.Reed@Sun.COM nulldev,
9710639SDarren.Reed@Sun.COM nulldev,
9810639SDarren.Reed@Sun.COM bpf_attach,
9910639SDarren.Reed@Sun.COM bpf_detach,
10010639SDarren.Reed@Sun.COM nodev, /* reset */
10110639SDarren.Reed@Sun.COM &bpf_cb_ops,
10210639SDarren.Reed@Sun.COM (struct bus_ops *)0
10310639SDarren.Reed@Sun.COM };
10410639SDarren.Reed@Sun.COM
10510639SDarren.Reed@Sun.COM extern struct mod_ops mod_driverops;
10610639SDarren.Reed@Sun.COM static struct modldrv bpfmod = {
10710639SDarren.Reed@Sun.COM &mod_driverops, "Berkely Packet Filter", &bpf_ops
10810639SDarren.Reed@Sun.COM };
10910639SDarren.Reed@Sun.COM static struct modlinkage modlink1 = { MODREV_1, &bpfmod, NULL };
11010639SDarren.Reed@Sun.COM
11110639SDarren.Reed@Sun.COM static dev_info_t *bpf_dev_info = NULL;
11210639SDarren.Reed@Sun.COM static net_instance_t *bpf_inst = NULL;
11310639SDarren.Reed@Sun.COM
11410639SDarren.Reed@Sun.COM int
_init()11510639SDarren.Reed@Sun.COM _init()
11610639SDarren.Reed@Sun.COM {
11710639SDarren.Reed@Sun.COM int bpfinst;
11810639SDarren.Reed@Sun.COM
11910639SDarren.Reed@Sun.COM bpfinst = mod_install(&modlink1);
12010639SDarren.Reed@Sun.COM return (bpfinst);
12110639SDarren.Reed@Sun.COM }
12210639SDarren.Reed@Sun.COM
12310639SDarren.Reed@Sun.COM int
_fini(void)12410639SDarren.Reed@Sun.COM _fini(void)
12510639SDarren.Reed@Sun.COM {
12610639SDarren.Reed@Sun.COM int bpfinst;
12710639SDarren.Reed@Sun.COM
12810639SDarren.Reed@Sun.COM bpfinst = mod_remove(&modlink1);
12910639SDarren.Reed@Sun.COM return (bpfinst);
13010639SDarren.Reed@Sun.COM }
13110639SDarren.Reed@Sun.COM
13210639SDarren.Reed@Sun.COM int
_info(struct modinfo * modinfop)13310639SDarren.Reed@Sun.COM _info(struct modinfo *modinfop)
13410639SDarren.Reed@Sun.COM {
13510639SDarren.Reed@Sun.COM int bpfinst;
13610639SDarren.Reed@Sun.COM
13710639SDarren.Reed@Sun.COM bpfinst = mod_info(&modlink1, modinfop);
13810639SDarren.Reed@Sun.COM return (bpfinst);
13910639SDarren.Reed@Sun.COM }
14010639SDarren.Reed@Sun.COM
14110639SDarren.Reed@Sun.COM static int
bpf_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)14210639SDarren.Reed@Sun.COM bpf_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
14310639SDarren.Reed@Sun.COM {
14410639SDarren.Reed@Sun.COM
14510639SDarren.Reed@Sun.COM switch (cmd) {
14610639SDarren.Reed@Sun.COM case DDI_ATTACH:
14710639SDarren.Reed@Sun.COM /*
14810639SDarren.Reed@Sun.COM * Default buffer size from bpf's driver.conf file
14910639SDarren.Reed@Sun.COM */
15010639SDarren.Reed@Sun.COM bpf_bufsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15110639SDarren.Reed@Sun.COM "buf_size", 32 * 1024);
15210639SDarren.Reed@Sun.COM /*
15310639SDarren.Reed@Sun.COM * Maximum buffer size from bpf's driver.conf file
15410639SDarren.Reed@Sun.COM */
15510639SDarren.Reed@Sun.COM bpf_maxbufsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0,
15610639SDarren.Reed@Sun.COM "max_buf_size", 16 * 1024 * 1024);
15710639SDarren.Reed@Sun.COM
15810639SDarren.Reed@Sun.COM if (ddi_create_minor_node(dip, "bpf", S_IFCHR, 0,
15910639SDarren.Reed@Sun.COM DDI_PSEUDO, 0) == DDI_FAILURE) {
16010639SDarren.Reed@Sun.COM ddi_remove_minor_node(dip, NULL);
16110639SDarren.Reed@Sun.COM goto attach_failed;
16210639SDarren.Reed@Sun.COM }
16310639SDarren.Reed@Sun.COM bpf_dev_info = dip;
16410639SDarren.Reed@Sun.COM ddi_report_dev(dip);
16510639SDarren.Reed@Sun.COM
16610639SDarren.Reed@Sun.COM LIST_INIT(&bpf_providers);
16710639SDarren.Reed@Sun.COM
16810639SDarren.Reed@Sun.COM if (bpfilterattach() != 0)
16910639SDarren.Reed@Sun.COM goto attach_failed;
17010639SDarren.Reed@Sun.COM
171*11179SDarren.Reed@Sun.COM ipnet_set_itap(bpf_itap);
172*11179SDarren.Reed@Sun.COM VERIFY(bpf_provider_add(&bpf_ipnet) == 0);
173*11179SDarren.Reed@Sun.COM VERIFY(bpf_provider_add(&bpf_mac) == 0);
17410639SDarren.Reed@Sun.COM
17510639SDarren.Reed@Sun.COM /*
17610639SDarren.Reed@Sun.COM * Set up to be notified about zones coming and going
17710639SDarren.Reed@Sun.COM * so that proper interaction with ipnet is possible.
17810639SDarren.Reed@Sun.COM */
17910639SDarren.Reed@Sun.COM bpf_inst = net_instance_alloc(NETINFO_VERSION);
18010639SDarren.Reed@Sun.COM if (bpf_inst == NULL)
18110639SDarren.Reed@Sun.COM goto attach_failed;
18210639SDarren.Reed@Sun.COM bpf_inst->nin_name = "bpf";
18310639SDarren.Reed@Sun.COM bpf_inst->nin_create = bpf_create_inst;
18410639SDarren.Reed@Sun.COM bpf_inst->nin_destroy = bpf_destroy_inst;
18510639SDarren.Reed@Sun.COM bpf_inst->nin_shutdown = bpf_shutdown_inst;
18610639SDarren.Reed@Sun.COM if (net_instance_register(bpf_inst) != 0) {
18710639SDarren.Reed@Sun.COM net_instance_free(bpf_inst);
18810639SDarren.Reed@Sun.COM goto attach_failed;
18910639SDarren.Reed@Sun.COM }
19010639SDarren.Reed@Sun.COM
19110639SDarren.Reed@Sun.COM return (DDI_SUCCESS);
19210639SDarren.Reed@Sun.COM /* NOTREACHED */
19310639SDarren.Reed@Sun.COM case DDI_RESUME:
19410639SDarren.Reed@Sun.COM return (DDI_SUCCESS);
19510639SDarren.Reed@Sun.COM /* NOTREACHED */
19610639SDarren.Reed@Sun.COM default:
19710639SDarren.Reed@Sun.COM break;
19810639SDarren.Reed@Sun.COM }
19910639SDarren.Reed@Sun.COM
20010639SDarren.Reed@Sun.COM attach_failed:
20110639SDarren.Reed@Sun.COM
20210639SDarren.Reed@Sun.COM /*
20310639SDarren.Reed@Sun.COM * Use our own detach routine to toss
20410639SDarren.Reed@Sun.COM * away any stuff we allocated above.
20510639SDarren.Reed@Sun.COM */
20610639SDarren.Reed@Sun.COM (void) bpfilterdetach();
20710639SDarren.Reed@Sun.COM (void) bpf_detach(dip, DDI_DETACH);
20810639SDarren.Reed@Sun.COM return (DDI_FAILURE);
20910639SDarren.Reed@Sun.COM }
21010639SDarren.Reed@Sun.COM
21110639SDarren.Reed@Sun.COM static int
bpf_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)21210639SDarren.Reed@Sun.COM bpf_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
21310639SDarren.Reed@Sun.COM {
21410639SDarren.Reed@Sun.COM int error;
21510639SDarren.Reed@Sun.COM
21610639SDarren.Reed@Sun.COM switch (cmd) {
21710639SDarren.Reed@Sun.COM case DDI_DETACH:
21810639SDarren.Reed@Sun.COM if (net_instance_unregister(bpf_inst) != 0)
21910639SDarren.Reed@Sun.COM return (DDI_FAILURE);
22010639SDarren.Reed@Sun.COM net_instance_free(bpf_inst);
22110639SDarren.Reed@Sun.COM
222*11179SDarren.Reed@Sun.COM ipnet_set_itap(NULL);
22310639SDarren.Reed@Sun.COM error = bpfilterdetach();
22410639SDarren.Reed@Sun.COM if (error != 0)
22510639SDarren.Reed@Sun.COM return (DDI_FAILURE);
226*11179SDarren.Reed@Sun.COM VERIFY(bpf_provider_remove(&bpf_ipnet) == 0);
227*11179SDarren.Reed@Sun.COM VERIFY(bpf_provider_remove(&bpf_mac) == 0);
22810639SDarren.Reed@Sun.COM
22910639SDarren.Reed@Sun.COM ASSERT(LIST_EMPTY(&bpf_providers));
23010639SDarren.Reed@Sun.COM
23110639SDarren.Reed@Sun.COM ddi_prop_remove_all(dip);
23210639SDarren.Reed@Sun.COM
23310639SDarren.Reed@Sun.COM return (DDI_SUCCESS);
23410639SDarren.Reed@Sun.COM /* NOTREACHED */
23510639SDarren.Reed@Sun.COM case DDI_SUSPEND:
23610639SDarren.Reed@Sun.COM case DDI_PM_SUSPEND:
23710639SDarren.Reed@Sun.COM return (DDI_SUCCESS);
23810639SDarren.Reed@Sun.COM /* NOTREACHED */
23910639SDarren.Reed@Sun.COM default:
24010639SDarren.Reed@Sun.COM break;
24110639SDarren.Reed@Sun.COM }
24210639SDarren.Reed@Sun.COM return (DDI_FAILURE);
24310639SDarren.Reed@Sun.COM }
24410639SDarren.Reed@Sun.COM
24510639SDarren.Reed@Sun.COM /*ARGSUSED*/
24610639SDarren.Reed@Sun.COM static int
bpf_getinfo(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)24710639SDarren.Reed@Sun.COM bpf_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
24810639SDarren.Reed@Sun.COM {
24910639SDarren.Reed@Sun.COM int error = DDI_FAILURE;
25010639SDarren.Reed@Sun.COM
25110639SDarren.Reed@Sun.COM switch (infocmd) {
25210639SDarren.Reed@Sun.COM case DDI_INFO_DEVT2DEVINFO:
25310639SDarren.Reed@Sun.COM *result = bpf_dev_info;
25410639SDarren.Reed@Sun.COM error = DDI_SUCCESS;
25510639SDarren.Reed@Sun.COM break;
25610639SDarren.Reed@Sun.COM case DDI_INFO_DEVT2INSTANCE:
25710639SDarren.Reed@Sun.COM *result = (void *)0;
25810639SDarren.Reed@Sun.COM error = DDI_SUCCESS;
25910639SDarren.Reed@Sun.COM break;
26010639SDarren.Reed@Sun.COM default:
26110639SDarren.Reed@Sun.COM break;
26210639SDarren.Reed@Sun.COM }
26310639SDarren.Reed@Sun.COM return (error);
26410639SDarren.Reed@Sun.COM }
26510639SDarren.Reed@Sun.COM
26610639SDarren.Reed@Sun.COM /*
26710639SDarren.Reed@Sun.COM * The two functions below work with and manage a list of providers that
26810639SDarren.Reed@Sun.COM * supply BPF with packets. Their addition and removal is only happens
26910639SDarren.Reed@Sun.COM * when the bpf module is attaching/detaching, thus there is no race
27010639SDarren.Reed@Sun.COM * condition to guard against with using locks as the kernel module system
27110639SDarren.Reed@Sun.COM * takes care of this for us. Similarly, bpf_provider_tickle() is called
27210639SDarren.Reed@Sun.COM * from bpf_setif, which implies an open file descriptor that would get
27310639SDarren.Reed@Sun.COM * in the way of detach being active.
27410639SDarren.Reed@Sun.COM */
27510639SDarren.Reed@Sun.COM static int
bpf_provider_add(bpf_provider_t * provider)27610639SDarren.Reed@Sun.COM bpf_provider_add(bpf_provider_t *provider)
27710639SDarren.Reed@Sun.COM {
27810639SDarren.Reed@Sun.COM bpf_provider_list_t *bp;
27910639SDarren.Reed@Sun.COM
28010639SDarren.Reed@Sun.COM LIST_FOREACH(bp, &bpf_providers, bpl_next) {
28110639SDarren.Reed@Sun.COM if (bp->bpl_what == provider)
28210639SDarren.Reed@Sun.COM return (EEXIST);
28310639SDarren.Reed@Sun.COM }
28410639SDarren.Reed@Sun.COM
28510639SDarren.Reed@Sun.COM
28610639SDarren.Reed@Sun.COM bp = kmem_alloc(sizeof (*bp), KM_SLEEP);
28710639SDarren.Reed@Sun.COM bp->bpl_what = provider;
28810639SDarren.Reed@Sun.COM LIST_INSERT_HEAD(&bpf_providers, bp, bpl_next);
28910639SDarren.Reed@Sun.COM
29010639SDarren.Reed@Sun.COM return (0);
29110639SDarren.Reed@Sun.COM }
29210639SDarren.Reed@Sun.COM
29310639SDarren.Reed@Sun.COM static int
bpf_provider_remove(bpf_provider_t * provider)29410639SDarren.Reed@Sun.COM bpf_provider_remove(bpf_provider_t *provider)
29510639SDarren.Reed@Sun.COM {
29610639SDarren.Reed@Sun.COM bpf_provider_list_t *bp;
29710639SDarren.Reed@Sun.COM
29810639SDarren.Reed@Sun.COM LIST_FOREACH(bp, &bpf_providers, bpl_next) {
29910639SDarren.Reed@Sun.COM if (bp->bpl_what == provider)
30010639SDarren.Reed@Sun.COM break;
30110639SDarren.Reed@Sun.COM }
30210639SDarren.Reed@Sun.COM
30310639SDarren.Reed@Sun.COM if (bp == NULL)
30410639SDarren.Reed@Sun.COM return (ESRCH);
30510639SDarren.Reed@Sun.COM
30610639SDarren.Reed@Sun.COM LIST_REMOVE(bp, bpl_next);
30710639SDarren.Reed@Sun.COM
30810639SDarren.Reed@Sun.COM kmem_free(bp, sizeof (*bp));
30910639SDarren.Reed@Sun.COM
31010639SDarren.Reed@Sun.COM return (0);
31110639SDarren.Reed@Sun.COM }
31210639SDarren.Reed@Sun.COM
31310639SDarren.Reed@Sun.COM /*
31410639SDarren.Reed@Sun.COM * return a pointer to the structure that holds all of the functions
31510639SDarren.Reed@Sun.COM * available to be used to support a particular packet provider.
31610639SDarren.Reed@Sun.COM */
31710639SDarren.Reed@Sun.COM bpf_provider_t *
bpf_find_provider_by_id(int who)31810639SDarren.Reed@Sun.COM bpf_find_provider_by_id(int who)
31910639SDarren.Reed@Sun.COM {
32010639SDarren.Reed@Sun.COM bpf_provider_list_t *b;
32110639SDarren.Reed@Sun.COM
32210639SDarren.Reed@Sun.COM LIST_FOREACH(b, &bpf_providers, bpl_next) {
32310639SDarren.Reed@Sun.COM if (b->bpl_what->bpr_unit == who)
32410639SDarren.Reed@Sun.COM return (b->bpl_what);
32510639SDarren.Reed@Sun.COM }
32610639SDarren.Reed@Sun.COM
32710639SDarren.Reed@Sun.COM return (NULL);
32810639SDarren.Reed@Sun.COM }
32910639SDarren.Reed@Sun.COM
33010639SDarren.Reed@Sun.COM /*
33110639SDarren.Reed@Sun.COM * This function is used by bpf_setif() to force an open() to be called on
33210639SDarren.Reed@Sun.COM * a given device name. If a device has been unloaded by the kernel, but it
33310639SDarren.Reed@Sun.COM * is still recognised, then calling this function will hopefully cause it
33410639SDarren.Reed@Sun.COM * to be loaded back into the kernel. When this function is called, it is
33510639SDarren.Reed@Sun.COM * not known which packet provider the name belongs to so all are tried.
33610639SDarren.Reed@Sun.COM */
33710639SDarren.Reed@Sun.COM int
bpf_provider_tickle(char * name,zoneid_t zone)33810639SDarren.Reed@Sun.COM bpf_provider_tickle(char *name, zoneid_t zone)
33910639SDarren.Reed@Sun.COM {
34010639SDarren.Reed@Sun.COM bpf_provider_list_t *bp;
34110639SDarren.Reed@Sun.COM uintptr_t handle;
34210639SDarren.Reed@Sun.COM int tickled = 0;
34310639SDarren.Reed@Sun.COM
34410639SDarren.Reed@Sun.COM LIST_FOREACH(bp, &bpf_providers, bpl_next) {
34510639SDarren.Reed@Sun.COM handle = 0;
34610639SDarren.Reed@Sun.COM if (bp->bpl_what->bpr_open(name, &handle, zone) == 0) {
34710639SDarren.Reed@Sun.COM bp->bpl_what->bpr_close(handle);
34810639SDarren.Reed@Sun.COM tickled++;
34910639SDarren.Reed@Sun.COM } else if (bp->bpl_what->bpr_unit == BPR_MAC) {
35010639SDarren.Reed@Sun.COM /*
35110639SDarren.Reed@Sun.COM * For mac devices, sometimes the open/close is not
35210639SDarren.Reed@Sun.COM * enough. In that case, further provocation is
35310639SDarren.Reed@Sun.COM * attempted by fetching the linkid and trying to
35410639SDarren.Reed@Sun.COM * use that as the key for open, rather than the
35510639SDarren.Reed@Sun.COM * name.
35610639SDarren.Reed@Sun.COM */
35710639SDarren.Reed@Sun.COM datalink_id_t id;
35810639SDarren.Reed@Sun.COM
35910639SDarren.Reed@Sun.COM if (bp->bpl_what->bpr_getlinkid(name, &id,
36010639SDarren.Reed@Sun.COM zone) == 0) {
36110639SDarren.Reed@Sun.COM if (bp->bpl_what->bpr_open(name, &handle,
36210639SDarren.Reed@Sun.COM zone) == 0) {
36310639SDarren.Reed@Sun.COM bp->bpl_what->bpr_close(handle);
36410639SDarren.Reed@Sun.COM tickled++;
36510639SDarren.Reed@Sun.COM } else {
36610639SDarren.Reed@Sun.COM mac_handle_t mh;
36710639SDarren.Reed@Sun.COM
36810639SDarren.Reed@Sun.COM if (mac_open_by_linkid(id, &mh) == 0) {
36910639SDarren.Reed@Sun.COM mac_close(mh);
37010639SDarren.Reed@Sun.COM tickled++;
37110639SDarren.Reed@Sun.COM }
37210639SDarren.Reed@Sun.COM }
37310639SDarren.Reed@Sun.COM }
37410639SDarren.Reed@Sun.COM }
37510639SDarren.Reed@Sun.COM
37610639SDarren.Reed@Sun.COM }
37710639SDarren.Reed@Sun.COM
37810639SDarren.Reed@Sun.COM if (tickled != 0)
37910639SDarren.Reed@Sun.COM return (EWOULDBLOCK);
38010639SDarren.Reed@Sun.COM
38110639SDarren.Reed@Sun.COM return (ENXIO);
38210639SDarren.Reed@Sun.COM }
38310639SDarren.Reed@Sun.COM
38410639SDarren.Reed@Sun.COM /*
38510639SDarren.Reed@Sun.COM * The following three functions provide the necessary callbacks into
38610639SDarren.Reed@Sun.COM * the netinfo API. This API is primarily used to trigger awareness of
38710639SDarren.Reed@Sun.COM * when a zone is being torn down, allowing BPF to drive IPNET to
38810639SDarren.Reed@Sun.COM * tell it which interfaces need to go away.
38910639SDarren.Reed@Sun.COM */
39010639SDarren.Reed@Sun.COM /*ARGSUSED*/
39110639SDarren.Reed@Sun.COM static void *
bpf_create_inst(const netid_t netid)39210639SDarren.Reed@Sun.COM bpf_create_inst(const netid_t netid)
39310639SDarren.Reed@Sun.COM {
39410639SDarren.Reed@Sun.COM /*
39510639SDarren.Reed@Sun.COM * BPF does not keep any per-instance state, its list of
39610639SDarren.Reed@Sun.COM * interfaces is global, as is its device hash table.
39710639SDarren.Reed@Sun.COM */
39810639SDarren.Reed@Sun.COM return ((void *)bpf_itap);
39910639SDarren.Reed@Sun.COM }
40010639SDarren.Reed@Sun.COM
40110639SDarren.Reed@Sun.COM /*ARGSUSED*/
40210639SDarren.Reed@Sun.COM static void
bpf_shutdown_inst(const netid_t netid,void * arg)40310639SDarren.Reed@Sun.COM bpf_shutdown_inst(const netid_t netid, void *arg)
40410639SDarren.Reed@Sun.COM {
40510639SDarren.Reed@Sun.COM }
40610639SDarren.Reed@Sun.COM
40710639SDarren.Reed@Sun.COM /*ARGSUSED*/
40810639SDarren.Reed@Sun.COM static void
bpf_destroy_inst(const netid_t netid,void * arg)40910639SDarren.Reed@Sun.COM bpf_destroy_inst(const netid_t netid, void *arg)
41010639SDarren.Reed@Sun.COM {
41110639SDarren.Reed@Sun.COM }
412