ilb_nat.c revision 10946:324bab2b3370
199461Sobrien/*
2218822Sdim * CDDL HEADER START
3218822Sdim *
499461Sobrien * The contents of this file are subject to the terms of the
599461Sobrien * Common Development and Distribution License (the "License").
699461Sobrien * You may not use this file except in compliance with the License.
799461Sobrien *
899461Sobrien * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
999461Sobrien * or http://www.opensolaris.org/os/licensing.
1099461Sobrien * See the License for the specific language governing permissions
1199461Sobrien * and limitations under the License.
1299461Sobrien *
1399461Sobrien * When distributing Covered Code, include this CDDL HEADER in each
1499461Sobrien * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1599461Sobrien * If applicable, add the following below this CDDL HEADER, with the
1699461Sobrien * fields enclosed by brackets "[]" replaced with your own identifying
1799461Sobrien * information: Portions Copyright [yyyy] [name of copyright owner]
1899461Sobrien *
1999461Sobrien * CDDL HEADER END
20218822Sdim */
21218822Sdim
2299461Sobrien/*
2399461Sobrien * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2499461Sobrien * Use is subject to license terms.
2599461Sobrien */
2699461Sobrien
27130561Sobrien#include <stdlib.h>
28130561Sobrien#include <strings.h>
2999461Sobrien#include <unistd.h>
3099461Sobrien#include <stddef.h>
3199461Sobrien#include <sys/types.h>
3299461Sobrien#include <sys/socket.h>
3399461Sobrien#include "libilb.h"
3499461Sobrien#include "libilb_impl.h"
3599461Sobrien
3699461Sobrienenum which_tbl {
3799461Sobrien	show_nat = 1,
3899461Sobrien	show_persist
39130561Sobrien};
4099461Sobrien
41130561Sobrien/* The common function to show kernel info. */
42130561Sobrienstatic ilb_status_t ilb_show_info(ilb_handle_t, char *, size_t *, boolean_t *,
43130561Sobrien    enum which_tbl);
44130561Sobrien
4599461Sobrien/*
46130561Sobrien * To get the ILB NAT table.
4799461Sobrien *
4899461Sobrien * buf: The buffer to return the NAT table entries.
49130561Sobrien * num: The caller sets it to the number of ilb_nat_info_t entries buf can
5099461Sobrien *      hold.  On return, it contains the actual number of entries put in buf.
5199461Sobrien * end: The caller sets it to B_TRUE if it only wants at most num entries to
52130561Sobrien *      be returned.  The transaction to ilbd will be termianted when this
5399461Sobrien *      call returns.
5499461Sobrien *      The caller sets it to B_FALSE if it intends to get the whole table.
5599461Sobrien *      If the whole table has more than num entries, the caller can call
5699461Sobrien *      this function again to retrieve the rest of the table.
5799461Sobrien *      On return, end is set to B_TRUE if end of table is reached; B_FALSE
5899461Sobrien *      if there are still remaining entries.
5999461Sobrien */
6099461Sobrienilb_status_t
6199461Sobrienilb_show_nat(ilb_handle_t h, ilb_nat_info_t buf[], size_t *num,
6299461Sobrien    boolean_t *end)
6399461Sobrien{
6499461Sobrien	return (ilb_show_info(h, (char *)buf, num, end, show_nat));
6599461Sobrien}
6699461Sobrien
6799461Sobrien/*
6899461Sobrien * To get the ILB persistent entry table.
6999461Sobrien *
7099461Sobrien * buf: The buffer to return the persistent table entries.
7199461Sobrien * num: The caller sets it to the number of ilb_persist_info_t entries buf can
7299461Sobrien *      hold.  On return, it contains the actual number of entries put in buf.
7399461Sobrien * end: The caller sets it to B_TRUE if it only wants at most num entries to
74130561Sobrien *      be returned.  The transaction to ilbd will be termianted when this
75130561Sobrien *      call returns.
76130561Sobrien *      The caller sets it to B_FALSE if it intends to get the whole table.
7799461Sobrien *      If the whole table has more than num entries, the caller can call
7899461Sobrien *      this function again to retrieve the rest of the table.
7999461Sobrien *      On return, end is set to B_TRUE if end of table is reached; B_FALSE
8099461Sobrien *      if there are still remaining entries.
8199461Sobrien */
8299461Sobrienilb_status_t
8399461Sobrienilb_show_persist(ilb_handle_t h, ilb_persist_info_t buf[], size_t *num,
8499461Sobrien    boolean_t *end)
8599461Sobrien{
8699461Sobrien	return (ilb_show_info(h, (char *)buf, num, end, show_persist));
8799461Sobrien}
8899461Sobrien
89107492Sobrien/*
9099461Sobrien * The function doing the work...  The tbl parameter determines whith table
9199461Sobrien * to show.
9299461Sobrien */
9399461Sobrienstatic ilb_status_t
9499461Sobrienilb_show_info(ilb_handle_t h, char *buf, size_t *num, boolean_t *end,
9599461Sobrien    enum which_tbl tbl)
9699461Sobrien{
9799461Sobrien	ilb_comm_t	*req, *rbuf;
9899461Sobrien	ilb_show_info_t	*req_si, *tmp_si;
9999461Sobrien	size_t		reqsz, rbufsz, tmp_rbufsz, cur_num;
10099461Sobrien	size_t		entry_sz;
10199461Sobrien	ilb_status_t	rc;
10299461Sobrien
10399461Sobrien	if (*num == 0)
10499461Sobrien		return (ILB_STATUS_EINVAL);
10599461Sobrien
10699461Sobrien	reqsz = sizeof (ilb_comm_t) + sizeof (ilb_show_info_t);
10799461Sobrien	if ((req = malloc(reqsz)) == NULL)
10899461Sobrien		return (ILB_STATUS_ENOMEM);
10999461Sobrien	req_si = (ilb_show_info_t *)&req->ic_data;
11099461Sobrien
11199461Sobrien	/*
11299461Sobrien	 * Need to allocate a receive buffer and then copy the buffer
11399461Sobrien	 * content to the passed in buf.  The reason is that the
11499461Sobrien	 * communication to ilbd is message based and the protocol
11599461Sobrien	 * includes a header in the reply.  We need to remove this header
11699461Sobrien	 * from the message, hence the copying...
11799461Sobrien	 */
11899461Sobrien	if (tbl == show_nat)
11999461Sobrien		entry_sz = sizeof (ilb_nat_info_t);
12099461Sobrien	else
12199461Sobrien		entry_sz = sizeof (ilb_persist_info_t);
12299461Sobrien	rbufsz = *num * entry_sz + sizeof (ilb_comm_t) +
12399461Sobrien	    sizeof (ilb_show_info_t);
12499461Sobrien	if ((rbuf = malloc(rbufsz)) == NULL) {
12599461Sobrien		free(req);
12699461Sobrien		return (ILB_STATUS_ENOMEM);
12799461Sobrien	}
128107492Sobrien
12999461Sobrien	if (tbl == show_nat)
13099461Sobrien		req->ic_cmd = ILBD_SHOW_NAT;
13199461Sobrien	else
13299461Sobrien		req->ic_cmd = ILBD_SHOW_PERSIST;
13399461Sobrien	req->ic_flags = 0;
13499461Sobrien	req_si->sn_num = *num;
13599461Sobrien	cur_num = 0;
13699461Sobrien
13799461Sobrien	do {
13899461Sobrien		tmp_rbufsz = rbufsz;
13999461Sobrien		rc = i_ilb_do_comm(h, req, reqsz, rbuf, &tmp_rbufsz);
14099461Sobrien		if (rc != ILB_STATUS_OK)
14199461Sobrien			goto out;
14299461Sobrien		if (rbuf->ic_cmd != ILBD_CMD_OK) {
14399461Sobrien			rc = *(ilb_status_t *)&rbuf->ic_data;
14499461Sobrien			goto out;
14599461Sobrien		}
14699461Sobrien
14799461Sobrien		tmp_si = (ilb_show_info_t *)&rbuf->ic_data;
14899461Sobrien
14999461Sobrien		cur_num += tmp_si->sn_num;
15099461Sobrien		bcopy(&tmp_si->sn_data, buf, tmp_si->sn_num * entry_sz);
15199461Sobrien		buf += tmp_si->sn_num * entry_sz;
15299461Sobrien
15399461Sobrien		/*
15499461Sobrien		 * Buffer is filled, regardless of this is the end of table or
15599461Sobrien		 * not, we need to stop.
15699461Sobrien		 */
15799461Sobrien		if (cur_num == *num)
15899461Sobrien			break;
15999461Sobrien		/* Try to fill in the rest. */
16099461Sobrien		req_si->sn_num = *num - cur_num;
16199461Sobrien	} while (!(rbuf->ic_flags & ILB_COMM_END));
16299461Sobrien
16399461Sobrien	*num = cur_num;
16499461Sobrien
16599461Sobrien	/* End of transaction, let the caller know. */
16699461Sobrien	if (rbuf->ic_flags & ILB_COMM_END) {
16799461Sobrien		*end = B_TRUE;
16899461Sobrien	} else {
16999461Sobrien		/* The user wants to terminate the transaction */
17099461Sobrien		if (*end) {
17199461Sobrien			req->ic_flags = ILB_COMM_END;
17299461Sobrien			tmp_rbufsz = rbufsz;
17399461Sobrien			rc = i_ilb_do_comm(h, req, reqsz, rbuf, &tmp_rbufsz);
17499461Sobrien		}
17599461Sobrien	}
17699461Sobrienout:
17799461Sobrien	free(req);
17899461Sobrien	free(rbuf);
17999461Sobrien	return (rc);
18099461Sobrien}
18199461Sobrien