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
33 static 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 */
40 void (*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;
43 void (*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
47 int (*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;
53 void (*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 */
70 int
cl_tcp_walk_list(netstackid_t stack_id,int (* cl_callback)(cl_tcp_info_t *,void *),void * arg)71 cl_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
98 static int
cl_tcp_walk_list_stack(int (* callback)(cl_tcp_info_t *,void *),void * arg,tcp_stack_t * tcps)99 cl_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