1*721fffe3SKacheong Poon /*
2*721fffe3SKacheong Poon  * CDDL HEADER START
3*721fffe3SKacheong Poon  *
4*721fffe3SKacheong Poon  * The contents of this file are subject to the terms of the
5*721fffe3SKacheong Poon  * Common Development and Distribution License (the "License").
6*721fffe3SKacheong Poon  * You may not use this file except in compliance with the License.
7*721fffe3SKacheong Poon  *
8*721fffe3SKacheong Poon  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*721fffe3SKacheong Poon  * or http://www.opensolaris.org/os/licensing.
10*721fffe3SKacheong Poon  * See the License for the specific language governing permissions
11*721fffe3SKacheong Poon  * and limitations under the License.
12*721fffe3SKacheong Poon  *
13*721fffe3SKacheong Poon  * When distributing Covered Code, include this CDDL HEADER in each
14*721fffe3SKacheong Poon  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*721fffe3SKacheong Poon  * If applicable, add the following below this CDDL HEADER, with the
16*721fffe3SKacheong Poon  * fields enclosed by brackets "[]" replaced with your own identifying
17*721fffe3SKacheong Poon  * information: Portions Copyright [yyyy] [name of copyright owner]
18*721fffe3SKacheong Poon  *
19*721fffe3SKacheong Poon  * CDDL HEADER END
20*721fffe3SKacheong Poon  */
21*721fffe3SKacheong Poon 
22*721fffe3SKacheong Poon /*
23*721fffe3SKacheong Poon  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
24*721fffe3SKacheong Poon  * Use is subject to license terms.
25*721fffe3SKacheong Poon  */
26*721fffe3SKacheong Poon 
27*721fffe3SKacheong Poon /* This file contains Solaris Cluster related TCP hooks and functions. */
28*721fffe3SKacheong Poon 
29*721fffe3SKacheong Poon #include <inet/tcp.h>
30*721fffe3SKacheong Poon #include <inet/tcp_impl.h>
31*721fffe3SKacheong Poon #include <inet/tcp_cluster.h>
32*721fffe3SKacheong Poon 
33*721fffe3SKacheong Poon static int cl_tcp_walk_list_stack(int (*callback)(cl_tcp_info_t *, void *),
34*721fffe3SKacheong Poon     void *arg, tcp_stack_t *tcps);
35*721fffe3SKacheong Poon 
36*721fffe3SKacheong Poon /*
37*721fffe3SKacheong Poon  * Hook functions to enable cluster networking
38*721fffe3SKacheong Poon  * On non-clustered systems these vectors must always be NULL.
39*721fffe3SKacheong Poon  */
40*721fffe3SKacheong Poon void (*cl_inet_listen)(netstackid_t stack_id, uint8_t protocol,
41*721fffe3SKacheong Poon 			    sa_family_t addr_family, uint8_t *laddrp,
42*721fffe3SKacheong Poon 			    in_port_t lport, void *args) = NULL;
43*721fffe3SKacheong Poon void (*cl_inet_unlisten)(netstackid_t stack_id, uint8_t protocol,
44*721fffe3SKacheong Poon 			    sa_family_t addr_family, uint8_t *laddrp,
45*721fffe3SKacheong Poon 			    in_port_t lport, void *args) = NULL;
46*721fffe3SKacheong Poon 
47*721fffe3SKacheong Poon int (*cl_inet_connect2)(netstackid_t stack_id, uint8_t protocol,
48*721fffe3SKacheong Poon 			    boolean_t is_outgoing,
49*721fffe3SKacheong Poon 			    sa_family_t addr_family,
50*721fffe3SKacheong Poon 			    uint8_t *laddrp, in_port_t lport,
51*721fffe3SKacheong Poon 			    uint8_t *faddrp, in_port_t fport,
52*721fffe3SKacheong Poon 			    void *args) = NULL;
53*721fffe3SKacheong Poon void (*cl_inet_disconnect)(netstackid_t stack_id, uint8_t protocol,
54*721fffe3SKacheong Poon 			    sa_family_t addr_family, uint8_t *laddrp,
55*721fffe3SKacheong Poon 			    in_port_t lport, uint8_t *faddrp,
56*721fffe3SKacheong Poon 			    in_port_t fport, void *args) = NULL;
57*721fffe3SKacheong Poon 
58*721fffe3SKacheong Poon /*
59*721fffe3SKacheong Poon  * Exported routine for extracting active tcp connection status.
60*721fffe3SKacheong Poon  *
61*721fffe3SKacheong Poon  * This is used by the Solaris Cluster Networking software to
62*721fffe3SKacheong Poon  * gather a list of connections that need to be forwarded to
63*721fffe3SKacheong Poon  * specific nodes in the cluster when configuration changes occur.
64*721fffe3SKacheong Poon  *
65*721fffe3SKacheong Poon  * The callback is invoked for each tcp_t structure from all netstacks,
66*721fffe3SKacheong Poon  * if 'stack_id' is less than 0. Otherwise, only for tcp_t structures
67*721fffe3SKacheong Poon  * from the netstack with the specified stack_id. Returning
68*721fffe3SKacheong Poon  * non-zero from the callback routine terminates the search.
69*721fffe3SKacheong Poon  */
70*721fffe3SKacheong Poon int
cl_tcp_walk_list(netstackid_t stack_id,int (* cl_callback)(cl_tcp_info_t *,void *),void * arg)71*721fffe3SKacheong Poon cl_tcp_walk_list(netstackid_t stack_id,
72*721fffe3SKacheong Poon     int (*cl_callback)(cl_tcp_info_t *, void *), void *arg)
73*721fffe3SKacheong Poon {
74*721fffe3SKacheong Poon 	netstack_handle_t nh;
75*721fffe3SKacheong Poon 	netstack_t *ns;
76*721fffe3SKacheong Poon 	int ret = 0;
77*721fffe3SKacheong Poon 
78*721fffe3SKacheong Poon 	if (stack_id >= 0) {
79*721fffe3SKacheong Poon 		if ((ns = netstack_find_by_stackid(stack_id)) == NULL)
80*721fffe3SKacheong Poon 			return (EINVAL);
81*721fffe3SKacheong Poon 
82*721fffe3SKacheong Poon 		ret = cl_tcp_walk_list_stack(cl_callback, arg,
83*721fffe3SKacheong Poon 		    ns->netstack_tcp);
84*721fffe3SKacheong Poon 		netstack_rele(ns);
85*721fffe3SKacheong Poon 		return (ret);
86*721fffe3SKacheong Poon 	}
87*721fffe3SKacheong Poon 
88*721fffe3SKacheong Poon 	netstack_next_init(&nh);
89*721fffe3SKacheong Poon 	while ((ns = netstack_next(&nh)) != NULL) {
90*721fffe3SKacheong Poon 		ret = cl_tcp_walk_list_stack(cl_callback, arg,
91*721fffe3SKacheong Poon 		    ns->netstack_tcp);
92*721fffe3SKacheong Poon 		netstack_rele(ns);
93*721fffe3SKacheong Poon 	}
94*721fffe3SKacheong Poon 	netstack_next_fini(&nh);
95*721fffe3SKacheong Poon 	return (ret);
96*721fffe3SKacheong Poon }
97*721fffe3SKacheong Poon 
98*721fffe3SKacheong Poon static int
cl_tcp_walk_list_stack(int (* callback)(cl_tcp_info_t *,void *),void * arg,tcp_stack_t * tcps)99*721fffe3SKacheong Poon cl_tcp_walk_list_stack(int (*callback)(cl_tcp_info_t *, void *), void *arg,
100*721fffe3SKacheong Poon     tcp_stack_t *tcps)
101*721fffe3SKacheong Poon {
102*721fffe3SKacheong Poon 	tcp_t *tcp;
103*721fffe3SKacheong Poon 	cl_tcp_info_t	cl_tcpi;
104*721fffe3SKacheong Poon 	connf_t	*connfp;
105*721fffe3SKacheong Poon 	conn_t	*connp;
106*721fffe3SKacheong Poon 	int	i;
107*721fffe3SKacheong Poon 	ip_stack_t	*ipst = tcps->tcps_netstack->netstack_ip;
108*721fffe3SKacheong Poon 
109*721fffe3SKacheong Poon 	ASSERT(callback != NULL);
110*721fffe3SKacheong Poon 
111*721fffe3SKacheong Poon 	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
112*721fffe3SKacheong Poon 		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
113*721fffe3SKacheong Poon 		connp = NULL;
114*721fffe3SKacheong Poon 
115*721fffe3SKacheong Poon 		while ((connp =
116*721fffe3SKacheong Poon 		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
117*721fffe3SKacheong Poon 
118*721fffe3SKacheong Poon 			tcp = connp->conn_tcp;
119*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_version = CL_TCPI_V1;
120*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_ipversion = connp->conn_ipversion;
121*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_state = tcp->tcp_state;
122*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_lport = connp->conn_lport;
123*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_fport = connp->conn_fport;
124*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_laddr_v6 = connp->conn_laddr_v6;
125*721fffe3SKacheong Poon 			cl_tcpi.cl_tcpi_faddr_v6 = connp->conn_faddr_v6;
126*721fffe3SKacheong Poon 
127*721fffe3SKacheong Poon 			/*
128*721fffe3SKacheong Poon 			 * If the callback returns non-zero
129*721fffe3SKacheong Poon 			 * we terminate the traversal.
130*721fffe3SKacheong Poon 			 */
131*721fffe3SKacheong Poon 			if ((*callback)(&cl_tcpi, arg) != 0) {
132*721fffe3SKacheong Poon 				CONN_DEC_REF(tcp->tcp_connp);
133*721fffe3SKacheong Poon 				return (1);
134*721fffe3SKacheong Poon 			}
135*721fffe3SKacheong Poon 		}
136*721fffe3SKacheong Poon 	}
137*721fffe3SKacheong Poon 
138*721fffe3SKacheong Poon 	return (0);
139*721fffe3SKacheong Poon }
140