xref: /illumos-gate/usr/src/lib/libilb/common/ilb_hc.c (revision 66582b606a8194f7f3ba5b3a3a6dca5b0d346361)
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 #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>
35 
36 /*
37  * Create a health check, returning a health check handle upon success.
38  * Health check created will be recorded in persistent datastore.
39  */
40 ilb_status_t
41 ilb_create_hc(ilb_handle_t h, const ilb_hc_info_t *hc)
42 {
43 	ilb_status_t	rc;
44 	ilb_comm_t	*ic;
45 	size_t		ic_sz;
46 
47 	if (h == ILB_INVALID_HANDLE || hc == NULL || *hc->hci_name == '\0' ||
48 	    hc->hci_timeout < 0 || hc->hci_count < 0 ||
49 	    hc->hci_interval <= hc->hci_timeout * hc->hci_count)
50 		return (ILB_STATUS_EINVAL);
51 
52 	if ((ic = i_ilb_alloc_req(ILBD_CREATE_HC, &ic_sz)) == NULL)
53 		return (ILB_STATUS_ENOMEM);
54 
55 	(void) memcpy(&ic->ic_data, hc, sizeof (ilb_hc_info_t));
56 
57 	rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz);
58 	if (rc != ILB_STATUS_OK)
59 		goto out;
60 
61 	if (ic->ic_cmd != ILBD_CMD_OK)
62 		rc = *(ilb_status_t *)&ic->ic_data;
63 
64 out:
65 	free(ic);
66 	return (rc);
67 }
68 
69 /*
70  * Given a health check handle, destroy the corresponding health check.
71  * Persistent datastore will be updated as well.
72  */
73 ilb_status_t
74 ilb_destroy_hc(ilb_handle_t h, const char *hcname)
75 {
76 	ilb_status_t	rc;
77 	ilb_comm_t	*ic;
78 	size_t		ic_sz;
79 
80 	if (h == ILB_INVALID_HANDLE || hcname == NULL || *hcname == '\0')
81 		return (ILB_STATUS_EINVAL);
82 
83 	if ((ic = i_ilb_alloc_req(ILBD_DESTROY_HC, &ic_sz)) == NULL)
84 		return (ILB_STATUS_ENOMEM);
85 
86 	(void) strlcpy((char *)&ic->ic_data, hcname, sizeof (ilbd_name_t));
87 
88 	rc = i_ilb_do_comm(h, ic, ic_sz, ic, &ic_sz);
89 	if (rc != ILB_STATUS_OK)
90 		goto out;
91 
92 	if (ic->ic_cmd != ILBD_CMD_OK)
93 		rc = *(ilb_status_t *)&ic->ic_data;
94 
95 out:
96 	free(ic);
97 	return (rc);
98 }
99 
100 /*
101  * Given a health check name, get hc info associated with this handle
102  */
103 ilb_status_t
104 ilb_get_hc_info(ilb_handle_t h, const char *name, ilb_hc_info_t *hcp)
105 {
106 	ilb_status_t	rc;
107 	ilb_comm_t	*ic, *rbuf;
108 	size_t		ic_sz, rbufsz;
109 
110 	if (h == ILB_INVALID_HANDLE || name == NULL || hcp == NULL)
111 		return (ILB_STATUS_EINVAL);
112 
113 	if ((ic = i_ilb_alloc_req(ILBD_GET_HC_INFO, &ic_sz)) == NULL)
114 		return (ILB_STATUS_ENOMEM);
115 	rbufsz = sizeof (ilb_comm_t) + sizeof (ilb_hc_info_t);
116 	if ((rbuf = malloc(rbufsz)) == NULL) {
117 		free(ic);
118 		return (ILB_STATUS_ENOMEM);
119 	}
120 
121 	(void) strlcpy((char *)&ic->ic_data, name, sizeof (ilbd_name_t));
122 
123 	rc = i_ilb_do_comm(h, ic, ic_sz, rbuf, &rbufsz);
124 	if (rc != ILB_STATUS_OK)
125 		goto out;
126 
127 	if (rbuf->ic_cmd != ILBD_CMD_OK) {
128 		rc = *(ilb_status_t *)&rbuf->ic_data;
129 		goto out;
130 	}
131 	(void) memcpy(hcp, &rbuf->ic_data, sizeof (*hcp));
132 
133 out:
134 	free(ic);
135 	free(rbuf);
136 	return (rc);
137 }
138 
139 /*
140  * Walk through all health checks, will need if we implement list-hc
141  */
142 ilb_status_t
143 ilb_walk_hc(ilb_handle_t h, hc_walkerfunc_t func, void *arg)
144 {
145 	ilb_status_t	rc;
146 	ilb_hc_info_t	hc_info;
147 	ilbd_namelist_t	*hc_names;
148 	ilb_comm_t	ic, *rbuf;
149 	size_t		rbufsz;
150 	int		i;
151 
152 	rbufsz = ILBD_MSG_SIZE;
153 	if ((rbuf = malloc(rbufsz)) == NULL)
154 		return (ILB_STATUS_ENOMEM);
155 	ic.ic_cmd = ILBD_RETRIEVE_HC_NAMES;
156 
157 	rc = i_ilb_do_comm(h, &ic, sizeof (ic), rbuf, &rbufsz);
158 	if (rc != ILB_STATUS_OK)
159 		goto out;
160 	if (rbuf->ic_cmd != ILBD_CMD_OK) {
161 		rc = *(ilb_status_t *)&rbuf->ic_data;
162 		goto out;
163 	}
164 
165 	hc_names = (ilbd_namelist_t *)&rbuf->ic_data;
166 	for (i = 0; i < hc_names->ilbl_count; i++) {
167 		rc = ilb_get_hc_info(h, hc_names->ilbl_name[i], &hc_info);
168 		/*
169 		 * Since getting the list of hc names and getting the info
170 		 * of each of them are not atomic, some hc objects may have
171 		 * been deleted.  If this is the case, just skip them.
172 		 */
173 		if (rc == ILB_STATUS_ENOENT) {
174 			rc = ILB_STATUS_OK;
175 			continue;
176 		} else if (rc != ILB_STATUS_OK) {
177 			break;
178 		}
179 		rc = func(h, &hc_info, arg);
180 	}
181 
182 out:
183 	free(rbuf);
184 	return (rc);
185 }
186 
187 static ilb_status_t
188 ilb_get_hc_srvs(ilb_handle_t h, const char *rulename, ilb_comm_t **rbuf,
189     size_t *rbufsz)
190 {
191 	ilb_status_t	rc;
192 	ilb_comm_t	*ic, *tmp_rbuf;
193 	size_t		ic_sz;
194 
195 	if ((ic = i_ilb_alloc_req(ILBD_GET_HC_SRVS, &ic_sz)) == NULL)
196 		return (ILB_STATUS_ENOMEM);
197 	*rbufsz = ILBD_MSG_SIZE;
198 	if ((tmp_rbuf = malloc(*rbufsz)) == NULL) {
199 		free(ic);
200 		return (ILB_STATUS_ENOMEM);
201 	}
202 
203 	(void) strlcpy((char *)&ic->ic_data, rulename,
204 	    sizeof (ilbd_name_t));
205 
206 	rc = i_ilb_do_comm(h, ic, ic_sz, tmp_rbuf, rbufsz);
207 	if (rc != ILB_STATUS_OK)
208 		goto out;
209 
210 	if (tmp_rbuf->ic_cmd == ILBD_CMD_OK) {
211 		*rbuf = tmp_rbuf;
212 		return (rc);
213 	}
214 	rc = *(ilb_status_t *)&tmp_rbuf->ic_data;
215 out:
216 	free(ic);
217 	free(tmp_rbuf);
218 	*rbuf = NULL;
219 	return (rc);
220 }
221 
222 ilb_status_t
223 ilb_walk_hc_srvs(ilb_handle_t h, hc_srvwalkerfunc_t fn, const char *rulename,
224     void *arg)
225 {
226 	ilb_status_t		rc;
227 	ilb_hc_rule_srv_t	*srvs;
228 	int			i, j;
229 	ilb_comm_t		*rbuf;
230 	size_t			rbufsz;
231 
232 	if (rulename != NULL) {
233 		rc = ilb_get_hc_srvs(h, rulename, &rbuf, &rbufsz);
234 		if (rc != ILB_STATUS_OK)
235 			return (rc);
236 		srvs = (ilb_hc_rule_srv_t *)&rbuf->ic_data;
237 		for (i = 0; i < srvs->rs_num_srvs; i++) {
238 			rc = fn(h, &srvs->rs_srvs[i], arg);
239 			if (rc != ILB_STATUS_OK)
240 				break;
241 		}
242 		free(rbuf);
243 	} else {
244 		ilbd_namelist_t *names;
245 		ilb_comm_t	*srv_rbuf;
246 		size_t		srv_rbufsz;
247 
248 		rc = i_ilb_retrieve_rule_names(h, &rbuf, &rbufsz);
249 		if (rc != ILB_STATUS_OK)
250 			return (rc);
251 		names = (ilbd_namelist_t *)&rbuf->ic_data;
252 
253 		for (i = 0; i < names->ilbl_count; i++) {
254 			rc = ilb_get_hc_srvs(h, names->ilbl_name[i],
255 			    &srv_rbuf, &srv_rbufsz);
256 
257 			/* Not all rules have HC, so reset the error to OK. */
258 			if (rc == ILB_STATUS_RULE_NO_HC) {
259 				rc = ILB_STATUS_OK;
260 				continue;
261 			} else if (rc != ILB_STATUS_OK) {
262 				break;
263 			}
264 
265 			srvs = (ilb_hc_rule_srv_t *)&srv_rbuf->ic_data;
266 			for (j = 0; j < srvs->rs_num_srvs; j++) {
267 				rc = fn(h, &srvs->rs_srvs[j], arg);
268 				if (rc != ILB_STATUS_OK)
269 					break;
270 			}
271 			free(srv_rbuf);
272 		}
273 		free(rbuf);
274 	}
275 	return (rc);
276 }
277