dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.lib / ilbd / ilbd_nat.c
blobcdb114c7950c80b2d30fbb227bcd44115770dd0e
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 <sys/types.h>
28 #include <libilb.h>
29 #include <inet/ilb.h>
30 #include <stddef.h>
31 #include <stdlib.h>
32 #include <strings.h>
33 #include <errno.h>
34 #include <assert.h>
35 #include <macros.h>
36 #include "libilb_impl.h"
37 #include "ilbd.h"
40 * We only allow one show nat/persist command running at any time. Note that
41 * there is no lock for this since ilbd is single threaded. And we only care
42 * about the pointer value of client, not its type.
44 * The following variables store the current client making the request.
46 static void *nat_cur_cli;
47 static void *sticky_cur_cli;
49 /* Maximum number of NAT/sticky entries to request from kernel. */
50 #define NUM_ENTRIES 500
53 * Clear the current requesting client. This will allow a new client
54 * to make a request.
56 void
57 ilbd_show_nat_cleanup(void)
59 nat_cur_cli = NULL;
62 void
63 ilbd_show_sticky_cleanup(void)
65 sticky_cur_cli = NULL;
69 * To show the kernel NAT table.
71 * cli: the client pointer making the request.
72 * ic: the client request.
73 * rbuf: reply buffer to be filled in.
74 * rbufsz: reply buffer size.
76 ilb_status_t
77 ilbd_show_nat(void *cli, const ilb_comm_t *ic, uint32_t *rbuf, size_t *rbufsz)
79 ilb_show_info_t *req_si = (ilb_show_info_t *)&ic->ic_data;
80 ilb_list_nat_cmd_t *kcmd;
81 boolean_t start;
82 size_t tmp_rbufsz, kbufsz;
83 uint32_t max_num;
84 ilb_status_t ret;
85 int i;
86 ilb_show_info_t *reply;
87 ilb_nat_info_t *nat_ret;
89 /* For new client request, start from the beginning of the table. */
90 if (nat_cur_cli == NULL) {
91 nat_cur_cli = cli;
92 start = B_TRUE;
93 } else if (cli == nat_cur_cli) {
95 * Another request from client. If the client does not
96 * want to continue, reset the current client and reply OK.
98 if (ic->ic_flags & ILB_COMM_END) {
99 ilbd_show_nat_cleanup();
100 ilbd_reply_ok(rbuf, rbufsz);
101 return (ILB_STATUS_OK);
103 start = B_FALSE;
104 } else {
105 /* A request is on-going, so reject a new client. */
106 return (ILB_STATUS_INPROGRESS);
109 tmp_rbufsz = *rbufsz;
110 ilbd_reply_ok(rbuf, rbufsz);
111 reply = (ilb_show_info_t *)&((ilb_comm_t *)rbuf)->ic_data;
114 * Calculate the max number of ilb_nat_info_t can be fitted in the
115 * reply.
117 *rbufsz += sizeof (ilb_show_info_t *);
118 tmp_rbufsz -= *rbufsz;
119 max_num = tmp_rbufsz / sizeof (ilb_nat_info_t);
122 * Calculate the exact number of entries we should request from kernel.
124 max_num = min(req_si->sn_num, min(NUM_ENTRIES, max_num));
126 kbufsz = max_num * sizeof (ilb_nat_entry_t) +
127 offsetof(ilb_list_nat_cmd_t, entries);
128 if ((kcmd = malloc(kbufsz)) == NULL) {
129 logdebug("ilbd_show_nat: malloc(cmd)");
130 ilbd_reply_err(rbuf, rbufsz, ILB_STATUS_ENOMEM);
131 return (ILB_STATUS_ENOMEM);
134 kcmd->cmd = ILB_LIST_NAT_TABLE;
135 kcmd->flags = start ? ILB_LIST_BEGIN : ILB_LIST_CONT;
136 kcmd->num_nat = max_num;
137 if ((ret = do_ioctl(kcmd, kbufsz)) != ILB_STATUS_OK) {
138 logperror("ilbd_show_nat: ioctl(ILB_LIST_NAT_TABLE)");
139 ilbd_reply_err(rbuf, rbufsz, ret);
140 free(kcmd);
141 return (ret);
144 reply->sn_num = kcmd->num_nat;
145 *rbufsz += reply->sn_num * sizeof (ilb_nat_info_t);
148 * It is the end of table, let the client know. And the transaction
149 * is done.
151 if (kcmd->flags & ILB_LIST_END) {
152 nat_cur_cli = NULL;
153 } else {
155 * ilbd_reply_ok() sets ic_flags to ILB_COMM_END by default.
156 * Need to clear it here.
158 ((ilb_comm_t *)rbuf)->ic_flags = 0;
161 nat_ret = (ilb_nat_info_t *)&reply->sn_data;
163 for (i = 0; i < kcmd->num_nat; i++) {
164 ilb_nat_entry_t *nat;
166 nat = &kcmd->entries[i];
168 nat_ret->nat_proto = nat->proto;
170 nat_ret->nat_in_local = nat->in_local;
171 nat_ret->nat_in_global = nat->in_global;
172 nat_ret->nat_out_local = nat->out_local;
173 nat_ret->nat_out_global = nat->out_global;
175 nat_ret->nat_in_local_port = nat->in_local_port;
176 nat_ret->nat_in_global_port = nat->in_global_port;
177 nat_ret->nat_out_local_port = nat->out_local_port;
178 nat_ret->nat_out_global_port = nat->out_global_port;
180 nat_ret++;
183 end:
184 free(kcmd);
185 return (ret);
189 * To show the kernel sticky table.
191 * cli: the client pointer making the request.
192 * req_si: information about the show-persist request.
193 * rbuf: reply buffer to be filled in.
194 * rbufsz: reply buffer size.
196 ilb_status_t
197 ilbd_show_sticky(void *cli, const ilb_comm_t *ic, uint32_t *rbuf,
198 size_t *rbufsz)
200 ilb_show_info_t *req_si = (ilb_show_info_t *)&ic->ic_data;
201 ilb_list_sticky_cmd_t *kcmd;
202 boolean_t start;
203 size_t tmp_rbufsz, kbufsz;
204 uint32_t max_num;
205 ilb_status_t ret;
206 int i;
207 ilb_show_info_t *reply;
208 ilb_persist_info_t *st_ret;
210 /* For new client request, start from the beginning of the table. */
211 if (sticky_cur_cli == NULL) {
212 sticky_cur_cli = cli;
213 start = B_TRUE;
214 } else if (cli == sticky_cur_cli) {
216 * Another request from client. If the client does not
217 * want to continue, reset the current client and reply OK.
219 if (ic->ic_flags & ILB_COMM_END) {
220 ilbd_show_sticky_cleanup();
221 ilbd_reply_ok(rbuf, rbufsz);
222 return (ILB_STATUS_OK);
224 start = B_FALSE;
225 } else {
226 /* A request is on-going, so reject a new client. */
227 return (ILB_STATUS_INPROGRESS);
230 tmp_rbufsz = *rbufsz;
231 ilbd_reply_ok(rbuf, rbufsz);
232 reply = (ilb_show_info_t *)&((ilb_comm_t *)rbuf)->ic_data;
235 * Calculate the max number of ilb_persist_info_t can be fitted in the
236 * reply.
238 *rbufsz += sizeof (ilb_show_info_t *);
239 tmp_rbufsz -= *rbufsz;
240 max_num = tmp_rbufsz / sizeof (ilb_persist_info_t);
243 * Calculate the exact number of entries we should request from kernel.
245 max_num = min(req_si->sn_num, min(NUM_ENTRIES, max_num));
247 kbufsz = max_num * sizeof (ilb_sticky_entry_t) +
248 offsetof(ilb_list_sticky_cmd_t, entries);
249 if ((kcmd = malloc(kbufsz)) == NULL) {
250 logdebug("ilbd_show_nat: malloc(cmd)");
251 ilbd_reply_err(rbuf, rbufsz, ILB_STATUS_ENOMEM);
252 return (ILB_STATUS_ENOMEM);
255 kcmd->cmd = ILB_LIST_STICKY_TABLE;
256 kcmd->flags = start ? ILB_LIST_BEGIN : ILB_LIST_CONT;
257 kcmd->num_sticky = max_num;
258 if ((ret = do_ioctl(kcmd, kbufsz)) != ILB_STATUS_OK) {
259 logperror("ilbd_show_nat: ioctl(ILB_LIST_STICKY_TABLE)");
260 ilbd_reply_err(rbuf, rbufsz, ret);
261 free(kcmd);
262 return (ret);
265 reply->sn_num = kcmd->num_sticky;
266 *rbufsz += reply->sn_num * sizeof (ilb_persist_info_t);
268 if (kcmd->flags & ILB_LIST_END) {
269 sticky_cur_cli = NULL;
270 } else {
272 * ilbd_reply_ok() sets ic_flags to ILB_COMM_END by default.
273 * Need to clear it here.
275 ((ilb_comm_t *)rbuf)->ic_flags = 0;
278 st_ret = (ilb_persist_info_t *)&reply->sn_data;
280 for (i = 0; i < kcmd->num_sticky; i++) {
281 ilb_sticky_entry_t *st;
283 st = &kcmd->entries[i];
285 (void) strlcpy(st_ret->persist_rule_name, st->rule_name,
286 ILB_NAMESZ);
287 st_ret->persist_req_addr = st->req_addr;
288 st_ret->persist_srv_addr = st->srv_addr;
289 st_ret++;
292 end:
293 free(kcmd);
294 return (ret);