1 /* $FreeBSD$ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) 9 */ 10 11 #include "ipf.h" 12 #include "kmem.h" 13 14 15 #if !defined(lint) 16 static const char rcsid[] = "@(#)$Id$"; 17 #endif 18 19 20 /* 21 * Print out a NAT rule 22 */ 23 void 24 printnat(ipnat_t *np, int opts) 25 { 26 struct protoent *pr; 27 char *base; 28 int family; 29 int proto; 30 31 if (np->in_v[0] == 4) 32 family = AF_INET; 33 #ifdef USE_INET6 34 else if (np->in_v[0] == 6) 35 family = AF_INET6; 36 #endif 37 else 38 family = AF_UNSPEC; 39 40 if (np->in_flags & IPN_NO) 41 PRINTF("no "); 42 43 switch (np->in_redir) 44 { 45 case NAT_REDIRECT|NAT_ENCAP : 46 PRINTF("encap in on"); 47 proto = np->in_pr[0]; 48 break; 49 case NAT_MAP|NAT_ENCAP : 50 PRINTF("encap out on"); 51 proto = np->in_pr[1]; 52 break; 53 case NAT_REDIRECT|NAT_DIVERTUDP : 54 PRINTF("divert in on"); 55 proto = np->in_pr[0]; 56 break; 57 case NAT_MAP|NAT_DIVERTUDP : 58 PRINTF("divert out on"); 59 proto = np->in_pr[1]; 60 break; 61 case NAT_REDIRECT|NAT_REWRITE : 62 PRINTF("rewrite in on"); 63 proto = np->in_pr[0]; 64 break; 65 case NAT_MAP|NAT_REWRITE : 66 PRINTF("rewrite out on"); 67 proto = np->in_pr[1]; 68 break; 69 case NAT_REDIRECT : 70 PRINTF("rdr"); 71 proto = np->in_pr[0]; 72 break; 73 case NAT_MAP : 74 PRINTF("map"); 75 proto = np->in_pr[1]; 76 break; 77 case NAT_MAPBLK : 78 PRINTF("map-block"); 79 proto = np->in_pr[1]; 80 break; 81 case NAT_BIMAP : 82 PRINTF("bimap"); 83 proto = np->in_pr[0]; 84 break; 85 default : 86 FPRINTF(stderr, "unknown value for in_redir: %#x\n", 87 np->in_redir); 88 proto = np->in_pr[0]; 89 break; 90 } 91 92 pr = getprotobynumber(proto); 93 94 base = np->in_names; 95 if (!strcmp(base + np->in_ifnames[0], "-")) 96 PRINTF(" \"%s\"", base + np->in_ifnames[0]); 97 else 98 PRINTF(" %s", base + np->in_ifnames[0]); 99 if ((np->in_ifnames[1] != -1) && 100 (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) { 101 if (!strcmp(base + np->in_ifnames[1], "-")) 102 PRINTF(",\"%s\"", base + np->in_ifnames[1]); 103 else 104 PRINTF(",%s", base + np->in_ifnames[1]); 105 } 106 putchar(' '); 107 108 if (family == AF_INET6) 109 PRINTF("inet6 "); 110 111 if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) { 112 if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) { 113 PRINTF("proto "); 114 printproto(pr, proto, np); 115 putchar(' '); 116 } 117 } 118 119 if (np->in_flags & IPN_FILTER) { 120 if (np->in_flags & IPN_NOTSRC) 121 PRINTF("! "); 122 PRINTF("from "); 123 printnataddr(np->in_v[0], np->in_names, &np->in_osrc, 124 np->in_ifnames[0]); 125 if (np->in_scmp) 126 printportcmp(proto, &np->in_tuc.ftu_src); 127 128 if (np->in_flags & IPN_NOTDST) 129 PRINTF(" !"); 130 PRINTF(" to "); 131 printnataddr(np->in_v[0], np->in_names, &np->in_odst, 132 np->in_ifnames[0]); 133 if (np->in_dcmp) 134 printportcmp(proto, &np->in_tuc.ftu_dst); 135 } 136 137 if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) { 138 PRINTF(" -> src "); 139 printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, 140 np->in_ifnames[0]); 141 if ((np->in_redir & NAT_DIVERTUDP) != 0) 142 PRINTF(",%u", np->in_spmin); 143 PRINTF(" dst "); 144 printnataddr(np->in_v[1], np->in_names, &np->in_ndst, 145 np->in_ifnames[0]); 146 if ((np->in_redir & NAT_DIVERTUDP) != 0) 147 PRINTF(",%u udp", np->in_dpmin); 148 if ((np->in_flags & IPN_PURGE) != 0) 149 PRINTF(" purge"); 150 PRINTF(";\n"); 151 152 } else if (np->in_redir & NAT_REWRITE) { 153 PRINTF(" -> src "); 154 if (np->in_nsrc.na_atype == FRI_LOOKUP && 155 np->in_nsrc.na_type == IPLT_DSTLIST) { 156 PRINTF("dstlist/"); 157 if (np->in_nsrc.na_subtype == 0) 158 PRINTF("%d", np->in_nsrc.na_num); 159 else 160 PRINTF("%s", base + np->in_nsrc.na_num); 161 } else { 162 printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, 163 np->in_ifnames[0]); 164 } 165 if ((((np->in_flags & IPN_TCPUDP) != 0)) && 166 (np->in_spmin != 0)) { 167 if ((np->in_flags & IPN_FIXEDSPORT) != 0) { 168 PRINTF(",port = %u", np->in_spmin); 169 } else { 170 PRINTF(",%u", np->in_spmin); 171 if (np->in_spmax != np->in_spmin) 172 PRINTF("-%u", np->in_spmax); 173 } 174 } 175 PRINTF(" dst "); 176 if (np->in_ndst.na_atype == FRI_LOOKUP && 177 np->in_ndst.na_type == IPLT_DSTLIST) { 178 PRINTF("dstlist/"); 179 if (np->in_ndst.na_subtype == 0) 180 PRINTF("%d", np->in_nsrc.na_num); 181 else 182 PRINTF("%s", base + np->in_ndst.na_num); 183 } else { 184 printnataddr(np->in_v[1], np->in_names, &np->in_ndst, 185 np->in_ifnames[0]); 186 } 187 if ((((np->in_flags & IPN_TCPUDP) != 0)) && 188 (np->in_dpmin != 0)) { 189 if ((np->in_flags & IPN_FIXEDDPORT) != 0) { 190 PRINTF(",port = %u", np->in_dpmin); 191 } else { 192 PRINTF(",%u", np->in_dpmin); 193 if (np->in_dpmax != np->in_dpmin) 194 PRINTF("-%u", np->in_dpmax); 195 } 196 } 197 if ((np->in_flags & IPN_PURGE) != 0) 198 PRINTF(" purge"); 199 PRINTF(";\n"); 200 201 } else if (np->in_redir == NAT_REDIRECT) { 202 if (!(np->in_flags & IPN_FILTER)) { 203 printnataddr(np->in_v[0], np->in_names, &np->in_odst, 204 np->in_ifnames[0]); 205 if (np->in_flags & IPN_TCPUDP) { 206 PRINTF(" port %d", np->in_odport); 207 if (np->in_odport != np->in_dtop) 208 PRINTF("-%d", np->in_dtop); 209 } 210 } 211 if (np->in_flags & IPN_NO) { 212 putchar(' '); 213 printproto(pr, proto, np); 214 PRINTF(";\n"); 215 return; 216 } 217 PRINTF(" -> "); 218 printnataddr(np->in_v[1], np->in_names, &np->in_ndst, 219 np->in_ifnames[0]); 220 if (np->in_flags & IPN_TCPUDP) { 221 if ((np->in_flags & IPN_FIXEDDPORT) != 0) 222 PRINTF(" port = %d", np->in_dpmin); 223 else { 224 PRINTF(" port %d", np->in_dpmin); 225 if (np->in_dpmin != np->in_dpmax) 226 PRINTF("-%d", np->in_dpmax); 227 } 228 } 229 putchar(' '); 230 printproto(pr, proto, np); 231 if (np->in_flags & IPN_ROUNDR) 232 PRINTF(" round-robin"); 233 if (np->in_flags & IPN_FRAG) 234 PRINTF(" frag"); 235 if (np->in_age[0] != 0 || np->in_age[1] != 0) { 236 PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); 237 } 238 if (np->in_flags & IPN_STICKY) 239 PRINTF(" sticky"); 240 if (np->in_mssclamp != 0) 241 PRINTF(" mssclamp %d", np->in_mssclamp); 242 if (np->in_plabel != -1) 243 PRINTF(" proxy %s", np->in_names + np->in_plabel); 244 if (np->in_tag.ipt_tag[0] != '\0') 245 PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag); 246 if ((np->in_flags & IPN_PURGE) != 0) 247 PRINTF(" purge"); 248 PRINTF("\n"); 249 if (opts & OPT_DEBUG) 250 PRINTF("\tpmax %u\n", np->in_dpmax); 251 252 } else { 253 int protoprinted = 0; 254 255 if (!(np->in_flags & IPN_FILTER)) { 256 printnataddr(np->in_v[0], np->in_names, &np->in_osrc, 257 np->in_ifnames[0]); 258 } 259 if (np->in_flags & IPN_NO) { 260 putchar(' '); 261 printproto(pr, proto, np); 262 PRINTF(";\n"); 263 return; 264 } 265 PRINTF(" -> "); 266 if (np->in_flags & IPN_SIPRANGE) { 267 PRINTF("range "); 268 printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, 269 np->in_ifnames[0]); 270 } else { 271 printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, 272 np->in_ifnames[0]); 273 } 274 if (np->in_plabel != -1) { 275 PRINTF(" proxy port "); 276 if (np->in_odport != 0) { 277 char *s; 278 279 s = portname(proto, np->in_odport); 280 if (s != NULL) 281 fputs(s, stdout); 282 else 283 fputs("???", stdout); 284 } 285 PRINTF(" %s/", np->in_names + np->in_plabel); 286 printproto(pr, proto, NULL); 287 protoprinted = 1; 288 } else if (np->in_redir == NAT_MAPBLK) { 289 if ((np->in_spmin == 0) && 290 (np->in_flags & IPN_AUTOPORTMAP)) 291 PRINTF(" ports auto"); 292 else 293 PRINTF(" ports %d", np->in_spmin); 294 if (opts & OPT_DEBUG) 295 PRINTF("\n\tip modulous %d", np->in_spmax); 296 297 } else if (np->in_spmin || np->in_spmax) { 298 if (np->in_flags & IPN_ICMPQUERY) { 299 PRINTF(" icmpidmap "); 300 } else { 301 PRINTF(" portmap "); 302 } 303 printproto(pr, proto, np); 304 protoprinted = 1; 305 if (np->in_flags & IPN_AUTOPORTMAP) { 306 PRINTF(" auto"); 307 if (opts & OPT_DEBUG) 308 PRINTF(" [%d:%d %d %d]", 309 np->in_spmin, np->in_spmax, 310 np->in_ippip, np->in_ppip); 311 } else { 312 PRINTF(" %d:%d", np->in_spmin, np->in_spmax); 313 } 314 if (np->in_flags & IPN_SEQUENTIAL) 315 PRINTF(" sequential"); 316 } 317 318 if (np->in_flags & IPN_FRAG) 319 PRINTF(" frag"); 320 if (np->in_age[0] != 0 || np->in_age[1] != 0) { 321 PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); 322 } 323 if (np->in_mssclamp != 0) 324 PRINTF(" mssclamp %d", np->in_mssclamp); 325 if (np->in_tag.ipt_tag[0] != '\0') 326 PRINTF(" tag %s", np->in_tag.ipt_tag); 327 if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) { 328 putchar(' '); 329 printproto(pr, proto, np); 330 } 331 if ((np->in_flags & IPN_PURGE) != 0) 332 PRINTF(" purge"); 333 PRINTF("\n"); 334 if (opts & OPT_DEBUG) { 335 PRINTF("\tnextip "); 336 printip(family, &np->in_snip); 337 PRINTF(" pnext %d\n", np->in_spnext); 338 } 339 } 340 341 if (opts & OPT_DEBUG) { 342 PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d", 343 np->in_space, np->in_use, np->in_hits, 344 np->in_flags, np->in_pr[0], np->in_pr[1]); 345 PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]); 346 PRINTF("\tifp[0] %p ifp[1] %p apr %p\n", 347 np->in_ifps[0], np->in_ifps[1], np->in_apr); 348 PRINTF("\ttqehead %p/%p comment %p\n", 349 np->in_tqehead[0], np->in_tqehead[1], np->in_comment); 350 } 351 } 352