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