diff options
Diffstat (limited to 'contrib/ipfilter/ipnat.c')
-rw-r--r-- | contrib/ipfilter/ipnat.c | 597 |
1 files changed, 104 insertions, 493 deletions
diff --git a/contrib/ipfilter/ipnat.c b/contrib/ipfilter/ipnat.c index ae0f71d..11997a3 100644 --- a/contrib/ipfilter/ipnat.c +++ b/contrib/ipfilter/ipnat.c @@ -1,20 +1,11 @@ /* - * Copyright (C) 1993-1997 by Darren Reed. + * Copyright (C) 1993-1998 by Darren Reed. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and due credit is given * to the original author and the contributors. * * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) - * - * Broken still: - * Displaying the nat with redirect entries is way confusing - * - * Example redirection line: - * rdr le1 0.0.0.0/0 port 79 -> 199.165.219.129 port 9901 - * - * Will redirect all incoming packets on le1 to any machine, port 79 to - * host 199.165.219.129, port 9901 */ #include <stdio.h> #include <string.h> @@ -42,6 +33,9 @@ #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> @@ -62,7 +56,7 @@ extern char *sys_errlist[]; #if !defined(lint) static const char sccsid[] ="@(#)ipnat.c 1.9 6/5/96 (C) 1993 Darren Reed"; -static const char rcsid[] = "@(#)$Id: ipnat.c,v 2.0.2.21.2.6 1998/05/23 19:07:02 darrenr Exp $"; +static const char rcsid[] = "@(#)$Id: ipnat.c,v 2.1 1999/08/04 17:30:07 darrenr Exp $"; #endif @@ -71,18 +65,18 @@ static const char rcsid[] = "@(#)$Id: ipnat.c,v 2.0.2.21.2.6 1998/05/23 19:07:02 #endif extern char *optarg; +extern ipnat_t *natparse __P((char *, int)); +extern void natparsefile __P((int, char *, int)); +extern void printnat __P((ipnat_t *, int, void *)); -ipnat_t *parse __P((char *)); -u_32_t hostnum __P((char *, int *)); +u_32_t hostnum __P((char *, int *, int)); u_32_t hostmask __P((char *)); -u_short portnum __P((char *, char *)); void dostats __P((int, int)), flushtable __P((int, int)); -void printnat __P((ipnat_t *, int, void *)); -void parsefile __P((int, char *, int)); void usage __P((char *)); int countbits __P((u_32_t)); char *getnattype __P((ipnat_t *)); int main __P((int, char*[])); +void printaps __P((ap_session_t *, int)); #define OPT_REM 1 #define OPT_NODO 2 @@ -91,12 +85,13 @@ int main __P((int, char*[])); #define OPT_VERBOSE 16 #define OPT_FLUSH 32 #define OPT_CLEAR 64 +#define OPT_HITS 128 void usage(name) char *name; { - fprintf(stderr, "%s: [-CFlnrsv] [-f filename]\n", name); + fprintf(stderr, "%s: [-CFhlnrsv] [-f filename]\n", name); exit(1); } @@ -106,9 +101,9 @@ int argc; char *argv[]; { char *file = NULL; - int fd = -1, opts = 1, c; + int fd = -1, opts = 0, c; - while ((c = getopt(argc, argv, "CFf:lnrsv")) != -1) + while ((c = getopt(argc, argv, "CFf:hlnrsv")) != -1) switch (c) { case 'C' : @@ -120,6 +115,9 @@ char *argv[]; case 'F' : opts |= OPT_FLUSH; break; + case 'h' : + opts |=OPT_HITS; + break; case 'l' : opts |= OPT_LIST; break; @@ -127,7 +125,7 @@ char *argv[]; opts |= OPT_NODO; break; case 'r' : - opts &= ~OPT_REM; + opts |= OPT_REM; break; case 's' : opts |= OPT_STAT; @@ -149,7 +147,7 @@ char *argv[]; if (opts & (OPT_FLUSH|OPT_CLEAR)) flushtable(fd, opts); if (file) - parsefile(fd, file, opts); + natparsefile(fd, file, opts); if (opts & (OPT_LIST|OPT_STAT)) dostats(fd, opts); return 0; @@ -185,94 +183,58 @@ u_32_t ip; } -void printnat(np, verbose, ptr) -ipnat_t *np; -int verbose; -void *ptr; +void printaps(aps, opts) +ap_session_t *aps; +int opts; { - int bits; - struct protoent *pr; + ap_session_t ap; + aproxy_t apr; + raudio_t ra; - switch (np->in_redir) - { - case NAT_REDIRECT : - printf("rdr "); - break; - case NAT_MAP : - printf("map "); - break; - case NAT_BIMAP : - printf("bimap "); - break; - default : - fprintf(stderr, "unknown value for in_redir: %#x\n", - np->in_redir); - break; + 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", ap.aps_bytes, ap.aps_pkts); +#else + printf("%lu pkts %lu", ap.aps_bytes, ap.aps_pkts); +#endif + printf(" data %p psiz %d\n", ap.aps_data, 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 (np->in_redir == NAT_REDIRECT) { - printf("%s %s", np->in_ifname, 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_pmin) - printf("port %d ", ntohs(np->in_pmin)); - printf("-> %s", inet_ntoa(np->in_in[0])); - if (np->in_pnext) - 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"); - printf("\n"); - if (verbose) - printf("\t%p %u %x %u %p %d\n", np->in_ifp, - np->in_space, np->in_flags, np->in_pnext, np, - np->in_use); - } else { - np->in_nextip.s_addr = htonl(np->in_nextip.s_addr); - printf("%s %s/", np->in_ifname, 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(" -> %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) - printf(" %hu", ntohs(np->in_dport)); - printf(" %.*s/", (int)sizeof(np->in_plabel), - np->in_plabel); - if ((pr = getprotobynumber(np->in_p))) - fputs(pr->p_name, stdout); - else - printf("%d", np->in_p); - } 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"); - printf(" %d:%d", ntohs(np->in_pmin), - ntohs(np->in_pmax)); - } - printf("\n"); - if (verbose) - printf("\t%p %u %s %d %x\n", np->in_ifp, - np->in_space, inet_ntoa(np->in_nextip), - np->in_pnext, np->in_flags); + 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); } } @@ -286,8 +248,8 @@ ipnat_t *ipnat; char *which; ipnat_t ipnatbuff; - if (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, - sizeof(ipnatbuff))) + if (!ipnat || (ipnat && kmemcpy((char *)&ipnatbuff, (long)ipnat, + sizeof(ipnatbuff)))) return "???"; switch (ipnatbuff.in_redir) @@ -295,6 +257,9 @@ ipnat_t *ipnat; case NAT_MAP : which = "MAP"; break; + case NAT_MAPBLK : + which = "MAP-BLOCK"; + break; case NAT_REDIRECT : which = "RDR"; break; @@ -341,6 +306,8 @@ int fd, opts; perror("kmemcpy"); break; } + if (opts & OPT_HITS) + printf("%d ", ipn.in_hits); printnat(&ipn, opts & OPT_VERBOSE, (void *)ns.ns_list); ns.ns_list = ipn.in_next; } @@ -354,66 +321,39 @@ int fd, opts; printf("\nList of active sessions:\n"); - for (i = 0; i < NAT_SIZE; i++) - for (np = nt[0][i]; np; np = nat.nat_hnext[0]) { - if (kmemcpy((char *)&nat, (long)np, - sizeof(nat))) - break; - - printf("%s %-15s %-5hu <- ->", - getnattype(nat.nat_ptr), - inet_ntoa(nat.nat_inip), - ntohs(nat.nat_inport)); - printf(" %-15s %-5hu", - inet_ntoa(nat.nat_outip), - ntohs(nat.nat_outport)); - printf(" [%s %hu]", inet_ntoa(nat.nat_oip), - ntohs(nat.nat_oport)); - printf(" %ld %hu %lx", nat.nat_age, - nat.nat_use, nat.nat_sumd); + for (np = ns.ns_instances; np; np = nat.nat_next) { + if (kmemcpy((char *)&nat, (long)np, sizeof(nat))) + break; + + printf("%s %-15s %-5hu <- ->", getnattype(nat.nat_ptr), + inet_ntoa(nat.nat_inip), ntohs(nat.nat_inport)); + printf(" %-15s %-5hu", inet_ntoa(nat.nat_outip), + ntohs(nat.nat_outport)); + printf(" [%s %hu]", inet_ntoa(nat.nat_oip), + ntohs(nat.nat_oport)); + if (opts & OPT_VERBOSE) { + printf("\n\tage %lu use %hu sumd %x pr %u", + nat.nat_age, nat.nat_use, nat.nat_sumd, + nat.nat_p); + printf(" bkt %d flags %x ", i, nat.nat_flags); +#ifdef USE_QUAD_T + printf("bytes %qu pkts %qu", + nat.nat_bytes, 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'); } - free(nt[0]); - } -} - + putchar('\n'); + if (nat.nat_aps) + printaps(nat.nat_aps, opts); + } -u_short portnum(name, proto) -char *name, *proto; -{ - struct servent *sp, *sp2; - u_short p1 = 0; - - if (isdigit(*name)) - return htons((u_short)atoi(name)); - if (!proto) - proto = "tcp/udp"; - if (strcasecmp(proto, "tcp/udp")) { - sp = getservbyname(name, proto); - if (sp) - return sp->s_port; - (void) fprintf(stderr, "unknown service \"%s\".\n", name); - return 0; - } - sp = getservbyname(name, "tcp"); - if (sp) - p1 = sp->s_port; - sp2 = getservbyname(name, "udp"); - if (!sp || !sp2) { - (void) fprintf(stderr, "unknown tcp/udp service \"%s\".\n", - name); - return 0; - } - if (p1 != sp2->s_port) { - (void) fprintf(stderr, "%s %d/tcp is a different port to ", - name, p1); - (void) fprintf(stderr, "%s %d/udp\n", name, sp->s_port); - return 0; + free(nt[0]); } - return p1; } @@ -445,9 +385,10 @@ char *msk; * returns an ip address as a long var as a result of either a DNS lookup or * straight inet_addr() call */ -u_32_t hostnum(host, resolved) +u_32_t hostnum(host, resolved, linenum) char *host; int *resolved; +int linenum; { struct hostent *hp; struct netent *np; @@ -461,7 +402,7 @@ int *resolved; if (!(hp = gethostbyname(host))) { if (!(np = getnetbyname(host))) { *resolved = -1; - fprintf(stderr, "can't resolve hostname: %s\n", host); + fprintf(stderr, "Line %d: can't resolve hostname: %s\n", linenum, host); return 0; } return htonl(np->n_net); @@ -470,336 +411,6 @@ int *resolved; } -ipnat_t *parse(line) -char *line; -{ - struct protoent *pr; - static ipnat_t ipn; - char *s, *t; - char *shost, *snetm, *dhost, *proto; - char *dnetm = NULL, *dport = NULL, *tport = NULL; - int resolved; - - bzero((char *)&ipn, sizeof(ipn)); - if ((s = strchr(line, '\n'))) - *s = '\0'; - if ((s = strchr(line, '#'))) - *s = '\0'; - if (!*line) - return NULL; - if (!(s = strtok(line, " \t"))) - return NULL; - if (!strcasecmp(s, "map")) - ipn.in_redir = NAT_MAP; - else if (!strcasecmp(s, "rdr")) - ipn.in_redir = NAT_REDIRECT; - else if (!strcasecmp(s, "bimap")) - ipn.in_redir = NAT_BIMAP; - else { - (void)fprintf(stderr, - "expected map/rdr/bimap, got \"%s\"\n", s); - return NULL; - } - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (interface)\n"); - return NULL; - } - strncpy(ipn.in_ifname, s, sizeof(ipn.in_ifname) - 1); - ipn.in_ifname[sizeof(ipn.in_ifname) - 1] = '\0'; - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (%s)\n", - ipn.in_redir ? "destination": "source"); - return NULL; - } - shost = s; - - if (ipn.in_redir == NAT_REDIRECT) { - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (destination port)\n"); - return NULL; - } - - if (strcasecmp(s, "port")) { - fprintf(stderr, "missing fields (port)\n"); - return NULL; - } - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (destination port)\n"); - return NULL; - } - - dport = s; - } - - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (->)\n"); - return NULL; - } - if (!strcmp(s, "->")) { - snetm = strrchr(shost, '/'); - if (!snetm) { - fprintf(stderr, "missing fields (%s netmask)\n", - ipn.in_redir ? "destination":"source"); - return NULL; - } - } else { - if (strcasecmp(s, "netmask")) { - fprintf(stderr, "missing fields (netmask)\n"); - return NULL; - } - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (%s netmask)\n", - ipn.in_redir ? "destination":"source"); - return NULL; - } - snetm = s; - } - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (%s)\n", - ipn.in_redir ? "destination":"target"); - return NULL; - } - dhost = s; - - if (ipn.in_redir & NAT_MAP) { - if (!(s = strtok(NULL, " \t"))) { - dnetm = strrchr(dhost, '/'); - if (!dnetm) { - fprintf(stderr, - "missing fields (dest netmask)\n"); - return NULL; - } - } - if (!s || !strcasecmp(s, "portmap") || - !strcasecmp(s, "proxy")) { - dnetm = strrchr(dhost, '/'); - if (!dnetm) { - fprintf(stderr, - "missing fields (dest netmask)\n"); - return NULL; - } - } else { - if (strcasecmp(s, "netmask")) { - fprintf(stderr, - "missing fields (dest netmask)\n"); - return NULL; - } - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "missing fields (dest netmask)\n"); - return NULL; - } - dnetm = s; - } - if (*dnetm == '/') - *dnetm++ = '\0'; - } else { - /* If it's a in_redir, expect target port */ - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (destination port)\n"); - return NULL; - } - - if (strcasecmp(s, "port")) { - fprintf(stderr, "missing fields (port)\n"); - return NULL; - } - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing fields (destination port)\n"); - return NULL; - } - tport = s; - } - - - if (*snetm == '/') - *snetm++ = '\0'; - - if (ipn.in_redir & NAT_MAP) { - ipn.in_inip = hostnum(shost, &resolved); - if (resolved == -1) - return NULL; - ipn.in_inmsk = hostmask(snetm); - ipn.in_outip = hostnum(dhost, &resolved); - if (resolved == -1) - return NULL; - ipn.in_outmsk = hostmask(dnetm); - } else { - ipn.in_inip = hostnum(dhost, &resolved); /* Inside is target */ - if (resolved == -1) - return NULL; - ipn.in_inmsk = hostmask("255.255.255.255"); - ipn.in_outip = hostnum(shost, &resolved); - if (resolved == -1) - return NULL; - ipn.in_outmsk = hostmask(snetm); - if (!(s = strtok(NULL, " \t"))) { - ipn.in_flags = IPN_TCP; /* XXX- TCP only by default */ - proto = "tcp"; - } else { - if (!strcasecmp(s, "tcp")) - ipn.in_flags = IPN_TCP; - else if (!strcasecmp(s, "udp")) - ipn.in_flags = IPN_UDP; - else if (!strcasecmp(s, "tcp/udp")) - ipn.in_flags = IPN_TCPUDP; - else if (!strcasecmp(s, "tcpudp")) - ipn.in_flags = IPN_TCPUDP; - else { - fprintf(stderr, - "expected protocol - got \"%s\"\n", s); - return NULL; - } - proto = s; - if ((s = strtok(NULL, " \t"))) { - fprintf(stderr, - "extra junk at the end of rdr: %s\n", - s); - return NULL; - } - } - ipn.in_pmin = portnum(dport, proto); /* dest port */ - ipn.in_pmax = ipn.in_pmin; /* NECESSARY of removing nats */ - ipn.in_pnext = portnum(tport, proto); /* target port */ - s = NULL; /* That's all she wrote! */ - } - ipn.in_inip &= ipn.in_inmsk; - ipn.in_outip &= ipn.in_outmsk; - - if (!s) - return &ipn; - - if (ipn.in_redir == NAT_BIMAP) { - fprintf(stderr, "extra words at the end of bimap line: %s\n", - s); - return NULL; - } - if (!strcasecmp(s, "proxy")) { - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "missing parameter for \"proxy\"\n"); - return NULL; - } - dport = NULL; - - if (!strcasecmp(s, "port")) { - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "missing parameter for \"port\"\n"); - return NULL; - } - - dport = s; - - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, - "missing parameter for \"proxy\"\n"); - return NULL; - } - } - if ((proto = index(s, '/'))) { - *proto++ = '\0'; - if ((pr = getprotobyname(proto))) - ipn.in_p = pr->p_proto; - else - ipn.in_p = atoi(proto); - if (dport) - ipn.in_dport = portnum(dport, proto); - } else { - ipn.in_p = 0; - if (dport) - ipn.in_dport = portnum(dport, NULL); - } - - (void) strncpy(ipn.in_plabel, s, sizeof(ipn.in_plabel)); - if ((s = strtok(NULL, " \t"))) { - fprintf(stderr, "too many parameters for \"proxy\"\n"); - return NULL; - } - return &ipn; - - } - if (strcasecmp(s, "portmap")) { - fprintf(stderr, "expected \"portmap\" - got \"%s\"\n", s); - return NULL; - } - if (!(s = strtok(NULL, " \t"))) - return NULL; - if (!strcasecmp(s, "tcp")) - ipn.in_flags = IPN_TCP; - else if (!strcasecmp(s, "udp")) - ipn.in_flags = IPN_UDP; - else if (!strcasecmp(s, "tcpudp")) - ipn.in_flags = IPN_TCPUDP; - else if (!strcasecmp(s, "tcp/udp")) - ipn.in_flags = IPN_TCPUDP; - else { - fprintf(stderr, "expected protocol name - got \"%s\"\n", s); - return NULL; - } - proto = s; - if (!(s = strtok(NULL, " \t"))) { - fprintf(stderr, "no port range found\n"); - return NULL; - } - if (!(t = strchr(s, ':'))) { - fprintf(stderr, "no port range in \"%s\"\n", s); - return NULL; - } - *t++ = '\0'; - ipn.in_pmin = portnum(s, proto); - ipn.in_pmax = portnum(t, proto); - return &ipn; -} - - -void parsefile(fd, file, opts) -int fd; -char *file; -int opts; -{ - char line[512], *s; - ipnat_t *np; - FILE *fp; - int linenum = 1; - - if (strcmp(file, "-")) { - if (!(fp = fopen(file, "r"))) { - (void) fprintf(stderr, "%s: open: %s\n", file, - STRERROR(errno)); - exit(1); - } - } else - fp = stdin; - - while (fgets(line, sizeof(line) - 1, fp)) { - line[sizeof(line) - 1] = '\0'; - if ((s = strchr(line, '\n'))) - *s = '\0'; - if (!(np = parse(line))) { - if (*line) - fprintf(stderr, "%d: syntax error in \"%s\"\n", - linenum, line); - } else if (!(opts & OPT_NODO)) { - if ((opts & OPT_VERBOSE) && np) - printnat(np, opts & OPT_VERBOSE, NULL); - if (opts & OPT_REM) { - if (ioctl(fd, SIOCADNAT, np) == -1) - perror("ioctl(SIOCADNAT)"); - } else if (ioctl(fd, SIOCRMNAT, np) == -1) - perror("ioctl(SIOCRMNAT)"); - } - linenum++; - } - if (fp != stdin) - fclose(fp); -} - - void flushtable(fd, opts) int fd, opts; { |