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 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 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