/* $NetBSD: printnat.c,v 1.10 2002/09/19 08:11:38 martti Exp $ */ /* * 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) */ #ifdef __sgi # include #endif #include #include #include #include #include #if !defined(__SVR4) && !defined(__svr4__) #include #else #include #endif #include #include #include #include #include #include #include #if defined(sun) && (defined(__svr4__) || defined(__SVR4)) # include # include #endif #include #include #include #include #include #if __FreeBSD_version >= 300000 # include #endif #include #include #include #include #include #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[] __attribute__((__unused__)) = "@(#)Id: printnat.c,v 1.1.2.10 2002/08/28 12:45:51 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]); 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 { np->in_nextip.s_addr = htonl(np->in_nextip.s_addr); 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_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_mssclamp) printf(" mssclamp %u", (unsigned)np->in_mssclamp); if (np->in_age[0]) printf(" age %d/%d", np->in_age[0], np->in_age[1]); printf("\n"); if (opts & OPT_DEBUG) { printf("\tspace %lu nextip %s pnext %d", np->in_space, inet_ntoa(np->in_nextip), np->in_pnext); printf(" flags %x use %u\n", np->in_flags, np->in_use); } } }