Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: printnat.c,v 1.4 2018/02/04 08:19:42 mrg Exp $	*/
      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 (at) EnGarde.com)
      9  */
     10 
     11 #include "ipf.h"
     12 #include "kmem.h"
     13 
     14 
     15 #if !defined(lint)
     16 static __attribute__((__used__)) const char rcsid[] = "@(#)Id: printnat.c,v 1.1.1.2 2012/07/22 13:44:41 darrenr Exp $";
     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