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 <unistd.h> 30 #include <stddef.h> 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include "libilb.h" 34 #include "libilb_impl.h" 35 36 enum which_tbl { 37 show_nat = 1, 38 show_persist 39 }; 40 41 /* The common function to show kernel info. */ 42 static ilb_status_t ilb_show_info(ilb_handle_t, char *, size_t *, boolean_t *, 43 enum which_tbl); 44 45 /* 46 * To get the ILB NAT table. 47 * 48 * buf: The buffer to return the NAT table entries. 49 * num: The caller sets it to the number of ilb_nat_info_t entries buf can 50 * hold. On return, it contains the actual number of entries put in buf. 51 * end: The caller sets it to B_TRUE if it only wants at most num entries to 52 * be returned. The transaction to ilbd will be termianted when this 53 * call returns. 54 * The caller sets it to B_FALSE if it intends to get the whole table. 55 * If the whole table has more than num entries, the caller can call 56 * this function again to retrieve the rest of the table. 57 * On return, end is set to B_TRUE if end of table is reached; B_FALSE 58 * if there are still remaining entries. 59 */ 60 ilb_status_t 61 ilb_show_nat(ilb_handle_t h, ilb_nat_info_t buf[], size_t *num, 62 boolean_t *end) 63 { 64 return (ilb_show_info(h, (char *)buf, num, end, show_nat)); 65 } 66 67 /* 68 * To get the ILB persistent entry table. 69 * 70 * buf: The buffer to return the persistent table entries. 71 * num: The caller sets it to the number of ilb_persist_info_t entries buf can 72 * hold. On return, it contains the actual number of entries put in buf. 73 * end: The caller sets it to B_TRUE if it only wants at most num entries to 74 * be returned. The transaction to ilbd will be termianted when this 75 * call returns. 76 * The caller sets it to B_FALSE if it intends to get the whole table. 77 * If the whole table has more than num entries, the caller can call 78 * this function again to retrieve the rest of the table. 79 * On return, end is set to B_TRUE if end of table is reached; B_FALSE 80 * if there are still remaining entries. 81 */ 82 ilb_status_t 83 ilb_show_persist(ilb_handle_t h, ilb_persist_info_t buf[], size_t *num, 84 boolean_t *end) 85 { 86 return (ilb_show_info(h, (char *)buf, num, end, show_persist)); 87 } 88 89 /* 90 * The function doing the work... The tbl parameter determines whith table 91 * to show. 92 */ 93 static ilb_status_t 94 ilb_show_info(ilb_handle_t h, char *buf, size_t *num, boolean_t *end, 95 enum which_tbl tbl) 96 { 97 ilb_comm_t *req, *rbuf; 98 ilb_show_info_t *req_si, *tmp_si; 99 size_t reqsz, rbufsz, tmp_rbufsz, cur_num; 100 size_t entry_sz; 101 ilb_status_t rc; 102 103 if (*num == 0) 104 return (ILB_STATUS_EINVAL); 105 106 reqsz = sizeof (ilb_comm_t) + sizeof (ilb_show_info_t); 107 if ((req = malloc(reqsz)) == NULL) 108 return (ILB_STATUS_ENOMEM); 109 req_si = (ilb_show_info_t *)&req->ic_data; 110 111 /* 112 * Need to allocate a receive buffer and then copy the buffer 113 * content to the passed in buf. The reason is that the 114 * communication to ilbd is message based and the protocol 115 * includes a header in the reply. We need to remove this header 116 * from the message, hence the copying... 117 */ 118 if (tbl == show_nat) 119 entry_sz = sizeof (ilb_nat_info_t); 120 else 121 entry_sz = sizeof (ilb_persist_info_t); 122 rbufsz = *num * entry_sz + sizeof (ilb_comm_t) + 123 sizeof (ilb_show_info_t); 124 if ((rbuf = malloc(rbufsz)) == NULL) { 125 free(req); 126 return (ILB_STATUS_ENOMEM); 127 } 128 129 if (tbl == show_nat) 130 req->ic_cmd = ILBD_SHOW_NAT; 131 else 132 req->ic_cmd = ILBD_SHOW_PERSIST; 133 req->ic_flags = 0; 134 req_si->sn_num = *num; 135 cur_num = 0; 136 137 do { 138 tmp_rbufsz = rbufsz; 139 rc = i_ilb_do_comm(h, req, reqsz, rbuf, &tmp_rbufsz); 140 if (rc != ILB_STATUS_OK) 141 goto out; 142 if (rbuf->ic_cmd != ILBD_CMD_OK) { 143 rc = *(ilb_status_t *)&rbuf->ic_data; 144 goto out; 145 } 146 147 tmp_si = (ilb_show_info_t *)&rbuf->ic_data; 148 149 cur_num += tmp_si->sn_num; 150 bcopy(&tmp_si->sn_data, buf, tmp_si->sn_num * entry_sz); 151 buf += tmp_si->sn_num * entry_sz; 152 153 /* 154 * Buffer is filled, regardless of this is the end of table or 155 * not, we need to stop. 156 */ 157 if (cur_num == *num) 158 break; 159 /* Try to fill in the rest. */ 160 req_si->sn_num = *num - cur_num; 161 } while (!(rbuf->ic_flags & ILB_COMM_END)); 162 163 *num = cur_num; 164 165 /* End of transaction, let the caller know. */ 166 if (rbuf->ic_flags & ILB_COMM_END) { 167 *end = B_TRUE; 168 } else { 169 /* The user wants to terminate the transaction */ 170 if (*end) { 171 req->ic_flags = ILB_COMM_END; 172 tmp_rbufsz = rbufsz; 173 rc = i_ilb_do_comm(h, req, reqsz, rbuf, &tmp_rbufsz); 174 } 175 } 176 out: 177 free(req); 178 free(rbuf); 179 return (rc); 180 } 181