feature_tests.h: always use largefile interfaces
[unleashed.git] / usr / src / lib / libilb / common / ilb_sg.c
blob62990f0f09efd763b67ad8adfd669377fe120ae3
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <stddef.h>
33 #include <libilb_impl.h>
34 #include <libilb.h>
36 static ilb_status_t
37 i_ilb_addrem_sg(ilb_handle_t h, const char *sgname, ilbd_cmd_t cmd)
39 ilb_status_t rc;
40 ilb_comm_t *ic;
41 size_t ic_sz;
43 if (h == ILB_INVALID_HANDLE || sgname == NULL || *sgname == '\0')
44 return (ILB_STATUS_EINVAL);
46 if (strlen(sgname) > ILB_SGNAME_SZ - 1)
47 return (ILB_STATUS_NAMETOOLONG);
49 if ((ic = i_ilb_alloc_req(cmd, &ic_sz)) == NULL)
50 return (ILB_STATUS_ENOMEM);
52 (void) strlcpy((char *)&ic->ic_data, sgname, sizeof (ilbd_name_t));
54 rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz);
55 if (rc != ILB_STATUS_OK)
56 goto out;
58 if (ic->ic_cmd != ILBD_CMD_OK)
59 rc = *(ilb_status_t *)&ic->ic_data;
60 out:
61 free(ic);
62 return (rc);
65 ilb_status_t
66 ilb_destroy_servergroup(ilb_handle_t h, const char *sgname)
68 return (i_ilb_addrem_sg(h, sgname, ILBD_DESTROY_SERVERGROUP));
71 ilb_status_t
72 ilb_create_servergroup(ilb_handle_t h, const char *sgname)
74 return (i_ilb_addrem_sg(h, sgname, ILBD_CREATE_SERVERGROUP));
77 static ilb_status_t
78 i_ilb_addrem_server_to_group(ilb_handle_t h, const char *sgname,
79 ilb_server_data_t *srv, ilbd_cmd_t cmd)
81 ilb_status_t rc = ILB_STATUS_OK;
82 ilb_sg_info_t *sg;
83 ilb_sg_srv_t *sgs;
84 in_port_t h_maxport, h_minport;
85 ilb_comm_t *ic;
86 size_t ic_sz;
88 if (h == ILB_INVALID_HANDLE || sgname == NULL ||
89 *sgname == '\0' || srv == NULL)
90 return (ILB_STATUS_EINVAL);
92 if (strlen(sgname) > ILB_SGNAME_SZ - 1)
93 return (ILB_STATUS_NAMETOOLONG);
95 /* now all the checks have passed, we can pass on the goods */
96 if ((ic = i_ilb_alloc_req(cmd, &ic_sz)) == NULL)
97 return (ILB_STATUS_ENOMEM);
99 sg = (ilb_sg_info_t *)&ic->ic_data;
100 sg->sg_srvcount = 1;
101 (void) strlcpy(sg->sg_name, sgname, sizeof (sg->sg_name));
103 sgs = &sg->sg_servers[0];
105 IP_COPY_CLI_2_IMPL(&srv->sd_addr, &sgs->sgs_addr);
106 h_minport = ntohs(srv->sd_minport);
107 h_maxport = ntohs(srv->sd_maxport);
108 sgs->sgs_minport = srv->sd_minport;
109 if (h_minport != 0 && h_maxport < h_minport)
110 sgs->sgs_maxport = srv->sd_minport;
111 else
112 sgs->sgs_maxport = srv->sd_maxport;
114 sgs->sgs_flags = srv->sd_flags;
115 if (srv->sd_srvID[0] == ILB_SRVID_PREFIX)
116 (void) strlcpy(sgs->sgs_srvID, srv->sd_srvID,
117 sizeof (sgs->sgs_srvID));
119 rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz);
120 if (rc != ILB_STATUS_OK)
121 goto out;
123 if (ic->ic_cmd != ILBD_CMD_OK)
124 rc = *(ilb_status_t *)&ic->ic_data;
126 out:
127 free(ic);
128 return (rc);
131 ilb_status_t
132 ilb_add_server_to_group(ilb_handle_t h, const char *sgname,
133 ilb_server_data_t *srv)
135 return (i_ilb_addrem_server_to_group(h, sgname, srv,
136 ILBD_ADD_SERVER_TO_GROUP));
139 ilb_status_t
140 ilb_rem_server_from_group(ilb_handle_t h, const char *sgname,
141 ilb_server_data_t *srv)
143 return (i_ilb_addrem_server_to_group(h, sgname, srv,
144 ILBD_REM_SERVER_FROM_GROUP));
147 static ilb_status_t
148 i_ilb_retrieve_sg_names(ilb_handle_t h, ilb_comm_t **rbuf, size_t *rbufsz)
150 ilb_status_t rc;
151 ilb_comm_t ic, *tmp_rbuf;
153 *rbufsz = ILBD_MSG_SIZE;
154 if ((tmp_rbuf = malloc(*rbufsz)) == NULL)
155 return (ILB_STATUS_ENOMEM);
157 ic.ic_cmd = ILBD_RETRIEVE_SG_NAMES;
158 rc = i_ilb_do_comm(h, &ic, sizeof (ic), tmp_rbuf, rbufsz);
159 if (rc != ILB_STATUS_OK)
160 goto out;
162 if (tmp_rbuf->ic_cmd == ILBD_CMD_OK) {
163 *rbuf = tmp_rbuf;
164 return (rc);
166 rc = *(ilb_status_t *)&tmp_rbuf->ic_data;
167 out:
168 free(tmp_rbuf);
169 *rbuf = NULL;
170 return (rc);
173 static ilb_status_t
174 i_ilb_retrieve_sg_hosts(ilb_handle_t h, const char *sgname, ilb_comm_t **rbuf,
175 size_t *rbufsz)
177 ilb_status_t rc;
178 ilb_comm_t *ic, *tmp_rbuf;
179 size_t ic_sz;
181 if ((ic = i_ilb_alloc_req(ILBD_RETRIEVE_SG_HOSTS, &ic_sz)) == NULL)
182 return (ILB_STATUS_ENOMEM);
183 *rbufsz = ILBD_MSG_SIZE;
184 if ((tmp_rbuf = malloc(*rbufsz)) == NULL) {
185 free(ic);
186 *rbuf = NULL;
187 return (ILB_STATUS_ENOMEM);
190 (void) strlcpy((char *)&ic->ic_data, sgname, sizeof (ilbd_name_t));
191 rc = i_ilb_do_comm(h, ic, ic_sz, tmp_rbuf, rbufsz);
192 if (rc != ILB_STATUS_OK)
193 goto out;
195 if (tmp_rbuf->ic_cmd == ILBD_CMD_OK) {
196 *rbuf = tmp_rbuf;
197 free(ic);
198 return (rc);
200 rc = *(ilb_status_t *)&tmp_rbuf->ic_data;
201 out:
202 free(ic);
203 free(tmp_rbuf);
204 *rbuf = NULL;
205 return (rc);
208 typedef enum {
209 walk_servers,
210 walk_sg
211 } sgwalk_t;
214 * "walks" one sg (retrieves data) and depending on "walktype" argument
215 * call servergroup function once per sg or server function once
216 * for every server. in both cases, the argument "f" is cast to
217 * be the proper function pointer type
219 static ilb_status_t
220 i_ilb_walk_one_sg(ilb_handle_t h, void *f, const char *sgname, void *arg,
221 sgwalk_t walktype)
223 ilb_status_t rc = ILB_STATUS_OK;
224 ilb_sg_info_t *sg_info;
225 ilb_sg_srv_t *srv;
226 int i;
227 ilb_comm_t *rbuf;
228 size_t rbufsz;
230 rc = i_ilb_retrieve_sg_hosts(h, sgname, &rbuf, &rbufsz);
231 if (rc != ILB_STATUS_OK)
232 return (rc);
233 sg_info = (ilb_sg_info_t *)&rbuf->ic_data;
235 if (walktype == walk_sg) {
236 sg_walkerfunc_t sg_func = (sg_walkerfunc_t)f;
237 ilb_sg_data_t sgd;
239 (void) strlcpy(sgd.sgd_name, sg_info->sg_name,
240 sizeof (sgd.sgd_name));
241 sgd.sgd_srvcount = sg_info->sg_srvcount;
242 sgd.sgd_flags = sg_info->sg_flags;
243 rc = sg_func(h, &sgd, arg);
244 goto out;
247 for (i = 0; i < sg_info->sg_srvcount; i++) {
248 srv_walkerfunc_t srv_func = (srv_walkerfunc_t)f;
249 ilb_server_data_t sd;
251 srv = &sg_info->sg_servers[i];
252 IP_COPY_IMPL_2_CLI(&srv->sgs_addr, &sd.sd_addr);
253 sd.sd_minport = srv->sgs_minport;
254 sd.sd_maxport = srv->sgs_maxport;
255 sd.sd_flags = srv->sgs_flags;
256 (void) strlcpy(sd.sd_srvID, srv->sgs_srvID,
257 sizeof (sd.sd_srvID));
259 rc = srv_func(h, &sd, sg_info->sg_name, arg);
260 if (rc != ILB_STATUS_OK)
261 break;
264 out:
265 free(rbuf);
266 return (rc);
270 * wrapper function for i_walk_one_sg; if necessary, gets list of
271 * SG names and calles i_walk_one_sg with every name
273 static ilb_status_t
274 i_walk_sgs(ilb_handle_t h, void *f, const char *sgname,
275 void *arg, sgwalk_t walktype)
277 ilb_status_t rc;
278 ilbd_namelist_t *sgl;
279 ilb_comm_t *rbuf;
280 size_t rbufsz;
281 int i;
283 if (sgname != NULL) {
284 rc = i_ilb_walk_one_sg(h, f, sgname, arg, walktype);
285 return (rc);
288 rc = i_ilb_retrieve_sg_names(h, &rbuf, &rbufsz);
289 if (rc != ILB_STATUS_OK)
290 return (rc);
291 sgl = (ilbd_namelist_t *)&rbuf->ic_data;
293 for (i = 0; i < sgl->ilbl_count; i++) {
294 rc = i_ilb_walk_one_sg(h, f, sgl->ilbl_name[i], arg, walktype);
296 * The server group may have been removed by another
297 * process, just continue.
299 if (rc == ILB_STATUS_SGUNAVAIL) {
300 rc = ILB_STATUS_OK;
301 continue;
303 if (rc != ILB_STATUS_OK)
304 break;
306 free(rbuf);
307 return (rc);
310 ilb_status_t
311 ilb_walk_servergroups(ilb_handle_t h, sg_walkerfunc_t f, const char *sgname,
312 void *arg)
314 return (i_walk_sgs(h, (void *)f, sgname, arg, walk_sg));
317 ilb_status_t
318 ilb_walk_servers(ilb_handle_t h, srv_walkerfunc_t f, const char *sgname,
319 void *arg)
321 return (i_walk_sgs(h, (void *)f, sgname, arg, walk_servers));
324 static ilb_status_t
325 ilb_Xable_server(ilb_handle_t h, ilb_server_data_t *srv, void *reserved,
326 ilbd_cmd_t cmd)
328 ilb_status_t rc;
329 ilb_sg_info_t *sg_info;
330 ilb_sg_srv_t *sgs;
331 in_port_t h_maxport, h_minport;
332 ilb_comm_t *ic;
333 size_t ic_sz;
335 if (h == NULL)
336 return (ILB_STATUS_EINVAL);
339 * In this implementation, this needs to be NULL, so
340 * there's no ugly surprises with old apps once we attach
341 * meaning to this parameter.
343 if (reserved != NULL)
344 return (ILB_STATUS_EINVAL);
346 /* now all the checks have passed, we can pass on the goods */
347 if ((ic = i_ilb_alloc_req(cmd, &ic_sz)) == NULL)
348 return (ILB_STATUS_ENOMEM);
350 sg_info = (ilb_sg_info_t *)&ic->ic_data;
351 sg_info->sg_srvcount = 1;
353 sgs = &sg_info->sg_servers[0];
355 /* make sure min_port <= max_port; comparison in host byte order! */
356 h_maxport = ntohs(srv->sd_maxport);
357 h_minport = ntohs(srv->sd_minport);
358 if (h_maxport != 0 && h_maxport < h_minport)
359 sgs->sgs_maxport = sgs->sgs_minport;
360 else
361 sgs->sgs_maxport = srv->sd_maxport;
362 sgs->sgs_minport = srv->sd_minport;
364 sgs->sgs_flags = srv->sd_flags;
365 (void) strlcpy(sgs->sgs_srvID, srv->sd_srvID, sizeof (sgs->sgs_srvID));
366 IP_COPY_CLI_2_IMPL(&srv->sd_addr, &sgs->sgs_addr);
368 rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz);
369 if (rc != ILB_STATUS_OK)
370 goto out;
372 if (ic->ic_cmd != ILBD_CMD_OK)
373 rc = *(ilb_status_t *)&ic->ic_data;
374 out:
375 free(ic);
376 return (rc);
379 ilb_status_t
380 ilb_enable_server(ilb_handle_t h, ilb_server_data_t *srv, void *reserved)
382 return (ilb_Xable_server(h, srv, reserved, ILBD_ENABLE_SERVER));
385 ilb_status_t
386 ilb_disable_server(ilb_handle_t h, ilb_server_data_t *srv, void *reserved)
388 return (ilb_Xable_server(h, srv, reserved, ILBD_DISABLE_SERVER));
391 static ilb_status_t
392 i_ilb_fillin_srvdata(ilb_handle_t h, ilb_server_data_t *srv, const char *sgname,
393 ilbd_cmd_t cmd)
395 ilb_status_t rc;
396 ilb_sg_info_t *sg_info;
397 ilb_sg_srv_t *sgs;
398 ilb_comm_t *ic;
399 size_t ic_sz;
400 ilb_comm_t *rbuf;
401 size_t rbufsz;
403 if (h == ILB_INVALID_HANDLE || sgname == NULL ||
404 *sgname == '\0' || srv == NULL)
405 return (ILB_STATUS_EINVAL);
407 if (cmd == ILBD_SRV_ID2ADDR && srv->sd_srvID[0] == '\0')
408 return (ILB_STATUS_EINVAL);
409 if (cmd == ILBD_SRV_ADDR2ID && !IS_AF_VALID(srv->sd_addr.ia_af))
410 return (ILB_STATUS_EINVAL);
412 if ((ic = i_ilb_alloc_req(cmd, &ic_sz)) == NULL)
413 return (ILB_STATUS_ENOMEM);
414 rbufsz = sizeof (ilb_comm_t) + sizeof (ilb_sg_srv_t);
415 if ((rbuf = malloc(rbufsz)) == NULL) {
416 free(ic);
417 return (ILB_STATUS_ENOMEM);
420 sg_info = (ilb_sg_info_t *)&ic->ic_data;
421 sg_info->sg_srvcount = 1;
422 (void) strlcpy(sg_info->sg_name, sgname, sizeof (sg_info->sg_name));
424 sgs = &sg_info->sg_servers[0];
426 if (cmd == ILBD_SRV_ID2ADDR)
427 (void) strlcpy(sgs->sgs_srvID, srv->sd_srvID,
428 sizeof (sgs->sgs_srvID));
429 else
430 IP_COPY_CLI_2_IMPL(&srv->sd_addr, &sgs->sgs_addr);
432 rc = i_ilb_do_comm(h, ic, ic_sz, rbuf, &rbufsz);
433 if (rc != ILB_STATUS_OK)
434 goto out;
436 if (rbuf->ic_cmd == ILBD_CMD_OK) {
437 sgs = (ilb_sg_srv_t *)&rbuf->ic_data;
438 if (cmd == ILBD_SRV_ID2ADDR) {
439 IP_COPY_IMPL_2_CLI(&sgs->sgs_addr, &srv->sd_addr);
440 } else {
441 (void) strlcpy(srv->sd_srvID, sgs->sgs_srvID,
442 sizeof (sgs->sgs_srvID));
444 return (rc);
447 rc = *(ilb_status_t *)&rbuf->ic_data;
448 out:
449 free(ic);
450 return (rc);
453 ilb_status_t
454 ilb_srvID_to_address(ilb_handle_t h, ilb_server_data_t *srv, const char *sgname)
456 return (i_ilb_fillin_srvdata(h, srv, sgname, ILBD_SRV_ID2ADDR));
460 ilb_status_t
461 ilb_address_to_srvID(ilb_handle_t h, ilb_server_data_t *srv, const char *sgname)
463 return (i_ilb_fillin_srvdata(h, srv, sgname, ILBD_SRV_ADDR2ID));