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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <stdlib.h> 29 #include <strings.h> 30 #include <sys/types.h> 31 #include <sys/socket.h> 32 #include <sys/stropts.h> 33 #include <netinet/in.h> 34 #include <stddef.h> 35 #include "libilb.h" 36 #include "libilb_impl.h" 37 38 /* ARGSUSED */ 39 static ilb_status_t 40 i_drop_hc(ilb_handle_t h, ilb_hc_info_t *hc, void *arg) 41 { 42 return (ilb_destroy_hc(h, hc->hci_name)); 43 } 44 45 /* ARGSUSED */ 46 static ilb_status_t 47 i_drop_rule(ilb_handle_t h, ilb_rule_data_t *rd, void *arg) 48 { 49 return (ilb_destroy_rule(h, rd->r_name)); 50 } 51 52 /* ARGSUSED */ 53 static ilb_status_t 54 i_drop_sg_srvs(ilb_handle_t h, ilb_server_data_t *srv, const char *sgname, 55 void *arg) 56 { 57 return (ilb_rem_server_from_group(h, sgname, srv)); 58 } 59 60 /* ARGSUSED */ 61 static ilb_status_t 62 i_drop_sg(ilb_handle_t h, ilb_sg_data_t *sg, void *arg) 63 { 64 ilb_status_t rc; 65 66 rc = ilb_walk_servers(h, i_drop_sg_srvs, sg->sgd_name, (void *)sg); 67 if (rc != ILB_STATUS_OK) 68 return (rc); 69 70 return (ilb_destroy_servergroup(h, sg->sgd_name)); 71 } 72 73 ilb_status_t 74 ilb_reset_config(ilb_handle_t h) 75 { 76 ilb_status_t rc; 77 78 if (h == NULL) 79 return (ILB_STATUS_EINVAL); 80 81 rc = ilb_walk_rules(h, i_drop_rule, NULL, NULL); 82 if (rc != ILB_STATUS_OK) 83 goto out; 84 85 rc = ilb_walk_servergroups(h, i_drop_sg, NULL, NULL); 86 if (rc != ILB_STATUS_OK) 87 goto out; 88 89 rc = ilb_walk_hc(h, i_drop_hc, NULL); 90 out: 91 return (rc); 92 } 93 94 ilb_status_t 95 ilb_create_rule(ilb_handle_t h, const ilb_rule_data_t *rd) 96 { 97 ilb_status_t rc; 98 ilb_comm_t *ic; 99 size_t ic_sz; 100 ilb_rule_info_t *rl; 101 102 if (h == ILB_INVALID_HANDLE || rd == NULL || *rd->r_name == '\0') 103 return (ILB_STATUS_EINVAL); 104 105 if ((ic = i_ilb_alloc_req(ILBD_CREATE_RULE, &ic_sz)) == NULL) 106 return (ILB_STATUS_ENOMEM); 107 rl = (ilb_rule_info_t *)&ic->ic_data; 108 109 /* 110 * Since the IP address representation in ilb_rule_data_t and 111 * ilb_rule_info_t is different, we need to convert between 112 * them. 113 */ 114 (void) strlcpy(rl->rl_name, rd->r_name, sizeof (rl->rl_name)); 115 (void) strlcpy(rl->rl_sgname, rd->r_sgname, sizeof (rl->rl_sgname)); 116 (void) strlcpy(rl->rl_hcname, rd->r_hcname, sizeof (rl->rl_hcname)); 117 rl->rl_flags = rd->r_flags; 118 rl->rl_proto = rd->r_proto; 119 rl->rl_ipversion = rd->r_vip.ia_af; 120 rl->rl_minport = rd->r_minport; 121 if (ntohs(rd->r_maxport) < ntohs(rd->r_minport)) 122 rl->rl_maxport = rd->r_minport; 123 else 124 rl->rl_maxport = rd->r_maxport; 125 rl->rl_algo = rd->r_algo; 126 rl->rl_topo = rd->r_topo; 127 rl->rl_conndrain = rd->r_conndrain; 128 rl->rl_nat_timeout = rd->r_nat_timeout; 129 rl->rl_sticky_timeout = rd->r_sticky_timeout; 130 rl->rl_hcport = rd->r_hcport; 131 rl->rl_hcpflag = rd->r_hcpflag; 132 133 IP_COPY_CLI_2_IMPL(&rd->r_vip, &rl->rl_vip); 134 IP_COPY_CLI_2_IMPL(&rd->r_stickymask, &rl->rl_stickymask); 135 IP_COPY_CLI_2_IMPL(&rd->r_nat_src_start, &rl->rl_nat_src_start); 136 IP_COPY_CLI_2_IMPL(&rd->r_nat_src_end, &rl->rl_nat_src_end); 137 138 rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz); 139 if (rc != ILB_STATUS_OK) 140 goto out; 141 142 if (ic->ic_cmd != ILBD_CMD_OK) 143 rc = *(ilb_status_t *)&ic->ic_data; 144 145 out: 146 free(ic); 147 return (rc); 148 } 149 150 static ilb_status_t 151 i_ilb_rule_action(ilb_handle_t h, const char *name, ilbd_cmd_t cmd) 152 { 153 ilb_status_t rc; 154 ilb_comm_t *ic; 155 size_t ic_sz; 156 157 if (h == ILB_INVALID_HANDLE) 158 return (ILB_STATUS_EINVAL); 159 160 if ((ic = i_ilb_alloc_req(cmd, &ic_sz)) == NULL) 161 return (ILB_STATUS_ENOMEM); 162 163 if (name == NULL) { 164 bzero(&ic->ic_data, sizeof (ilbd_name_t)); 165 } else { 166 (void) strlcpy((char *)&ic->ic_data, name, 167 sizeof (ilbd_name_t)); 168 } 169 170 rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz); 171 if (rc != ILB_STATUS_OK) 172 goto out; 173 174 if (ic->ic_cmd != ILBD_CMD_OK) 175 rc = *(ilb_status_t *)&ic->ic_data; 176 177 out: 178 free(ic); 179 return (rc); 180 } 181 182 ilb_status_t 183 ilb_destroy_rule(ilb_handle_t h, const char *name) 184 { 185 return (i_ilb_rule_action(h, name, ILBD_DESTROY_RULE)); 186 } 187 188 ilb_status_t 189 ilb_enable_rule(ilb_handle_t h, const char *name) 190 { 191 return (i_ilb_rule_action(h, name, ILBD_ENABLE_RULE)); 192 } 193 194 ilb_status_t 195 ilb_disable_rule(ilb_handle_t h, const char *name) 196 { 197 return (i_ilb_rule_action(h, name, ILBD_DISABLE_RULE)); 198 } 199 200 ilb_status_t 201 i_ilb_retrieve_rule_names(ilb_handle_t h, ilb_comm_t **rbuf, size_t *rbufsz) 202 { 203 ilb_status_t rc; 204 ilb_comm_t ic, *tmp_rbuf; 205 206 *rbufsz = ILBD_MSG_SIZE; 207 if ((tmp_rbuf = malloc(*rbufsz)) == NULL) 208 return (ILB_STATUS_ENOMEM); 209 210 ic.ic_cmd = ILBD_RETRIEVE_RULE_NAMES; 211 212 rc = i_ilb_do_comm(h, &ic, sizeof (ic), tmp_rbuf, rbufsz); 213 if (rc != ILB_STATUS_OK) 214 goto out; 215 216 if (tmp_rbuf->ic_cmd == ILBD_CMD_OK) { 217 *rbuf = tmp_rbuf; 218 return (rc); 219 } 220 rc = *(ilb_status_t *)&tmp_rbuf->ic_data; 221 out: 222 free(tmp_rbuf); 223 *rbuf = NULL; 224 return (rc); 225 } 226 227 static ilb_status_t 228 i_ilb_walk_one_rule(ilb_handle_t h, rule_walkerfunc_t f, const char *name, 229 void *arg) 230 { 231 ilb_status_t rc = ILB_STATUS_OK; 232 ilb_rule_info_t *rl = NULL; 233 ilb_rule_data_t rd; 234 ilb_comm_t *ic, *rbuf; 235 size_t ic_sz, rbufsz; 236 237 238 if ((ic = i_ilb_alloc_req(ILBD_RETRIEVE_RULE, &ic_sz)) == NULL) 239 return (ILB_STATUS_ENOMEM); 240 rbufsz = sizeof (ilb_comm_t) + sizeof (ilb_rule_info_t); 241 if ((rbuf = malloc(rbufsz)) == NULL) { 242 free(ic); 243 return (ILB_STATUS_ENOMEM); 244 } 245 246 (void) strlcpy((char *)&ic->ic_data, name, sizeof (ilbd_name_t)); 247 rc = i_ilb_do_comm(h, ic, ic_sz, rbuf, &rbufsz); 248 if (rc != ILB_STATUS_OK) 249 goto out; 250 if (rbuf->ic_cmd != ILBD_CMD_OK) { 251 rc = *(ilb_status_t *)&rbuf->ic_data; 252 goto out; 253 } 254 rl = (ilb_rule_info_t *)&rbuf->ic_data; 255 256 /* 257 * Since the IP address representation in ilb_rule_data_t and 258 * ilb_rule_info_t is different, we need to convert between 259 * them. 260 */ 261 (void) strlcpy(rd.r_name, rl->rl_name, sizeof (rd.r_name)); 262 (void) strlcpy(rd.r_hcname, rl->rl_hcname, sizeof (rd.r_hcname)); 263 (void) strlcpy(rd.r_sgname, rl->rl_sgname, sizeof (rd.r_sgname)); 264 rd.r_flags = rl->rl_flags; 265 rd.r_proto = rl->rl_proto; 266 rd.r_minport = rl->rl_minport; 267 rd.r_maxport = rl->rl_maxport; 268 rd.r_algo = rl->rl_algo; 269 rd.r_topo = rl->rl_topo; 270 rd.r_conndrain = rl->rl_conndrain; 271 rd.r_nat_timeout = rl->rl_nat_timeout; 272 rd.r_sticky_timeout = rl->rl_sticky_timeout; 273 rd.r_hcport = rl->rl_hcport; 274 rd.r_hcpflag = rl->rl_hcpflag; 275 276 IP_COPY_IMPL_2_CLI(&rl->rl_vip, &rd.r_vip); 277 IP_COPY_IMPL_2_CLI(&rl->rl_nat_src_start, &rd.r_nat_src_start); 278 IP_COPY_IMPL_2_CLI(&rl->rl_nat_src_end, &rd.r_nat_src_end); 279 IP_COPY_IMPL_2_CLI(&rl->rl_stickymask, &rd.r_stickymask); 280 281 rc = f(h, &rd, arg); 282 283 out: 284 free(ic); 285 free(rbuf); 286 return (rc); 287 } 288 289 ilb_status_t 290 ilb_walk_rules(ilb_handle_t h, rule_walkerfunc_t f, const char *name, 291 void *arg) 292 { 293 ilb_status_t rc; 294 ilbd_namelist_t *names; 295 ilb_comm_t *rbuf; 296 size_t rbufsz; 297 int i; 298 299 if (h == NULL) 300 return (ILB_STATUS_EINVAL); 301 302 if (name != NULL) 303 return (i_ilb_walk_one_rule(h, f, name, arg)); 304 305 rc = i_ilb_retrieve_rule_names(h, &rbuf, &rbufsz); 306 if (rc != ILB_STATUS_OK) 307 return (rc); 308 309 names = (ilbd_namelist_t *)&rbuf->ic_data; 310 for (i = 0; i < names->ilbl_count; i++) { 311 rc = i_ilb_walk_one_rule(h, f, names->ilbl_name[i], arg); 312 /* 313 * The rule may have been removed by another process since 314 * we retrieve all the rule names, just continue. 315 */ 316 if (rc == ILB_STATUS_ENOENT) { 317 rc = ILB_STATUS_OK; 318 continue; 319 } 320 if (rc != ILB_STATUS_OK) 321 break; 322 } 323 324 free(rbuf); 325 return (rc); 326 } 327