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
i_drop_hc(ilb_handle_t h,ilb_hc_info_t * hc,void * arg)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
i_drop_rule(ilb_handle_t h,ilb_rule_data_t * rd,void * arg)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
i_drop_sg_srvs(ilb_handle_t h,ilb_server_data_t * srv,const char * sgname,void * arg)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
i_drop_sg(ilb_handle_t h,ilb_sg_data_t * sg,void * arg)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
ilb_reset_config(ilb_handle_t h)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
ilb_create_rule(ilb_handle_t h,const ilb_rule_data_t * rd)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
i_ilb_rule_action(ilb_handle_t h,const char * name,ilbd_cmd_t cmd)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
ilb_destroy_rule(ilb_handle_t h,const char * name)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
ilb_enable_rule(ilb_handle_t h,const char * name)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
ilb_disable_rule(ilb_handle_t h,const char * name)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
i_ilb_retrieve_rule_names(ilb_handle_t h,ilb_comm_t ** rbuf,size_t * rbufsz)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
i_ilb_walk_one_rule(ilb_handle_t h,rule_walkerfunc_t f,const char * name,void * arg)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
ilb_walk_rules(ilb_handle_t h,rule_walkerfunc_t f,const char * name,void * arg)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