1b127ac41SPhilip Kirk /* 2b127ac41SPhilip Kirk * CDDL HEADER START 3b127ac41SPhilip Kirk * 4b127ac41SPhilip Kirk * The contents of this file are subject to the terms of the 5b127ac41SPhilip Kirk * Common Development and Distribution License (the "License"). 6b127ac41SPhilip Kirk * You may not use this file except in compliance with the License. 7b127ac41SPhilip Kirk * 8b127ac41SPhilip Kirk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9b127ac41SPhilip Kirk * or http://www.opensolaris.org/os/licensing. 10b127ac41SPhilip Kirk * See the License for the specific language governing permissions 11b127ac41SPhilip Kirk * and limitations under the License. 12b127ac41SPhilip Kirk * 13b127ac41SPhilip Kirk * When distributing Covered Code, include this CDDL HEADER in each 14b127ac41SPhilip Kirk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15b127ac41SPhilip Kirk * If applicable, add the following below this CDDL HEADER, with the 16b127ac41SPhilip Kirk * fields enclosed by brackets "[]" replaced with your own identifying 17b127ac41SPhilip Kirk * information: Portions Copyright [yyyy] [name of copyright owner] 18b127ac41SPhilip Kirk * 19b127ac41SPhilip Kirk * CDDL HEADER END 20b127ac41SPhilip Kirk */ 21b127ac41SPhilip Kirk 22b127ac41SPhilip Kirk /* 230a0e9771SDarren Reed * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24b127ac41SPhilip Kirk * Use is subject to license terms. 25b127ac41SPhilip Kirk */ 26b127ac41SPhilip Kirk 27b127ac41SPhilip Kirk #ifndef _INET_IPNET_H 28b127ac41SPhilip Kirk #define _INET_IPNET_H 29b127ac41SPhilip Kirk 30b127ac41SPhilip Kirk #ifdef __cplusplus 31b127ac41SPhilip Kirk extern "C" { 32b127ac41SPhilip Kirk #endif 33b127ac41SPhilip Kirk 34b127ac41SPhilip Kirk #include <sys/types.h> 35b127ac41SPhilip Kirk #include <sys/netstack.h> 36b127ac41SPhilip Kirk #include <sys/list.h> 37b127ac41SPhilip Kirk #include <netinet/in.h> 38b127ac41SPhilip Kirk #include <net/if.h> 390a0e9771SDarren Reed #include <net/bpf.h> 40b7ea883bSDarren Reed #include <net/bpfdesc.h> 41b127ac41SPhilip Kirk #include <sys/avl.h> 42b127ac41SPhilip Kirk #include <sys/neti.h> 430a0e9771SDarren Reed #include <sys/hook_event.h> 440a0e9771SDarren Reed #include <sys/zone.h> 450a0e9771SDarren Reed #include <sys/kstat.h> 460a0e9771SDarren Reed 47*9963d0d2SArne Jansen /* 48*9963d0d2SArne Jansen * ATTN: when changing this structure, also keep stats_template in ipnet.c 49*9963d0d2SArne Jansen * in sync 50*9963d0d2SArne Jansen */ 510a0e9771SDarren Reed typedef struct ipnet_kstats_s { 520a0e9771SDarren Reed kstat_named_t ik_duplicationFail; 530a0e9771SDarren Reed kstat_named_t ik_dispatchOk; 540a0e9771SDarren Reed kstat_named_t ik_dispatchFail; 550a0e9771SDarren Reed kstat_named_t ik_dispatchHeaderDrop; 560a0e9771SDarren Reed kstat_named_t ik_dispatchDupDrop; 570a0e9771SDarren Reed kstat_named_t ik_dispatchPutDrop; 580a0e9771SDarren Reed kstat_named_t ik_dispatchDeliver; 590a0e9771SDarren Reed kstat_named_t ik_acceptOk; 600a0e9771SDarren Reed kstat_named_t ik_acceptFail; 610a0e9771SDarren Reed } ipnet_kstats_t; 620a0e9771SDarren Reed 630a0e9771SDarren Reed #define IPSK_BUMP(_x, _y) (_x)->ips_stats._y.value.ui64++ 64b127ac41SPhilip Kirk 65b127ac41SPhilip Kirk /* 66b127ac41SPhilip Kirk * Structure used to hold information for both IPv4 and IPv6 addresses. 670a0e9771SDarren Reed * 680a0e9771SDarren Reed * When ifa_shared is non-NULL, it points to a "fake" ipnetif_t structure 690a0e9771SDarren Reed * that represents the network interface for each zone that shares its 700a0e9771SDarren Reed * network stack. This is used by BPF to build a list of interface names 710a0e9771SDarren Reed * present in each zone. Multiple ipnetif_addr_t's may point to a single 720a0e9771SDarren Reed * ipnetif_t using ifa_shared. The typical case is the global zone has 730a0e9771SDarren Reed * a bge0 that other zones use as bge0:1, bge0:2, etc. In ipnet, the 740a0e9771SDarren Reed * ipnetif_addr_t's that store the IP address for bge0:1, etc, would 750a0e9771SDarren Reed * point to an ipnetif_t stored in the if_avl_by_shared tree that has 760a0e9771SDarren Reed * the name "bge0". 77b127ac41SPhilip Kirk */ 78b127ac41SPhilip Kirk typedef struct ipnetif_addr { 79b127ac41SPhilip Kirk union { 80b127ac41SPhilip Kirk ipaddr_t ifau_ip4addr; 81b127ac41SPhilip Kirk in6_addr_t ifau_ip6addr; 82b127ac41SPhilip Kirk } ifa_addr; 83b127ac41SPhilip Kirk ipaddr_t ifa_brdaddr; 84b127ac41SPhilip Kirk zoneid_t ifa_zone; 85b127ac41SPhilip Kirk uint64_t ifa_id; 86b127ac41SPhilip Kirk list_node_t ifa_link; 870a0e9771SDarren Reed struct ipnetif *ifa_shared; 88b127ac41SPhilip Kirk } ipnetif_addr_t; 89b127ac41SPhilip Kirk #define ifa_ip4addr ifa_addr.ifau_ip4addr 90b127ac41SPhilip Kirk #define ifa_ip6addr ifa_addr.ifau_ip6addr 91b127ac41SPhilip Kirk 92b127ac41SPhilip Kirk /* 93b127ac41SPhilip Kirk * Structure describes the ipnet module representation of an ip interface. 94b127ac41SPhilip Kirk * The structure holds both IPv4 and IPv6 addresses, the address lists are 95b127ac41SPhilip Kirk * protected by a mutex. The ipnetif structures are held per stack instance 96b127ac41SPhilip Kirk * within avl trees indexed on name and ip index. 970a0e9771SDarren Reed * 980a0e9771SDarren Reed * if_avl_by_shared is used by zones that share their instance of IP with 990a0e9771SDarren Reed * other zones. It is used to store ipnetif_t structures. An example of this 1000a0e9771SDarren Reed * is the global zone sharing its instance of IP with other local zones. 1010a0e9771SDarren Reed * In this case, if_avl_by_shared is a tree of names that are in active use 1020a0e9771SDarren Reed * by zones using a shared instance of IP. 1030a0e9771SDarren Reed * The value in if_sharecnt represents the number of ipnetif_addr_t's that 1040a0e9771SDarren Reed * point to it. 105b127ac41SPhilip Kirk */ 106b127ac41SPhilip Kirk typedef struct ipnetif { 107b127ac41SPhilip Kirk char if_name[LIFNAMSIZ]; 108b127ac41SPhilip Kirk uint_t if_flags; 1090a0e9771SDarren Reed uint_t if_index; 110b127ac41SPhilip Kirk kmutex_t if_addr_lock; /* protects both addr lists */ 111b127ac41SPhilip Kirk list_t if_ip4addr_list; 112b127ac41SPhilip Kirk list_t if_ip6addr_list; 113b127ac41SPhilip Kirk avl_node_t if_avl_by_index; 114b127ac41SPhilip Kirk avl_node_t if_avl_by_name; 115b127ac41SPhilip Kirk dev_t if_dev; 116b127ac41SPhilip Kirk uint_t if_multicnt; /* protected by ips_event_lock */ 117b127ac41SPhilip Kirk kmutex_t if_reflock; /* protects if_refcnt */ 1180a0e9771SDarren Reed int if_refcnt; /* if_reflock */ 1190a0e9771SDarren Reed zoneid_t if_zoneid; 1200a0e9771SDarren Reed avl_node_t if_avl_by_shared; /* protected by ips_avl_lock */ 1210a0e9771SDarren Reed struct ipnet_stack *if_stackp; 1220a0e9771SDarren Reed int if_sharecnt; /* protected by if_reflock */ 123b127ac41SPhilip Kirk } ipnetif_t; 124b127ac41SPhilip Kirk 125b127ac41SPhilip Kirk /* if_flags */ 126b127ac41SPhilip Kirk #define IPNETIF_IPV4PLUMBED 0x01 127b127ac41SPhilip Kirk #define IPNETIF_IPV6PLUMBED 0x02 128b127ac41SPhilip Kirk #define IPNETIF_IPV4ALLMULTI 0x04 129b127ac41SPhilip Kirk #define IPNETIF_IPV6ALLMULTI 0x08 1300a0e9771SDarren Reed #define IPNETIF_LOOPBACK 0x10 131b127ac41SPhilip Kirk 132b127ac41SPhilip Kirk /* 133b127ac41SPhilip Kirk * Structure used by the accept callback function. This is simply an address 134b127ac41SPhilip Kirk * pointer into a packet (either IPv4 or IPv6), along with an address family 135b127ac41SPhilip Kirk * that denotes which pointer is valid. 136b127ac41SPhilip Kirk */ 137b127ac41SPhilip Kirk typedef struct ipnet_addrp { 138b127ac41SPhilip Kirk sa_family_t iap_family; 139b127ac41SPhilip Kirk union { 140b127ac41SPhilip Kirk ipaddr_t *iapu_addr4; 141b127ac41SPhilip Kirk in6_addr_t *iapu_addr6; 142b127ac41SPhilip Kirk } iap_addrp; 143b127ac41SPhilip Kirk } ipnet_addrp_t; 144b127ac41SPhilip Kirk #define iap_addr4 iap_addrp.iapu_addr4 145b127ac41SPhilip Kirk #define iap_addr6 iap_addrp.iapu_addr6 146b127ac41SPhilip Kirk 147b127ac41SPhilip Kirk struct ipnet; 148b127ac41SPhilip Kirk struct ipobs_hook_data; 1490a0e9771SDarren Reed typedef boolean_t ipnet_acceptfn_t(struct ipnet *, struct hook_pkt_observe_s *, 150b127ac41SPhilip Kirk ipnet_addrp_t *, ipnet_addrp_t *); 151b127ac41SPhilip Kirk 152b127ac41SPhilip Kirk /* 153b127ac41SPhilip Kirk * Per instance data for all open streams. Instance data is held on a 154b127ac41SPhilip Kirk * per netstack list see struct ipnet_stack below. 155b127ac41SPhilip Kirk */ 156b127ac41SPhilip Kirk typedef struct ipnet { 157b127ac41SPhilip Kirk queue_t *ipnet_rq; /* read queue pointer */ 158b127ac41SPhilip Kirk minor_t ipnet_minor; /* minor number for this instance */ 159b127ac41SPhilip Kirk ipnetif_t *ipnet_if; /* ipnetif for this open instance */ 160b127ac41SPhilip Kirk zoneid_t ipnet_zoneid; /* zoneid the device was opened in */ 1610a0e9771SDarren Reed uint_t ipnet_flags; /* see below */ 1620a0e9771SDarren Reed t_scalar_t ipnet_family; /* protocol family of this instance */ 163b127ac41SPhilip Kirk t_uscalar_t ipnet_dlstate; /* dlpi state */ 164b127ac41SPhilip Kirk list_node_t ipnet_next; /* list next member */ 165b127ac41SPhilip Kirk netstack_t *ipnet_ns; /* netstack of zone we were opened in */ 166b127ac41SPhilip Kirk ipnet_acceptfn_t *ipnet_acceptfn; /* accept callback function pointer */ 1670a0e9771SDarren Reed hook_t *ipnet_hook; /* hook token to unregister */ 1680a0e9771SDarren Reed void *ipnet_data; /* value to pass back to bpf_itap */ 169b127ac41SPhilip Kirk } ipnet_t; 170b127ac41SPhilip Kirk 171b127ac41SPhilip Kirk /* ipnet_flags */ 172b127ac41SPhilip Kirk #define IPNET_PROMISC_PHYS 0x01 173b127ac41SPhilip Kirk #define IPNET_PROMISC_MULTI 0x02 174b127ac41SPhilip Kirk #define IPNET_PROMISC_SAP 0x04 175b127ac41SPhilip Kirk #define IPNET_INFO 0x08 176b127ac41SPhilip Kirk #define IPNET_LOMODE 0x10 177b127ac41SPhilip Kirk 178b127ac41SPhilip Kirk /* 179b127ac41SPhilip Kirk * Per-netstack data holding: 180b127ac41SPhilip Kirk * - net_handle_t references for IPv4 and IPv6 for this netstack. 181b127ac41SPhilip Kirk * - avl trees by name and index for ip interfaces associated with this 182b127ac41SPhilip Kirk * netstack. The trees are protected by ips_avl_lock. 183b127ac41SPhilip Kirk * - ips_str_list is a list of open client streams. ips_walkers_lock in 184b127ac41SPhilip Kirk * conjunction with ips_walkers_cv and ips_walkers_cnt synchronize access to 185b127ac41SPhilip Kirk * the list. The count is incremented in ipnet_dispatch() at the start of a 186b127ac41SPhilip Kirk * walk and decremented when the walk is finished. If the walkers count is 0 187b127ac41SPhilip Kirk * then we cv_broadcast() waiting any threads waiting on the walkers count. 188b127ac41SPhilip Kirk * - ips_event_lock synchronizes ipnet_if_init() and incoming NIC info events. 189b127ac41SPhilip Kirk * We cannot be processing any NIC info events while initializing interfaces 190b127ac41SPhilip Kirk * in ipnet_if_init(). 191b127ac41SPhilip Kirk * 192b127ac41SPhilip Kirk * Note on lock ordering: If a thread needs to both hold the ips_event_lock 193b127ac41SPhilip Kirk * and any other lock such as ips_walkers_lock, ips_avl_lock, or if_addr_lock, 194b127ac41SPhilip Kirk * the ips_event_lock must be held first. This lock ordering is mandated by 195b127ac41SPhilip Kirk * ipnet_nicevent_cb() which must always grab ips_event_lock before continuing 196b127ac41SPhilip Kirk * with processing NIC events. 197b127ac41SPhilip Kirk */ 198b127ac41SPhilip Kirk typedef struct ipnet_stack { 199b127ac41SPhilip Kirk net_handle_t ips_ndv4; 200b127ac41SPhilip Kirk net_handle_t ips_ndv6; 201b127ac41SPhilip Kirk netstack_t *ips_netstack; 202b127ac41SPhilip Kirk hook_t *ips_nicevents; 203b127ac41SPhilip Kirk kmutex_t ips_event_lock; 204b127ac41SPhilip Kirk kmutex_t ips_avl_lock; 205b127ac41SPhilip Kirk avl_tree_t ips_avl_by_index; 206b127ac41SPhilip Kirk avl_tree_t ips_avl_by_name; 207b127ac41SPhilip Kirk kmutex_t ips_walkers_lock; 208b127ac41SPhilip Kirk kcondvar_t ips_walkers_cv; 209b127ac41SPhilip Kirk uint_t ips_walkers_cnt; 210b127ac41SPhilip Kirk list_t ips_str_list; 2110a0e9771SDarren Reed kstat_t *ips_kstatp; 2120a0e9771SDarren Reed ipnet_kstats_t ips_stats; 2130a0e9771SDarren Reed avl_tree_t ips_avl_by_shared; 2140a0e9771SDarren Reed hook_t *ips_hook; 215b127ac41SPhilip Kirk } ipnet_stack_t; 216b127ac41SPhilip Kirk 217b127ac41SPhilip Kirk /* 218b127ac41SPhilip Kirk * Template for dl_info_ack_t initialization. We don't have an address, so we 219b127ac41SPhilip Kirk * set the address length to just the SAP length (16 bits). We don't really 220b127ac41SPhilip Kirk * have a maximum SDU, but setting it to UINT_MAX proved problematic with 221b127ac41SPhilip Kirk * applications that performed arithmetic on dl_max_sdu and wrapped around, so 222b127ac41SPhilip Kirk * we sleaze out and use INT_MAX. 223b127ac41SPhilip Kirk */ 224b127ac41SPhilip Kirk #define IPNET_INFO_ACK_INIT { \ 225b127ac41SPhilip Kirk DL_INFO_ACK, /* dl_primitive */ \ 226b127ac41SPhilip Kirk INT_MAX, /* dl_max_sdu */ \ 227b127ac41SPhilip Kirk 0, /* dl_min_sdu */ \ 228b127ac41SPhilip Kirk sizeof (uint16_t), /* dl_addr_length */ \ 229b127ac41SPhilip Kirk DL_IPNET, /* dl_mac_type */ \ 230b127ac41SPhilip Kirk 0, /* dl_reserved */ \ 231b127ac41SPhilip Kirk 0, /* dl_current_state */ \ 232b127ac41SPhilip Kirk sizeof (uint16_t), /* dl_sap_length */ \ 233b127ac41SPhilip Kirk DL_CLDLS, /* dl_service_mode */ \ 234b127ac41SPhilip Kirk 0, /* dl_qos_length */ \ 235b127ac41SPhilip Kirk 0, /* dl_qos_offset */ \ 236b127ac41SPhilip Kirk 0, /* dl_range_length */ \ 237b127ac41SPhilip Kirk 0, /* dl_range_offset */ \ 238b127ac41SPhilip Kirk DL_STYLE1, /* dl_provider_style */ \ 239b127ac41SPhilip Kirk 0, /* dl_addr_offset */ \ 240b127ac41SPhilip Kirk DL_VERSION_2, /* dl_version */ \ 241b127ac41SPhilip Kirk 0, /* dl_brdcst_addr_length */ \ 242b127ac41SPhilip Kirk 0 /* dl_brdcst_addr_offset */ \ 243b127ac41SPhilip Kirk } 244b127ac41SPhilip Kirk 245b127ac41SPhilip Kirk typedef void ipnet_walkfunc_t(const char *, void *, dev_t); 2460a0e9771SDarren Reed 2470a0e9771SDarren Reed extern int ipnet_client_open(ipnetif_t *, ipnetif_t **); 2480a0e9771SDarren Reed extern void ipnet_client_close(ipnetif_t *); 2490a0e9771SDarren Reed extern void ipnet_close_byhandle(ipnetif_t *); 250b7ea883bSDarren Reed extern ipnet_stack_t *ipnet_find_by_zoneid(zoneid_t zoneid); 2510a0e9771SDarren Reed extern int ipnet_get_linkid_byname(const char *, datalink_id_t *, 2520a0e9771SDarren Reed zoneid_t); 253b127ac41SPhilip Kirk extern dev_t ipnet_if_getdev(char *, zoneid_t); 2540a0e9771SDarren Reed extern const char *ipnet_name(ipnetif_t *); 2550a0e9771SDarren Reed extern int ipnet_open_byname(const char *, ipnetif_t **, zoneid_t); 2560a0e9771SDarren Reed extern int ipnet_promisc_add(void *, uint_t, void *, uintptr_t *, int); 2570a0e9771SDarren Reed extern void ipnet_promisc_remove(void *); 258b7ea883bSDarren Reed extern void ipnet_rele(ipnet_stack_t *); 259b7ea883bSDarren Reed extern void ipnet_set_itap(bpf_itap_fn_t); 2600a0e9771SDarren Reed extern void ipnet_walk_if(ipnet_walkfunc_t *, void *, zoneid_t); 2610a0e9771SDarren Reed 2620a0e9771SDarren Reed extern bpf_provider_t bpf_ipnet; 263b127ac41SPhilip Kirk 264b127ac41SPhilip Kirk #ifdef __cplusplus 265b127ac41SPhilip Kirk } 266b127ac41SPhilip Kirk #endif 267b127ac41SPhilip Kirk 268b127ac41SPhilip Kirk #endif /* _INET_IPNET_H */ 269