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