b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * CDDL HEADER START
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The contents of this file are subject to the terms of the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Common Development and Distribution License (the "License").
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * You may not use this file except in compliance with the License.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * or http://www.opensolaris.org/os/licensing.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * See the License for the specific language governing permissions
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * and limitations under the License.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * When distributing Covered Code, include this CDDL HEADER in each
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * If applicable, add the following below this CDDL HEADER, with the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * fields enclosed by brackets "[]" replaced with your own identifying
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * information: Portions Copyright [yyyy] [name of copyright owner]
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * CDDL HEADER END
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Use is subject to license terms.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill/*
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill * Copyright (c) 2016, Joyent, Inc. All rights reserved.
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill */
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The ipnet device defined here provides access to packets at the IP layer. To
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * provide access to packets at this layer it registers a callback function in
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * the ip module and when there are open instances of the device ip will pass
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * packets into the device. Packets from ip are passed on the input, output and
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * loopback paths. Internally the module returns to ip as soon as possible by
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * deferring processing using a taskq.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Management of the devices in /dev/ipnet/ is handled by the devname
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * filesystem and use of the neti interfaces. This module registers for NIC
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * events using the neti framework so that when IP interfaces are bought up,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * taken down etc. the ipnet module is notified and its view of the interfaces
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * configured on the system adjusted. On attach, the module gets an initial
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * view of the system again using the neti framework but as it has already
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * registered for IP interface events, it is still up-to-date with any changes.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/types.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/conf.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/cred.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/stat.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/ddi.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/sunddi.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/modctl.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/dlpi.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/strsun.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/id_space.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/kmem.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/mkdev.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/neti.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <net/if.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/errno.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/list.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/ksynch.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/hook_event.h>
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed#include <sys/sdt.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/stropts.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <sys/sysmacros.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <inet/ip.h>
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed#include <inet/ip_if.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <inet/ip_multi.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <inet/ip6.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk#include <inet/ipnet.h>
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed#include <net/bpf.h>
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed#include <net/bpfdesc.h>
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed#include <net/dlt.h>
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct module_info ipnet_minfo = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk 1, /* mi_idnum */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk "ipnet", /* mi_idname */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk 0, /* mi_minpsz */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk INFPSZ, /* mi_maxpsz */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk 2048, /* mi_hiwat */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk 0 /* mi_lowat */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * List to hold static view of ipnetif_t's on the system. This is needed to
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * avoid holding the lock protecting the avl tree of ipnetif's over the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * callback into the dev filesystem.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirktypedef struct ipnetif_cbdata {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk char ic_ifname[LIFNAMSIZ];
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dev_t ic_dev;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_node_t ic_next;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk} ipnetif_cbdata_t;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Convenience enumerated type for ipnet_accept(). It describes the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * properties of a given ipnet_addrp_t relative to a single ipnet_t
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * client stream. The values represent whether the address is ...
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirktypedef enum {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk IPNETADDR_MYADDR, /* an address on my ipnetif_t. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk IPNETADDR_MBCAST, /* a multicast or broadcast address. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk IPNETADDR_UNKNOWN /* none of the above. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk} ipnet_addrtype_t;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* Argument used for the ipnet_nicevent_taskq callback. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirktypedef struct ipnet_nicevent_s {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk nic_event_t ipne_event;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk net_handle_t ipne_protocol;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstackid_t ipne_stackid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t ipne_ifindex;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t ipne_lifindex;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk char ipne_ifname[LIFNAMSIZ];
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk} ipnet_nicevent_t;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic dev_info_t *ipnet_dip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic major_t ipnet_major;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ddi_taskq_t *ipnet_taskq; /* taskq for packets */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ddi_taskq_t *ipnet_nicevent_taskq; /* taskq for NIC events */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic id_space_t *ipnet_minor_space;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic const int IPNET_MINOR_LO = 1; /* minor number for /dev/lo0 */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic const int IPNET_MINOR_MIN = 2; /* start of dynamic minors */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic dl_info_ack_t ipnet_infoack = IPNET_INFO_ACK_INIT;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnet_acceptfn_t ipnet_accept, ipnet_loaccept;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic bpf_itap_fn_t ipnet_itap;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_input(mblk_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_wput(queue_t *, mblk_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_rsrv(queue_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_open(queue_t *, dev_t *, int, int, cred_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_close(queue_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_ioctl(queue_t *, mblk_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_iocdata(queue_t *, mblk_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_wputnondata(queue_t *, mblk_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_attach(dev_info_t *, ddi_attach_cmd_t);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_detach(dev_info_t *, ddi_detach_cmd_t);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_devinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_inforeq(queue_t *q, mblk_t *mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_bindreq(queue_t *q, mblk_t *mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_unbindreq(queue_t *q, mblk_t *mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_dlpromisconreq(queue_t *q, mblk_t *mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_dlpromiscoffreq(queue_t *q, mblk_t *mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_join_allmulti(ipnetif_t *, ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_leave_allmulti(ipnetif_t *, ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_nicevent_cb(hook_event_token_t, hook_data_t, void *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_nicevent_task(void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *ipnetif_create(const char *, uint64_t, ipnet_stack_t *,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uint64_t);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic void ipnetif_remove(ipnetif_t *, ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnetif_addr_t *ipnet_match_lif(ipnetif_t *, lif_if_t, boolean_t);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *ipnetif_getby_index(uint64_t, ipnet_stack_t *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *ipnetif_getby_dev(dev_t, ipnet_stack_t *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic boolean_t ipnetif_in_zone(ipnetif_t *, zoneid_t, ipnet_stack_t *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic void ipnetif_zonecheck(ipnetif_t *, ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int ipnet_populate_if(net_handle_t, ipnet_stack_t *, boolean_t);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int ipnetif_compare_name(const void *, const void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int ipnetif_compare_name_zone(const void *, const void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int ipnetif_compare_index(const void *, const void *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_add_ifaddr(uint64_t, ipnetif_t *, net_handle_t);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_delete_ifaddr(ipnetif_addr_t *, ipnetif_t *, boolean_t);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnetif_refhold(ipnetif_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnetif_refrele(ipnetif_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_walkers_inc(ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_walkers_dec(ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_register_netihook(ipnet_stack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void *ipnet_stack_init(netstackid_t, netstack_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void ipnet_stack_fini(netstackid_t, void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic void ipnet_dispatch(void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int ipobs_bounce_func(hook_event_token_t, hook_data_t, void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int ipnet_bpf_bounce(hook_event_token_t, hook_data_t, void *);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *ipnetif_clone_create(ipnetif_t *, zoneid_t);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic void ipnetif_clone_release(ipnetif_t *);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct qinit ipnet_rinit = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_putp */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_rsrv, /* qi_srvp */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_open, /* qi_qopen */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_close, /* qi_qclose */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_qadmin */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnet_minfo, /* qi_minfo */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct qinit ipnet_winit = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_wput, /* qi_putp */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_srvp */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_qopen */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_qclose */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk NULL, /* qi_qadmin */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnet_minfo, /* qi_minfo */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct streamtab ipnet_info = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnet_rinit, &ipnet_winit
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip KirkDDI_DEFINE_STREAM_OPS(ipnet_ops, nulldev, nulldev, ipnet_attach,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_detach, nodev, ipnet_devinfo, D_MP | D_MTPERMOD, &ipnet_info,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_quiesce_not_supported);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct modldrv modldrv = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &mod_driverops,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk "STREAMS ipnet driver",
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnet_ops
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic struct modlinkage modlinkage = {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk MODREV_1, &modldrv, NULL
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk};
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * This structure contains the template data (names and type) that is
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * copied, in bulk, into the new kstats structure created by net_kstat_create.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * No actual statistical information is stored in this instance of the
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * ipnet_kstats_t structure.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnet_kstats_t stats_template = {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "duplicationFail", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "dispatchOk", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "dispatchFail", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "dispatchHeaderDrop", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "dispatchDupDrop", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "dispatchDeliver", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "acceptOk", KSTAT_DATA_UINT64 },
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed { "acceptFail", KSTAT_DATA_UINT64 }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed};
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Walk the list of physical interfaces on the machine, for each
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * interface create a new ipnetif_t and add any addresses to it. We
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * need to do the walk twice, once for IPv4 and once for IPv6.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The interfaces are destroyed as part of ipnet_stack_fini() for each
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * stack. Note that we cannot do this initialization in
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * ipnet_stack_init(), since ipnet_stack_init() cannot fail.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_init(void)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_handle_t nh;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_t *ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int ret = 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_next_init(&nh);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while ((ns = netstack_next(&nh)) != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = ns->netstack_ipnet;
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((ret = ipnet_populate_if(ips->ips_ndv4, ips, B_FALSE)) == 0)
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy ret = ipnet_populate_if(ips->ips_ndv6, ips, B_TRUE);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy netstack_rele(ns);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if (ret != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_next_fini(&nh);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ret);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Standard module entry points.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkint
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk_init(void)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int ret;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed boolean_t netstack_registered = B_FALSE;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ipnet_major = ddi_name_to_major("ipnet")) == (major_t)-1)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ENODEV);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_minor_space = id_space_create("ipnet_minor_space",
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk IPNET_MINOR_MIN, MAXMIN32);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * We call ddi_taskq_create() with nthread == 1 to ensure in-order
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * delivery of packets to clients. Note that we need to create the
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * taskqs before calling netstack_register() since ipnet_stack_init()
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * registers callbacks that use 'em.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_taskq = ddi_taskq_create(NULL, "ipnet", 1, TASKQ_DEFAULTPRI, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_nicevent_taskq = ddi_taskq_create(NULL, "ipnet_nic_event_queue",
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk 1, TASKQ_DEFAULTPRI, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet_taskq == NULL || ipnet_nicevent_taskq == NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ret = ENOMEM;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem netstack_register(NS_IPNET, ipnet_stack_init, NULL, ipnet_stack_fini);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem netstack_registered = B_TRUE;
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ret = ipnetif_init()) == 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ret = mod_install(&modlinkage);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdone:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ret != 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet_taskq != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_taskq_destroy(ipnet_taskq);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet_nicevent_taskq != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_taskq_destroy(ipnet_nicevent_taskq);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (netstack_registered)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem netstack_unregister(NS_IPNET);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk id_space_destroy(ipnet_minor_space);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ret);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkint
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk_fini(void)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int err;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((err = mod_remove(&modlinkage)) != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (err);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem netstack_unregister(NS_IPNET);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_taskq_destroy(ipnet_nicevent_taskq);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_taskq_destroy(ipnet_taskq);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk id_space_destroy(ipnet_minor_space);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkint
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk_info(struct modinfo *modinfop)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (mod_info(&modlinkage, modinfop));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_register_netihook(ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int ret;
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy zoneid_t zoneid;
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy netid_t netid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk HOOK_INIT(ips->ips_nicevents, ipnet_nicevent_cb, "ipnet_nicevents",
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * It is possible for an exclusive stack to be in the process of
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * shutting down here, and the netid and protocol lookups could fail
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * in that case.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy zoneid = netstackid_to_zoneid(ips->ips_netstack->netstack_stackid);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((netid = net_zoneidtonetid(zoneid)) == -1)
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((ips->ips_ndv4 = net_protocol_lookup(netid, NHF_INET)) != NULL) {
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((ret = net_hook_register(ips->ips_ndv4, NH_NIC_EVENTS,
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy ips->ips_nicevents)) != 0) {
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy VERIFY(net_protocol_release(ips->ips_ndv4) == 0);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy ips->ips_ndv4 = NULL;
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy cmn_err(CE_WARN, "unable to register IPv4 netinfo hooks"
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy " in zone %d: %d", zoneid, ret);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((ips->ips_ndv6 = net_protocol_lookup(netid, NHF_INET6)) != NULL) {
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if ((ret = net_hook_register(ips->ips_ndv6, NH_NIC_EVENTS,
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy ips->ips_nicevents)) != 0) {
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy VERIFY(net_protocol_release(ips->ips_ndv6) == 0);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy ips->ips_ndv6 = NULL;
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy cmn_err(CE_WARN, "unable to register IPv6 netinfo hooks"
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy " in zone %d: %d", zoneid, ret);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Create a local set of kstats for each zone.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips->ips_kstatp = net_kstat_create(netid, "ipnet", 0, "ipnet_stats",
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed "misc", KSTAT_TYPE_NAMED,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed sizeof (ipnet_kstats_t) / sizeof (kstat_named_t), 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ips->ips_kstatp != NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed bcopy(&stats_template, &ips->ips_stats,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed sizeof (ips->ips_stats));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips->ips_kstatp->ks_data = &ips->ips_stats;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips->ips_kstatp->ks_private =
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void *)(uintptr_t)ips->ips_netstack->netstack_stackid;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed kstat_install(ips->ips_kstatp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed cmn_err(CE_WARN, "net_kstat_create(%s,%s,%s) failed",
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed "ipnet", "ipnet_stats", "misc");
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * This function is called on attach to build an initial view of the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * interfaces on the system. It will be called once for IPv4 and once
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * for IPv6, although there is only one ipnet interface for both IPv4
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * and IPv6 there are separate address lists.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_populate_if(net_handle_t nd, ipnet_stack_t *ips, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed phy_if_t phyif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed lif_if_t lif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ipnetif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed char name[LIFNAMSIZ];
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed boolean_t new_if = B_FALSE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uint64_t ifflags;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int ret = 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy /*
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * If ipnet_register_netihook() was unable to initialize this
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * stack's net_handle_t, then we cannot populate any interface
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * information. This usually happens when we attempted to
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * grab a net_handle_t as a stack was shutting down. We don't
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * want to fail the entire _init() operation because of a
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * stack shutdown (other stacks will continue to work just
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy * fine), so we silently return success here.
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy */
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy if (nd == NULL)
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy return (0);
133be3055da09253fc544763dcb744957f1f6319Sebastien Roy
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Make sure we're not processing NIC events during the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * population of our interfaces and address lists.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (phyif = net_phygetnext(nd, 0); phyif != 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk phyif = net_phygetnext(nd, phyif)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (net_getifname(nd, phyif, name, LIFNAMSIZ) != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifflags = 0;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_getlifflags(nd, phyif, 0, &ifflags);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnetif_getby_index(phyif, ips)) == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif = ipnetif_create(name, phyif, ips, ifflags);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif == NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ret = ENOMEM;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk new_if = B_TRUE;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags |=
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk isv6 ? IPNETIF_IPV6PLUMBED : IPNETIF_IPV4PLUMBED;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (lif = net_lifgetnext(nd, phyif, 0); lif != 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk lif = net_lifgetnext(nd, phyif, lif)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Skip addresses that aren't up. We'll add
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * them when we receive an NE_LIF_UP event.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (net_getlifflags(nd, phyif, lif, &ifflags) != 0 ||
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk !(ifflags & IFF_UP))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* Don't add it if we already have it. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet_match_lif(ipnetif, lif, isv6) != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_add_ifaddr(lif, ipnetif, nd);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (!new_if)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdone:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ret);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (cmd != DDI_ATTACH)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (DDI_FAILURE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ddi_create_minor_node(dip, "lo0", S_IFCHR, IPNET_MINOR_LO,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk DDI_PSEUDO, 0) == DDI_FAILURE)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (DDI_FAILURE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_dip = dip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (DDI_SUCCESS);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (cmd != DDI_DETACH)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (DDI_FAILURE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(dip == ipnet_dip);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ddi_remove_minor_node(ipnet_dip, NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_dip = NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (DDI_SUCCESS);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_devinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int error = DDI_FAILURE;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (infocmd) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DDI_INFO_DEVT2INSTANCE:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *result = (void *)0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk error = DDI_SUCCESS;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DDI_INFO_DEVT2DEVINFO:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet_dip != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *result = ipnet_dip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk error = DDI_SUCCESS;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (error);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_open(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_t *ns = NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int err = 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk zoneid_t zoneid = crgetzoneid(crp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * If the system is labeled, only the global zone is allowed to open
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * IP observability nodes.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (is_system_labeled() && zoneid != GLOBAL_ZONEID)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (EACCES);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* We don't support open as a module */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (sflag & MODOPEN)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ENOTSUP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* This driver is self-cloning, we don't support re-open. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (rq->q_ptr != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (EBUSY);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ipnet = kmem_zalloc(sizeof (*ipnet), KM_NOSLEEP)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ENOMEM);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY((ns = netstack_find_by_cred(crp)) != NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = ns->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk rq->q_ptr = WR(rq)->q_ptr = ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_rq = rq;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_minor = (minor_t)id_alloc(ipnet_minor_space);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_zoneid = zoneid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_dlstate = DL_UNBOUND;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_ns = ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * We need to hold ips_event_lock here as any NE_LIF_DOWN events need
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * to be processed after ipnet_if is set and the ipnet_t has been
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * inserted in the ips_str_list.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (getminor(*dev) == IPNET_MINOR_LO) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags |= IPNET_LOMODE;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_acceptfn = ipnet_loaccept;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_acceptfn = ipnet_accept;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_if = ipnetif_getby_dev(*dev, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_if == NULL ||
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed !ipnetif_in_zone(ipnet->ipnet_if, zoneid, ips)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk err = ENODEV;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while (ips->ips_walkers_cnt != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cv_wait(&ips->ips_walkers_cv, &ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_insert_head(&ips->ips_str_list, ipnet);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *dev = makedevice(getmajor(*dev), ipnet->ipnet_minor);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk qprocson(rq);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Only register our callback if we're the first open client; we call
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * unregister in close() for the last open client.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (list_head(&ips->ips_str_list) == list_tail(&ips->ips_str_list))
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips->ips_hook = ipobs_register_hook(ns, ipnet_input);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdone:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (err != 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_rele(ns);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk id_free(ipnet_minor_space, ipnet->ipnet_minor);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_if != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnet->ipnet_if);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ipnet, sizeof (*ipnet));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (err);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_close(queue_t *rq)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet = rq->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips = ipnet->ipnet_ns->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_leave_allmulti(ipnet->ipnet_if, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_MULTI)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_leave_allmulti(ipnet->ipnet_if, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while (ips->ips_walkers_cnt != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cv_wait(&ips->ips_walkers_cv, &ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk qprocsoff(rq);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_remove(&ips->ips_str_list, ipnet);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_if != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnet->ipnet_if);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk id_free(ipnet_minor_space, ipnet->ipnet_minor);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (list_is_empty(&ips->ips_str_list)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipobs_unregister_hook(ips->ips_netstack, ips->ips_hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips->ips_hook = NULL;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed kmem_free(ipnet, sizeof (*ipnet));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_rele(ips->ips_netstack);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_wput(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (mp->b_datap->db_type) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case M_FLUSH:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (*mp->b_rptr & FLUSHW) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk flushq(q, FLUSHDATA);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *mp->b_rptr &= ~FLUSHW;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (*mp->b_rptr & FLUSHR)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk qreply(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk else
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case M_PROTO:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case M_PCPROTO:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_wputnondata(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case M_IOCTL:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_ioctl(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case M_IOCDATA:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_iocdata(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_rsrv(queue_t *q)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mblk_t *mp;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while ((mp = getq(q)) != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(DB_TYPE(mp) == M_DATA);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (canputnext(q)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk putnext(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) putbq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_ioctl(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (iocp->ioc_cmd) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DLIOCRAW:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk miocack(q, mp, 0, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DLIOCIPNETINFO:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (iocp->ioc_count == TRANSPARENT) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mcopyin(mp, NULL, sizeof (uint_t), NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk qreply(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* Fallthrough, we don't support I_STR with DLIOCIPNETINFO. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk miocnak(q, mp, 0, EINVAL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_iocdata(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_t *ipnet = q->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (iocp->ioc_cmd) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DLIOCIPNETINFO:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (*(int *)mp->b_cont->b_rptr == 1)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags |= IPNET_INFO;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk else if (*(int *)mp->b_cont->b_rptr == 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags &= ~IPNET_INFO;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk else
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto iocnak;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk miocack(q, mp, 0, DL_IPNETINFO_VERSION);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reediocnak:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk miocnak(q, mp, 0, EINVAL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_wputnondata(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk t_uscalar_t prim = dlp->dl_primitive;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (prim) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_INFO_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_inforeq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_UNBIND_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_unbindreq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_BIND_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_bindreq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISCON_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_dlpromisconreq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISCOFF_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_dlpromiscoffreq(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_UNITDATA_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_DETACH_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PHYS_ADDR_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_SET_PHYS_ADDR_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_ENABMULTI_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_DISABMULTI_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_ATTACH_REQ:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, prim, DL_UNSUPPORTED, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, prim, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_inforeq(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dl_info_ack_t *dlip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk size_t size = sizeof (dl_info_ack_t) + sizeof (ushort_t);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (MBLKL(mp) < DL_INFO_REQ_SIZE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_INFO_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((mp = mexchange(q, mp, size, M_PCPROTO, DL_INFO_ACK)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlip = (dl_info_ack_t *)mp->b_rptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *dlip = ipnet_infoack;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk qreply(q, mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_bindreq(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed union DL_primitives *dlp = (union DL_primitives *)mp->b_rptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_t *ipnet = q->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (MBLKL(mp) < DL_BIND_REQ_SIZE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_BIND_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed switch (dlp->bind_req.dl_sap) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed case 0 :
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family = AF_UNSPEC;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed break;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed case IPV4_VERSION :
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family = AF_INET;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed break;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed case IPV6_VERSION :
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family = AF_INET6;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed break;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed default :
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_BIND_REQ, DL_BADSAP, 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*NOTREACHED*/
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_dlstate = DL_IDLE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dlbindack(q, mp, dlp->bind_req.dl_sap, 0, 0, 0, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_unbindreq(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet = q->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (MBLKL(mp) < DL_UNBIND_REQ_SIZE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_UNBIND_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_dlstate != DL_IDLE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_dlstate = DL_UNBOUND;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family = AF_UNSPEC;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlokack(q, mp, DL_UNBIND_REQ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_dlpromisconreq(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet = q->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk t_uscalar_t level;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int err;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (MBLKL(mp) < DL_PROMISCON_REQ_SIZE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_LOMODE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlokack(q, mp, DL_PROMISCON_REQ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (level == DL_PROMISC_PHYS || level == DL_PROMISC_MULTI) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((err = ipnet_join_allmulti(ipnet->ipnet_if,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_ns->netstack_ipnet)) != 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCON_REQ, DL_SYSERR, err);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (level) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_PHYS:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags |= IPNET_PROMISC_PHYS;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_SAP:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags |= IPNET_PROMISC_SAP;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_MULTI:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags |= IPNET_PROMISC_MULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlokack(q, mp, DL_PROMISCON_REQ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_dlpromiscoffreq(queue_t *q, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet = q->q_ptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk t_uscalar_t level;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint16_t orig_ipnet_flags = ipnet->ipnet_flags;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (MBLKL(mp) < DL_PROMISCOFF_REQ_SIZE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_LOMODE) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlokack(q, mp, DL_PROMISCOFF_REQ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk level = ((dl_promiscon_req_t *)mp->b_rptr)->dl_level;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (level) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_PHYS:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags &= ~IPNET_PROMISC_PHYS;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_SAP:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_SAP)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags &= ~IPNET_PROMISC_SAP;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case DL_PROMISC_MULTI:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_MULTI)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_flags &= ~IPNET_PROMISC_MULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (orig_ipnet_flags == ipnet->ipnet_flags) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlerrorack(q, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (level == DL_PROMISC_PHYS || level == DL_PROMISC_MULTI) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_leave_allmulti(ipnet->ipnet_if,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_ns->netstack_ipnet);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlokack(q, mp, DL_PROMISCOFF_REQ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_join_allmulti(ipnetif_t *ipnetif, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int err = 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ip_stack_t *ipst = ips->ips_netstack->netstack_ip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t index = ipnetif->if_index;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_multicnt == 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT((ipnetif->if_flags &
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (IPNETIF_IPV4ALLMULTI | IPNETIF_IPV6ALLMULTI)) == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_flags & IPNETIF_IPV4PLUMBED) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk err = ip_join_allmulti(index, B_FALSE, ipst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (err != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags |= IPNETIF_IPV4ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_flags & IPNETIF_IPV6PLUMBED) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk err = ip_join_allmulti(index, B_TRUE, ipst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (err != 0 &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (ipnetif->if_flags & IPNETIF_IPV4ALLMULTI)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) ip_leave_allmulti(index, B_FALSE, ipst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags &= ~IPNETIF_IPV4ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags |= IPNETIF_IPV6ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_multicnt++;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdone:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (err);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_leave_allmulti(ipnetif_t *ipnetif, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk int err;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ip_stack_t *ipst = ips->ips_netstack->netstack_ip;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t index = ipnetif->if_index;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(ipnetif->if_multicnt != 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (--ipnetif->if_multicnt == 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_flags & IPNETIF_IPV4ALLMULTI) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk err = ip_leave_allmulti(index, B_FALSE, ipst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(err == 0 || err == ENODEV);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags &= ~IPNETIF_IPV4ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_flags & IPNETIF_IPV6ALLMULTI) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk err = ip_leave_allmulti(index, B_TRUE, ipst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(err == 0 || err == ENODEV);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags &= ~IPNETIF_IPV6ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Allocate a new mblk_t and put a dl_ipnetinfo_t in it.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * The structure it copies the header information from,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * hook_pkt_observe_t, is constructed using network byte
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * order in ipobs_hook(), so there is no conversion here.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic mblk_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_addheader(hook_pkt_observe_t *hdr, mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mblk_t *dlhdr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dl_ipnetinfo_t *dl;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((dlhdr = allocb(sizeof (dl_ipnetinfo_t), BPRI_HI)) == NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dl = (dl_ipnetinfo_t *)dlhdr->b_rptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dl->dli_version = DL_IPNETINFO_VERSION;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_family = hdr->hpo_family;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_htype = hdr->hpo_htype;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_pktlen = hdr->hpo_pktlen;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_ifindex = hdr->hpo_ifindex;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_grifindex = hdr->hpo_grifindex;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_zsrc = hdr->hpo_zsrc;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dl->dli_zdst = hdr->hpo_zdst;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlhdr->b_wptr += sizeof (*dl);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dlhdr->b_cont = mp;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (dlhdr);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnet_addrtype_t
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_get_addrtype(ipnet_t *ipnet, ipnet_addrp_t *addr)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_t *list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif = ipnet->ipnet_if;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_addr_t *ifaddr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_addrtype_t addrtype = IPNETADDR_UNKNOWN;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* First check if the address is multicast or limited broadcast. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (addr->iap_family) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (CLASSD(*(addr->iap_addr4)) ||
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *(addr->iap_addr4) == INADDR_BROADCAST)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (IPNETADDR_MBCAST);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET6:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (IN6_IS_ADDR_MULTICAST(addr->iap_addr6))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (IPNETADDR_MBCAST);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Walk the address list to see if the address belongs to our
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * interface or is one of our subnet broadcast addresses.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list = (addr->iap_family == AF_INET) ?
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnetif->if_ip4addr_list : &ipnetif->if_ip6addr_list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ifaddr = list_head(list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr != NULL && addrtype == IPNETADDR_UNKNOWN;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr = list_next(list, ifaddr)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * If we're not in the global zone, then only look at
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * addresses in our zone.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_zoneid != GLOBAL_ZONEID &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet->ipnet_zoneid != ifaddr->ifa_zone)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (addr->iap_family) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ifaddr->ifa_ip4addr != INADDR_ANY &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *(addr->iap_addr4) == ifaddr->ifa_ip4addr)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk addrtype = IPNETADDR_MYADDR;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk else if (ifaddr->ifa_brdaddr != INADDR_ANY &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk *(addr->iap_addr4) == ifaddr->ifa_brdaddr)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk addrtype = IPNETADDR_MBCAST;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET6:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (IN6_ARE_ADDR_EQUAL(addr->iap_addr6,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ifaddr->ifa_ip6addr))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk addrtype = IPNETADDR_MYADDR;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (addrtype);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Verify if the packet contained in hdr should be passed up to the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * ipnet client stream.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic boolean_t
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_accept(ipnet_t *ipnet, hook_pkt_observe_t *hdr, ipnet_addrp_t *src,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_addrp_t *dst)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem boolean_t obsif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t ifindex = ipnet->ipnet_if->if_index;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrtype_t srctype;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrtype_t dsttype;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk srctype = ipnet_get_addrtype(ipnet, src);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dsttype = ipnet_get_addrtype(ipnet, dst);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem /*
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * If the packet's ifindex matches ours, or the packet's group ifindex
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * matches ours, it's on the interface we're observing. (Thus,
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem * observing on the group ifindex matches all ifindexes in the group.)
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed obsif = (ntohl(hdr->hpo_ifindex) == ifindex ||
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ntohl(hdr->hpo_grifindex) == ifindex);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed DTRACE_PROBE5(ipnet_accept__addr,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrtype_t, srctype, ipnet_addrp_t *, src,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrtype_t, dsttype, ipnet_addrp_t *, dst,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed boolean_t, obsif);
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Do not allow an ipnet stream to see packets that are not from or to
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * its zone. The exception is when zones are using the shared stack
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * model. In this case, streams in the global zone have visibility
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * into other shared-stack zones, and broadcast and multicast traffic
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * is visible by all zones in the stack.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_zoneid != GLOBAL_ZONEID &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dsttype != IPNETADDR_MBCAST) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnet->ipnet_zoneid != ntohl(hdr->hpo_zsrc) &&
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_zoneid != ntohl(hdr->hpo_zdst))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_FALSE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * If DL_PROMISC_SAP isn't enabled, then the bound SAP must match the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * packet's IP version.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (!(ipnet->ipnet_flags & IPNET_PROMISC_SAP) &&
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family != hdr->hpo_family)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_FALSE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* If the destination address is ours, then accept the packet. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (dsttype == IPNETADDR_MYADDR)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_TRUE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * If DL_PROMISC_PHYS is enabled, then we can see all packets that are
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * sent or received on the interface we're observing, or packets that
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * have our source address (this allows us to see packets we send).
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_PROMISC_PHYS) {
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (srctype == IPNETADDR_MYADDR || obsif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_TRUE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * We accept multicast and broadcast packets transmitted or received
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * on the interface we're observing.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (dsttype == IPNETADDR_MBCAST && obsif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_TRUE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_FALSE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Verify if the packet contained in hdr should be passed up to the ipnet
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * client stream that's in IPNET_LOMODE.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic boolean_t
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_loaccept(ipnet_t *ipnet, hook_pkt_observe_t *hdr, ipnet_addrp_t *src,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_addrp_t *dst)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
fc5884fc5cbeced353b19c8153bd02be0d801d97Darren Reed if (hdr->hpo_htype != htons(IPOBS_HOOK_LOCAL)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * ipnet_if is only NULL for IPNET_MINOR_LO devices.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnet->ipnet_if == NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (B_FALSE);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * An ipnet stream must not see packets that are not from/to its zone.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_zoneid != GLOBAL_ZONEID) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnet->ipnet_zoneid != ntohl(hdr->hpo_zsrc) &&
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_zoneid != ntohl(hdr->hpo_zdst))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_FALSE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ipnet->ipnet_family == AF_UNSPEC ||
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_family == hdr->hpo_family);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_dispatch(void *arg)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mblk_t *mp = arg;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_pkt_observe_t *hdr = (hook_pkt_observe_t *)mp->b_rptr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mblk_t *netmp;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_t *list;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrp_t src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrp_t dst;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed netmp = hdr->hpo_pkt->b_cont;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_family = hdr->hpo_family;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_family = hdr->hpo_family;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (hdr->hpo_family == AF_INET) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_dst;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_dst;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_inc(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list = &ips->ips_str_list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnet = list_head(list); ipnet != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet = list_next(list, ipnet)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (!(*ipnet->ipnet_acceptfn)(ipnet, hdr, &src, &dst)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_acceptFail);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_acceptOk);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (list_next(list, ipnet) == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed netmp = hdr->hpo_pkt->b_cont;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hdr->hpo_pkt->b_cont = NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((netmp = dupmsg(hdr->hpo_pkt->b_cont)) == NULL &&
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (netmp = copymsg(hdr->hpo_pkt->b_cont)) == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_duplicationFail);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_flags & IPNET_INFO) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((netmp = ipnet_addheader(hdr, netmp)) == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchHeaderDrop);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_rq->q_first == NULL &&
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk canputnext(ipnet->ipnet_rq)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk putnext(ipnet->ipnet_rq, netmp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchDeliver);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else if (canput(ipnet->ipnet_rq)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) putq(ipnet->ipnet_rq, netmp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchDeliver);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk } else {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(netmp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchPutDrop);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_dec(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(mp);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_input(mblk_t *mp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_pkt_observe_t *hdr = (hook_pkt_observe_t *)mp->b_rptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ddi_taskq_dispatch(ipnet_taskq, ipnet_dispatch, mp, DDI_NOSLEEP) !=
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk DDI_SUCCESS) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchFail);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk freemsg(mp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_dispatchOk);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_alloc_if(ipnet_stack_t *ips)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ipnetif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = kmem_zalloc(sizeof (*ipnetif), KM_NOSLEEP)) == NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_init(&ipnetif->if_addr_lock, NULL, MUTEX_DEFAULT, 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed list_create(&ipnetif->if_ip4addr_list, sizeof (ipnetif_addr_t),
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed offsetof(ipnetif_addr_t, ifa_link));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed list_create(&ipnetif->if_ip6addr_list, sizeof (ipnetif_addr_t),
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed offsetof(ipnetif_addr_t, ifa_link));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_init(&ipnetif->if_reflock, NULL, MUTEX_DEFAULT, 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif->if_stackp = ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ipnetif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Create a new ipnetif_t and new minor node for it. If creation is
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * successful the new ipnetif_t is inserted into an avl_tree
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * containing ipnetif's for this stack instance.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnetif_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_create(const char *name, uint64_t index, ipnet_stack_t *ips,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uint64_t ifflags)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_index_t where = 0;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk minor_t ifminor;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Because ipnetif_create() can be called from a NIC event
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * callback, it should not block.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifminor = (minor_t)id_alloc_nosleep(ipnet_minor_space);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ifminor == (minor_t)-1)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnet_alloc_if(ips)) == NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk id_free(ipnet_minor_space, ifminor);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) strlcpy(ipnetif->if_name, name, LIFNAMSIZ);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif->if_index = (uint_t)index;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif->if_zoneid = netstack_get_zoneid(ips->ips_netstack);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_dev = makedevice(ipnet_major, ifminor);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_refcnt = 1;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ifflags & IFF_LOOPBACK) != 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif->if_flags = IPNETIF_LOOPBACK;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(avl_find(&ips->ips_avl_by_index, &index, &where) == NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_insert(&ips->ips_avl_by_index, ipnetif, where);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(avl_find(&ips->ips_avl_by_name, (void *)name, &where) == NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_insert(&ips->ips_avl_by_name, ipnetif, where);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_remove(ipnetif_t *ipnetif, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_inc(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* Send a SIGHUP to all open streams associated with this ipnetif. */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnet = list_head(&ips->ips_str_list); ipnet != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet = list_next(&ips->ips_str_list, ipnet)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_if == ipnetif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) putnextctl(ipnet->ipnet_rq, M_HANGUP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_dec(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_remove(&ips->ips_avl_by_index, ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_remove(&ips->ips_avl_by_name, ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Release the reference we implicitly held in ipnetif_create().
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_purge_addrlist(list_t *addrlist)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_addr_t *ifa;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while ((ifa = list_head(addrlist)) != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_remove(addrlist, ifa);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ifa->ifa_shared != NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_clone_release(ifa->ifa_shared);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ifa, sizeof (*ifa));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_free(ipnetif_t *ipnetif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(ipnetif->if_refcnt == 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ipnetif->if_sharecnt == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* Remove IPv4/v6 address lists from the ipnetif */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_purge_addrlist(&ipnetif->if_ip4addr_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_destroy(&ipnetif->if_ip4addr_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_purge_addrlist(&ipnetif->if_ip6addr_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_destroy(&ipnetif->if_ip6addr_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_destroy(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_destroy(&ipnetif->if_reflock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnetif->if_dev != 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed id_free(ipnet_minor_space, getminor(ipnetif->if_dev));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ipnetif, sizeof (*ipnetif));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Create an ipnetif_addr_t with the given logical interface id (lif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * and add it to the supplied ipnetif. The lif is the netinfo
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * representation of logical interface id, and we use this id to match
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * incoming netinfo events against our lists of addresses.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_add_ifaddr(uint64_t lif, ipnetif_t *ipnetif, net_handle_t nd)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_addr_t *ifaddr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk zoneid_t zoneid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk struct sockaddr_in bcast;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk struct sockaddr_storage addr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk net_ifaddr_t type = NA_ADDRESS;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk uint64_t phyif = ipnetif->if_index;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (net_getlifaddr(nd, phyif, lif, 1, &type, &addr) != 0 ||
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk net_getlifzone(nd, phyif, lif, &zoneid) != 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ifaddr = kmem_alloc(sizeof (*ifaddr), KM_NOSLEEP)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr->ifa_zone = zoneid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr->ifa_id = lif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifaddr->ifa_shared = NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (addr.ss_family) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr->ifa_ip4addr =
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Try and get the broadcast address. Note that it's okay for
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * an interface to not have a broadcast address, so we don't
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * fail the entire operation if net_getlifaddr() fails here.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk type = NA_BROADCAST;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (net_getlifaddr(nd, phyif, lif, 1, &type, &bcast) == 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr->ifa_brdaddr = bcast.sin_addr.s_addr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case AF_INET6:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr->ifa_ip6addr = ((struct sockaddr_in6 *)&addr)->sin6_addr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed /*
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed * The zoneid stored in ipnetif_t needs to correspond to the actual
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed * zone the address is being used in. This facilitates finding the
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed * correct netstack_t pointer, amongst other things, later.
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed */
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed if (zoneid == ALL_ZONES)
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed zoneid = GLOBAL_ZONEID;
7b57f05abb8796d3c91c8d4d4c75dcafb5af6b69Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (zoneid != ipnetif->if_zoneid) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ifp2;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifp2 = ipnetif_clone_create(ipnetif, zoneid);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifaddr->ifa_shared = ifp2;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_insert_tail(addr.ss_family == AF_INET ?
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnetif->if_ip4addr_list : &ipnetif->if_ip6addr_list, ifaddr);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_delete_ifaddr(ipnetif_addr_t *ifaddr, ipnetif_t *ipnetif, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ifaddr->ifa_shared != NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_clone_release(ifaddr->ifa_shared);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_remove(isv6 ?
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list, ifaddr);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ifaddr, sizeof (*ifaddr));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_plumb_ev(ipnet_nicevent_t *ipne, ipnet_stack_t *ips, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk boolean_t refrele_needed = B_TRUE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uint64_t ifflags;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uint64_t ifindex;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed char *ifname;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifflags = 0;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifname = ipne->ipne_ifname;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifindex = ipne->ipne_ifindex;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_getlifflags(ipne->ipne_protocol, ifindex, 0, &ifflags);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif = ipnetif_create(ifname, ifindex, ips, ifflags);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk refrele_needed = B_FALSE;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags |=
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk isv6 ? IPNETIF_IPV6PLUMBED : IPNETIF_IPV4PLUMBED;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_multicnt != 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ip_join_allmulti(ifindex, isv6,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_netstack->netstack_ip) == 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags |=
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk isv6 ? IPNETIF_IPV6ALLMULTI : IPNETIF_IPV4ALLMULTI;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (refrele_needed)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_unplumb_ev(uint64_t ifindex, ipnet_stack_t *ips, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_purge_addrlist(isv6 ?
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Note that we have one ipnetif for both IPv4 and IPv6, but we receive
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * separate NE_UNPLUMB events for IPv4 and IPv6. We remove the ipnetif
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * if both IPv4 and IPv6 interfaces have been unplumbed.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_flags &= isv6 ? ~IPNETIF_IPV6PLUMBED : ~IPNETIF_IPV4PLUMBED;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (!(ipnetif->if_flags & (IPNETIF_IPV4PLUMBED | IPNETIF_IPV6PLUMBED)))
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_remove(ipnetif, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_lifup_ev(uint64_t ifindex, uint64_t lifindex, net_handle_t nd,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_addr_t *ifaddr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ifaddr = ipnet_match_lif(ipnetif, lifindex, isv6)) != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * We must have missed a NE_LIF_DOWN event. Delete this
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * ifaddr and re-create it.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_delete_ifaddr(ifaddr, ipnetif, isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_add_ifaddr(lifindex, ipnetif, nd);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_lifdown_ev(uint64_t ifindex, uint64_t lifindex, ipnet_stack_t *ips,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_addr_t *ifaddr;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ipnetif = ipnetif_getby_index(ifindex, ips)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ifaddr = ipnet_match_lif(ipnetif, lifindex, isv6)) != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_delete_ifaddr(ifaddr, ipnetif, isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refrele(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Make sure that open streams on this ipnetif are still allowed to
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * have it open.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_zonecheck(ipnetif, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * This callback from the NIC event framework dispatches a taskq as the event
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * handlers may block.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_nicevent_cb(hook_event_token_t token, hook_data_t info, void *arg)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips = arg;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk hook_nic_event_t *hn = (hook_nic_event_t *)info;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_nicevent_t *ipne;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ipne = kmem_alloc(sizeof (ipnet_nicevent_t), KM_NOSLEEP)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_event = hn->hne_event;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_protocol = hn->hne_protocol;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_stackid = ips->ips_netstack->netstack_stackid;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_ifindex = hn->hne_nic;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_lifindex = hn->hne_lif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (hn->hne_datalen != 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) strlcpy(ipne->ipne_ifname, hn->hne_data,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk sizeof (ipne->ipne_ifname));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) ddi_taskq_dispatch(ipnet_nicevent_taskq, ipnet_nicevent_task,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne, DDI_NOSLEEP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_nicevent_task(void *arg)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_nicevent_t *ipne = arg;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_t *ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk boolean_t isv6;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ns = netstack_find_by_stackid(ipne->ipne_stackid)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk goto done;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = ns->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk isv6 = (ipne->ipne_protocol == ips->ips_ndv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk switch (ipne->ipne_event) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case NE_PLUMB:
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_plumb_ev(ipne, ips, isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case NE_UNPLUMB:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_unplumb_ev(ipne->ipne_ifindex, ips, isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case NE_LIF_UP:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_lifup_ev(ipne->ipne_ifindex, ipne->ipne_lifindex,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipne->ipne_protocol, ips, isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case NE_LIF_DOWN:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_lifdown_ev(ipne->ipne_ifindex, ipne->ipne_lifindex, ips,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk isv6);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk default:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_event_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdone:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ns != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_rele(ns);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ipne, sizeof (ipnet_nicevent_t));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkdev_t
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_if_getdev(char *name, zoneid_t zoneid)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_t *ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dev_t dev = (dev_t)-1;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (is_system_labeled() && zoneid != GLOBAL_ZONEID)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (dev);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ns = netstack_find_by_zoneid(zoneid)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (dev);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = ns->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ipnetif = avl_find(&ips->ips_avl_by_name, name, NULL)) != NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnetif_in_zone(ipnetif, zoneid, ips))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk dev = ipnetif->if_dev;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_rele(ns);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (dev);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnetif_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_getby_index(uint64_t id, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ipnetif = avl_find(&ips->ips_avl_by_index, &id, NULL)) != NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refhold(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnetif_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_getby_dev(dev_t dev, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_tree_t *tree;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk tree = &ips->ips_avl_by_index;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnetif = avl_first(tree); ipnetif != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif = avl_walk(tree, ipnetif, AVL_AFTER)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnetif->if_dev == dev) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_refhold(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic ipnetif_addr_t *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_match_lif(ipnetif_t *ipnetif, lif_if_t lid, boolean_t isv6)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_addr_t *ifaddr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed list_t *list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list = isv6 ? &ipnetif->if_ip6addr_list : &ipnetif->if_ip4addr_list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ifaddr = list_head(list); ifaddr != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifaddr = list_next(list, ifaddr)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (lid == ifaddr->ifa_id)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ifaddr);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void *
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_stack_init(netstackid_t stackid, netstack_t *ns)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = kmem_zalloc(sizeof (*ips), KM_SLEEP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_netstack = ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_init(&ips->ips_avl_lock, NULL, MUTEX_DEFAULT, 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_create(&ips->ips_avl_by_index, ipnetif_compare_index,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_index));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_create(&ips->ips_avl_by_name, ipnetif_compare_name,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_name));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_create(&ips->ips_avl_by_shared, ipnetif_compare_name_zone,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed sizeof (ipnetif_t), offsetof(ipnetif_t, if_avl_by_shared));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_init(&ips->ips_walkers_lock, NULL, MUTEX_DEFAULT, NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cv_init(&ips->ips_walkers_cv, NULL, CV_DRIVER, NULL);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_create(&ips->ips_str_list, sizeof (ipnet_t),
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk offsetof(ipnet_t, ipnet_next));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_register_netihook(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* ARGSUSED */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_stack_fini(netstackid_t stackid, void *arg)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips = arg;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_t *ipnetif, *nipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ips->ips_kstatp != NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed zoneid_t zoneid;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed zoneid = netstackid_to_zoneid(stackid);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed net_kstat_delete(net_zoneidtonetid(zoneid), ips->ips_kstatp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ips->ips_ndv4 != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(net_hook_unregister(ips->ips_ndv4, NH_NIC_EVENTS,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_nicevents) == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(net_protocol_release(ips->ips_ndv4) == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ips->ips_ndv6 != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(net_hook_unregister(ips->ips_ndv6, NH_NIC_EVENTS,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_nicevents) == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk VERIFY(net_protocol_release(ips->ips_ndv6) == 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk hook_free(ips->ips_nicevents);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnetif = avl_first(&ips->ips_avl_by_index); ipnetif != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif = nipnetif) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk nipnetif = AVL_NEXT(&ips->ips_avl_by_index, ipnetif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_remove(ipnetif, ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_destroy(&ips->ips_avl_by_shared);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_destroy(&ips->ips_avl_by_index);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk avl_destroy(&ips->ips_avl_by_name);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_destroy(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_destroy(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cv_destroy(&ips->ips_walkers_cv);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_destroy(&ips->ips_str_list);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(ips, sizeof (*ips));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* Do any of the addresses in addrlist belong the supplied zoneid? */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic boolean_t
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_addrs_in_zone(list_t *addrlist, zoneid_t zoneid)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_addr_t *ifa;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ifa = list_head(addrlist); ifa != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ifa = list_next(addrlist, ifa)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ifa->ifa_zone == zoneid)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_TRUE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_FALSE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/* Should the supplied ipnetif be visible from the supplied zoneid? */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic boolean_t
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_in_zone(ipnetif_t *ipnetif, zoneid_t zoneid, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int ret;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The global zone has visibility into all interfaces in the global
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * stack, and exclusive stack zones have visibility into all
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * interfaces in their stack.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (zoneid == GLOBAL_ZONEID ||
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (B_TRUE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Shared-stack zones only have visibility for interfaces that have
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * addresses in their zone.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ret = ipnet_addrs_in_zone(&ipnetif->if_ip4addr_list, zoneid) ||
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_addrs_in_zone(&ipnetif->if_ip6addr_list, zoneid);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_addr_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (ret);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk/*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * Verify that any ipnet_t that has a reference to the supplied ipnetif should
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * still be allowed to have it open. A given ipnet_t may no longer be allowed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * to have an ipnetif open if there are no longer any addresses that belong to
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * the ipnetif in the ipnet_t's non-global shared-stack zoneid. If that's the
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * case, send the ipnet_t an M_HANGUP.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_zonecheck(ipnetif_t *ipnetif, ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_t *strlist = &ips->ips_str_list;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_t *ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_inc(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnet = list_head(strlist); ipnet != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet = list_next(strlist, ipnet)) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (ipnet->ipnet_if != ipnetif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (!ipnetif_in_zone(ipnetif, ipnet->ipnet_zoneid, ips))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) putnextctl(ipnet->ipnet_rq, M_HANGUP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_walkers_dec(ips);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkvoid
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_walk_if(ipnet_walkfunc_t *cb, void *arg, zoneid_t zoneid)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ipnetif;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_t cbdata;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif_cbdata_t *cbnode;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_t *ns;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnet_stack_t *ips;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * On labeled systems, non-global zones shouldn't see anything
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * in /dev/ipnet.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (is_system_labeled() && zoneid != GLOBAL_ZONEID)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if ((ns = netstack_find_by_zoneid(zoneid)) == NULL)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips = ns->netstack_ipnet;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_create(&cbdata, sizeof (ipnetif_cbdata_t),
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk offsetof(ipnetif_cbdata_t, ic_next));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk for (ipnetif = avl_first(&ips->ips_avl_by_index); ipnetif != NULL;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif = avl_walk(&ips->ips_avl_by_index, ipnetif, AVL_AFTER)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (!ipnetif_in_zone(ipnetif, zoneid, ips))
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk continue;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cbnode = kmem_zalloc(sizeof (ipnetif_cbdata_t), KM_SLEEP);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk (void) strlcpy(cbnode->ic_ifname, ipnetif->if_name, LIFNAMSIZ);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cbnode->ic_dev = ipnetif->if_dev;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_insert_head(&cbdata, cbnode);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_avl_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk while ((cbnode = list_head(&cbdata)) != NULL) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cb(cbnode->ic_ifname, arg, cbnode->ic_dev);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_remove(&cbdata, cbnode);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk kmem_free(cbnode, sizeof (ipnetif_cbdata_t));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk list_destroy(&cbdata);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk netstack_rele(ns);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_compare_index(const void *index_ptr, const void *ipnetifp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int64_t index1 = *((int64_t *)index_ptr);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int64_t index2 = (int64_t)((ipnetif_t *)ipnetifp)->if_index;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (SIGNOF(index2 - index1));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_compare_name(const void *name_ptr, const void *ipnetifp)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int res;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk res = strcmp(((ipnetif_t *)ipnetifp)->if_name, name_ptr);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk return (SIGNOF(res));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_compare_name_zone(const void *key_ptr, const void *ipnetifp)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed const uintptr_t *ptr = key_ptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed const ipnetif_t *ifp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int res;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifp = ipnetifp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed res = ifp->if_zoneid - ptr[0];
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (res != 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (SIGNOF(res));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed res = strcmp(ifp->if_name, (char *)ptr[1]);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (SIGNOF(res));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnetif_refhold(ipnetif_t *ipnetif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_reflock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ipnetif->if_refcnt++;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_reflock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnetif_refrele(ipnetif_t *ipnetif)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ipnetif->if_reflock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ipnetif->if_refcnt > 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (--ipnetif->if_refcnt == 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_free(ipnetif);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk else
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ipnetif->if_reflock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_walkers_inc(ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ips->ips_walkers_cnt++;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkstatic void
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirkipnet_walkers_dec(ipnet_stack_t *ips)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk{
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_enter(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(ips->ips_walkers_cnt != 0);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (--ips->ips_walkers_cnt == 0)
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk cv_broadcast(&ips->ips_walkers_cv);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk mutex_exit(&ips->ips_walkers_lock);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*ARGSUSED*/
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipobs_bounce_func(hook_event_token_t token, hook_data_t info, void *arg)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_pkt_observe_t *hdr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed pfv_t func = (pfv_t)arg;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mblk_t *mp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hdr = (hook_pkt_observe_t *)info;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra /*
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * Code in ip_input() expects that it is the only one accessing the
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra * packet.
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra */
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra mp = copymsg(hdr->hpo_pkt);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra if (mp == NULL) {
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra netstack_t *ns = hdr->hpo_ctx;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra ipnet_stack_t *ips = ns->netstack_ipnet;
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra IPSK_BUMP(ips, ik_dispatchDupDrop);
dbed73cbda2229fd1aa6dc5743993cae7f0a7ee9Sangeeta Misra return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hdr = (hook_pkt_observe_t *)mp->b_rptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hdr->hpo_pkt = mp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed func(mp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedhook_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipobs_register_hook(netstack_t *ns, pfv_t func)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ip_stack_t *ipst = ns->netstack_ip;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed char name[32];
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_t *hook;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed HOOK_INIT(hook, ipobs_bounce_func, "", (void *)func);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY(hook != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * To register multiple hooks with he same callback function,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * a unique name is needed.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
391710f23076bd83c9cf29287fda8576773aec1eDarren Reed (void) snprintf(name, sizeof (name), "ipobserve_%p", (void *)hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook->h_name = strdup(name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_hook_register(ipst->ips_ip4_observe_pr, NH_OBSERVE, hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_hook_register(ipst->ips_ip6_observe_pr, NH_OBSERVE, hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedvoid
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipobs_unregister_hook(netstack_t *ns, hook_t *hook)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ip_stack_t *ipst = ns->netstack_ip;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_hook_unregister(ipst->ips_ip4_observe_pr, NH_OBSERVE, hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_hook_unregister(ipst->ips_ip6_observe_pr, NH_OBSERVE, hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed strfree(hook->h_name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_free(hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/* ******************************************************************** */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/* BPF Functions below */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/* ******************************************************************** */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Convenience function to make mapping a zoneid to an ipnet_stack_t easy.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reedipnet_stack_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_find_by_zoneid(zoneid_t zoneid)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed netstack_t *ns;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY((ns = netstack_find_by_zoneid(zoneid)) != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ns->netstack_ipnet);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * Functions, such as the above ipnet_find_by_zoneid(), will return a
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * pointer to ipnet_stack_t by calling a netstack lookup function.
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * The netstack_find_*() functions return a pointer after doing a "hold"
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * on the data structure and thereby require a "release" when the caller
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * is finished with it. We need to mirror that API here and thus a caller
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * of ipnet_find_by_zoneid() is required to call ipnet_rele().
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reedvoid
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reedipnet_rele(ipnet_stack_t *ips)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed netstack_rele(ips->ips_netstack);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedvoid
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reedipnet_set_itap(bpf_itap_fn_t tapfunc)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnet_itap = tapfunc;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * The list of interfaces available via ipnet is private for each zone,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * so the AVL tree of each zone must be searched for a given name, even
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * if all names are unique.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedint
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_open_byname(const char *name, ipnetif_t **ptr, zoneid_t zoneid)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ipnetif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ptr != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_enter(&ips->ips_avl_lock);
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed /*
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed * Shared instance zone?
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed */
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed if (netstackid_to_zoneid(zoneid_to_netstackid(zoneid)) != zoneid) {
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed uintptr_t key[2] = { zoneid, (uintptr_t)name };
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnetif = avl_find(&ips->ips_avl_by_shared, (void *)key, NULL);
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed } else {
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnetif = avl_find(&ips->ips_avl_by_name, (void *)name, NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed if (ipnetif != NULL)
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnetif_refhold(ipnetif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *ptr = ipnetif;
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnet_rele(ips);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ipnetif == NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ESRCH);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedvoid
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_close_byhandle(ipnetif_t *ifp)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ifp != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_refrele(ifp);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedconst char *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_name(ipnetif_t *ifp)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ifp != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ifp->if_name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * To find the linkid for a given name, it is necessary to know which zone
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * the interface name belongs to and to search the avl tree for that zone
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * as there is no master list of all interfaces and which zone they belong
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * to. It is assumed that the caller of this function is somehow already
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * working with the ipnet interfaces and hence the ips_event_lock is held.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * When BPF calls into this function, it is doing so because of an event
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * in ipnet, and thus ipnet holds the ips_event_lock. Thus the datalink id
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * value returned has meaning without the need for grabbing a hold on the
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * owning structure.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedint
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_get_linkid_byname(const char *name, uint_t *idp, zoneid_t zoneid)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ifp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY((ips = ipnet_find_by_zoneid(zoneid)) != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(mutex_owned(&ips->ips_event_lock));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_enter(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifp = avl_find(&ips->ips_avl_by_name, (void *)name, NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ifp != NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *idp = (uint_t)ifp->if_index;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Shared instance zone?
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (netstackid_to_zoneid(zoneid_to_netstackid(zoneid)) != zoneid) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uintptr_t key[2] = { zoneid, (uintptr_t)name };
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifp = avl_find(&ips->ips_avl_by_shared, (void *)key, NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ifp != NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *idp = (uint_t)ifp->if_index;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ipnet_rele(ips);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (ifp == NULL)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (ESRCH);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * Strictly speaking, there is no such thing as a "client" in ipnet, like
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * there is in mac. BPF only needs to have this because it is required as
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * part of interfacing correctly with mac. The reuse of the original
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * ipnetif_t as a client poses no danger, so long as it is done with its
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * own ref-count'd hold that is given up on close.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedint
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_client_open(ipnetif_t *ptr, ipnetif_t **result)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ptr != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(result != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_refhold(ptr);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *result = ptr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedvoid
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_client_close(ipnetif_t *ptr)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ptr != NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_refrele(ptr);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * This is called from BPF when it needs to start receiving packets
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * from ipnet.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * The use of the ipnet_t structure here is somewhat lightweight when
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * compared to how it is used elsewhere but it already has all of the
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * right fields in it, so reuse here doesn't seem out of order. Its
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * primary purpose here is to provide the means to store pointers for
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * use when ipnet_promisc_remove() needs to be called.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * This should never be called for the IPNET_MINOR_LO device as it is
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * never created via ipnetif_create.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*ARGSUSED*/
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedint
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_promisc_add(void *handle, uint_t how, void *data, uintptr_t *mhandle,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int flags)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ip_stack_t *ipst;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed netstack_t *ns;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *ifp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_t *ipnet;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed char name[32];
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed int error;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ifp = (ipnetif_t *)handle;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill if (how != DL_PROMISC_PHYS && how != DL_PROMISC_MULTI)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (EINVAL);
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill ns = netstack_find_by_zoneid(ifp->if_zoneid);
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill if ((error = ipnet_join_allmulti(ifp, ns->netstack_ipnet)) != 0) {
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill netstack_rele(ns);
854956ce2a18fd37e3f6160d38ffb87fdbc2edc4Bryan Cantrill return (error);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet = kmem_zalloc(sizeof (*ipnet), KM_SLEEP);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_if = ifp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_ns = ns;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_flags = flags;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if ((ifp->if_flags & IPNETIF_LOOPBACK) != 0) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_acceptfn = ipnet_loaccept;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_acceptfn = ipnet_accept;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed /*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * To register multiple hooks with the same callback function,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * a unique name is needed.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed HOOK_INIT(ipnet->ipnet_hook, ipnet_bpf_bounce, "", ipnet);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) snprintf(name, sizeof (name), "ipnet_promisc_%p",
391710f23076bd83c9cf29287fda8576773aec1eDarren Reed (void *)ipnet->ipnet_hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_hook->h_name = strdup(name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_data = data;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_zoneid = ifp->if_zoneid;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipst = ns->netstack_ip;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed error = net_hook_register(ipst->ips_ip4_observe_pr, NH_OBSERVE,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (error != 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed goto regfail;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed error = net_hook_register(ipst->ips_ip6_observe_pr, NH_OBSERVE,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet->ipnet_hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (error != 0) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) net_hook_unregister(ipst->ips_ip4_observe_pr,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed NH_OBSERVE, ipnet->ipnet_hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed goto regfail;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *mhandle = (uintptr_t)ipnet;
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed netstack_rele(ns);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedregfail:
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed cmn_err(CE_WARN, "net_hook_register failed: %d", error);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed strfree(ipnet->ipnet_hook->h_name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_free(ipnet->ipnet_hook);
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed netstack_rele(ns);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (error);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedvoid
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_promisc_remove(void *data)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ip_stack_t *ipst;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_t *ipnet;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_t *hook;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet = data;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipst = ipnet->ipnet_ns->netstack_ip;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook = ipnet->ipnet_hook;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY(net_hook_unregister(ipst->ips_ip4_observe_pr, NH_OBSERVE,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook) == 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed VERIFY(net_hook_unregister(ipst->ips_ip6_observe_pr, NH_OBSERVE,
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook) == 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed strfree(hook->h_name);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_free(hook);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed kmem_free(ipnet, sizeof (*ipnet));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * arg here comes from the ipnet_t allocated in ipnet_promisc_add.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * An important field from that structure is "ipnet_data" that
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * contains the "data" pointer passed into ipnet_promisc_add: it needs
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * to be passed back to bpf when we call into ipnet_itap.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * ipnet_itap is set by ipnet_set_bpfattach, which in turn is called
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * from BPF.
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*ARGSUSED*/
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic int
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnet_bpf_bounce(hook_event_token_t token, hook_data_t info, void *arg)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hook_pkt_observe_t *hdr;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrp_t src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_addrp_t dst;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_t *ipnet;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mblk_t *netmp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mblk_t *mp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed hdr = (hook_pkt_observe_t *)info;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mp = hdr->hpo_pkt;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet = (ipnet_t *)arg;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ips = ((netstack_t *)hdr->hpo_ctx)->netstack_ipnet;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed netmp = hdr->hpo_pkt->b_cont;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_family = hdr->hpo_family;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_family = hdr->hpo_family;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (hdr->hpo_family == AF_INET) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_addr4 = &((ipha_t *)(netmp->b_rptr))->ipha_dst;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed } else {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed src.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_src;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dst.iap_addr6 = &((ip6_t *)(netmp->b_rptr))->ip6_dst;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (!(*ipnet->ipnet_acceptfn)(ipnet, hdr, &src, &dst)) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_acceptFail);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed IPSK_BUMP(ips, ik_acceptOk);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_itap(ipnet->ipnet_data, mp,
fc5884fc5cbeced353b19c8153bd02be0d801d97Darren Reed hdr->hpo_htype == htons(IPOBS_HOOK_OUTBOUND),
b7ea883b48e925772db7fa37388112c84c6d5f5bDarren Reed ntohl(hdr->hpo_pktlen) + MBLKL(mp));
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed/*
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * clone'd ipnetif_t's are created when a shared IP instance zone comes
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * to life and configures an IP address. The model that BPF uses is that
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * each interface must have a unique pointer and each interface must be
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * representative of what it can capture. They are limited to one DLT
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * per interface and one zone per interface. Thus every interface that
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * can be seen in a zone must be announced via an attach to bpf. For
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * shared instance zones, this means the ipnet driver needs to detect
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * when an address is added to an interface in a zone for the first
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed * time (and also when the last address is removed.)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed */
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic ipnetif_t *
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_clone_create(ipnetif_t *ifp, zoneid_t zoneid)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed uintptr_t key[2] = { zoneid, (uintptr_t)ifp->if_name };
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips = ifp->if_stackp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_index_t where = 0;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_t *newif;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_enter(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif = avl_find(&ips->ips_avl_by_shared, (void *)key, &where);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (newif != NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_refhold(newif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_sharecnt++;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (newif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif = ipnet_alloc_if(ips);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (newif == NULL) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (NULL);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_refcnt = 1;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_sharecnt = 1;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_zoneid = zoneid;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed (void) strlcpy(newif->if_name, ifp->if_name, LIFNAMSIZ);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_flags = ifp->if_flags & IPNETIF_LOOPBACK;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed newif->if_index = ifp->if_index;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_insert(&ips->ips_avl_by_shared, newif, where);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed return (newif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedstatic void
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reedipnetif_clone_release(ipnetif_t *ipnetif)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed{
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed boolean_t dofree = B_FALSE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed boolean_t doremove = B_FALSE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnet_stack_t *ips = ipnetif->if_stackp;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_enter(&ipnetif->if_reflock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ipnetif->if_refcnt > 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (--ipnetif->if_refcnt == 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed dofree = B_TRUE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ipnetif->if_sharecnt > 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (--ipnetif->if_sharecnt == 0)
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed doremove = B_TRUE;
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ipnetif->if_reflock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (doremove) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_enter(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed avl_remove(&ips->ips_avl_by_shared, ipnetif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed mutex_exit(&ips->ips_avl_lock);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed if (dofree) {
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ASSERT(ipnetif->if_sharecnt == 0);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed ipnetif_free(ipnetif);
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed }
0a0e9771ca0211c15f3ac4466b661c145feeb9e4Darren Reed}