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 2008 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 <sys/avl.h> 40 #include <sys/neti.h> 41 42 /* 43 * Structure used to hold information for both IPv4 and IPv6 addresses. 44 */ 45 typedef struct ipnetif_addr { 46 union { 47 ipaddr_t ifau_ip4addr; 48 in6_addr_t ifau_ip6addr; 49 } ifa_addr; 50 ipaddr_t ifa_brdaddr; 51 zoneid_t ifa_zone; 52 uint64_t ifa_id; 53 list_node_t ifa_link; 54 } ipnetif_addr_t; 55 #define ifa_ip4addr ifa_addr.ifau_ip4addr 56 #define ifa_ip6addr ifa_addr.ifau_ip6addr 57 58 /* 59 * Structure describes the ipnet module representation of an ip interface. 60 * The structure holds both IPv4 and IPv6 addresses, the address lists are 61 * protected by a mutex. The ipnetif structures are held per stack instance 62 * within avl trees indexed on name and ip index. 63 */ 64 typedef struct ipnetif { 65 char if_name[LIFNAMSIZ]; 66 uint_t if_flags; 67 uint64_t if_index; 68 kmutex_t if_addr_lock; /* protects both addr lists */ 69 list_t if_ip4addr_list; 70 list_t if_ip6addr_list; 71 avl_node_t if_avl_by_index; 72 avl_node_t if_avl_by_name; 73 dev_t if_dev; 74 uint_t if_multicnt; /* protected by ips_event_lock */ 75 kmutex_t if_reflock; /* protects if_refcnt */ 76 uint_t if_refcnt; 77 } ipnetif_t; 78 79 /* if_flags */ 80 #define IPNETIF_IPV4PLUMBED 0x01 81 #define IPNETIF_IPV6PLUMBED 0x02 82 #define IPNETIF_IPV4ALLMULTI 0x04 83 #define IPNETIF_IPV6ALLMULTI 0x08 84 85 /* 86 * Structure used by the accept callback function. This is simply an address 87 * pointer into a packet (either IPv4 or IPv6), along with an address family 88 * that denotes which pointer is valid. 89 */ 90 typedef struct ipnet_addrp { 91 sa_family_t iap_family; 92 union { 93 ipaddr_t *iapu_addr4; 94 in6_addr_t *iapu_addr6; 95 } iap_addrp; 96 } ipnet_addrp_t; 97 #define iap_addr4 iap_addrp.iapu_addr4 98 #define iap_addr6 iap_addrp.iapu_addr6 99 100 struct ipnet; 101 struct ipobs_hook_data; 102 typedef boolean_t ipnet_acceptfn_t(struct ipnet *, struct ipobs_hook_data *, 103 ipnet_addrp_t *, ipnet_addrp_t *); 104 105 /* 106 * Per instance data for all open streams. Instance data is held on a 107 * per netstack list see struct ipnet_stack below. 108 */ 109 typedef struct ipnet { 110 queue_t *ipnet_rq; /* read queue pointer */ 111 minor_t ipnet_minor; /* minor number for this instance */ 112 ipnetif_t *ipnet_if; /* ipnetif for this open instance */ 113 zoneid_t ipnet_zoneid; /* zoneid the device was opened in */ 114 uint16_t ipnet_flags; /* see below */ 115 t_scalar_t ipnet_sap; /* sap this instance is bound to */ 116 t_uscalar_t ipnet_dlstate; /* dlpi state */ 117 list_node_t ipnet_next; /* list next member */ 118 netstack_t *ipnet_ns; /* netstack of zone we were opened in */ 119 ipnet_acceptfn_t *ipnet_acceptfn; /* accept callback function pointer */ 120 } ipnet_t; 121 122 /* ipnet_flags */ 123 #define IPNET_PROMISC_PHYS 0x01 124 #define IPNET_PROMISC_MULTI 0x02 125 #define IPNET_PROMISC_SAP 0x04 126 #define IPNET_INFO 0x08 127 #define IPNET_LOMODE 0x10 128 129 /* 130 * Per-netstack data holding: 131 * - net_handle_t references for IPv4 and IPv6 for this netstack. 132 * - avl trees by name and index for ip interfaces associated with this 133 * netstack. The trees are protected by ips_avl_lock. 134 * - ips_str_list is a list of open client streams. ips_walkers_lock in 135 * conjunction with ips_walkers_cv and ips_walkers_cnt synchronize access to 136 * the list. The count is incremented in ipnet_dispatch() at the start of a 137 * walk and decremented when the walk is finished. If the walkers count is 0 138 * then we cv_broadcast() waiting any threads waiting on the walkers count. 139 * - ips_event_lock synchronizes ipnet_if_init() and incoming NIC info events. 140 * We cannot be processing any NIC info events while initializing interfaces 141 * in ipnet_if_init(). 142 * 143 * Note on lock ordering: If a thread needs to both hold the ips_event_lock 144 * and any other lock such as ips_walkers_lock, ips_avl_lock, or if_addr_lock, 145 * the ips_event_lock must be held first. This lock ordering is mandated by 146 * ipnet_nicevent_cb() which must always grab ips_event_lock before continuing 147 * with processing NIC events. 148 */ 149 typedef struct ipnet_stack { 150 net_handle_t ips_ndv4; 151 net_handle_t ips_ndv6; 152 netstack_t *ips_netstack; 153 hook_t *ips_nicevents; 154 kmutex_t ips_event_lock; 155 kmutex_t ips_avl_lock; 156 avl_tree_t ips_avl_by_index; 157 avl_tree_t ips_avl_by_name; 158 kmutex_t ips_walkers_lock; 159 kcondvar_t ips_walkers_cv; 160 uint_t ips_walkers_cnt; 161 list_t ips_str_list; 162 uint64_t ips_drops; 163 } ipnet_stack_t; 164 165 /* 166 * Template for dl_info_ack_t initialization. We don't have an address, so we 167 * set the address length to just the SAP length (16 bits). We don't really 168 * have a maximum SDU, but setting it to UINT_MAX proved problematic with 169 * applications that performed arithmetic on dl_max_sdu and wrapped around, so 170 * we sleaze out and use INT_MAX. 171 */ 172 #define IPNET_INFO_ACK_INIT { \ 173 DL_INFO_ACK, /* dl_primitive */ \ 174 INT_MAX, /* dl_max_sdu */ \ 175 0, /* dl_min_sdu */ \ 176 sizeof (uint16_t), /* dl_addr_length */ \ 177 DL_IPNET, /* dl_mac_type */ \ 178 0, /* dl_reserved */ \ 179 0, /* dl_current_state */ \ 180 sizeof (uint16_t), /* dl_sap_length */ \ 181 DL_CLDLS, /* dl_service_mode */ \ 182 0, /* dl_qos_length */ \ 183 0, /* dl_qos_offset */ \ 184 0, /* dl_range_length */ \ 185 0, /* dl_range_offset */ \ 186 DL_STYLE1, /* dl_provider_style */ \ 187 0, /* dl_addr_offset */ \ 188 DL_VERSION_2, /* dl_version */ \ 189 0, /* dl_brdcst_addr_length */ \ 190 0 /* dl_brdcst_addr_offset */ \ 191 } 192 193 typedef void ipnet_walkfunc_t(const char *, void *, dev_t); 194 extern void ipnet_walk_if(ipnet_walkfunc_t *, void *, zoneid_t); 195 extern dev_t ipnet_if_getdev(char *, zoneid_t); 196 197 #ifdef __cplusplus 198 } 199 #endif 200 201 #endif /* _INET_IPNET_H */ 202