1*dbed73cbSSangeeta Misra /*
2*dbed73cbSSangeeta Misra * CDDL HEADER START
3*dbed73cbSSangeeta Misra *
4*dbed73cbSSangeeta Misra * The contents of this file are subject to the terms of the
5*dbed73cbSSangeeta Misra * Common Development and Distribution License (the "License").
6*dbed73cbSSangeeta Misra * You may not use this file except in compliance with the License.
7*dbed73cbSSangeeta Misra *
8*dbed73cbSSangeeta Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*dbed73cbSSangeeta Misra * or http://www.opensolaris.org/os/licensing.
10*dbed73cbSSangeeta Misra * See the License for the specific language governing permissions
11*dbed73cbSSangeeta Misra * and limitations under the License.
12*dbed73cbSSangeeta Misra *
13*dbed73cbSSangeeta Misra * When distributing Covered Code, include this CDDL HEADER in each
14*dbed73cbSSangeeta Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*dbed73cbSSangeeta Misra * If applicable, add the following below this CDDL HEADER, with the
16*dbed73cbSSangeeta Misra * fields enclosed by brackets "[]" replaced with your own identifying
17*dbed73cbSSangeeta Misra * information: Portions Copyright [yyyy] [name of copyright owner]
18*dbed73cbSSangeeta Misra *
19*dbed73cbSSangeeta Misra * CDDL HEADER END
20*dbed73cbSSangeeta Misra */
21*dbed73cbSSangeeta Misra
22*dbed73cbSSangeeta Misra /*
23*dbed73cbSSangeeta Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*dbed73cbSSangeeta Misra * Use is subject to license terms.
25*dbed73cbSSangeeta Misra */
26*dbed73cbSSangeeta Misra
27*dbed73cbSSangeeta Misra #include <sys/types.h>
28*dbed73cbSSangeeta Misra #include <sys/socket.h>
29*dbed73cbSSangeeta Misra #include <stdlib.h>
30*dbed73cbSSangeeta Misra #include <stdio.h>
31*dbed73cbSSangeeta Misra #include <strings.h>
32*dbed73cbSSangeeta Misra #include <netinet/in.h>
33*dbed73cbSSangeeta Misra #include <arpa/inet.h>
34*dbed73cbSSangeeta Misra #include <libilb.h>
35*dbed73cbSSangeeta Misra #include "ilbadm.h"
36*dbed73cbSSangeeta Misra
37*dbed73cbSSangeeta Misra /*
38*dbed73cbSSangeeta Misra * For each iteration through the kernel table, ask for at most NUM_ENTRIES
39*dbed73cbSSangeeta Misra * entries to be returned.
40*dbed73cbSSangeeta Misra */
41*dbed73cbSSangeeta Misra #define NUM_ENTRIES 500
42*dbed73cbSSangeeta Misra
43*dbed73cbSSangeeta Misra static void
print_nat_info(ilb_nat_info_t * info)44*dbed73cbSSangeeta Misra print_nat_info(ilb_nat_info_t *info)
45*dbed73cbSSangeeta Misra {
46*dbed73cbSSangeeta Misra char *tmp;
47*dbed73cbSSangeeta Misra ipaddr_t addr_v4;
48*dbed73cbSSangeeta Misra char addr[INET6_ADDRSTRLEN];
49*dbed73cbSSangeeta Misra
50*dbed73cbSSangeeta Misra if (info->nat_proto == IPPROTO_TCP)
51*dbed73cbSSangeeta Misra tmp = "TCP";
52*dbed73cbSSangeeta Misra else if (info->nat_proto == IPPROTO_UDP)
53*dbed73cbSSangeeta Misra tmp = "UDP";
54*dbed73cbSSangeeta Misra else
55*dbed73cbSSangeeta Misra tmp = "Unknown";
56*dbed73cbSSangeeta Misra (void) printf("%4s: ", tmp);
57*dbed73cbSSangeeta Misra
58*dbed73cbSSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&info->nat_out_global)) {
59*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->nat_out_global, addr_v4);
60*dbed73cbSSangeeta Misra (void) printf("%s.%d > ", inet_ntop(AF_INET, &addr_v4, addr,
61*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN), ntohs(info->nat_out_global_port));
62*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->nat_in_global, addr_v4);
63*dbed73cbSSangeeta Misra (void) printf("%s.%d >>> ", inet_ntop(AF_INET, &addr_v4, addr,
64*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN), ntohs(info->nat_in_global_port));
65*dbed73cbSSangeeta Misra
66*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->nat_out_local, addr_v4);
67*dbed73cbSSangeeta Misra (void) printf("%s.%d > ", inet_ntop(AF_INET, &addr_v4, addr,
68*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN), ntohs(info->nat_out_local_port));
69*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->nat_in_local, addr_v4);
70*dbed73cbSSangeeta Misra (void) printf("%s.%d\n", inet_ntop(AF_INET, &addr_v4, addr,
71*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN), ntohs(info->nat_in_local_port));
72*dbed73cbSSangeeta Misra } else {
73*dbed73cbSSangeeta Misra (void) printf("%s.%d > ", inet_ntop(AF_INET6,
74*dbed73cbSSangeeta Misra &info->nat_out_global, addr, INET6_ADDRSTRLEN),
75*dbed73cbSSangeeta Misra ntohs(info->nat_out_global_port));
76*dbed73cbSSangeeta Misra (void) printf("%s.%d >>> ", inet_ntop(AF_INET6,
77*dbed73cbSSangeeta Misra &info->nat_in_global, addr, INET6_ADDRSTRLEN),
78*dbed73cbSSangeeta Misra ntohs(info->nat_in_global_port));
79*dbed73cbSSangeeta Misra
80*dbed73cbSSangeeta Misra (void) printf("%s.%d > ", inet_ntop(AF_INET6,
81*dbed73cbSSangeeta Misra &info->nat_out_local, addr, INET6_ADDRSTRLEN),
82*dbed73cbSSangeeta Misra ntohs(info->nat_out_local_port));
83*dbed73cbSSangeeta Misra (void) printf("%s.%d\n", inet_ntop(AF_INET6,
84*dbed73cbSSangeeta Misra &info->nat_in_local, addr, INET6_ADDRSTRLEN),
85*dbed73cbSSangeeta Misra ntohs(info->nat_in_local_port));
86*dbed73cbSSangeeta Misra }
87*dbed73cbSSangeeta Misra }
88*dbed73cbSSangeeta Misra
89*dbed73cbSSangeeta Misra static void
print_persist_info(ilb_persist_info_t * info)90*dbed73cbSSangeeta Misra print_persist_info(ilb_persist_info_t *info)
91*dbed73cbSSangeeta Misra {
92*dbed73cbSSangeeta Misra char addr[INET6_ADDRSTRLEN];
93*dbed73cbSSangeeta Misra
94*dbed73cbSSangeeta Misra (void) printf("%s: ", info->persist_rule_name);
95*dbed73cbSSangeeta Misra if (IN6_IS_ADDR_V4MAPPED(&info->persist_req_addr)) {
96*dbed73cbSSangeeta Misra ipaddr_t addr_v4;
97*dbed73cbSSangeeta Misra
98*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->persist_req_addr, addr_v4);
99*dbed73cbSSangeeta Misra (void) printf("%s --> ", inet_ntop(AF_INET, &addr_v4, addr,
100*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN));
101*dbed73cbSSangeeta Misra IN6_V4MAPPED_TO_IPADDR(&info->persist_srv_addr, addr_v4);
102*dbed73cbSSangeeta Misra (void) printf("%s\n", inet_ntop(AF_INET, &addr_v4, addr,
103*dbed73cbSSangeeta Misra INET6_ADDRSTRLEN));
104*dbed73cbSSangeeta Misra } else {
105*dbed73cbSSangeeta Misra (void) printf("%s --> ", inet_ntop(AF_INET6,
106*dbed73cbSSangeeta Misra &info->persist_req_addr, addr, INET6_ADDRSTRLEN));
107*dbed73cbSSangeeta Misra (void) printf("%s\n", inet_ntop(AF_INET6,
108*dbed73cbSSangeeta Misra &info->persist_srv_addr, addr, INET6_ADDRSTRLEN));
109*dbed73cbSSangeeta Misra }
110*dbed73cbSSangeeta Misra }
111*dbed73cbSSangeeta Misra
112*dbed73cbSSangeeta Misra /* Tell ilbadm_show_info() which table to show. */
113*dbed73cbSSangeeta Misra enum which_tbl {
114*dbed73cbSSangeeta Misra show_nat = 1,
115*dbed73cbSSangeeta Misra show_persist
116*dbed73cbSSangeeta Misra };
117*dbed73cbSSangeeta Misra
118*dbed73cbSSangeeta Misra typedef union {
119*dbed73cbSSangeeta Misra ilb_nat_info_t *nbuf;
120*dbed73cbSSangeeta Misra ilb_persist_info_t *pbuf;
121*dbed73cbSSangeeta Misra char *buf;
122*dbed73cbSSangeeta Misra } show_buf_t;
123*dbed73cbSSangeeta Misra
124*dbed73cbSSangeeta Misra static ilbadm_status_t
ilbadm_show_info(int argc,char * argv[],enum which_tbl tbl)125*dbed73cbSSangeeta Misra ilbadm_show_info(int argc, char *argv[], enum which_tbl tbl)
126*dbed73cbSSangeeta Misra {
127*dbed73cbSSangeeta Misra ilb_handle_t h = ILB_INVALID_HANDLE;
128*dbed73cbSSangeeta Misra show_buf_t buf;
129*dbed73cbSSangeeta Misra ilb_status_t rclib = ILB_STATUS_OK;
130*dbed73cbSSangeeta Misra ilbadm_status_t rc = ILBADM_OK;
131*dbed73cbSSangeeta Misra int32_t i, num_entries;
132*dbed73cbSSangeeta Misra size_t num;
133*dbed73cbSSangeeta Misra boolean_t end;
134*dbed73cbSSangeeta Misra size_t entry_sz;
135*dbed73cbSSangeeta Misra
136*dbed73cbSSangeeta Misra /*
137*dbed73cbSSangeeta Misra * If the user does not specify a count, return the whole table.
138*dbed73cbSSangeeta Misra * This requires setting the fourth param to ilb_show_nat/persist()
139*dbed73cbSSangeeta Misra * end to B_FALSE. Otherwise, set end to B_TRUE;
140*dbed73cbSSangeeta Misra */
141*dbed73cbSSangeeta Misra
142*dbed73cbSSangeeta Misra switch (argc) {
143*dbed73cbSSangeeta Misra case 1:
144*dbed73cbSSangeeta Misra num_entries = -1;
145*dbed73cbSSangeeta Misra end = B_FALSE;
146*dbed73cbSSangeeta Misra break;
147*dbed73cbSSangeeta Misra case 2:
148*dbed73cbSSangeeta Misra num_entries = atoi(argv[1]);
149*dbed73cbSSangeeta Misra if (num_entries < 1) {
150*dbed73cbSSangeeta Misra rc = ILBADM_EINVAL;
151*dbed73cbSSangeeta Misra goto out;
152*dbed73cbSSangeeta Misra }
153*dbed73cbSSangeeta Misra end = B_TRUE;
154*dbed73cbSSangeeta Misra break;
155*dbed73cbSSangeeta Misra default:
156*dbed73cbSSangeeta Misra rc = ILBADM_EINVAL;
157*dbed73cbSSangeeta Misra goto out;
158*dbed73cbSSangeeta Misra }
159*dbed73cbSSangeeta Misra
160*dbed73cbSSangeeta Misra if (tbl == show_nat)
161*dbed73cbSSangeeta Misra entry_sz = sizeof (ilb_nat_info_t);
162*dbed73cbSSangeeta Misra else
163*dbed73cbSSangeeta Misra entry_sz = sizeof (ilb_persist_info_t);
164*dbed73cbSSangeeta Misra if ((buf.buf = malloc((num_entries > 0 ? num_entries : NUM_ENTRIES) *
165*dbed73cbSSangeeta Misra entry_sz)) == NULL) {
166*dbed73cbSSangeeta Misra rc = ILBADM_ENOMEM;
167*dbed73cbSSangeeta Misra goto out;
168*dbed73cbSSangeeta Misra }
169*dbed73cbSSangeeta Misra
170*dbed73cbSSangeeta Misra rclib = ilb_open(&h);
171*dbed73cbSSangeeta Misra if (rclib != ILB_STATUS_OK)
172*dbed73cbSSangeeta Misra goto out;
173*dbed73cbSSangeeta Misra
174*dbed73cbSSangeeta Misra do {
175*dbed73cbSSangeeta Misra num = num_entries > 0 ? num_entries : NUM_ENTRIES;
176*dbed73cbSSangeeta Misra bzero(buf.buf, num * entry_sz);
177*dbed73cbSSangeeta Misra
178*dbed73cbSSangeeta Misra if (tbl == show_nat)
179*dbed73cbSSangeeta Misra rclib = ilb_show_nat(h, buf.nbuf, &num, &end);
180*dbed73cbSSangeeta Misra else
181*dbed73cbSSangeeta Misra rclib = ilb_show_persist(h, buf.pbuf, &num, &end);
182*dbed73cbSSangeeta Misra
183*dbed73cbSSangeeta Misra if (rclib != ILB_STATUS_OK)
184*dbed73cbSSangeeta Misra break;
185*dbed73cbSSangeeta Misra
186*dbed73cbSSangeeta Misra for (i = 0; i < num; i++) {
187*dbed73cbSSangeeta Misra if (tbl == show_nat)
188*dbed73cbSSangeeta Misra print_nat_info(&buf.nbuf[i]);
189*dbed73cbSSangeeta Misra else
190*dbed73cbSSangeeta Misra print_persist_info(&buf.pbuf[i]);
191*dbed73cbSSangeeta Misra }
192*dbed73cbSSangeeta Misra if (num_entries > 0) {
193*dbed73cbSSangeeta Misra num_entries -= num;
194*dbed73cbSSangeeta Misra if (num_entries <= 0)
195*dbed73cbSSangeeta Misra break;
196*dbed73cbSSangeeta Misra }
197*dbed73cbSSangeeta Misra } while (!end);
198*dbed73cbSSangeeta Misra free(buf.buf);
199*dbed73cbSSangeeta Misra out:
200*dbed73cbSSangeeta Misra if (h != ILB_INVALID_HANDLE)
201*dbed73cbSSangeeta Misra (void) ilb_close(h);
202*dbed73cbSSangeeta Misra if (rclib != ILB_STATUS_OK) {
203*dbed73cbSSangeeta Misra ilbadm_err(ilb_errstr(rclib));
204*dbed73cbSSangeeta Misra rc = ILBADM_LIBERR;
205*dbed73cbSSangeeta Misra }
206*dbed73cbSSangeeta Misra if ((rc != ILBADM_OK) && (rc != ILBADM_LIBERR))
207*dbed73cbSSangeeta Misra ilbadm_err(ilbadm_errstr(rc));
208*dbed73cbSSangeeta Misra return (rc);
209*dbed73cbSSangeeta Misra }
210*dbed73cbSSangeeta Misra
211*dbed73cbSSangeeta Misra
212*dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_show_nat(int argc,char * argv[])213*dbed73cbSSangeeta Misra ilbadm_show_nat(int argc, char *argv[])
214*dbed73cbSSangeeta Misra {
215*dbed73cbSSangeeta Misra return (ilbadm_show_info(argc, argv, show_nat));
216*dbed73cbSSangeeta Misra }
217*dbed73cbSSangeeta Misra
218*dbed73cbSSangeeta Misra ilbadm_status_t
ilbadm_show_persist(int argc,char * argv[])219*dbed73cbSSangeeta Misra ilbadm_show_persist(int argc, char *argv[])
220*dbed73cbSSangeeta Misra {
221*dbed73cbSSangeeta Misra return (ilbadm_show_info(argc, argv, show_persist));
222*dbed73cbSSangeeta Misra }
223