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 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/* This file contains Solaris Cluster related TCP hooks and functions. */
28
29#include <inet/tcp.h>
30#include <inet/tcp_impl.h>
31#include <inet/tcp_cluster.h>
32
33static int cl_tcp_walk_list_stack(int (*callback)(cl_tcp_info_t *, void *),
34    void *arg, tcp_stack_t *tcps);
35
36/*
37 * Hook functions to enable cluster networking
38 * On non-clustered systems these vectors must always be NULL.
39 */
40void (*cl_inet_listen)(netstackid_t stack_id, uint8_t protocol,
41			    sa_family_t addr_family, uint8_t *laddrp,
42			    in_port_t lport, void *args) = NULL;
43void (*cl_inet_unlisten)(netstackid_t stack_id, uint8_t protocol,
44			    sa_family_t addr_family, uint8_t *laddrp,
45			    in_port_t lport, void *args) = NULL;
46
47int (*cl_inet_connect2)(netstackid_t stack_id, uint8_t protocol,
48			    boolean_t is_outgoing,
49			    sa_family_t addr_family,
50			    uint8_t *laddrp, in_port_t lport,
51			    uint8_t *faddrp, in_port_t fport,
52			    void *args) = NULL;
53void (*cl_inet_disconnect)(netstackid_t stack_id, uint8_t protocol,
54			    sa_family_t addr_family, uint8_t *laddrp,
55			    in_port_t lport, uint8_t *faddrp,
56			    in_port_t fport, void *args) = NULL;
57
58/*
59 * Exported routine for extracting active tcp connection status.
60 *
61 * This is used by the Solaris Cluster Networking software to
62 * gather a list of connections that need to be forwarded to
63 * specific nodes in the cluster when configuration changes occur.
64 *
65 * The callback is invoked for each tcp_t structure from all netstacks,
66 * if 'stack_id' is less than 0. Otherwise, only for tcp_t structures
67 * from the netstack with the specified stack_id. Returning
68 * non-zero from the callback routine terminates the search.
69 */
70int
71cl_tcp_walk_list(netstackid_t stack_id,
72    int (*cl_callback)(cl_tcp_info_t *, void *), void *arg)
73{
74	netstack_handle_t nh;
75	netstack_t *ns;
76	int ret = 0;
77
78	if (stack_id >= 0) {
79		if ((ns = netstack_find_by_stackid(stack_id)) == NULL)
80			return (EINVAL);
81
82		ret = cl_tcp_walk_list_stack(cl_callback, arg,
83		    ns->netstack_tcp);
84		netstack_rele(ns);
85		return (ret);
86	}
87
88	netstack_next_init(&nh);
89	while ((ns = netstack_next(&nh)) != NULL) {
90		ret = cl_tcp_walk_list_stack(cl_callback, arg,
91		    ns->netstack_tcp);
92		netstack_rele(ns);
93	}
94	netstack_next_fini(&nh);
95	return (ret);
96}
97
98static int
99cl_tcp_walk_list_stack(int (*callback)(cl_tcp_info_t *, void *), void *arg,
100    tcp_stack_t *tcps)
101{
102	tcp_t *tcp;
103	cl_tcp_info_t	cl_tcpi;
104	connf_t	*connfp;
105	conn_t	*connp;
106	int	i;
107	ip_stack_t	*ipst = tcps->tcps_netstack->netstack_ip;
108
109	ASSERT(callback != NULL);
110
111	for (i = 0; i < CONN_G_HASH_SIZE; i++) {
112		connfp = &ipst->ips_ipcl_globalhash_fanout[i];
113		connp = NULL;
114
115		while ((connp =
116		    ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) {
117
118			tcp = connp->conn_tcp;
119			cl_tcpi.cl_tcpi_version = CL_TCPI_V1;
120			cl_tcpi.cl_tcpi_ipversion = connp->conn_ipversion;
121			cl_tcpi.cl_tcpi_state = tcp->tcp_state;
122			cl_tcpi.cl_tcpi_lport = connp->conn_lport;
123			cl_tcpi.cl_tcpi_fport = connp->conn_fport;
124			cl_tcpi.cl_tcpi_laddr_v6 = connp->conn_laddr_v6;
125			cl_tcpi.cl_tcpi_faddr_v6 = connp->conn_faddr_v6;
126
127			/*
128			 * If the callback returns non-zero
129			 * we terminate the traversal.
130			 */
131			if ((*callback)(&cl_tcpi, arg) != 0) {
132				CONN_DEC_REF(tcp->tcp_connp);
133				return (1);
134			}
135		}
136	}
137
138	return (0);
139}
140