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