diff options
Diffstat (limited to 'printnat.c')
-rw-r--r-- | printnat.c | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/printnat.c b/printnat.c new file mode 100644 index 0000000..5a12b32 --- /dev/null +++ b/printnat.c @@ -0,0 +1,487 @@ +/* + * Copyright (C) 1993-2001 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ +#if defined(__sgi) && (IRIX > 602) +# include <sys/ptimers.h> +#endif +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#if !defined(__SVR4) && !defined(__svr4__) +#include <strings.h> +#else +#include <sys/byteorder.h> +#endif +#include <sys/time.h> +#include <sys/param.h> +#include <stdlib.h> +#include <unistd.h> +#include <stddef.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#if defined(sun) && (defined(__svr4__) || defined(__SVR4)) +# include <sys/ioccom.h> +# include <sys/sysmacros.h> +#endif +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <net/if.h> +#if __FreeBSD_version >= 300000 +# include <net/if_var.h> +#endif +#include <netdb.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <resolv.h> +#include <ctype.h> +#include "netinet/ip_compat.h" +#include "netinet/ip_fil.h" +#include "netinet/ip_nat.h" +#include "netinet/ip_state.h" +#include "netinet/ip_proxy.h" +#include "ipf.h" +#include "kmem.h" + +#if defined(sun) && !SOLARIS2 +# define STRERROR(x) sys_errlist[x] +extern char *sys_errlist[]; +#else +# define STRERROR(x) strerror(x) +#endif + +#if !defined(lint) +static const char rcsid[] = "@(#)$Id: printnat.c,v 1.1.2.15 2003/03/22 15:31:49 darrenr Exp $"; +#endif + + +#if SOLARIS +#define bzero(a,b) memset(a,0,b) +#endif +#ifdef USE_INET6 +extern int use_inet6; +#endif + +extern char thishost[MAXHOSTNAMELEN]; + +extern int countbits __P((u_32_t)); + +void printnat __P((ipnat_t *, int)); +char *getnattype __P((ipnat_t *)); +void printactivenat __P((nat_t *, int)); +void printhostmap __P((hostmap_t *, u_int)); +char *getsumd __P((u_32_t)); + +static void printaps __P((ap_session_t *, int)); + +static void printaps(aps, opts) +ap_session_t *aps; +int opts; +{ + ipsec_pxy_t ipsec; + ap_session_t ap; + ftpinfo_t ftp; + aproxy_t apr; + raudio_t ra; + + if (kmemcpy((char *)&ap, (long)aps, sizeof(ap))) + return; + if (kmemcpy((char *)&apr, (long)ap.aps_apr, sizeof(apr))) + return; + printf("\tproxy %s/%d use %d flags %x\n", apr.apr_label, + apr.apr_p, apr.apr_ref, apr.apr_flags); + printf("\t\tproto %d flags %#x bytes ", ap.aps_p, ap.aps_flags); +#ifdef USE_QUAD_T + printf("%qu pkts %qu", (unsigned long long)ap.aps_bytes, + (unsigned long long)ap.aps_pkts); +#else + printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts); +#endif + printf(" data %s size %d\n", ap.aps_data ? "YES" : "NO", ap.aps_psiz); + if ((ap.aps_p == IPPROTO_TCP) && (opts & OPT_VERBOSE)) { + printf("\t\tstate[%u,%u], sel[%d,%d]\n", + ap.aps_state[0], ap.aps_state[1], + ap.aps_sel[0], ap.aps_sel[1]); +#if (defined(NetBSD) && (NetBSD >= 199905) && (NetBSD < 1991011)) || \ + (__FreeBSD_version >= 300000) || defined(OpenBSD) + printf("\t\tseq: off %hd/%hd min %x/%x\n", + ap.aps_seqoff[0], ap.aps_seqoff[1], + ap.aps_seqmin[0], ap.aps_seqmin[1]); + printf("\t\tack: off %hd/%hd min %x/%x\n", + ap.aps_ackoff[0], ap.aps_ackoff[1], + ap.aps_ackmin[0], ap.aps_ackmin[1]); +#else + printf("\t\tseq: off %hd/%hd min %lx/%lx\n", + ap.aps_seqoff[0], ap.aps_seqoff[1], + ap.aps_seqmin[0], ap.aps_seqmin[1]); + printf("\t\tack: off %hd/%hd min %lx/%lx\n", + ap.aps_ackoff[0], ap.aps_ackoff[1], + ap.aps_ackmin[0], ap.aps_ackmin[1]); +#endif + } + + if (!strcmp(apr.apr_label, "raudio") && ap.aps_psiz == sizeof(ra)) { + if (kmemcpy((char *)&ra, (long)ap.aps_data, sizeof(ra))) + return; + printf("\tReal Audio Proxy:\n"); + printf("\t\tSeen PNA: %d\tVersion: %d\tEOS: %d\n", + ra.rap_seenpna, ra.rap_version, ra.rap_eos); + printf("\t\tMode: %#x\tSBF: %#x\n", ra.rap_mode, ra.rap_sbf); + printf("\t\tPorts:pl %hu, pr %hu, sr %hu\n", + ra.rap_plport, ra.rap_prport, ra.rap_srport); + } else if (!strcmp(apr.apr_label, "ftp") && + (ap.aps_psiz == sizeof(ftp))) { + if (kmemcpy((char *)&ftp, (long)ap.aps_data, sizeof(ftp))) + return; + printf("\tFTP Proxy:\n"); + printf("\t\tpassok: %d\n", ftp.ftp_passok); + ftp.ftp_side[0].ftps_buf[FTP_BUFSZ - 1] = '\0'; + ftp.ftp_side[1].ftps_buf[FTP_BUFSZ - 1] = '\0'; + printf("\tClient:\n"); + printf("\t\tseq %08x%08x len %d junk %d cmds %d\n", + ftp.ftp_side[0].ftps_seq[1], + ftp.ftp_side[0].ftps_seq[0], + ftp.ftp_side[0].ftps_len, + ftp.ftp_side[0].ftps_junk, ftp.ftp_side[0].ftps_cmds); + printf("\t\tbuf ["); + printbuf(ftp.ftp_side[0].ftps_buf, FTP_BUFSZ, 1); + printf("]\n\tServer:\n"); + printf("\t\tseq %08x%08x len %d junk %d cmds %d\n", + ftp.ftp_side[1].ftps_seq[1], + ftp.ftp_side[1].ftps_seq[0], + ftp.ftp_side[1].ftps_len, + ftp.ftp_side[1].ftps_junk, ftp.ftp_side[1].ftps_cmds); + printf("\t\tbuf ["); + printbuf(ftp.ftp_side[1].ftps_buf, FTP_BUFSZ, 1); + printf("]\n"); + } else if (!strcmp(apr.apr_label, "ipsec") && + (ap.aps_psiz == sizeof(ipsec))) { + if (kmemcpy((char *)&ipsec, (long)ap.aps_data, sizeof(ipsec))) + return; + printf("\tIPSec Proxy:\n"); + printf("\t\tICookie %08x%08x RCookie %08x%08x %s\n", + (u_int)ntohl(ipsec.ipsc_icookie[0]), + (u_int)ntohl(ipsec.ipsc_icookie[1]), + (u_int)ntohl(ipsec.ipsc_rcookie[0]), + (u_int)ntohl(ipsec.ipsc_rcookie[1]), + ipsec.ipsc_rckset ? "(Set)" : "(Not set)"); + } +} + + +/* + * Get a nat filter type given its kernel address. + */ +char *getnattype(ipnat) +ipnat_t *ipnat; +{ + static char unknownbuf[20]; + ipnat_t ipnatbuff; + char *which; + + if (!ipnat || (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, + sizeof(ipnatbuff)))) + return "???"; + + switch (ipnatbuff.in_redir) + { + case NAT_MAP : + which = "MAP"; + break; + case NAT_MAPBLK : + which = "MAP-BLOCK"; + break; + case NAT_REDIRECT : + which = "RDR"; + break; + case NAT_BIMAP : + which = "BIMAP"; + break; + default : + sprintf(unknownbuf, "unknown(%04x)", + ipnatbuff.in_redir & 0xffffffff); + which = unknownbuf; + break; + } + return which; +} + + +void printactivenat(nat, opts) +nat_t *nat; +int opts; +{ + u_int hv1, hv2; + + printf("%s %-15s", getnattype(nat->nat_ptr), inet_ntoa(nat->nat_inip)); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %-5hu", ntohs(nat->nat_inport)); + + printf(" <- -> %-15s",inet_ntoa(nat->nat_outip)); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %-5hu", ntohs(nat->nat_outport)); + + printf(" [%s", inet_ntoa(nat->nat_oip)); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + printf(" %hu", ntohs(nat->nat_oport)); + printf("]"); + + if (opts & OPT_VERBOSE) { + printf("\n\tage %lu use %hu sumd %s/", + nat->nat_age, nat->nat_use, getsumd(nat->nat_sumd[0])); + hv1 = NAT_HASH_FN(nat->nat_inip.s_addr, nat->nat_inport, + 0xffffffff), + hv1 = NAT_HASH_FN(nat->nat_oip.s_addr, hv1 + nat->nat_oport, + NAT_TABLE_SZ), + hv2 = NAT_HASH_FN(nat->nat_outip.s_addr, nat->nat_outport, + 0xffffffff), + hv2 = NAT_HASH_FN(nat->nat_oip.s_addr, hv2 + nat->nat_oport, + NAT_TABLE_SZ), + printf("%s pr %u bkt %d/%d flags %x drop %d/%d\n", + getsumd(nat->nat_sumd[1]), nat->nat_p, + hv1, hv2, nat->nat_flags, + nat->nat_drop[0], nat->nat_drop[1]); + printf("\tifp %s ", getifname(nat->nat_ifp)); +#ifdef USE_QUAD_T + printf("bytes %qu pkts %qu", + (unsigned long long)nat->nat_bytes, + (unsigned long long)nat->nat_pkts); +#else + printf("bytes %lu pkts %lu", nat->nat_bytes, nat->nat_pkts); +#endif +#if SOLARIS + printf(" %lx", nat->nat_ipsumd); +#endif + } + + putchar('\n'); + if (nat->nat_aps) + printaps(nat->nat_aps, opts); +} + + +void printhostmap(hmp, hv) +hostmap_t *hmp; +u_int hv; +{ + printf("%s -> ", inet_ntoa(hmp->hm_realip)); + printf("%s ", inet_ntoa(hmp->hm_mapip)); + printf("(use = %d hv = %u)\n", hmp->hm_ref, hv); +} + + +char *getsumd(sum) +u_32_t sum; +{ + static char sumdbuf[17]; + + if (sum & NAT_HW_CKSUM) + sprintf(sumdbuf, "hw(%#0x)", sum & 0xffff); + else + sprintf(sumdbuf, "%#0x", sum); + return sumdbuf; +} + + +/* + * Print out a NAT rule + */ +void printnat(np, opts) +ipnat_t *np; +int opts; +{ + struct protoent *pr; + struct servent *sv; + int bits; + + pr = getprotobynumber(np->in_p); + + switch (np->in_redir) + { + case NAT_REDIRECT : + printf("rdr"); + break; + case NAT_MAP : + printf("map"); + break; + case NAT_MAPBLK : + printf("map-block"); + break; + case NAT_BIMAP : + printf("bimap"); + break; + default : + fprintf(stderr, "unknown value for in_redir: %#x\n", + np->in_redir); + break; + } + + printf(" %s ", np->in_ifname); + + if (np->in_flags & IPN_FILTER) { + if (np->in_flags & IPN_NOTSRC) + printf("! "); + printf("from "); + if (np->in_redir == NAT_REDIRECT) { + printhostmask(4, (u_32_t *)&np->in_srcip, + (u_32_t *)&np->in_srcmsk); + } else { + printhostmask(4, (u_32_t *)&np->in_inip, + (u_32_t *)&np->in_inmsk); + } + if (np->in_scmp) + printportcmp(np->in_p, &np->in_tuc.ftu_src); + + if (np->in_flags & IPN_NOTDST) + printf(" !"); + printf(" to "); + if (np->in_redir == NAT_REDIRECT) { + printhostmask(4, (u_32_t *)&np->in_outip, + (u_32_t *)&np->in_outmsk); + } else { + printhostmask(4, (u_32_t *)&np->in_srcip, + (u_32_t *)&np->in_srcmsk); + } + if (np->in_dcmp) + printportcmp(np->in_p, &np->in_tuc.ftu_dst); + } + + if (np->in_redir == NAT_REDIRECT) { + if (!(np->in_flags & IPN_FILTER)) { + printf("%s", inet_ntoa(np->in_out[0])); + bits = countbits(np->in_out[1].s_addr); + if (bits != -1) + printf("/%d ", bits); + else + printf("/%s ", inet_ntoa(np->in_out[1])); + printf("port %d", ntohs(np->in_pmin)); + if (np->in_pmax != np->in_pmin) + printf("- %d", ntohs(np->in_pmax)); + } + printf(" -> %s", inet_ntoa(np->in_in[0])); + if (np->in_flags & IPN_SPLIT) + printf(",%s", inet_ntoa(np->in_in[1])); + printf(" port %d", ntohs(np->in_pnext)); + if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) + printf(" tcp/udp"); + else if ((np->in_flags & IPN_TCP) == IPN_TCP) + printf(" tcp"); + else if ((np->in_flags & IPN_UDP) == IPN_UDP) + printf(" udp"); + else if (np->in_p == 0) + printf(" ip"); + else if (np->in_p != 0) { + if (pr != NULL) + printf(" %s", pr->p_name); + else + printf(" %d", np->in_p); + } + if (np->in_flags & IPN_ROUNDR) + printf(" round-robin"); + if (np->in_flags & IPN_FRAG) + printf(" frag"); + if (np->in_age[0]) + printf(" age %d/%d", np->in_age[0], np->in_age[1]); + if (np->in_mssclamp) + printf(" mssclamp %u", np->in_mssclamp); + printf("\n"); + if (opts & OPT_DEBUG) + printf("\tspc %lu flg %#x max %u use %d\n", + np->in_space, np->in_flags, + np->in_pmax, np->in_use); + } else { + if (!(np->in_flags & IPN_FILTER)) { + printf("%s/", inet_ntoa(np->in_in[0])); + bits = countbits(np->in_in[1].s_addr); + if (bits != -1) + printf("%d", bits); + else + printf("%s", inet_ntoa(np->in_in[1])); + } + printf(" -> "); + if (np->in_flags & IPN_IPRANGE) { + printf("range %s-", inet_ntoa(np->in_out[0])); + printf("%s", inet_ntoa(np->in_out[1])); + } else { + printf("%s/", inet_ntoa(np->in_out[0])); + bits = countbits(np->in_out[1].s_addr); + if (bits != -1) + printf("%d", bits); + else + printf("%s", inet_ntoa(np->in_out[1])); + } + if (*np->in_plabel) { + printf(" proxy port"); + if (np->in_dcmp != 0) + np->in_dport = htons(np->in_dport); + if (np->in_dport != 0) { + if (pr != NULL) + sv = getservbyport(np->in_dport, + pr->p_name); + else + sv = getservbyport(np->in_dport, NULL); + if (sv != NULL) + printf(" %s", sv->s_name); + else + printf(" %hu", ntohs(np->in_dport)); + } + printf(" %.*s/", (int)sizeof(np->in_plabel), + np->in_plabel); + if (pr != NULL) + fputs(pr->p_name, stdout); + else + printf("%d", np->in_p); + } else if (np->in_redir == NAT_MAPBLK) { + if ((np->in_pmin == 0) && + (np->in_flags & IPN_AUTOPORTMAP)) + printf(" ports auto"); + else + printf(" ports %d", np->in_pmin); + if (opts & OPT_DEBUG) + printf("\n\tip modulous %d", np->in_pmax); + } else if (np->in_pmin || np->in_pmax) { + printf(" portmap"); + if ((np->in_flags & IPN_TCPUDP) == IPN_TCPUDP) + printf(" tcp/udp"); + else if (np->in_flags & IPN_TCP) + printf(" tcp"); + else if (np->in_flags & IPN_UDP) + printf(" udp"); + if (np->in_flags & IPN_AUTOPORTMAP) { + printf(" auto"); + if (opts & OPT_DEBUG) + printf(" [%d:%d %d %d]", + ntohs(np->in_pmin), + ntohs(np->in_pmax), + np->in_ippip, np->in_ppip); + } else { + printf(" %d:%d", ntohs(np->in_pmin), + ntohs(np->in_pmax)); + } + } + if (np->in_flags & IPN_FRAG) + printf(" frag"); + if (np->in_age[0]) + printf(" age %d/%d", np->in_age[0], np->in_age[1]); + printf("\n"); + if (opts & OPT_DEBUG) { + struct in_addr nip; + + nip.s_addr = htonl(np->in_nextip.s_addr); + + printf("\tspace %lu nextip %s pnext %d", np->in_space, + inet_ntoa(nip), np->in_pnext); + printf(" flags %x use %u\n", + np->in_flags, np->in_use); + } + } +} |