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