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 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 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 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 213 ilbadm_show_nat(int argc, char *argv[]) 214 { 215 return (ilbadm_show_info(argc, argv, show_nat)); 216 } 217 218 ilbadm_status_t 219 ilbadm_show_persist(int argc, char *argv[]) 220 { 221 return (ilbadm_show_info(argc, argv, show_persist)); 222 } 223