diff options
author | Erik Nordmark <Erik.Nordmark@Sun.COM> | 2009-11-11 11:49:49 -0800 |
---|---|---|
committer | Erik Nordmark <Erik.Nordmark@Sun.COM> | 2009-11-11 11:49:49 -0800 |
commit | bd670b35a010421b6e1a5536c34453a827007c81 (patch) | |
tree | 97c2057b6771dd40411a12eb89d2db2e2b2cce31 /usr/src/uts/common/inet/ip/ipclassifier.c | |
parent | b3388e4fc5f5c24c8a39fbe132a00b02dae5b717 (diff) | |
download | illumos-joyent-bd670b35a010421b6e1a5536c34453a827007c81.tar.gz |
PSARC/2009/331 IP Datapath Refactoring
PSARC/2008/522 EOF of 2001/070 IPsec HW Acceleration support
PSARC/2009/495 netstat -r flags for blackhole and reject routes
PSARC 2009/496 EOF of XRESOLV
PSARC/2009/494 IP_DONTFRAG socket option
PSARC/2009/515 fragmentation controls for ping and traceroute
6798716 ip_newroute delenda est
6798739 ARP and IP are too separate
6807265 IPv4 ip2mac() support
6756382 Please remove Venus IPsec HWACCEL code
6880632 sendto/sendmsg never returns EHOSTUNREACH in Solaris
6748582 sendmsg() return OK, but doesn't send message using IPv4-mapped x IPv6 addr
1119790 TCP and path mtu discovery
4637227 should support equal-cost multi-path (ECMP)
5078568 getsockopt() for IPV6_PATHMTU on a non-connected socket should not succeed
6419648 "AR* contract private note" should be removed as part of ATM SW EOL
6274715 Arp could keep the old entry in the cache while it waits for an arp response
6605615 Remove duplicated TCP/IP opt_set/opt_get code; use conn_t
6874677 IP_TTL can be used to send with ttl zero
4034090 arp should not let you delete your own entry
6882140 Implement IP_DONTFRAG socket option
6883858 Implement ping -D option; traceroute -F should work for IPv6 and shared-IP zones
1119792 TCP/IP black hole detection is broken on receiver
4078796 Directed broadcast forwarding code has problems
4104337 restrict the IPPROTO_IP and IPPROTO_IPV6 options based on the socket family
4203747 Source address selection for source routed packets
4230259 pmtu is increased every ip_ire_pathmtu_interval timer value.
4300533 When sticky option ipv6_pktinfo set to bogus address subsequent connect time out
4471035 ire_delete_cache_gw is called through ire_walk unnecessarily
4514572 SO_DONTROUTE socket option doesn't work with IPv6
4524980 tcp_lookup_ipv4() should compare the ifindex against tcpb->tcpb_bound_if
4532714 machine fails to switch quickly among failed default routes
4634219 IPv6 path mtu discovery is broken when using routing header
4691581 udp broadcast handling causes too many replicas
4708405 mcast is broken on machines when all interfaces are IFF_POINTOPOINT
4770457 netstat/route: source address of interface routes pretends to be gateway address
4786974 use routing table to determine routes/interface for multicast
4792619 An ip_fanout_udp_ipc_v6() routine might lead to some simpler code
4816115 Nuke ipsec_out_use_global_policy
4862844 ipsec offload corner case
4867533 tcp_rq and tcp_wq are redundant
4868589 NCEs should be shared across an IPMP group
4872093 unplumbing an improper virtual interface panics in ip_newroute_get_dst_ill()
4901671 FireEngine needs some cleanup
4907617 IPsec identity latching should be done before sending SYN-ACK
4941461 scopeid and IPV6_PKTINFO with UDP/ICMP connect() does not work properly
4944981 ip does nothing with IP6I_NEXTHOP
4963353 IPv4 and IPv6 proto fanout codes could be brought closer
4963360 consider passing zoneid using ip6i_t instead of ipsec_out_t in NDP
4963734 new ip6_asp locking is used incorrectly in ip_newroute_v6()
5008315 IPv6 code passes ip6i_t to IPsec code instead of ip6_t
5009636 memory leak in ip_fanout_proto_v6()
5092337 tcp/udp option handling can use some cleanup
5035841 Solaris can fail to create a valid broadcast ire
5043747 ar_query_xmit: Could not find the ace
5051574 tcp_check_policy is missing some checks
6305037 full hardware checksum is discarded when there're more than 2 mblks in the chain
6311149 ip.c needs to be put through a woodchipper
4708860 Unable to reassemble CGTP fragmented multicast packets
6224628 Large IPv6 packets with IPsec protection sometimes have length mismatch.
6213243 Solaris does not currently support Dead Gateway Detection
5029091 duplicate code in IP's input path for TCP/UDP/SCTP
4674643 through IPv6 CGTP routes, the very first packet is sent only after a while
6207318 Multiple default routes do not round robin connections to routers.
4823410 IP has an inconsistent view of link mtu
5105520 adding interface route to down interface causes ifconfig hang
5105707 advanced sockets API introduced some dead code
6318399 IP option handling for icmp and udp is too complicated
6321434 Every dropped packet in IP should use ip_drop_packet()
6341693 ifconfig mtu should operate on the physical interface, not individual ipif's
6352430 The credentials attached to an mblk are not particularly useful
6357894 uninitialised ipp_hoplimit needs to be cleaned up.
6363568 ip_xmit_v6() may be missing IRE releases in error cases
6364828 ip_rput_forward needs a makeover
6384416 System panics when running as multicast forwarder using multicast tunnels
6402382 TX: UDP v6 slowpath is not modified to handle mac_exempt conns
6418413 assertion failed ipha->ipha_ident == 0||ipha->ipha_ident == 0xFFFF
6420916 assertion failures in ipv6 wput path
6430851 use of b_prev to store ifindex is not 100% safe
6446106 IPv6 packets stored in nce->nce_qd_mp will be sent with incorrect tcp/udp checksums
6453711 SCTP OOTB sent as if genetated by global zone
6465212 ARP/IP merge should remove ire_freemblk.esballoc
6490163 ip_input() could misbehave if the first mblk's size is not big enough
6496664 missing ipif_refrele leads to reference leak and deferred crash in ip_wput_ipsec_out_v6
6504856 memory leak in ip_fanout_proto_v6() when using link local outer tunnel addresses
6507765 IRE cache hash function performs badly
6510186 IP_FORWARD_PROG bit is easily overlooked
6514727 cgtp ipv6 failure on snv54
6528286 MULTIRT (CGTP) should offload checksum to hardware
6533904 SCTP: doesn't support traffic class for IPv6
6539415 TX: ipif source selection is flawed for unlabeled gateways
6539851 plumbed unworking nic blocks sending broadcast packets
6564468 non-solaris SCTP stack over rawip socket: netstat command counts rawipInData not rawipOutDatagrams
6568511 ipIfStatsOutDiscards not bumped when discarding an ipsec packet on the wrong NIC
6584162 tcp_g_q_inactive() makes incorrect use of taskq_dispatch()
6603974 round-robin default with many interfaces causes infinite temporary IRE thrashing
6611750 ilm_lookup_ill_index_v4 was born an orphan
6618423 ip_wput_frag_mdt sends out packets that void pfhooks
6620964 IRE max bucket count calculations performed in ip_ire_init() are flawed
6626266 various _broadcasts seem redundant
6638182 IP_PKTINFO + SO_DONTROUTE + CIPSO IP option == panic
6647710 IPv6 possible DoS vulnerability
6657357 nce should be kmem_cache alloc'ed from an nce_cache.
6685131 ilg_add -> conn_ilg_alloc interacting with conn_ilg[] walkers can cause panic.
6730298 adding 0.0.0.0 key with mask != 0 causes 'route delete default' to fail
6730976 vni and ipv6 doesn't quite work.
6740956 assertion failed: mp->b_next == 0L && mp->b_prev == 0L in nce_queue_mp_common()
6748515 BUMP_MIB() is occasionally done on the wrong ill
6753250 ip_output_v6() `notv6' error path has an errant ill_refrele()
6756411 NULL-pointer dereference in ip_wput_local()
6769582 IP must forward packet returned from FW-HOOK
6781525 bogus usesrc usage leads directly to panic
6422839 System paniced in ip_multicast_loopback due to NULL pointer dereference
6785521 initial IPv6 DAD solicitation is dropped in ip_newroute_ipif_v6()
6787370 ipnet devices not seeing forwarded IP packets on outgoing interface
6791187 ip*dbg() calls in ip_output_options() claim to originate from ip_wput()
6794047 nce_fp_mp prevents sharing of NCEs across an IPMP group
6797926 many unnecessary ip0dbg() in ip_rput_data_v6
6846919 Packet queued for ND gets sent in the clear.
6856591 ping doesn't send packets with DF set
6861113 arp module has incorrect dependency path for hook module
6865664 IPV6_NEXTHOP does not work with TCP socket
6874681 No ICMP time exceeded when a router receives packet with ttl = 0
6880977 ip_wput_ire() uses over 1k of stack
6595433 IPsec performance could be significantly better when calling hw crypto provider synchronously
6848397 ifconfig down of an interface can hang.
6849602 IPV6_PATHMTU size issue for UDP
6885359 Add compile-time option for testing pure IPsec overhead
6889268 Odd loopback source address selection with IPMP
6895420 assertion failed: connp->conn_helper_info == NULL
6851189 Routing-related panic occurred during reboot on T2000 system running snv_117
6896174 Post-async-encryption, AH+ESP packets may have misinitialized ipha/ip6
6896687 iptun presents IPv6 with an MTU < 1280
6897006 assertion failed: ipif->ipif_id != 0 in ip_sioctl_slifzone_restart
Diffstat (limited to 'usr/src/uts/common/inet/ip/ipclassifier.c')
-rw-r--r-- | usr/src/uts/common/inet/ip/ipclassifier.c | 1118 |
1 files changed, 420 insertions, 698 deletions
diff --git a/usr/src/uts/common/inet/ip/ipclassifier.c b/usr/src/uts/common/inet/ip/ipclassifier.c index 45683ec967..31fa14b4af 100644 --- a/usr/src/uts/common/inet/ip/ipclassifier.c +++ b/usr/src/uts/common/inet/ip/ipclassifier.c @@ -52,16 +52,12 @@ * asynchronous and the reference protects the connection from being destroyed * before its processing is finished). * - * send and receive functions are currently used for TCP only. The send function - * determines the IP entry point for the packet once it leaves TCP to be sent to - * the destination address. The receive function is used by IP when the packet - * should be passed for TCP processing. When a new connection is created these - * are set to ip_output() and tcp_input() respectively. During the lifetime of - * the connection the send and receive functions may change depending on the - * changes in the connection state. For example, Once the connection is bound to - * an addresse, the receive function for this connection is set to - * tcp_conn_request(). This allows incoming SYNs to go directly into the - * listener SYN processing function without going to tcp_input() first. + * conn_recv is used to pass up packets to the ULP. + * For TCP conn_recv changes. It is tcp_input_listener_unbound initially for + * a listener, and changes to tcp_input_listener as the listener has picked a + * good squeue. For other cases it is set to tcp_input_data. + * + * conn_recvicmp is used to pass up ICMP errors to the ULP. * * Classifier uses several hash tables: * @@ -91,8 +87,8 @@ * Connection Lookup: * ------------------ * - * conn_t *ipcl_classify_v4(mp, protocol, hdr_len, zoneid, ip_stack) - * conn_t *ipcl_classify_v6(mp, protocol, hdr_len, zoneid, ip_stack) + * conn_t *ipcl_classify_v4(mp, protocol, hdr_len, ira, ip_stack) + * conn_t *ipcl_classify_v6(mp, protocol, hdr_len, ira, ip_stack) * * Finds connection for an incoming IPv4 or IPv6 packet. Returns NULL if * it can't find any associated connection. If the connection is found, its @@ -107,9 +103,12 @@ * hdr_len: The size of IP header. It is used to find TCP or UDP header in * the packet. * - * zoneid: The zone in which the returned connection must be; the zoneid - * corresponding to the ire_zoneid on the IRE located for the - * packet's destination address. + * ira->ira_zoneid: The zone in which the returned connection must be; the + * zoneid corresponding to the ire_zoneid on the IRE located for + * the packet's destination address. + * + * ira->ira_flags: Contains the IRAF_TX_MAC_EXEMPTABLE and + * IRAF_TX_SHARED_ADDR flags * * For TCP connections, the lookup order is as follows: * 5-tuple {src, dst, protocol, local port, remote port} @@ -156,7 +155,7 @@ * any. In any event, the receiving socket must have SO_MAC_EXEMPT set and the * receiver's label must dominate the sender's default label. * - * conn_t *ipcl_tcp_lookup_reversed_ipv4(ipha_t *, tcph_t *, int, ip_stack); + * conn_t *ipcl_tcp_lookup_reversed_ipv4(ipha_t *, tcpha_t *, int, ip_stack); * conn_t *ipcl_tcp_lookup_reversed_ipv6(ip6_t *, tcpha_t *, int, uint_t, * ip_stack); * @@ -184,34 +183,26 @@ * Table Updates * ------------- * - * int ipcl_conn_insert(connp, protocol, src, dst, ports) - * int ipcl_conn_insert_v6(connp, protocol, src, dst, ports, ifindex) + * int ipcl_conn_insert(connp); + * int ipcl_conn_insert_v4(connp); + * int ipcl_conn_insert_v6(connp); * * Insert 'connp' in the ipcl_conn_fanout. * Arguements : * connp conn_t to be inserted - * protocol connection protocol - * src source address - * dst destination address - * ports local and remote port - * ifindex interface index for IPv6 connections * * Return value : * 0 if connp was inserted * EADDRINUSE if the connection with the same tuple * already exists. * - * int ipcl_bind_insert(connp, protocol, src, lport); - * int ipcl_bind_insert_v6(connp, protocol, src, lport); + * int ipcl_bind_insert(connp); + * int ipcl_bind_insert_v4(connp); + * int ipcl_bind_insert_v6(connp); * * Insert 'connp' in ipcl_bind_fanout. * Arguements : * connp conn_t to be inserted - * protocol connection protocol - * src source address connection wants - * to bind to - * lport local port connection wants to - * bind to * * * void ipcl_hash_remove(connp); @@ -261,6 +252,8 @@ #include <netinet/icmp6.h> #include <inet/ip.h> +#include <inet/ip_if.h> +#include <inet/ip_ire.h> #include <inet/ip6.h> #include <inet/ip_ndp.h> #include <inet/ip_impl.h> @@ -280,19 +273,6 @@ #include <sys/tsol/tnet.h> #include <sys/sockio.h> -#ifdef DEBUG -#define IPCL_DEBUG -#else -#undef IPCL_DEBUG -#endif - -#ifdef IPCL_DEBUG -int ipcl_debug_level = 0; -#define IPCL_DEBUG_LVL(level, args) \ - if (ipcl_debug_level & level) { printf args; } -#else -#define IPCL_DEBUG_LVL(level, args) {; } -#endif /* Old value for compatibility. Setable in /etc/system */ uint_t tcp_conn_hash_size = 0; @@ -336,10 +316,8 @@ typedef union itc_s { struct kmem_cache *tcp_conn_cache; struct kmem_cache *ip_conn_cache; -struct kmem_cache *ip_helper_stream_cache; extern struct kmem_cache *sctp_conn_cache; extern struct kmem_cache *tcp_sack_info_cache; -extern struct kmem_cache *tcp_iphc_cache; struct kmem_cache *udp_conn_cache; struct kmem_cache *rawip_conn_cache; struct kmem_cache *rts_conn_cache; @@ -362,34 +340,6 @@ static void rawip_conn_destructor(void *, void *); static int rts_conn_constructor(void *, void *, int); static void rts_conn_destructor(void *, void *); -static int ip_helper_stream_constructor(void *, void *, int); -static void ip_helper_stream_destructor(void *, void *); - -boolean_t ip_use_helper_cache = B_TRUE; - -/* - * Hook functions to enable cluster networking - * On non-clustered systems these vectors must always be NULL. - */ -extern void (*cl_inet_listen)(netstackid_t, uint8_t, sa_family_t, - uint8_t *, in_port_t, void *); -extern void (*cl_inet_unlisten)(netstackid_t, uint8_t, sa_family_t, - uint8_t *, in_port_t, void *); - -#ifdef IPCL_DEBUG -#define INET_NTOA_BUFSIZE 18 - -static char * -inet_ntoa_r(uint32_t in, char *b) -{ - unsigned char *p; - - p = (unsigned char *)∈ - (void) sprintf(b, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - return (b); -} -#endif - /* * Global (for all stack instances) init routine */ @@ -420,15 +370,6 @@ ipcl_g_init(void) sizeof (itc_t) + sizeof (rts_t), CACHE_ALIGN_SIZE, rts_conn_constructor, rts_conn_destructor, NULL, NULL, NULL, 0); - - if (ip_use_helper_cache) { - ip_helper_stream_cache = kmem_cache_create - ("ip_helper_stream_cache", sizeof (ip_helper_stream_info_t), - CACHE_ALIGN_SIZE, ip_helper_stream_constructor, - ip_helper_stream_destructor, NULL, NULL, NULL, 0); - } else { - ip_helper_stream_cache = NULL; - } } /* @@ -493,10 +434,10 @@ ipcl_init(ip_stack_t *ipst) MUTEX_DEFAULT, NULL); } - ipst->ips_ipcl_proto_fanout = kmem_zalloc(IPPROTO_MAX * + ipst->ips_ipcl_proto_fanout_v4 = kmem_zalloc(IPPROTO_MAX * sizeof (connf_t), KM_SLEEP); for (i = 0; i < IPPROTO_MAX; i++) { - mutex_init(&ipst->ips_ipcl_proto_fanout[i].connf_lock, NULL, + mutex_init(&ipst->ips_ipcl_proto_fanout_v4[i].connf_lock, NULL, MUTEX_DEFAULT, NULL); } @@ -576,11 +517,12 @@ ipcl_destroy(ip_stack_t *ipst) ipst->ips_ipcl_bind_fanout = NULL; for (i = 0; i < IPPROTO_MAX; i++) { - ASSERT(ipst->ips_ipcl_proto_fanout[i].connf_head == NULL); - mutex_destroy(&ipst->ips_ipcl_proto_fanout[i].connf_lock); + ASSERT(ipst->ips_ipcl_proto_fanout_v4[i].connf_head == NULL); + mutex_destroy(&ipst->ips_ipcl_proto_fanout_v4[i].connf_lock); } - kmem_free(ipst->ips_ipcl_proto_fanout, IPPROTO_MAX * sizeof (connf_t)); - ipst->ips_ipcl_proto_fanout = NULL; + kmem_free(ipst->ips_ipcl_proto_fanout_v4, + IPPROTO_MAX * sizeof (connf_t)); + ipst->ips_ipcl_proto_fanout_v4 = NULL; for (i = 0; i < IPPROTO_MAX; i++) { ASSERT(ipst->ips_ipcl_proto_fanout_v6[i].connf_head == NULL); @@ -636,7 +578,6 @@ conn_t * ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns) { conn_t *connp; - sctp_stack_t *sctps; struct kmem_cache *conn_cache; switch (type) { @@ -644,10 +585,10 @@ ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns) if ((connp = kmem_cache_alloc(sctp_conn_cache, sleep)) == NULL) return (NULL); sctp_conn_init(connp); - sctps = ns->netstack_sctp; - SCTP_G_Q_REFHOLD(sctps); netstack_hold(ns); connp->conn_netstack = ns; + connp->conn_ixa->ixa_ipst = ns->netstack_ip; + ipcl_globalhash_insert(connp); return (connp); case IPCL_TCPCONN: @@ -681,6 +622,7 @@ ipcl_conn_create(uint32_t type, int sleep, netstack_t *ns) connp->conn_ref = 1; netstack_hold(ns); connp->conn_netstack = ns; + connp->conn_ixa->ixa_ipst = ns->netstack_ip; ipcl_globalhash_insert(connp); return (connp); } @@ -693,61 +635,61 @@ ipcl_conn_destroy(conn_t *connp) ASSERT(!MUTEX_HELD(&connp->conn_lock)); ASSERT(connp->conn_ref == 0); - ASSERT(connp->conn_ire_cache == NULL); DTRACE_PROBE1(conn__destroy, conn_t *, connp); - if (connp->conn_effective_cred != NULL) { - crfree(connp->conn_effective_cred); - connp->conn_effective_cred = NULL; - } - if (connp->conn_cred != NULL) { crfree(connp->conn_cred); connp->conn_cred = NULL; } + if (connp->conn_ht_iphc != NULL) { + kmem_free(connp->conn_ht_iphc, connp->conn_ht_iphc_allocated); + connp->conn_ht_iphc = NULL; + connp->conn_ht_iphc_allocated = 0; + connp->conn_ht_iphc_len = 0; + connp->conn_ht_ulp = NULL; + connp->conn_ht_ulp_len = 0; + } + ip_pkt_free(&connp->conn_xmit_ipp); + ipcl_globalhash_remove(connp); - /* FIXME: add separate tcp_conn_free()? */ + if (connp->conn_latch != NULL) { + IPLATCH_REFRELE(connp->conn_latch); + connp->conn_latch = NULL; + } + if (connp->conn_latch_in_policy != NULL) { + IPPOL_REFRELE(connp->conn_latch_in_policy); + connp->conn_latch_in_policy = NULL; + } + if (connp->conn_latch_in_action != NULL) { + IPACT_REFRELE(connp->conn_latch_in_action); + connp->conn_latch_in_action = NULL; + } + if (connp->conn_policy != NULL) { + IPPH_REFRELE(connp->conn_policy, ns); + connp->conn_policy = NULL; + } + + if (connp->conn_ipsec_opt_mp != NULL) { + freemsg(connp->conn_ipsec_opt_mp); + connp->conn_ipsec_opt_mp = NULL; + } + if (connp->conn_flags & IPCL_TCPCONN) { - tcp_t *tcp = connp->conn_tcp; - tcp_stack_t *tcps; - - ASSERT(tcp != NULL); - tcps = tcp->tcp_tcps; - if (tcps != NULL) { - if (connp->conn_latch != NULL) { - IPLATCH_REFRELE(connp->conn_latch, ns); - connp->conn_latch = NULL; - } - if (connp->conn_policy != NULL) { - IPPH_REFRELE(connp->conn_policy, ns); - connp->conn_policy = NULL; - } - tcp->tcp_tcps = NULL; - TCPS_REFRELE(tcps); - } + tcp_t *tcp = connp->conn_tcp; tcp_free(tcp); mp = tcp->tcp_timercache; - tcp->tcp_cred = NULL; + + tcp->tcp_tcps = NULL; if (tcp->tcp_sack_info != NULL) { bzero(tcp->tcp_sack_info, sizeof (tcp_sack_info_t)); kmem_cache_free(tcp_sack_info_cache, tcp->tcp_sack_info); } - if (tcp->tcp_iphc != NULL) { - if (tcp->tcp_hdr_grown) { - kmem_free(tcp->tcp_iphc, tcp->tcp_iphc_len); - } else { - bzero(tcp->tcp_iphc, tcp->tcp_iphc_len); - kmem_cache_free(tcp_iphc_cache, tcp->tcp_iphc); - } - tcp->tcp_iphc_len = 0; - } - ASSERT(tcp->tcp_iphc_len == 0); /* * tcp_rsrv_mp can be NULL if tcp_get_conn() fails to allocate @@ -759,17 +701,15 @@ ipcl_conn_destroy(conn_t *connp) mutex_destroy(&tcp->tcp_rsrv_mp_lock); } - ASSERT(connp->conn_latch == NULL); - ASSERT(connp->conn_policy == NULL); - + ipcl_conn_cleanup(connp); + connp->conn_flags = IPCL_TCPCONN; if (ns != NULL) { ASSERT(tcp->tcp_tcps == NULL); connp->conn_netstack = NULL; + connp->conn_ixa->ixa_ipst = NULL; netstack_rele(ns); } - ipcl_conn_cleanup(connp); - connp->conn_flags = IPCL_TCPCONN; bzero(tcp, sizeof (tcp_t)); tcp->tcp_timercache = mp; @@ -777,18 +717,6 @@ ipcl_conn_destroy(conn_t *connp) kmem_cache_free(tcp_conn_cache, connp); return; } - if (connp->conn_latch != NULL) { - IPLATCH_REFRELE(connp->conn_latch, connp->conn_netstack); - connp->conn_latch = NULL; - } - if (connp->conn_policy != NULL) { - IPPH_REFRELE(connp->conn_policy, connp->conn_netstack); - connp->conn_policy = NULL; - } - if (connp->conn_ipsec_opt_mp != NULL) { - freemsg(connp->conn_ipsec_opt_mp); - connp->conn_ipsec_opt_mp = NULL; - } if (connp->conn_flags & IPCL_SCTPCONN) { ASSERT(ns != NULL); @@ -796,21 +724,21 @@ ipcl_conn_destroy(conn_t *connp) return; } + ipcl_conn_cleanup(connp); if (ns != NULL) { connp->conn_netstack = NULL; + connp->conn_ixa->ixa_ipst = NULL; netstack_rele(ns); } - ipcl_conn_cleanup(connp); - /* leave conn_priv aka conn_udp, conn_icmp, etc in place. */ if (connp->conn_flags & IPCL_UDPCONN) { connp->conn_flags = IPCL_UDPCONN; kmem_cache_free(udp_conn_cache, connp); } else if (connp->conn_flags & IPCL_RAWIPCONN) { - connp->conn_flags = IPCL_RAWIPCONN; - connp->conn_ulp = IPPROTO_ICMP; + connp->conn_proto = IPPROTO_ICMP; + connp->conn_ixa->ixa_protocol = connp->conn_proto; kmem_cache_free(rawip_conn_cache, connp); } else if (connp->conn_flags & IPCL_RTSCONN) { connp->conn_flags = IPCL_RTSCONN; @@ -826,7 +754,6 @@ ipcl_conn_destroy(conn_t *connp) /* * Running in cluster mode - deregister listener information */ - static void ipcl_conn_unlisten(conn_t *connp) { @@ -837,12 +764,12 @@ ipcl_conn_unlisten(conn_t *connp) sa_family_t addr_family; uint8_t *laddrp; - if (connp->conn_pkt_isv6) { + if (connp->conn_ipversion == IPV6_VERSION) { addr_family = AF_INET6; - laddrp = (uint8_t *)&connp->conn_bound_source_v6; + laddrp = (uint8_t *)&connp->conn_bound_addr_v6; } else { addr_family = AF_INET; - laddrp = (uint8_t *)&connp->conn_bound_source; + laddrp = (uint8_t *)&connp->conn_bound_addr_v4; } (*cl_inet_unlisten)(connp->conn_netstack->netstack_stackid, IPPROTO_TCP, addr_family, laddrp, connp->conn_lport, NULL); @@ -859,8 +786,6 @@ ipcl_conn_unlisten(conn_t *connp) connf_t *connfp = (connp)->conn_fanout; \ ASSERT(!MUTEX_HELD(&((connp)->conn_lock))); \ if (connfp != NULL) { \ - IPCL_DEBUG_LVL(4, ("IPCL_HASH_REMOVE: connp %p", \ - (void *)(connp))); \ mutex_enter(&connfp->connf_lock); \ if ((connp)->conn_next != NULL) \ (connp)->conn_next->conn_prev = \ @@ -884,7 +809,11 @@ ipcl_conn_unlisten(conn_t *connp) void ipcl_hash_remove(conn_t *connp) { + uint8_t protocol = connp->conn_proto; + IPCL_HASH_REMOVE(connp); + if (protocol == IPPROTO_RSVP) + ill_set_inputfn_all(connp->conn_netstack->netstack_ip); } /* @@ -937,8 +866,6 @@ ipcl_hash_remove_locked(conn_t *connp, connf_t *connfp) } #define IPCL_HASH_INSERT_CONNECTED(connfp, connp) { \ - IPCL_DEBUG_LVL(8, ("IPCL_HASH_INSERT_CONNECTED: connfp %p " \ - "connp %p", (void *)(connfp), (void *)(connp))); \ IPCL_HASH_REMOVE((connp)); \ mutex_enter(&(connfp)->connf_lock); \ IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp); \ @@ -947,13 +874,11 @@ ipcl_hash_remove_locked(conn_t *connp, connf_t *connfp) #define IPCL_HASH_INSERT_BOUND(connfp, connp) { \ conn_t *pconnp = NULL, *nconnp; \ - IPCL_DEBUG_LVL(32, ("IPCL_HASH_INSERT_BOUND: connfp %p " \ - "connp %p", (void *)connfp, (void *)(connp))); \ IPCL_HASH_REMOVE((connp)); \ mutex_enter(&(connfp)->connf_lock); \ nconnp = (connfp)->connf_head; \ while (nconnp != NULL && \ - !_IPCL_V4_MATCH_ANY(nconnp->conn_srcv6)) { \ + !_IPCL_V4_MATCH_ANY(nconnp->conn_laddr_v6)) { \ pconnp = nconnp; \ nconnp = nconnp->conn_next; \ } \ @@ -977,16 +902,14 @@ ipcl_hash_remove_locked(conn_t *connp, connf_t *connfp) #define IPCL_HASH_INSERT_WILDCARD(connfp, connp) { \ conn_t **list, *prev, *next; \ boolean_t isv4mapped = \ - IN6_IS_ADDR_V4MAPPED(&(connp)->conn_srcv6); \ - IPCL_DEBUG_LVL(32, ("IPCL_HASH_INSERT_WILDCARD: connfp %p " \ - "connp %p", (void *)(connfp), (void *)(connp))); \ + IN6_IS_ADDR_V4MAPPED(&(connp)->conn_laddr_v6); \ IPCL_HASH_REMOVE((connp)); \ mutex_enter(&(connfp)->connf_lock); \ list = &(connfp)->connf_head; \ prev = NULL; \ while ((next = *list) != NULL) { \ if (isv4mapped && \ - IN6_IS_ADDR_UNSPECIFIED(&next->conn_srcv6) && \ + IN6_IS_ADDR_UNSPECIFIED(&next->conn_laddr_v6) && \ connp->conn_zoneid == next->conn_zoneid) { \ (connp)->conn_next = next; \ if (prev != NULL) \ @@ -1012,44 +935,13 @@ ipcl_hash_insert_wildcard(connf_t *connfp, conn_t *connp) IPCL_HASH_INSERT_WILDCARD(connfp, connp); } -void -ipcl_proto_insert(conn_t *connp, uint8_t protocol) -{ - connf_t *connfp; - ip_stack_t *ipst = connp->conn_netstack->netstack_ip; - - ASSERT(connp != NULL); - ASSERT((connp->conn_mac_mode == CONN_MAC_DEFAULT) || - protocol == IPPROTO_AH || protocol == IPPROTO_ESP); - - connp->conn_ulp = protocol; - - /* Insert it in the protocol hash */ - connfp = &ipst->ips_ipcl_proto_fanout[protocol]; - IPCL_HASH_INSERT_WILDCARD(connfp, connp); -} - -void -ipcl_proto_insert_v6(conn_t *connp, uint8_t protocol) -{ - connf_t *connfp; - ip_stack_t *ipst = connp->conn_netstack->netstack_ip; - - ASSERT(connp != NULL); - ASSERT((connp->conn_mac_mode == CONN_MAC_DEFAULT) || - protocol == IPPROTO_AH || protocol == IPPROTO_ESP); - - connp->conn_ulp = protocol; - - /* Insert it in the Bind Hash */ - connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol]; - IPCL_HASH_INSERT_WILDCARD(connfp, connp); -} - /* * Because the classifier is used to classify inbound packets, the destination * address is meant to be our local tunnel address (tunnel source), and the * source the remote tunnel address (tunnel destination). + * + * Note that conn_proto can't be used for fanout since the upper protocol + * can be both 41 and 4 when IPv6 and IPv4 are over the same tunnel. */ conn_t * ipcl_iptun_classify_v4(ipaddr_t *src, ipaddr_t *dst, ip_stack_t *ipst) @@ -1128,13 +1020,13 @@ ipcl_sctp_hash_insert(conn_t *connp, in_port_t lport) oconnp = oconnp->conn_next) { if (oconnp->conn_lport == lport && oconnp->conn_zoneid == connp->conn_zoneid && - oconnp->conn_af_isv6 == connp->conn_af_isv6 && - ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) || - IN6_IS_ADDR_UNSPECIFIED(&oconnp->conn_srcv6) || - IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_srcv6) || - IN6_IS_ADDR_V4MAPPED_ANY(&oconnp->conn_srcv6)) || - IN6_ARE_ADDR_EQUAL(&oconnp->conn_srcv6, - &connp->conn_srcv6))) { + oconnp->conn_family == connp->conn_family && + ((IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) || + IN6_IS_ADDR_UNSPECIFIED(&oconnp->conn_laddr_v6) || + IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_laddr_v6) || + IN6_IS_ADDR_V4MAPPED_ANY(&oconnp->conn_laddr_v6)) || + IN6_ARE_ADDR_EQUAL(&oconnp->conn_laddr_v6, + &connp->conn_laddr_v6))) { break; } } @@ -1142,10 +1034,10 @@ ipcl_sctp_hash_insert(conn_t *connp, in_port_t lport) if (oconnp != NULL) return (EADDRNOTAVAIL); - if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6) || - IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_remv6)) { - if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) || - IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_srcv6)) { + if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) || + IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) { + if (IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) || + IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_laddr_v6)) { IPCL_HASH_INSERT_WILDCARD(connfp, connp); } else { IPCL_HASH_INSERT_BOUND(connfp, connp); @@ -1157,17 +1049,18 @@ ipcl_sctp_hash_insert(conn_t *connp, in_port_t lport) } static int -ipcl_iptun_hash_insert(conn_t *connp, ipaddr_t src, ipaddr_t dst, - ip_stack_t *ipst) +ipcl_iptun_hash_insert(conn_t *connp, ip_stack_t *ipst) { connf_t *connfp; conn_t *tconnp; + ipaddr_t laddr = connp->conn_laddr_v4; + ipaddr_t faddr = connp->conn_faddr_v4; - connfp = &ipst->ips_ipcl_iptun_fanout[IPCL_IPTUN_HASH(src, dst)]; + connfp = &ipst->ips_ipcl_iptun_fanout[IPCL_IPTUN_HASH(laddr, faddr)]; mutex_enter(&connfp->connf_lock); for (tconnp = connfp->connf_head; tconnp != NULL; tconnp = tconnp->conn_next) { - if (IPCL_IPTUN_MATCH(tconnp, src, dst)) { + if (IPCL_IPTUN_MATCH(tconnp, laddr, faddr)) { /* A tunnel is already bound to these addresses. */ mutex_exit(&connfp->connf_lock); return (EADDRINUSE); @@ -1179,17 +1072,18 @@ ipcl_iptun_hash_insert(conn_t *connp, ipaddr_t src, ipaddr_t dst, } static int -ipcl_iptun_hash_insert_v6(conn_t *connp, const in6_addr_t *src, - const in6_addr_t *dst, ip_stack_t *ipst) +ipcl_iptun_hash_insert_v6(conn_t *connp, ip_stack_t *ipst) { connf_t *connfp; conn_t *tconnp; + in6_addr_t *laddr = &connp->conn_laddr_v6; + in6_addr_t *faddr = &connp->conn_faddr_v6; - connfp = &ipst->ips_ipcl_iptun_fanout[IPCL_IPTUN_HASH_V6(src, dst)]; + connfp = &ipst->ips_ipcl_iptun_fanout[IPCL_IPTUN_HASH_V6(laddr, faddr)]; mutex_enter(&connfp->connf_lock); for (tconnp = connfp->connf_head; tconnp != NULL; tconnp = tconnp->conn_next) { - if (IPCL_IPTUN_MATCH_V6(tconnp, src, dst)) { + if (IPCL_IPTUN_MATCH_V6(tconnp, laddr, faddr)) { /* A tunnel is already bound to these addresses. */ mutex_exit(&connfp->connf_lock); return (EADDRINUSE); @@ -1213,12 +1107,12 @@ check_exempt_conflict_v4(conn_t *connp, ip_stack_t *ipst) connf_t *connfp; conn_t *tconn; - connfp = &ipst->ips_ipcl_proto_fanout[connp->conn_ulp]; + connfp = &ipst->ips_ipcl_proto_fanout_v4[connp->conn_proto]; mutex_enter(&connfp->connf_lock); for (tconn = connfp->connf_head; tconn != NULL; tconn = tconn->conn_next) { /* We don't allow v4 fallback for v6 raw socket */ - if (connp->conn_af_isv6 != tconn->conn_af_isv6) + if (connp->conn_family != tconn->conn_family) continue; /* If neither is exempt, then there's no conflict */ if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) && @@ -1228,9 +1122,9 @@ check_exempt_conflict_v4(conn_t *connp, ip_stack_t *ipst) if (connp->conn_zoneid == tconn->conn_zoneid) continue; /* If both are bound to different specific addrs, ok */ - if (connp->conn_src != INADDR_ANY && - tconn->conn_src != INADDR_ANY && - connp->conn_src != tconn->conn_src) + if (connp->conn_laddr_v4 != INADDR_ANY && + tconn->conn_laddr_v4 != INADDR_ANY && + connp->conn_laddr_v4 != tconn->conn_laddr_v4) continue; /* These two conflict; fail */ break; @@ -1245,12 +1139,12 @@ check_exempt_conflict_v6(conn_t *connp, ip_stack_t *ipst) connf_t *connfp; conn_t *tconn; - connfp = &ipst->ips_ipcl_proto_fanout[connp->conn_ulp]; + connfp = &ipst->ips_ipcl_proto_fanout_v6[connp->conn_proto]; mutex_enter(&connfp->connf_lock); for (tconn = connfp->connf_head; tconn != NULL; tconn = tconn->conn_next) { /* We don't allow v4 fallback for v6 raw socket */ - if (connp->conn_af_isv6 != tconn->conn_af_isv6) + if (connp->conn_family != tconn->conn_family) continue; /* If neither is exempt, then there's no conflict */ if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) && @@ -1260,9 +1154,10 @@ check_exempt_conflict_v6(conn_t *connp, ip_stack_t *ipst) if (connp->conn_zoneid == tconn->conn_zoneid) continue; /* If both are bound to different addrs, ok */ - if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6) && - !IN6_IS_ADDR_UNSPECIFIED(&tconn->conn_srcv6) && - !IN6_ARE_ADDR_EQUAL(&connp->conn_srcv6, &tconn->conn_srcv6)) + if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6) && + !IN6_IS_ADDR_UNSPECIFIED(&tconn->conn_laddr_v6) && + !IN6_ARE_ADDR_EQUAL(&connp->conn_laddr_v6, + &tconn->conn_laddr_v6)) continue; /* These two conflict; fail */ break; @@ -1273,28 +1168,29 @@ check_exempt_conflict_v6(conn_t *connp, ip_stack_t *ipst) /* * (v4, v6) bind hash insertion routines + * The caller has already setup the conn (conn_proto, conn_laddr_v6, conn_lport) */ + +int +ipcl_bind_insert(conn_t *connp) +{ + if (connp->conn_ipversion == IPV6_VERSION) + return (ipcl_bind_insert_v6(connp)); + else + return (ipcl_bind_insert_v4(connp)); +} + int -ipcl_bind_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, uint16_t lport) +ipcl_bind_insert_v4(conn_t *connp) { connf_t *connfp; -#ifdef IPCL_DEBUG - char buf[INET_NTOA_BUFSIZE]; -#endif int ret = 0; ip_stack_t *ipst = connp->conn_netstack->netstack_ip; - - ASSERT(connp); - - IPCL_DEBUG_LVL(64, ("ipcl_bind_insert: connp %p, src = %s, " - "port = %d\n", (void *)connp, inet_ntoa_r(src, buf), lport)); - - connp->conn_ulp = protocol; - IN6_IPADDR_TO_V4MAPPED(src, &connp->conn_srcv6); - connp->conn_lport = lport; + uint16_t lport = connp->conn_lport; + uint8_t protocol = connp->conn_proto; if (IPCL_IS_IPTUN(connp)) - return (ipcl_iptun_hash_insert(connp, src, INADDR_ANY, ipst)); + return (ipcl_iptun_hash_insert(connp, ipst)); switch (protocol) { default: @@ -1304,45 +1200,40 @@ ipcl_bind_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, uint16_t lport) /* FALLTHROUGH */ case IPPROTO_UDP: if (protocol == IPPROTO_UDP) { - IPCL_DEBUG_LVL(64, - ("ipcl_bind_insert: connp %p - udp\n", - (void *)connp)); connfp = &ipst->ips_ipcl_udp_fanout[ IPCL_UDP_HASH(lport, ipst)]; } else { - IPCL_DEBUG_LVL(64, - ("ipcl_bind_insert: connp %p - protocol\n", - (void *)connp)); - connfp = &ipst->ips_ipcl_proto_fanout[protocol]; + connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol]; } - if (connp->conn_rem != INADDR_ANY) { + if (connp->conn_faddr_v4 != INADDR_ANY) { IPCL_HASH_INSERT_CONNECTED(connfp, connp); - } else if (connp->conn_src != INADDR_ANY) { + } else if (connp->conn_laddr_v4 != INADDR_ANY) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); } + if (protocol == IPPROTO_RSVP) + ill_set_inputfn_all(ipst); break; case IPPROTO_TCP: - /* Insert it in the Bind Hash */ ASSERT(connp->conn_zoneid != ALL_ZONES); connfp = &ipst->ips_ipcl_bind_fanout[ IPCL_BIND_HASH(lport, ipst)]; - if (connp->conn_src != INADDR_ANY) { + if (connp->conn_laddr_v4 != INADDR_ANY) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); } if (cl_inet_listen != NULL) { - ASSERT(!connp->conn_pkt_isv6); + ASSERT(connp->conn_ipversion == IPV4_VERSION); connp->conn_flags |= IPCL_CL_LISTENER; (*cl_inet_listen)( connp->conn_netstack->netstack_stackid, IPPROTO_TCP, AF_INET, - (uint8_t *)&connp->conn_bound_source, lport, NULL); + (uint8_t *)&connp->conn_bound_addr_v4, lport, NULL); } break; @@ -1355,20 +1246,16 @@ ipcl_bind_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, uint16_t lport) } int -ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, - uint16_t lport) +ipcl_bind_insert_v6(conn_t *connp) { connf_t *connfp; int ret = 0; ip_stack_t *ipst = connp->conn_netstack->netstack_ip; - - ASSERT(connp != NULL); connp->conn_ulp = protocol; - connp->conn_srcv6 = *src; - connp->conn_lport = lport; + uint16_t lport = connp->conn_lport; + uint8_t protocol = connp->conn_proto; if (IPCL_IS_IPTUN(connp)) { - return (ipcl_iptun_hash_insert_v6(connp, src, &ipv6_all_zeros, - ipst)); + return (ipcl_iptun_hash_insert_v6(connp, ipst)); } switch (protocol) { @@ -1379,21 +1266,15 @@ ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, /* FALLTHROUGH */ case IPPROTO_UDP: if (protocol == IPPROTO_UDP) { - IPCL_DEBUG_LVL(128, - ("ipcl_bind_insert_v6: connp %p - udp\n", - (void *)connp)); connfp = &ipst->ips_ipcl_udp_fanout[ IPCL_UDP_HASH(lport, ipst)]; } else { - IPCL_DEBUG_LVL(128, - ("ipcl_bind_insert_v6: connp %p - protocol\n", - (void *)connp)); connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol]; } - if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6)) { + if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) { IPCL_HASH_INSERT_CONNECTED(connfp, connp); - } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) { + } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); @@ -1401,13 +1282,11 @@ ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, break; case IPPROTO_TCP: - /* XXX - Need a separate table for IN6_IS_ADDR_UNSPECIFIED? */ - /* Insert it in the Bind Hash */ ASSERT(connp->conn_zoneid != ALL_ZONES); connfp = &ipst->ips_ipcl_bind_fanout[ IPCL_BIND_HASH(lport, ipst)]; - if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) { + if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); @@ -1416,13 +1295,13 @@ ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, sa_family_t addr_family; uint8_t *laddrp; - if (connp->conn_pkt_isv6) { + if (connp->conn_ipversion == IPV6_VERSION) { addr_family = AF_INET6; laddrp = - (uint8_t *)&connp->conn_bound_source_v6; + (uint8_t *)&connp->conn_bound_addr_v6; } else { addr_family = AF_INET; - laddrp = (uint8_t *)&connp->conn_bound_source; + laddrp = (uint8_t *)&connp->conn_bound_addr_v4; } connp->conn_flags |= IPCL_CL_LISTENER; (*cl_inet_listen)( @@ -1441,43 +1320,35 @@ ipcl_bind_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, /* * ipcl_conn_hash insertion routines. + * The caller has already set conn_proto and the addresses/ports in the conn_t. */ + int -ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, - ipaddr_t rem, uint32_t ports) +ipcl_conn_insert(conn_t *connp) +{ + if (connp->conn_ipversion == IPV6_VERSION) + return (ipcl_conn_insert_v6(connp)); + else + return (ipcl_conn_insert_v4(connp)); +} + +int +ipcl_conn_insert_v4(conn_t *connp) { connf_t *connfp; - uint16_t *up; conn_t *tconnp; -#ifdef IPCL_DEBUG - char sbuf[INET_NTOA_BUFSIZE], rbuf[INET_NTOA_BUFSIZE]; -#endif - in_port_t lport; int ret = 0; ip_stack_t *ipst = connp->conn_netstack->netstack_ip; - - IPCL_DEBUG_LVL(256, ("ipcl_conn_insert: connp %p, src = %s, " - "dst = %s, ports = %x, protocol = %x", (void *)connp, - inet_ntoa_r(src, sbuf), inet_ntoa_r(rem, rbuf), - ports, protocol)); + uint16_t lport = connp->conn_lport; + uint8_t protocol = connp->conn_proto; if (IPCL_IS_IPTUN(connp)) - return (ipcl_iptun_hash_insert(connp, src, rem, ipst)); + return (ipcl_iptun_hash_insert(connp, ipst)); switch (protocol) { case IPPROTO_TCP: - if (!(connp->conn_flags & IPCL_EAGER)) { - /* - * for a eager connection, i.e connections which - * have just been created, the initialization is - * already done in ip at conn_creation time, so - * we can skip the checks here. - */ - IPCL_CONN_INIT(connp, protocol, src, rem, ports); - } - /* - * For tcp, we check whether the connection tuple already + * For TCP, we check whether the connection tuple already * exists before allowing the connection to proceed. We * also allow indexing on the zoneid. This is to allow * multiple shared stack zones to have the same tcp @@ -1486,16 +1357,15 @@ ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, * doesn't have to be unique. */ connfp = &ipst->ips_ipcl_conn_fanout[ - IPCL_CONN_HASH(connp->conn_rem, + IPCL_CONN_HASH(connp->conn_faddr_v4, connp->conn_ports, ipst)]; mutex_enter(&connfp->connf_lock); for (tconnp = connfp->connf_head; tconnp != NULL; tconnp = tconnp->conn_next) { - if ((IPCL_CONN_MATCH(tconnp, connp->conn_ulp, - connp->conn_rem, connp->conn_src, - connp->conn_ports)) && - (IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid))) { - + if (IPCL_CONN_MATCH(tconnp, connp->conn_proto, + connp->conn_faddr_v4, connp->conn_laddr_v4, + connp->conn_ports) && + IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) { /* Already have a conn. bail out */ mutex_exit(&connfp->connf_lock); return (EADDRINUSE); @@ -1512,6 +1382,7 @@ ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, } ASSERT(connp->conn_recv != NULL); + ASSERT(connp->conn_recvicmp != NULL); IPCL_HASH_INSERT_CONNECTED_LOCKED(connfp, connp); mutex_exit(&connfp->connf_lock); @@ -1523,7 +1394,6 @@ ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, * from the hash first. */ IPCL_HASH_REMOVE(connp); - lport = htons((uint16_t)(ntohl(ports) & 0xFFFF)); ret = ipcl_sctp_hash_insert(connp, lport); break; @@ -1540,18 +1410,16 @@ ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, /* FALLTHROUGH */ case IPPROTO_UDP: - up = (uint16_t *)&ports; - IPCL_CONN_INIT(connp, protocol, src, rem, ports); if (protocol == IPPROTO_UDP) { connfp = &ipst->ips_ipcl_udp_fanout[ - IPCL_UDP_HASH(up[1], ipst)]; + IPCL_UDP_HASH(lport, ipst)]; } else { - connfp = &ipst->ips_ipcl_proto_fanout[protocol]; + connfp = &ipst->ips_ipcl_proto_fanout_v4[protocol]; } - if (connp->conn_rem != INADDR_ANY) { + if (connp->conn_faddr_v4 != INADDR_ANY) { IPCL_HASH_INSERT_CONNECTED(connfp, connp); - } else if (connp->conn_src != INADDR_ANY) { + } else if (connp->conn_laddr_v4 != INADDR_ANY) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); @@ -1563,25 +1431,21 @@ ipcl_conn_insert(conn_t *connp, uint8_t protocol, ipaddr_t src, } int -ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, - const in6_addr_t *rem, uint32_t ports, uint_t ifindex) +ipcl_conn_insert_v6(conn_t *connp) { connf_t *connfp; - uint16_t *up; conn_t *tconnp; - in_port_t lport; int ret = 0; ip_stack_t *ipst = connp->conn_netstack->netstack_ip; + uint16_t lport = connp->conn_lport; + uint8_t protocol = connp->conn_proto; + uint_t ifindex = connp->conn_bound_if; if (IPCL_IS_IPTUN(connp)) - return (ipcl_iptun_hash_insert_v6(connp, src, rem, ipst)); + return (ipcl_iptun_hash_insert_v6(connp, ipst)); switch (protocol) { case IPPROTO_TCP: - /* Just need to insert a conn struct */ - if (!(connp->conn_flags & IPCL_EAGER)) { - IPCL_CONN_INIT_V6(connp, protocol, *src, *rem, ports); - } /* * For tcp, we check whether the connection tuple already @@ -1593,17 +1457,18 @@ ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, * doesn't have to be unique. */ connfp = &ipst->ips_ipcl_conn_fanout[ - IPCL_CONN_HASH_V6(connp->conn_remv6, connp->conn_ports, + IPCL_CONN_HASH_V6(connp->conn_faddr_v6, connp->conn_ports, ipst)]; mutex_enter(&connfp->connf_lock); for (tconnp = connfp->connf_head; tconnp != NULL; tconnp = tconnp->conn_next) { - if (IPCL_CONN_MATCH_V6(tconnp, connp->conn_ulp, - connp->conn_remv6, connp->conn_srcv6, + /* NOTE: need to match zoneid. Bug in onnv-gate */ + if (IPCL_CONN_MATCH_V6(tconnp, connp->conn_proto, + connp->conn_faddr_v6, connp->conn_laddr_v6, connp->conn_ports) && - (tconnp->conn_tcp->tcp_bound_if == 0 || - tconnp->conn_tcp->tcp_bound_if == ifindex) && - (IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid))) { + (tconnp->conn_bound_if == 0 || + tconnp->conn_bound_if == ifindex) && + IPCL_ZONE_MATCH(tconnp, connp->conn_zoneid)) { /* Already have a conn. bail out */ mutex_exit(&connfp->connf_lock); return (EADDRINUSE); @@ -1624,7 +1489,6 @@ ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, case IPPROTO_SCTP: IPCL_HASH_REMOVE(connp); - lport = htons((uint16_t)(ntohl(ports) & 0xFFFF)); ret = ipcl_sctp_hash_insert(connp, lport); break; @@ -1634,18 +1498,16 @@ ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, return (EADDRINUSE); /* FALLTHROUGH */ case IPPROTO_UDP: - up = (uint16_t *)&ports; - IPCL_CONN_INIT_V6(connp, protocol, *src, *rem, ports); if (protocol == IPPROTO_UDP) { connfp = &ipst->ips_ipcl_udp_fanout[ - IPCL_UDP_HASH(up[1], ipst)]; + IPCL_UDP_HASH(lport, ipst)]; } else { connfp = &ipst->ips_ipcl_proto_fanout_v6[protocol]; } - if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_remv6)) { + if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6)) { IPCL_HASH_INSERT_CONNECTED(connfp, connp); - } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_srcv6)) { + } else if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_laddr_v6)) { IPCL_HASH_INSERT_BOUND(connfp, connp); } else { IPCL_HASH_INSERT_WILDCARD(connfp, connp); @@ -1667,8 +1529,8 @@ ipcl_conn_insert_v6(conn_t *connp, uint8_t protocol, const in6_addr_t *src, * zone, then label checks are omitted. */ conn_t * -ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, - ip_stack_t *ipst) +ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, + ip_recv_attr_t *ira, ip_stack_t *ipst) { ipha_t *ipha; connf_t *connfp, *bind_connfp; @@ -1677,8 +1539,7 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, uint32_t ports; conn_t *connp; uint16_t *up; - boolean_t shared_addr; - boolean_t unlabeled; + zoneid_t zoneid = ira->ira_zoneid; ipha = (ipha_t *)mp->b_rptr; up = (uint16_t *)((uchar_t *)ipha + hdr_len + TCP_PORTS_OFFSET); @@ -1692,11 +1553,14 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { - if ((IPCL_CONN_MATCH(connp, protocol, - ipha->ipha_src, ipha->ipha_dst, ports)) && - (IPCL_ZONE_MATCH(connp, zoneid))) { + if (IPCL_CONN_MATCH(connp, protocol, + ipha->ipha_src, ipha->ipha_dst, ports) && + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR)))) break; - } } if (connp != NULL) { @@ -1713,48 +1577,19 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, } mutex_exit(&connfp->connf_lock); - lport = up[1]; - unlabeled = B_FALSE; - /* Cred cannot be null on IPv4 */ - if (is_system_labeled()) { - cred_t *cr = msg_getcred(mp, NULL); - ASSERT(cr != NULL); - unlabeled = (crgetlabel(cr)->tsl_flags & - TSLF_UNLABELED) != 0; - } - shared_addr = (zoneid == ALL_ZONES); - if (shared_addr) { - /* - * No need to handle exclusive-stack zones since - * ALL_ZONES only applies to the shared stack. - */ - zoneid = tsol_mlp_findzone(protocol, lport); - /* - * If no shared MLP is found, tsol_mlp_findzone returns - * ALL_ZONES. In that case, we assume it's SLP, and - * search for the zone based on the packet label. - * - * If there is such a zone, we prefer to find a - * connection in it. Otherwise, we look for a - * MAC-exempt connection in any zone whose label - * dominates the default label on the packet. - */ - if (zoneid == ALL_ZONES) - zoneid = tsol_packet_to_zoneid(mp); - else - unlabeled = B_FALSE; - } - bind_connfp = &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)]; mutex_enter(&bind_connfp->connf_lock); for (connp = bind_connfp->connf_head; connp != NULL; connp = connp->conn_next) { if (IPCL_BIND_MATCH(connp, protocol, ipha->ipha_dst, - lport) && (IPCL_ZONE_MATCH(connp, zoneid) || - (unlabeled && shared_addr && - (connp->conn_mac_mode != CONN_MAC_DEFAULT)))) + lport) && + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR)))) break; } @@ -1762,16 +1597,17 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, * If the matching connection is SLP on a private address, then * the label on the packet must match the local zone's label. * Otherwise, it must be in the label range defined by tnrh. - * This is ensured by tsol_receive_label. + * This is ensured by tsol_receive_local. + * + * Note that we don't check tsol_receive_local for + * the connected case. */ - if (connp != NULL && is_system_labeled() && + if (connp != NULL && (ira->ira_flags & IRAF_SYSTEM_LABELED) && !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION, - shared_addr, connp)) { - DTRACE_PROBE3( - tx__ip__log__info__classify__tcp, - char *, - "connp(1) could not receive mp(2)", - conn_t *, connp, mblk_t *, mp); + ira, connp)) { + DTRACE_PROBE3(tx__ip__log__info__classify__tcp, + char *, "connp(1) could not receive mp(2)", + conn_t *, connp, mblk_t *, mp); connp = NULL; } @@ -1783,61 +1619,27 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, } mutex_exit(&bind_connfp->connf_lock); - - IPCL_DEBUG_LVL(512, - ("ipcl_classify: couldn't classify mp = %p\n", - (void *)mp)); break; case IPPROTO_UDP: lport = up[1]; - unlabeled = B_FALSE; - /* Cred cannot be null on IPv4 */ - if (is_system_labeled()) { - cred_t *cr = msg_getcred(mp, NULL); - ASSERT(cr != NULL); - unlabeled = (crgetlabel(cr)->tsl_flags & - TSLF_UNLABELED) != 0; - } - shared_addr = (zoneid == ALL_ZONES); - if (shared_addr) { - /* - * No need to handle exclusive-stack zones since - * ALL_ZONES only applies to the shared stack. - */ - zoneid = tsol_mlp_findzone(protocol, lport); - /* - * If no shared MLP is found, tsol_mlp_findzone returns - * ALL_ZONES. In that case, we assume it's SLP, and - * search for the zone based on the packet label. - * - * If there is such a zone, we prefer to find a - * connection in it. Otherwise, we look for a - * MAC-exempt connection in any zone whose label - * dominates the default label on the packet. - */ - if (zoneid == ALL_ZONES) - zoneid = tsol_packet_to_zoneid(mp); - else - unlabeled = B_FALSE; - } fport = up[0]; - IPCL_DEBUG_LVL(512, ("ipcl_udp_classify %x %x", lport, fport)); connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)]; mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { if (IPCL_UDP_MATCH(connp, lport, ipha->ipha_dst, fport, ipha->ipha_src) && - (IPCL_ZONE_MATCH(connp, zoneid) || - (unlabeled && shared_addr && - (connp->conn_mac_mode != CONN_MAC_DEFAULT)))) + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE)))) break; } - if (connp != NULL && is_system_labeled() && + if (connp != NULL && (ira->ira_flags & IRAF_SYSTEM_LABELED) && !tsol_receive_local(mp, &ipha->ipha_dst, IPV4_VERSION, - shared_addr, connp)) { + ira, connp)) { DTRACE_PROBE3(tx__ip__log__info__classify__udp, char *, "connp(1) could not receive mp(2)", conn_t *, connp, mblk_t *, mp); @@ -1854,9 +1656,7 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, * We shouldn't come here for multicast/broadcast packets */ mutex_exit(&connfp->connf_lock); - IPCL_DEBUG_LVL(512, - ("ipcl_classify: cant find udp conn_t for ports : %x %x", - lport, fport)); + break; case IPPROTO_ENCAP: @@ -1869,26 +1669,25 @@ ipcl_classify_v4(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, } conn_t * -ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, - ip_stack_t *ipst) +ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, + ip_recv_attr_t *ira, ip_stack_t *ipst) { ip6_t *ip6h; connf_t *connfp, *bind_connfp; uint16_t lport; uint16_t fport; - tcph_t *tcph; + tcpha_t *tcpha; uint32_t ports; conn_t *connp; uint16_t *up; - boolean_t shared_addr; - boolean_t unlabeled; + zoneid_t zoneid = ira->ira_zoneid; ip6h = (ip6_t *)mp->b_rptr; switch (protocol) { case IPPROTO_TCP: - tcph = (tcph_t *)&mp->b_rptr[hdr_len]; - up = (uint16_t *)tcph->th_lport; + tcpha = (tcpha_t *)&mp->b_rptr[hdr_len]; + up = &tcpha->tha_lport; ports = *(uint32_t *)up; connfp = @@ -1897,11 +1696,14 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { - if ((IPCL_CONN_MATCH_V6(connp, protocol, - ip6h->ip6_src, ip6h->ip6_dst, ports)) && - (IPCL_ZONE_MATCH(connp, zoneid))) { + if (IPCL_CONN_MATCH_V6(connp, protocol, + ip6h->ip6_src, ip6h->ip6_dst, ports) && + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR)))) break; - } } if (connp != NULL) { @@ -1920,37 +1722,6 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, mutex_exit(&connfp->connf_lock); lport = up[1]; - unlabeled = B_FALSE; - /* Cred can be null on IPv6 */ - if (is_system_labeled()) { - cred_t *cr = msg_getcred(mp, NULL); - - unlabeled = (cr != NULL && - crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0; - } - shared_addr = (zoneid == ALL_ZONES); - if (shared_addr) { - /* - * No need to handle exclusive-stack zones since - * ALL_ZONES only applies to the shared stack. - */ - zoneid = tsol_mlp_findzone(protocol, lport); - /* - * If no shared MLP is found, tsol_mlp_findzone returns - * ALL_ZONES. In that case, we assume it's SLP, and - * search for the zone based on the packet label. - * - * If there is such a zone, we prefer to find a - * connection in it. Otherwise, we look for a - * MAC-exempt connection in any zone whose label - * dominates the default label on the packet. - */ - if (zoneid == ALL_ZONES) - zoneid = tsol_packet_to_zoneid(mp); - else - unlabeled = B_FALSE; - } - bind_connfp = &ipst->ips_ipcl_bind_fanout[IPCL_BIND_HASH(lport, ipst)]; mutex_enter(&bind_connfp->connf_lock); @@ -1958,15 +1729,17 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, connp = connp->conn_next) { if (IPCL_BIND_MATCH_V6(connp, protocol, ip6h->ip6_dst, lport) && - (IPCL_ZONE_MATCH(connp, zoneid) || - (unlabeled && shared_addr && - (connp->conn_mac_mode != CONN_MAC_DEFAULT)))) + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR)))) break; } - if (connp != NULL && is_system_labeled() && + if (connp != NULL && (ira->ira_flags & IRAF_SYSTEM_LABELED) && !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION, - shared_addr, connp)) { + ira, connp)) { DTRACE_PROBE3(tx__ip__log__info__classify__tcp6, char *, "connp(1) could not receive mp(2)", conn_t *, connp, mblk_t *, mp); @@ -1977,72 +1750,33 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, /* Have a listner at least */ CONN_INC_REF(connp); mutex_exit(&bind_connfp->connf_lock); - IPCL_DEBUG_LVL(512, - ("ipcl_classify_v6: found listner " - "connp = %p\n", (void *)connp)); - return (connp); } mutex_exit(&bind_connfp->connf_lock); - - IPCL_DEBUG_LVL(512, - ("ipcl_classify_v6: couldn't classify mp = %p\n", - (void *)mp)); break; case IPPROTO_UDP: up = (uint16_t *)&mp->b_rptr[hdr_len]; lport = up[1]; - unlabeled = B_FALSE; - /* Cred can be null on IPv6 */ - if (is_system_labeled()) { - cred_t *cr = msg_getcred(mp, NULL); - - unlabeled = (cr != NULL && - crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0; - } - shared_addr = (zoneid == ALL_ZONES); - if (shared_addr) { - /* - * No need to handle exclusive-stack zones since - * ALL_ZONES only applies to the shared stack. - */ - zoneid = tsol_mlp_findzone(protocol, lport); - /* - * If no shared MLP is found, tsol_mlp_findzone returns - * ALL_ZONES. In that case, we assume it's SLP, and - * search for the zone based on the packet label. - * - * If there is such a zone, we prefer to find a - * connection in it. Otherwise, we look for a - * MAC-exempt connection in any zone whose label - * dominates the default label on the packet. - */ - if (zoneid == ALL_ZONES) - zoneid = tsol_packet_to_zoneid(mp); - else - unlabeled = B_FALSE; - } - fport = up[0]; - IPCL_DEBUG_LVL(512, ("ipcl_udp_classify_v6 %x %x", lport, - fport)); connfp = &ipst->ips_ipcl_udp_fanout[IPCL_UDP_HASH(lport, ipst)]; mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { if (IPCL_UDP_MATCH_V6(connp, lport, ip6h->ip6_dst, fport, ip6h->ip6_src) && - (IPCL_ZONE_MATCH(connp, zoneid) || - (unlabeled && shared_addr && - (connp->conn_mac_mode != CONN_MAC_DEFAULT)))) + (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR)))) break; } - if (connp != NULL && is_system_labeled() && + if (connp != NULL && (ira->ira_flags & IRAF_SYSTEM_LABELED) && !tsol_receive_local(mp, &ip6h->ip6_dst, IPV6_VERSION, - shared_addr, connp)) { + ira, connp)) { DTRACE_PROBE3(tx__ip__log__info__classify__udp6, char *, "connp(1) could not receive mp(2)", conn_t *, connp, mblk_t *, mp); @@ -2059,9 +1793,6 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, * We shouldn't come here for multicast/broadcast packets */ mutex_exit(&connfp->connf_lock); - IPCL_DEBUG_LVL(512, - ("ipcl_classify_v6: cant find udp conn_t for ports : %x %x", - lport, fport)); break; case IPPROTO_ENCAP: case IPPROTO_IPV6: @@ -2076,125 +1807,80 @@ ipcl_classify_v6(mblk_t *mp, uint8_t protocol, uint_t hdr_len, zoneid_t zoneid, * wrapper around ipcl_classify_(v4,v6) routines. */ conn_t * -ipcl_classify(mblk_t *mp, zoneid_t zoneid, ip_stack_t *ipst) +ipcl_classify(mblk_t *mp, ip_recv_attr_t *ira, ip_stack_t *ipst) { - uint16_t hdr_len; - ipha_t *ipha; - uint8_t *nexthdrp; - - if (MBLKL(mp) < sizeof (ipha_t)) - return (NULL); - - switch (IPH_HDR_VERSION(mp->b_rptr)) { - case IPV4_VERSION: - ipha = (ipha_t *)mp->b_rptr; - hdr_len = IPH_HDR_LENGTH(ipha); - return (ipcl_classify_v4(mp, ipha->ipha_protocol, hdr_len, - zoneid, ipst)); - case IPV6_VERSION: - if (!ip_hdr_length_nexthdr_v6(mp, (ip6_t *)mp->b_rptr, - &hdr_len, &nexthdrp)) - return (NULL); - - return (ipcl_classify_v6(mp, *nexthdrp, hdr_len, zoneid, ipst)); + if (ira->ira_flags & IRAF_IS_IPV4) { + return (ipcl_classify_v4(mp, ira->ira_protocol, + ira->ira_ip_hdr_length, ira, ipst)); + } else { + return (ipcl_classify_v6(mp, ira->ira_protocol, + ira->ira_ip_hdr_length, ira, ipst)); } - - return (NULL); } +/* + * Only used to classify SCTP RAW sockets + */ conn_t * -ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid, - uint32_t ports, ipha_t *hdr, ip_stack_t *ipst) +ipcl_classify_raw(mblk_t *mp, uint8_t protocol, uint32_t ports, + ipha_t *ipha, ip6_t *ip6h, ip_recv_attr_t *ira, ip_stack_t *ipst) { connf_t *connfp; conn_t *connp; in_port_t lport; - int af; - boolean_t shared_addr; - boolean_t unlabeled; + int ipversion; const void *dst; + zoneid_t zoneid = ira->ira_zoneid; lport = ((uint16_t *)&ports)[1]; - - unlabeled = B_FALSE; - /* Cred can be null on IPv6 */ - if (is_system_labeled()) { - cred_t *cr = msg_getcred(mp, NULL); - - unlabeled = (cr != NULL && - crgetlabel(cr)->tsl_flags & TSLF_UNLABELED) != 0; - } - shared_addr = (zoneid == ALL_ZONES); - if (shared_addr) { - /* - * No need to handle exclusive-stack zones since ALL_ZONES - * only applies to the shared stack. - */ - zoneid = tsol_mlp_findzone(protocol, lport); - /* - * If no shared MLP is found, tsol_mlp_findzone returns - * ALL_ZONES. In that case, we assume it's SLP, and search for - * the zone based on the packet label. - * - * If there is such a zone, we prefer to find a connection in - * it. Otherwise, we look for a MAC-exempt connection in any - * zone whose label dominates the default label on the packet. - */ - if (zoneid == ALL_ZONES) - zoneid = tsol_packet_to_zoneid(mp); - else - unlabeled = B_FALSE; + if (ira->ira_flags & IRAF_IS_IPV4) { + dst = (const void *)&ipha->ipha_dst; + ipversion = IPV4_VERSION; + } else { + dst = (const void *)&ip6h->ip6_dst; + ipversion = IPV6_VERSION; } - af = IPH_HDR_VERSION(hdr); - dst = af == IPV4_VERSION ? (const void *)&hdr->ipha_dst : - (const void *)&((ip6_t *)hdr)->ip6_dst; connfp = &ipst->ips_ipcl_raw_fanout[IPCL_RAW_HASH(ntohs(lport), ipst)]; - mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { /* We don't allow v4 fallback for v6 raw socket. */ - if (af == (connp->conn_af_isv6 ? IPV4_VERSION : - IPV6_VERSION)) + if (ipversion != connp->conn_ipversion) continue; - if (connp->conn_fully_bound) { - if (af == IPV4_VERSION) { + if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) && + !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) { + if (ipversion == IPV4_VERSION) { if (!IPCL_CONN_MATCH(connp, protocol, - hdr->ipha_src, hdr->ipha_dst, ports)) + ipha->ipha_src, ipha->ipha_dst, ports)) continue; } else { if (!IPCL_CONN_MATCH_V6(connp, protocol, - ((ip6_t *)hdr)->ip6_src, - ((ip6_t *)hdr)->ip6_dst, ports)) + ip6h->ip6_src, ip6h->ip6_dst, ports)) continue; } } else { - if (af == IPV4_VERSION) { + if (ipversion == IPV4_VERSION) { if (!IPCL_BIND_MATCH(connp, protocol, - hdr->ipha_dst, lport)) + ipha->ipha_dst, lport)) continue; } else { if (!IPCL_BIND_MATCH_V6(connp, protocol, - ((ip6_t *)hdr)->ip6_dst, lport)) + ip6h->ip6_dst, lport)) continue; } } - if (IPCL_ZONE_MATCH(connp, zoneid) || - (unlabeled && - (connp->conn_mac_mode != CONN_MAC_DEFAULT) && - shared_addr)) + if (connp->conn_zoneid == zoneid || + connp->conn_allzones || + ((connp->conn_mac_mode != CONN_MAC_DEFAULT) && + (ira->ira_flags & IRAF_TX_MAC_EXEMPTABLE) && + (ira->ira_flags & IRAF_TX_SHARED_ADDR))) break; } - /* - * If the connection is fully-bound and connection-oriented (TCP or - * SCTP), then we've already validated the remote system's label. - * There's no need to do it again for every packet. - */ - if (connp != NULL && is_system_labeled() && (!connp->conn_fully_bound || - !(connp->conn_flags & (IPCL_TCP|IPCL_SCTPCONN))) && - !tsol_receive_local(mp, dst, af, shared_addr, connp)) { + + if (connp != NULL && (ira->ira_flags & IRAF_SYSTEM_LABELED) && + !tsol_receive_local(mp, dst, ipversion, ira, connp)) { DTRACE_PROBE3(tx__ip__log__info__classify__rawip, char *, "connp(1) could not receive mp(2)", conn_t *, connp, mblk_t *, mp); @@ -2205,22 +1891,22 @@ ipcl_classify_raw(mblk_t *mp, uint8_t protocol, zoneid_t zoneid, goto found; mutex_exit(&connfp->connf_lock); - /* Try to look for a wildcard match. */ + /* Try to look for a wildcard SCTP RAW socket match. */ connfp = &ipst->ips_ipcl_raw_fanout[IPCL_RAW_HASH(0, ipst)]; mutex_enter(&connfp->connf_lock); for (connp = connfp->connf_head; connp != NULL; connp = connp->conn_next) { /* We don't allow v4 fallback for v6 raw socket. */ - if ((af == (connp->conn_af_isv6 ? IPV4_VERSION : - IPV6_VERSION)) || !IPCL_ZONE_MATCH(connp, zoneid)) { + if (ipversion != connp->conn_ipversion) continue; - } - if (af == IPV4_VERSION) { - if (IPCL_RAW_MATCH(connp, protocol, hdr->ipha_dst)) + if (!IPCL_ZONE_MATCH(connp, zoneid)) + continue; + + if (ipversion == IPV4_VERSION) { + if (IPCL_RAW_MATCH(connp, protocol, ipha->ipha_dst)) break; } else { - if (IPCL_RAW_MATCH_V6(connp, protocol, - ((ip6_t *)hdr)->ip6_dst)) { + if (IPCL_RAW_MATCH_V6(connp, protocol, ip6h->ip6_dst)) { break; } } @@ -2253,11 +1939,23 @@ tcp_conn_constructor(void *buf, void *cdrarg, int kmflags) mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL); cv_init(&connp->conn_sq_cv, NULL, CV_DEFAULT, NULL); - tcp->tcp_timercache = tcp_timermp_alloc(KM_NOSLEEP); + tcp->tcp_timercache = tcp_timermp_alloc(kmflags); + if (tcp->tcp_timercache == NULL) + return (ENOMEM); connp->conn_tcp = tcp; connp->conn_flags = IPCL_TCPCONN; - connp->conn_ulp = IPPROTO_TCP; + connp->conn_proto = IPPROTO_TCP; tcp->tcp_connp = connp; + rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL); + + connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags); + if (connp->conn_ixa == NULL) { + tcp_timermp_free(tcp); + return (ENOMEM); + } + connp->conn_ixa->ixa_refcnt = 1; + connp->conn_ixa->ixa_protocol = connp->conn_proto; + connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp); return (0); } @@ -2276,6 +1974,15 @@ tcp_conn_destructor(void *buf, void *cdrarg) mutex_destroy(&connp->conn_lock); cv_destroy(&connp->conn_cv); cv_destroy(&connp->conn_sq_cv); + rw_destroy(&connp->conn_ilg_lock); + + /* Can be NULL if constructor failed */ + if (connp->conn_ixa != NULL) { + ASSERT(connp->conn_ixa->ixa_refcnt == 1); + ASSERT(connp->conn_ixa->ixa_ire == NULL); + ASSERT(connp->conn_ixa->ixa_nce == NULL); + ixa_refrele(connp->conn_ixa); + } } /* ARGSUSED */ @@ -2289,7 +1996,13 @@ ip_conn_constructor(void *buf, void *cdrarg, int kmflags) mutex_init(&connp->conn_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL); connp->conn_flags = IPCL_IPCCONN; + rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL); + connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags); + if (connp->conn_ixa == NULL) + return (ENOMEM); + connp->conn_ixa->ixa_refcnt = 1; + connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp); return (0); } @@ -2304,6 +2017,15 @@ ip_conn_destructor(void *buf, void *cdrarg) ASSERT(connp->conn_priv == NULL); mutex_destroy(&connp->conn_lock); cv_destroy(&connp->conn_cv); + rw_destroy(&connp->conn_ilg_lock); + + /* Can be NULL if constructor failed */ + if (connp->conn_ixa != NULL) { + ASSERT(connp->conn_ixa->ixa_refcnt == 1); + ASSERT(connp->conn_ixa->ixa_ire == NULL); + ASSERT(connp->conn_ixa->ixa_nce == NULL); + ixa_refrele(connp->conn_ixa); + } } /* ARGSUSED */ @@ -2321,8 +2043,15 @@ udp_conn_constructor(void *buf, void *cdrarg, int kmflags) cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL); connp->conn_udp = udp; connp->conn_flags = IPCL_UDPCONN; - connp->conn_ulp = IPPROTO_UDP; + connp->conn_proto = IPPROTO_UDP; udp->udp_connp = connp; + rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL); + connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags); + if (connp->conn_ixa == NULL) + return (ENOMEM); + connp->conn_ixa->ixa_refcnt = 1; + connp->conn_ixa->ixa_protocol = connp->conn_proto; + connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp); return (0); } @@ -2339,6 +2068,15 @@ udp_conn_destructor(void *buf, void *cdrarg) ASSERT(connp->conn_udp == udp); mutex_destroy(&connp->conn_lock); cv_destroy(&connp->conn_cv); + rw_destroy(&connp->conn_ilg_lock); + + /* Can be NULL if constructor failed */ + if (connp->conn_ixa != NULL) { + ASSERT(connp->conn_ixa->ixa_refcnt == 1); + ASSERT(connp->conn_ixa->ixa_ire == NULL); + ASSERT(connp->conn_ixa->ixa_nce == NULL); + ixa_refrele(connp->conn_ixa); + } } /* ARGSUSED */ @@ -2356,8 +2094,15 @@ rawip_conn_constructor(void *buf, void *cdrarg, int kmflags) cv_init(&connp->conn_cv, NULL, CV_DEFAULT, NULL); connp->conn_icmp = icmp; connp->conn_flags = IPCL_RAWIPCONN; - connp->conn_ulp = IPPROTO_ICMP; + connp->conn_proto = IPPROTO_ICMP; icmp->icmp_connp = connp; + rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL); + connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags); + if (connp->conn_ixa == NULL) + return (ENOMEM); + connp->conn_ixa->ixa_refcnt = 1; + connp->conn_ixa->ixa_protocol = connp->conn_proto; + connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp); return (0); } @@ -2374,6 +2119,15 @@ rawip_conn_destructor(void *buf, void *cdrarg) ASSERT(connp->conn_icmp == icmp); mutex_destroy(&connp->conn_lock); cv_destroy(&connp->conn_cv); + rw_destroy(&connp->conn_ilg_lock); + + /* Can be NULL if constructor failed */ + if (connp->conn_ixa != NULL) { + ASSERT(connp->conn_ixa->ixa_refcnt == 1); + ASSERT(connp->conn_ixa->ixa_ire == NULL); + ASSERT(connp->conn_ixa->ixa_nce == NULL); + ixa_refrele(connp->conn_ixa); + } } /* ARGSUSED */ @@ -2392,6 +2146,12 @@ rts_conn_constructor(void *buf, void *cdrarg, int kmflags) connp->conn_rts = rts; connp->conn_flags = IPCL_RTSCONN; rts->rts_connp = connp; + rw_init(&connp->conn_ilg_lock, NULL, RW_DEFAULT, NULL); + connp->conn_ixa = kmem_zalloc(sizeof (ip_xmit_attr_t), kmflags); + if (connp->conn_ixa == NULL) + return (ENOMEM); + connp->conn_ixa->ixa_refcnt = 1; + connp->conn_ixa->ixa_xmit_hint = CONN_TO_XMIT_HINT(connp); return (0); } @@ -2408,71 +2168,35 @@ rts_conn_destructor(void *buf, void *cdrarg) ASSERT(connp->conn_rts == rts); mutex_destroy(&connp->conn_lock); cv_destroy(&connp->conn_cv); -} + rw_destroy(&connp->conn_ilg_lock); -/* ARGSUSED */ -int -ip_helper_stream_constructor(void *buf, void *cdrarg, int kmflags) -{ - int error; - netstack_t *ns; - int ret; - tcp_stack_t *tcps; - ip_helper_stream_info_t *ip_helper_str; - ip_stack_t *ipst; - - ns = netstack_find_by_cred(kcred); - ASSERT(ns != NULL); - tcps = ns->netstack_tcp; - ipst = ns->netstack_ip; - ASSERT(tcps != NULL); - ip_helper_str = (ip_helper_stream_info_t *)buf; - - do { - error = ldi_open_by_name(DEV_IP, IP_HELPER_STR, kcred, - &ip_helper_str->iphs_handle, ipst->ips_ldi_ident); - } while (error == EINTR); - - if (error == 0) { - do { - error = ldi_ioctl( - ip_helper_str->iphs_handle, SIOCSQPTR, - (intptr_t)buf, FKIOCTL, kcred, &ret); - } while (error == EINTR); - - if (error != 0) { - (void) ldi_close( - ip_helper_str->iphs_handle, 0, kcred); - } + /* Can be NULL if constructor failed */ + if (connp->conn_ixa != NULL) { + ASSERT(connp->conn_ixa->ixa_refcnt == 1); + ASSERT(connp->conn_ixa->ixa_ire == NULL); + ASSERT(connp->conn_ixa->ixa_nce == NULL); + ixa_refrele(connp->conn_ixa); } - - netstack_rele(ipst->ips_netstack); - - return (error); } -/* ARGSUSED */ -static void -ip_helper_stream_destructor(void *buf, void *cdrarg) -{ - ip_helper_stream_info_t *ip_helper_str = (ip_helper_stream_info_t *)buf; - - ip_helper_str->iphs_rq->q_ptr = - ip_helper_str->iphs_wq->q_ptr = - ip_helper_str->iphs_minfo; - (void) ldi_close(ip_helper_str->iphs_handle, 0, kcred); -} - - /* * Called as part of ipcl_conn_destroy to assert and clear any pointers * in the conn_t. + * + * Below we list all the pointers in the conn_t as a documentation aid. + * The ones that we can not ASSERT to be NULL are #ifdef'ed out. + * If you add any pointers to the conn_t please add an ASSERT here + * and #ifdef it out if it can't be actually asserted to be NULL. + * In any case, we bzero most of the conn_t at the end of the function. */ void ipcl_conn_cleanup(conn_t *connp) { - ASSERT(connp->conn_ire_cache == NULL); + ip_xmit_attr_t *ixa; + ASSERT(connp->conn_latch == NULL); + ASSERT(connp->conn_latch_in_policy == NULL); + ASSERT(connp->conn_latch_in_action == NULL); #ifdef notdef ASSERT(connp->conn_rq == NULL); ASSERT(connp->conn_wq == NULL); @@ -2485,18 +2209,6 @@ ipcl_conn_cleanup(conn_t *connp) ASSERT(connp->conn_fanout == NULL); ASSERT(connp->conn_next == NULL); ASSERT(connp->conn_prev == NULL); -#ifdef notdef - /* - * The ill and ipif pointers are not cleared before the conn_t - * goes away since they do not hold a reference on the ill/ipif. - * We should replace these pointers with ifindex/ipaddr_t to - * make the code less complex. - */ - ASSERT(connp->conn_outgoing_ill == NULL); - ASSERT(connp->conn_incoming_ill == NULL); - ASSERT(connp->conn_multicast_ipif == NULL); - ASSERT(connp->conn_multicast_ill == NULL); -#endif ASSERT(connp->conn_oper_pending_ill == NULL); ASSERT(connp->conn_ilg == NULL); ASSERT(connp->conn_drain_next == NULL); @@ -2506,10 +2218,19 @@ ipcl_conn_cleanup(conn_t *connp) ASSERT(connp->conn_idl == NULL); #endif ASSERT(connp->conn_ipsec_opt_mp == NULL); - ASSERT(connp->conn_effective_cred == NULL); +#ifdef notdef + /* conn_netstack is cleared by the caller; needed by ixa_cleanup */ ASSERT(connp->conn_netstack == NULL); +#endif ASSERT(connp->conn_helper_info == NULL); + ASSERT(connp->conn_ixa != NULL); + ixa = connp->conn_ixa; + ASSERT(ixa->ixa_refcnt == 1); + /* Need to preserve ixa_protocol */ + ixa_cleanup(ixa); + ixa->ixa_flags = 0; + /* Clear out the conn_t fields that are not preserved */ bzero(&connp->conn_start_clr, sizeof (conn_t) - @@ -2602,10 +2323,11 @@ ipcl_globalhash_remove(conn_t *connp) /* * Walk the list of all conn_t's in the system, calling the function provided - * with the specified argument for each. + * With the specified argument for each. * Applies to both IPv4 and IPv6. * - * IPCs may hold pointers to ipif/ill. To guard against stale pointers + * CONNs may hold pointers to ills (conn_dhcpinit_ill and + * conn_oper_pending_ill). To guard against stale pointers * ipcl_walk() is called to cleanup the conn_t's, typically when an interface is * unplumbed or removed. New conn_t's that are created while we are walking * may be missed by this walk, because they are not necessarily inserted @@ -2657,7 +2379,7 @@ ipcl_walk(pfv_t func, void *arg, ip_stack_t *ipst) * (peer tcp in ESTABLISHED state). */ conn_t * -ipcl_conn_tcp_lookup_reversed_ipv4(conn_t *connp, ipha_t *ipha, tcph_t *tcph, +ipcl_conn_tcp_lookup_reversed_ipv4(conn_t *connp, ipha_t *ipha, tcpha_t *tcpha, ip_stack_t *ipst) { uint32_t ports; @@ -2675,8 +2397,8 @@ ipcl_conn_tcp_lookup_reversed_ipv4(conn_t *connp, ipha_t *ipha, tcph_t *tcph, zone_chk = (ipha->ipha_src == htonl(INADDR_LOOPBACK) || ipha->ipha_dst == htonl(INADDR_LOOPBACK)); - bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t)); - bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t)); + pports[0] = tcpha->tha_fport; + pports[1] = tcpha->tha_lport; connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH(ipha->ipha_dst, ports, ipst)]; @@ -2707,7 +2429,7 @@ ipcl_conn_tcp_lookup_reversed_ipv4(conn_t *connp, ipha_t *ipha, tcph_t *tcph, * (peer tcp in ESTABLISHED state). */ conn_t * -ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcph_t *tcph, +ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcpha_t *tcpha, ip_stack_t *ipst) { uint32_t ports; @@ -2728,8 +2450,8 @@ ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcph_t *tcph, zone_chk = (IN6_IS_ADDR_LOOPBACK(&ip6h->ip6_src) || IN6_IS_ADDR_LOOPBACK(&ip6h->ip6_dst)); - bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t)); - bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t)); + pports[0] = tcpha->tha_fport; + pports[1] = tcpha->tha_lport; connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH_V6(ip6h->ip6_dst, ports, ipst)]; @@ -2738,7 +2460,7 @@ ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcph_t *tcph, for (tconnp = connfp->connf_head; tconnp != NULL; tconnp = tconnp->conn_next) { - /* We skip tcp_bound_if check here as this is loopback tcp */ + /* We skip conn_bound_if check here as this is loopback tcp */ if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP, ip6h->ip6_dst, ip6h->ip6_src, ports) && tconnp->conn_tcp->tcp_state == TCPS_ESTABLISHED && @@ -2760,7 +2482,7 @@ ipcl_conn_tcp_lookup_reversed_ipv6(conn_t *connp, ip6_t *ip6h, tcph_t *tcph, * Only checks for connected entries i.e. no INADDR_ANY checks. */ conn_t * -ipcl_tcp_lookup_reversed_ipv4(ipha_t *ipha, tcph_t *tcph, int min_state, +ipcl_tcp_lookup_reversed_ipv4(ipha_t *ipha, tcpha_t *tcpha, int min_state, ip_stack_t *ipst) { uint32_t ports; @@ -2769,8 +2491,8 @@ ipcl_tcp_lookup_reversed_ipv4(ipha_t *ipha, tcph_t *tcph, int min_state, conn_t *tconnp; pports = (uint16_t *)&ports; - bcopy(tcph->th_fport, &pports[0], sizeof (uint16_t)); - bcopy(tcph->th_lport, &pports[1], sizeof (uint16_t)); + pports[0] = tcpha->tha_fport; + pports[1] = tcpha->tha_lport; connfp = &ipst->ips_ipcl_conn_fanout[IPCL_CONN_HASH(ipha->ipha_dst, ports, ipst)]; @@ -2823,8 +2545,8 @@ ipcl_tcp_lookup_reversed_ipv6(ip6_t *ip6h, tcpha_t *tcpha, int min_state, if (IPCL_CONN_MATCH_V6(tconnp, IPPROTO_TCP, ip6h->ip6_dst, ip6h->ip6_src, ports) && tcp->tcp_state >= min_state && - (tcp->tcp_bound_if == 0 || - tcp->tcp_bound_if == ifindex)) { + (tconnp->conn_bound_if == 0 || + tconnp->conn_bound_if == ifindex)) { CONN_INC_REF(tconnp); mutex_exit(&connfp->connf_lock); @@ -2901,8 +2623,8 @@ ipcl_lookup_listener_v6(uint16_t lport, in6_addr_t *laddr, uint_t ifindex, tcp = connp->conn_tcp; if (IPCL_BIND_MATCH_V6(connp, IPPROTO_TCP, *laddr, lport) && IPCL_ZONE_MATCH(connp, zoneid) && - (tcp->tcp_bound_if == 0 || - tcp->tcp_bound_if == ifindex) && + (connp->conn_bound_if == 0 || + connp->conn_bound_if == ifindex) && tcp->tcp_listener == NULL) { CONN_INC_REF(connp); mutex_exit(&bind_connfp->connf_lock); |