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 <sys/types.h>
28 #include <sys/socket.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <strings.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <libilb.h>
35 #include "ilbadm.h"
36
37 /*
38 * For each iteration through the kernel table, ask for at most NUM_ENTRIES
39 * entries to be returned.
40 */
41 #define NUM_ENTRIES 500
42
43 static void
print_nat_info(ilb_nat_info_t * info)44 print_nat_info(ilb_nat_info_t *info)
45 {
46 char *tmp;
47 ipaddr_t addr_v4;
48 char addr[INET6_ADDRSTRLEN];
49
50 if (info->nat_proto == IPPROTO_TCP)
51 tmp = "TCP";
52 else if (info->nat_proto == IPPROTO_UDP)
53 tmp = "UDP";
54 else
55 tmp = "Unknown";
56 (void) printf("%4s: ", tmp);
57
58 if (IN6_IS_ADDR_V4MAPPED(&info->nat_out_global)) {
59 IN6_V4MAPPED_TO_IPADDR(&info->nat_out_global, addr_v4);
60 (void) printf("%s.%d > ", inet_ntop(AF_INET, &addr_v4, addr,
61 INET6_ADDRSTRLEN), ntohs(info->nat_out_global_port));
62 IN6_V4MAPPED_TO_IPADDR(&info->nat_in_global, addr_v4);
63 (void) printf("%s.%d >>> ", inet_ntop(AF_INET, &addr_v4, addr,
64 INET6_ADDRSTRLEN), ntohs(info->nat_in_global_port));
65
66 IN6_V4MAPPED_TO_IPADDR(&info->nat_out_local, addr_v4);
67 (void) printf("%s.%d > ", inet_ntop(AF_INET, &addr_v4, addr,
68 INET6_ADDRSTRLEN), ntohs(info->nat_out_local_port));
69 IN6_V4MAPPED_TO_IPADDR(&info->nat_in_local, addr_v4);
70 (void) printf("%s.%d\n", inet_ntop(AF_INET, &addr_v4, addr,
71 INET6_ADDRSTRLEN), ntohs(info->nat_in_local_port));
72 } else {
73 (void) printf("%s.%d > ", inet_ntop(AF_INET6,
74 &info->nat_out_global, addr, INET6_ADDRSTRLEN),
75 ntohs(info->nat_out_global_port));
76 (void) printf("%s.%d >>> ", inet_ntop(AF_INET6,
77 &info->nat_in_global, addr, INET6_ADDRSTRLEN),
78 ntohs(info->nat_in_global_port));
79
80 (void) printf("%s.%d > ", inet_ntop(AF_INET6,
81 &info->nat_out_local, addr, INET6_ADDRSTRLEN),
82 ntohs(info->nat_out_local_port));
83 (void) printf("%s.%d\n", inet_ntop(AF_INET6,
84 &info->nat_in_local, addr, INET6_ADDRSTRLEN),
85 ntohs(info->nat_in_local_port));
86 }
87 }
88
89 static void
print_persist_info(ilb_persist_info_t * info)90 print_persist_info(ilb_persist_info_t *info)
91 {
92 char addr[INET6_ADDRSTRLEN];
93
94 (void) printf("%s: ", info->persist_rule_name);
95 if (IN6_IS_ADDR_V4MAPPED(&info->persist_req_addr)) {
96 ipaddr_t addr_v4;
97
98 IN6_V4MAPPED_TO_IPADDR(&info->persist_req_addr, addr_v4);
99 (void) printf("%s --> ", inet_ntop(AF_INET, &addr_v4, addr,
100 INET6_ADDRSTRLEN));
101 IN6_V4MAPPED_TO_IPADDR(&info->persist_srv_addr, addr_v4);
102 (void) printf("%s\n", inet_ntop(AF_INET, &addr_v4, addr,
103 INET6_ADDRSTRLEN));
104 } else {
105 (void) printf("%s --> ", inet_ntop(AF_INET6,
106 &info->persist_req_addr, addr, INET6_ADDRSTRLEN));
107 (void) printf("%s\n", inet_ntop(AF_INET6,
108 &info->persist_srv_addr, addr, INET6_ADDRSTRLEN));
109 }
110 }
111
112 /* Tell ilbadm_show_info() which table to show. */
113 enum which_tbl {
114 show_nat = 1,
115 show_persist
116 };
117
118 typedef union {
119 ilb_nat_info_t *nbuf;
120 ilb_persist_info_t *pbuf;
121 char *buf;
122 } show_buf_t;
123
124 static ilbadm_status_t
ilbadm_show_info(int argc,char * argv[],enum which_tbl tbl)125 ilbadm_show_info(int argc, char *argv[], enum which_tbl tbl)
126 {
127 ilb_handle_t h = ILB_INVALID_HANDLE;
128 show_buf_t buf;
129 ilb_status_t rclib = ILB_STATUS_OK;
130 ilbadm_status_t rc = ILBADM_OK;
131 int32_t i, num_entries;
132 size_t num;
133 boolean_t end;
134 size_t entry_sz;
135
136 /*
137 * If the user does not specify a count, return the whole table.
138 * This requires setting the fourth param to ilb_show_nat/persist()
139 * end to B_FALSE. Otherwise, set end to B_TRUE;
140 */
141
142 switch (argc) {
143 case 1:
144 num_entries = -1;
145 end = B_FALSE;
146 break;
147 case 2:
148 num_entries = atoi(argv[1]);
149 if (num_entries < 1) {
150 rc = ILBADM_EINVAL;
151 goto out;
152 }
153 end = B_TRUE;
154 break;
155 default:
156 rc = ILBADM_EINVAL;
157 goto out;
158 }
159
160 if (tbl == show_nat)
161 entry_sz = sizeof (ilb_nat_info_t);
162 else
163 entry_sz = sizeof (ilb_persist_info_t);
164 if ((buf.buf = malloc((num_entries > 0 ? num_entries : NUM_ENTRIES) *
165 entry_sz)) == NULL) {
166 rc = ILBADM_ENOMEM;
167 goto out;
168 }
169
170 rclib = ilb_open(&h);
171 if (rclib != ILB_STATUS_OK)
172 goto out;
173
174 do {
175 num = num_entries > 0 ? num_entries : NUM_ENTRIES;
176 bzero(buf.buf, num * entry_sz);
177
178 if (tbl == show_nat)
179 rclib = ilb_show_nat(h, buf.nbuf, &num, &end);
180 else
181 rclib = ilb_show_persist(h, buf.pbuf, &num, &end);
182
183 if (rclib != ILB_STATUS_OK)
184 break;
185
186 for (i = 0; i < num; i++) {
187 if (tbl == show_nat)
188 print_nat_info(&buf.nbuf[i]);
189 else
190 print_persist_info(&buf.pbuf[i]);
191 }
192 if (num_entries > 0) {
193 num_entries -= num;
194 if (num_entries <= 0)
195 break;
196 }
197 } while (!end);
198 free(buf.buf);
199 out:
200 if (h != ILB_INVALID_HANDLE)
201 (void) ilb_close(h);
202 if (rclib != ILB_STATUS_OK) {
203 ilbadm_err(ilb_errstr(rclib));
204 rc = ILBADM_LIBERR;
205 }
206 if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
207 ilbadm_err(ilbadm_errstr(rc));
208 return (rc);
209 }
210
211
212 ilbadm_status_t
ilbadm_show_nat(int argc,char * argv[])213 ilbadm_show_nat(int argc, char *argv[])
214 {
215 return (ilbadm_show_info(argc, argv, show_nat));
216 }
217
218 ilbadm_status_t
ilbadm_show_persist(int argc,char * argv[])219 ilbadm_show_persist(int argc, char *argv[])
220 {
221 return (ilbadm_show_info(argc, argv, show_persist));
222 }
223