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