diff options
Diffstat (limited to 'sbin/ipf/libipf')
144 files changed, 11734 insertions, 0 deletions
diff --git a/sbin/ipf/libipf/Makefile b/sbin/ipf/libipf/Makefile new file mode 100644 index 000000000000..bdd56876dadd --- /dev/null +++ b/sbin/ipf/libipf/Makefile @@ -0,0 +1,47 @@ +PACKAGE= ipf +LIB= ipf +INTERNALLIB= + +SRCS= addicmp.c addipopt.c alist_free.c alist_new.c allocmbt.c \ + assigndefined.c bcopywrap.c \ + binprint.c buildopts.c checkrev.c connecttcp.c \ + count4bits.c count6bits.c \ + debug.c dupmbt.c \ + facpri.c familyname.c \ + fill6bits.c findword.c \ + flags.c freembt.c ftov.c \ + genmask.c \ + gethost.c getifname.c geticmptype.c \ + getnattype.c getport.c getportproto.c getproto.c getsumd.c \ + hostname.c icmpcode.c icmptypename.c icmptypes.c \ + initparse.c interror.c ionames.c \ + ipf_dotuning.c ipf_perror.c ipft_hx.c ipft_pc.c \ + ipft_tx.c ipoptsec.c kmem.c kmemcpywrap.c \ + kvatoname.c load_dstlist.c load_dstlistnode.c load_file.c \ + load_hash.c load_hashnode.c \ + load_http.c load_pool.c load_poolnode.c load_url.c \ + mb_hexdump.c msgdsize.c \ + mutex_emul.c nametokva.c nat_setgroupmap.c ntomask.c \ + optname.c optprint.c optprintv6.c optvalue.c parsefields.c \ + parseipfexpr.c parsewhoisline.c poolio.c portname.c \ + prependmbt.c \ + print_toif.c printactiveaddr.c printactivenat.c printaddr.c \ + printaps.c printbuf.c printdstl_live.c printdstlist.c \ + printdstlistdata.c printdstlistnode.c printdstlistpolicy.c \ + printfieldhdr.c \ + printfr.c printfraginfo.c printhash.c printhash_live.c \ + printhashdata.c printhashnode.c printhost.c printhostmap.c \ + printhostmask.c printifname.c printip.c printipfexpr.c printiphdr.c printlog.c printlookup.c \ + printmask.c printnat.c printnataddr.c printnatfield.c printnatside.c printpacket.c printpacket6.c \ + printpool.c printpool_live.c printpooldata.c printpoolfield.c printpoolnode.c \ + printportcmp.c printproto.c printsbuf.c printstate.c printstatefields.c \ + printtcpflags.c \ + printtqtable.c printtunable.c printunit.c remove_hash.c remove_hashnode.c \ + remove_pool.c remove_poolnode.c resetlexer.c rwlock_emul.c \ + save_execute.c save_file.c save_nothing.c save_syslog.c save_v1trap.c save_v2trap.c vtof.c \ + tcp_flags.c tcpflags.c tcpoptnames.c v6ionames.c v6optvalue.c \ + var.c verbose.c + +LIBADD= kvm + +.include <bsd.lib.mk> diff --git a/sbin/ipf/libipf/Makefile.depend b/sbin/ipf/libipf/Makefile.depend new file mode 100644 index 000000000000..f9d041194c3e --- /dev/null +++ b/sbin/ipf/libipf/Makefile.depend @@ -0,0 +1,14 @@ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + include \ + include/arpa \ + include/xlocale \ + lib/libkvm \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/sbin/ipf/libipf/addicmp.c b/sbin/ipf/libipf/addicmp.c new file mode 100644 index 000000000000..f84cae01644e --- /dev/null +++ b/sbin/ipf/libipf/addicmp.c @@ -0,0 +1,20 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> + +#include "ipf.h" + + +char *icmptypes[MAX_ICMPTYPE + 1] = { + "echorep", (char *)NULL, (char *)NULL, "unreach", "squench", + "redir", (char *)NULL, (char *)NULL, "echo", "routerad", + "routersol", "timex", "paramprob", "timest", "timestrep", + "inforeq", "inforep", "maskreq", "maskrep", "END" +}; diff --git a/sbin/ipf/libipf/addipopt.c b/sbin/ipf/libipf/addipopt.c new file mode 100644 index 000000000000..ab0579d00063 --- /dev/null +++ b/sbin/ipf/libipf/addipopt.c @@ -0,0 +1,61 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +int +addipopt(char *op, struct ipopt_names *io, int len, char *class) +{ + int olen = len; + struct in_addr ipadr; + u_short val; + u_char lvl; + char *s; + + if ((len + io->on_siz) > 48) { + fprintf(stderr, "options too long\n"); + return (0); + } + len += io->on_siz; + *op++ = io->on_value; + if (io->on_siz > 1) { + s = op; + *op++ = io->on_siz; + *op++ = IPOPT_MINOFF; + + if (class) { + switch (io->on_value) + { + case IPOPT_SECURITY : + lvl = seclevel(class); + *(op - 1) = lvl; + break; + case IPOPT_RR : + case IPOPT_TS : + s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; + break; + case IPOPT_LSRR : + case IPOPT_SSRR : + ipadr.s_addr = inet_addr(class); + s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4; + bcopy((char *)&ipadr, op, sizeof(ipadr)); + break; + case IPOPT_SATID : + val = atoi(class); + bcopy((char *)&val, op, 2); + break; + } + } + } + if (opts & OPT_DEBUG) + fprintf(stderr, "bo: %s %d %#x: %d\n", + io->on_name, io->on_value, io->on_bit, len); + return (len - olen); +} diff --git a/sbin/ipf/libipf/alist_free.c b/sbin/ipf/libipf/alist_free.c new file mode 100644 index 000000000000..4b2e17aba84b --- /dev/null +++ b/sbin/ipf/libipf/alist_free.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: alist_free.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ +#include "ipf.h" + +void +alist_free(alist_t *hosts) +{ + alist_t *a, *next; + + for (a = hosts; a != NULL; a = next) { + next = a->al_next; + free(a); + } +} diff --git a/sbin/ipf/libipf/alist_new.c b/sbin/ipf/libipf/alist_new.c new file mode 100644 index 000000000000..0f6a9c29940d --- /dev/null +++ b/sbin/ipf/libipf/alist_new.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: alist_new.c,v 1.5.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +alist_t * +alist_new(int family, char *host) +{ + int a, b, c, d, bits; + char *slash; + alist_t *al; + u_int mask; + + if (family == AF_UNSPEC) { + if (strchr(host, ':') != NULL) + family = AF_INET6; + else + family = AF_INET; + } + if (family != AF_INET && family != AF_INET6) + return (NULL); + + al = calloc(1, sizeof(*al)); + if (al == NULL) { + fprintf(stderr, "alist_new out of memory\n"); + return (NULL); + } + + while (ISSPACE(*host)) + host++; + + if (*host == '!') { + al->al_not = 1; + host++; + while (ISSPACE(*host)) + host++; + } + + bits = -1; + slash = strchr(host, '/'); + if (slash != NULL) { + *slash = '\0'; + bits = atoi(slash + 1); + } + + if (family == AF_INET) { + if (bits > 32) + goto bad; + + a = b = c = d = -1; + sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d); + + if (bits > 0 && bits < 33) { + mask = 0xffffffff << (32 - bits); + } else if (b == -1) { + mask = 0xff000000; + b = c = d = 0; + } else if (c == -1) { + mask = 0xffff0000; + c = d = 0; + } else if (d == -1) { + mask = 0xffffff00; + d = 0; + } else { + mask = 0xffffffff; + } + al->al_mask = htonl(mask); + } else { + if (bits > 128) + goto bad; + fill6bits(bits, al->al_i6mask.i6); + } + + if (gethost(family, host, &al->al_i6addr) == -1) { + if (slash != NULL) + *slash = '/'; + fprintf(stderr, "Cannot parse hostname\n"); + goto bad; + } + al->al_family = family; + if (slash != NULL) + *slash = '/'; + return (al); +bad: + free(al); + return (NULL); +} diff --git a/sbin/ipf/libipf/allocmbt.c b/sbin/ipf/libipf/allocmbt.c new file mode 100644 index 000000000000..87e62c23ea59 --- /dev/null +++ b/sbin/ipf/libipf/allocmbt.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: allocmbt.c,v 1.1.4.1 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +mb_t * +allocmbt(size_t len) +{ + mb_t *m; + + m = (mb_t *)malloc(sizeof(mb_t)); + if (m == NULL) + return (NULL); + m->mb_len = len; + m->mb_next = NULL; + m->mb_data = (char *)m->mb_buf; + return (m); +} diff --git a/sbin/ipf/libipf/assigndefined.c b/sbin/ipf/libipf/assigndefined.c new file mode 100644 index 000000000000..991ca70736d9 --- /dev/null +++ b/sbin/ipf/libipf/assigndefined.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: assigndefined.c,v 1.4.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void +assigndefined(char *env) +{ + char *s, *t; + + if (env == NULL) + return; + + for (s = strtok(env, ";"); s != NULL; s = strtok(NULL, ";")) { + t = strchr(s, '='); + if (t == NULL) + continue; + *t++ = '\0'; + set_variable(s, t); + *--t = '='; + } +} diff --git a/sbin/ipf/libipf/bcopywrap.c b/sbin/ipf/libipf/bcopywrap.c new file mode 100644 index 000000000000..e20462ea9b04 --- /dev/null +++ b/sbin/ipf/libipf/bcopywrap.c @@ -0,0 +1,18 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +int +bcopywrap(void *from, void *to, size_t size) +{ + bcopy((caddr_t)from, (caddr_t)to, size); + return (0); +} + diff --git a/sbin/ipf/libipf/binprint.c b/sbin/ipf/libipf/binprint.c new file mode 100644 index 000000000000..8d09b347db2c --- /dev/null +++ b/sbin/ipf/libipf/binprint.c @@ -0,0 +1,29 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +binprint(void *ptr, size_t size) +{ + u_char *s; + int i, j; + + for (i = size, j = 0, s = (u_char *)ptr; i; i--, s++) { + j++; + printf("%02x ", *s); + if (j == 16) { + printf("\n"); + j = 0; + } + } + putchar('\n'); + (void)fflush(stdout); +} diff --git a/sbin/ipf/libipf/buildopts.c b/sbin/ipf/libipf/buildopts.c new file mode 100644 index 000000000000..27eb1b7323f0 --- /dev/null +++ b/sbin/ipf/libipf/buildopts.c @@ -0,0 +1,48 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +u_32_t +buildopts(char *cp, char *op, int len) +{ + struct ipopt_names *io; + u_32_t msk = 0; + char *s, *t; + int inc; + + for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { + if ((t = strchr(s, '='))) + *t++ = '\0'; + else + t = ""; + for (io = ionames; io->on_name; io++) { + if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) + continue; + if ((inc = addipopt(op, io, len, t))) { + op += inc; + len += inc; + } + msk |= io->on_bit; + break; + } + if (!io->on_name) { + fprintf(stderr, "unknown IP option name %s\n", s); + return (0); + } + } + while ((len & 3) != 3) { + *op++ = IPOPT_NOP; + len++; + } + *op++ = IPOPT_EOL; + len++; + return (len); +} diff --git a/sbin/ipf/libipf/checkrev.c b/sbin/ipf/libipf/checkrev.c new file mode 100644 index 000000000000..ded9ce04d500 --- /dev/null +++ b/sbin/ipf/libipf/checkrev.c @@ -0,0 +1,45 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <sys/ioctl.h> +#include <fcntl.h> + +#include "ipf.h" +#include "netinet/ipl.h" + +int +checkrev(char *ipfname) +{ + static int vfd = -1; + struct friostat fio; + ipfobj_t obj; + + bzero((caddr_t)&obj, sizeof(obj)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(fio); + obj.ipfo_ptr = (void *)&fio; + obj.ipfo_type = IPFOBJ_IPFSTAT; + + if ((vfd == -1) && ((vfd = open(ipfname, O_RDONLY)) == -1)) { + perror("open device"); + return (-1); + } + + if (ioctl(vfd, SIOCGETFS, &obj)) { + ipferror(vfd, "ioctl(SIOCGETFS)"); + close(vfd); + vfd = -1; + return (-1); + } + + if (strncmp(IPL_VERSION, fio.f_version, sizeof(fio.f_version))) { + return (-1); + } + return (0); +} diff --git a/sbin/ipf/libipf/connecttcp.c b/sbin/ipf/libipf/connecttcp.c new file mode 100644 index 000000000000..7ab9d3430f58 --- /dev/null +++ b/sbin/ipf/libipf/connecttcp.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: connecttcp.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +/* + * Format expected is one address per line, at the start of each line. + */ +int +connecttcp(char *server, int port) +{ + struct sockaddr_in sin; + struct hostent *host; + int fd; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port & 65535); + + if (ISDIGIT(*server)) { + if (inet_aton(server, &sin.sin_addr) == -1) { + return (-1); + } + } else { + host = gethostbyname(server); + if (host == NULL) + return (-1); + memcpy(&sin.sin_addr, host->h_addr_list[0], + sizeof(sin.sin_addr)); + } + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + return (-1); + + if (connect(fd, (struct sockaddr *)&sin, sizeof(sin)) == -1) { + close(fd); + return (-1); + } + + return (fd); +} diff --git a/sbin/ipf/libipf/count4bits.c b/sbin/ipf/libipf/count4bits.c new file mode 100644 index 000000000000..10e9d6bb2207 --- /dev/null +++ b/sbin/ipf/libipf/count4bits.c @@ -0,0 +1,39 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +/* + * count consecutive 1's in bit mask. If the mask generated by counting +* consecutive 1's is different to that passed, return -1, else return # + * of bits. + */ +int +count4bits(u_int ip) +{ + int cnt = 0, i, j; + u_int ipn; + + ip = ipn = ntohl(ip); + for (i = 32; i; i--, ipn *= 2) + if (ipn & 0x80000000) + cnt++; + else + break; + ipn = 0; + for (i = 32, j = cnt; i; i--, j--) { + ipn *= 2; + if (j > 0) + ipn++; + } + if (ipn == ip) + return (cnt); + return (-1); +} diff --git a/sbin/ipf/libipf/count6bits.c b/sbin/ipf/libipf/count6bits.c new file mode 100644 index 000000000000..ff013046613c --- /dev/null +++ b/sbin/ipf/libipf/count6bits.c @@ -0,0 +1,28 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +int +count6bits(u_32_t *msk) +{ + int i = 0, k; + u_32_t j; + + for (k = 3; k >= 0; k--) + if (msk[k] == 0xffffffff) + i += 32; + else { + for (j = msk[k]; j; j <<= 1) + if (j & 0x80000000) + i++; + } + return (i); +} diff --git a/sbin/ipf/libipf/debug.c b/sbin/ipf/libipf/debug.c new file mode 100644 index 000000000000..9fcdf98317bd --- /dev/null +++ b/sbin/ipf/libipf/debug.c @@ -0,0 +1,42 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +# include <stdarg.h> +#include <stdio.h> + +#include "ipf.h" +#include "opts.h" + +int debuglevel = 0; + + +void +debug(int level, char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + + if ((debuglevel > 0) && (level <= debuglevel)) + vfprintf(stderr, fmt, pvar); + va_end(pvar); +} + + +void +ipfkdebug(char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + + if (opts & OPT_DEBUG) + debug(0x1fffffff, fmt, pvar); + va_end(pvar); +} diff --git a/sbin/ipf/libipf/dupmbt.c b/sbin/ipf/libipf/dupmbt.c new file mode 100644 index 000000000000..722d92e2705c --- /dev/null +++ b/sbin/ipf/libipf/dupmbt.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: dupmbt.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +mb_t * +dupmbt(mb_t *orig) +{ + mb_t *m; + + m = (mb_t *)malloc(sizeof(mb_t)); + if (m == NULL) + return (NULL); + m->mb_len = orig->mb_len; + m->mb_next = NULL; + m->mb_data = (char *)m->mb_buf + (orig->mb_data - (char *)orig->mb_buf); + bcopy(orig->mb_data, m->mb_data, m->mb_len); + return (m); +} diff --git a/sbin/ipf/libipf/facpri.c b/sbin/ipf/libipf/facpri.c new file mode 100644 index 000000000000..9325a03c8dc3 --- /dev/null +++ b/sbin/ipf/libipf/facpri.c @@ -0,0 +1,145 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <stdio.h> +#include <string.h> +#include <limits.h> +#include <sys/param.h> +#if !defined(__SVR4) && !defined(__svr4__) +#include <strings.h> +#endif +#include <stdlib.h> +#include <unistd.h> +#include <stddef.h> +#include <syslog.h> +#include "facpri.h" + + + +typedef struct table { + char *name; + int value; +} table_t; + +table_t facs[] = { + { "kern", LOG_KERN }, { "user", LOG_USER }, + { "mail", LOG_MAIL }, { "daemon", LOG_DAEMON }, + { "auth", LOG_AUTH }, { "syslog", LOG_SYSLOG }, + { "lpr", LOG_LPR }, { "news", LOG_NEWS }, + { "uucp", LOG_UUCP }, +#if LOG_CRON == LOG_CRON2 + { "cron2", LOG_CRON1 }, +#else + { "cron", LOG_CRON1 }, +#endif +#ifdef LOG_FTP + { "ftp", LOG_FTP }, +#endif +#ifdef LOG_AUTHPRIV + { "authpriv", LOG_AUTHPRIV }, +#endif +#ifdef LOG_AUDIT + { "audit", LOG_AUDIT }, +#endif +#ifdef LOG_LFMT + { "logalert", LOG_LFMT }, +#endif +#if LOG_CRON == LOG_CRON1 + { "cron", LOG_CRON2 }, +#else + { "cron2", LOG_CRON2 }, +#endif +#ifdef LOG_SECURITY + { "security", LOG_SECURITY }, +#endif + { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, + { NULL, 0 } +}; + + +/* + * map a facility number to its name + */ +char * +fac_toname(int facpri) +{ + int i, j, fac; + + fac = facpri & LOG_FACMASK; + j = fac >> 3; + if (j < nitems(facs)) { + if (facs[j].value == fac) + return (facs[j].name); + } + for (i = 0; facs[i].name; i++) + if (fac == facs[i].value) + return (facs[i].name); + + return (NULL); +} + + +/* + * map a facility name to its number + */ +int +fac_findname(char *name) +{ + int i; + + for (i = 0; facs[i].name; i++) + if (!strcmp(facs[i].name, name)) + return (facs[i].value); + return (-1); +} + + +table_t pris[] = { + { "emerg", LOG_EMERG }, { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, { "err", LOG_ERR }, + { "warn", LOG_WARNING }, { "notice", LOG_NOTICE }, + { "info", LOG_INFO }, { "debug", LOG_DEBUG }, + { NULL, 0 } +}; + + +/* + * map a facility name to its number + */ +int +pri_findname(char *name) +{ + int i; + + for (i = 0; pris[i].name; i++) + if (!strcmp(pris[i].name, name)) + return (pris[i].value); + return (-1); +} + + +/* + * map a priority number to its name + */ +char * +pri_toname(int facpri) +{ + int i, pri; + + pri = facpri & LOG_PRIMASK; + if (pris[pri].value == pri) + return (pris[pri].name); + for (i = 0; pris[i].name; i++) + if (pri == pris[i].value) + return (pris[i].name); + return (NULL); +} diff --git a/sbin/ipf/libipf/facpri.h b/sbin/ipf/libipf/facpri.h new file mode 100644 index 000000000000..dac5c591410c --- /dev/null +++ b/sbin/ipf/libipf/facpri.h @@ -0,0 +1,38 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#ifndef __FACPRI_H__ +#define __FACPRI_H__ + +#ifndef __P +# define P_DEF +# define __P(x) x +#endif + +extern char *fac_toname(int); +extern int fac_findname(char *); + +extern char *pri_toname(int); +extern int pri_findname(char *); + +#ifdef P_DEF +# undef __P +# undef P_DEF +#endif + +#if LOG_CRON == (9<<3) +# define LOG_CRON1 LOG_CRON +# define LOG_CRON2 (15<<3) +#endif +#if LOG_CRON == (15<<3) +# define LOG_CRON1 (9<<3) +# define LOG_CRON2 LOG_CRON +#endif + +#endif /* __FACPRI_H__ */ diff --git a/sbin/ipf/libipf/familyname.c b/sbin/ipf/libipf/familyname.c new file mode 100644 index 000000000000..aeb3bf74593f --- /dev/null +++ b/sbin/ipf/libipf/familyname.c @@ -0,0 +1,13 @@ +#include "ipf.h" + +const char * +familyname(int family) +{ + if (family == AF_INET) + return ("inet"); +#ifdef USE_INET6 + if (family == AF_INET6) + return ("inet6"); +#endif + return ("unknown"); +} diff --git a/sbin/ipf/libipf/fill6bits.c b/sbin/ipf/libipf/fill6bits.c new file mode 100644 index 000000000000..e9e8b7fe7099 --- /dev/null +++ b/sbin/ipf/libipf/fill6bits.c @@ -0,0 +1,46 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +fill6bits(int bits, u_int *msk) +{ + if (bits == 0) { + msk[0] = 0; + msk[1] = 0; + msk[2] = 0; + msk[3] = 0; + return; + } + + msk[0] = 0xffffffff; + msk[1] = 0xffffffff; + msk[2] = 0xffffffff; + msk[3] = 0xffffffff; + + if (bits == 128) + return; + if (bits > 96) { + msk[3] = htonl(msk[3] << (128 - bits)); + } else if (bits > 64) { + msk[3] = 0; + msk[2] = htonl(msk[2] << (96 - bits)); + } else if (bits > 32) { + msk[3] = 0; + msk[2] = 0; + msk[1] = htonl(msk[1] << (64 - bits)); + } else { + msk[3] = 0; + msk[2] = 0; + msk[1] = 0; + msk[0] = htonl(msk[0] << (32 - bits)); + } +} diff --git a/sbin/ipf/libipf/findword.c b/sbin/ipf/libipf/findword.c new file mode 100644 index 000000000000..0bb4745aed97 --- /dev/null +++ b/sbin/ipf/libipf/findword.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: findword.c,v 1.3.4.1 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + + +wordtab_t * +findword(wordtab_t *words, char *name) +{ + wordtab_t *w; + + for (w = words; w->w_word != NULL; w++) + if (!strcmp(name, w->w_word)) + break; + if (w->w_word == NULL) + return (NULL); + + return (w); +} diff --git a/sbin/ipf/libipf/flags.c b/sbin/ipf/libipf/flags.c new file mode 100644 index 000000000000..b476936e0dba --- /dev/null +++ b/sbin/ipf/libipf/flags.c @@ -0,0 +1,27 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +/* + * ECN is a new addition to TCP - RFC 2481 + */ +#ifndef TH_ECN +# define TH_ECN 0x40 +#endif +#ifndef TH_CWR +# define TH_CWR 0x80 +#endif +#ifndef TH_AE +# define TH_AE 0x100 +#endif + +char flagset[] = "FSRPAUEWe"; +uint16_t flags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, TH_ACK, TH_URG, + TH_ECN, TH_CWR, TH_AE }; diff --git a/sbin/ipf/libipf/freembt.c b/sbin/ipf/libipf/freembt.c new file mode 100644 index 000000000000..68daea842cd8 --- /dev/null +++ b/sbin/ipf/libipf/freembt.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: freembt.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void +freembt(mb_t *m) +{ + + free(m); +} diff --git a/sbin/ipf/libipf/ftov.c b/sbin/ipf/libipf/ftov.c new file mode 100644 index 000000000000..5e4aaca80c80 --- /dev/null +++ b/sbin/ipf/libipf/ftov.c @@ -0,0 +1,15 @@ +#include "ipf.h" + +int +ftov(int version) +{ +#ifdef USE_INET6 + if (version == AF_INET6) + return (6); +#endif + if (version == AF_INET) + return (4); + if (version == AF_UNSPEC) + return (0); + return (-1); +} diff --git a/sbin/ipf/libipf/gethost.c b/sbin/ipf/libipf/gethost.c new file mode 100644 index 000000000000..6ae34a577519 --- /dev/null +++ b/sbin/ipf/libipf/gethost.c @@ -0,0 +1,73 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +int +gethost(int family, char *name, i6addr_t *hostp) +{ + struct hostent *h; + struct netent *n; + u_32_t addr; + + bzero(hostp, sizeof(*hostp)); + if (!strcmp(name, "test.host.dots")) { + if (family == AF_INET) { + hostp->in4.s_addr = htonl(0xfedcba98); + } +#ifdef USE_INET6 + if (family == AF_INET6) { + hostp->i6[0] = htonl(0xfe80aa55); + hostp->i6[1] = htonl(0x12345678); + hostp->i6[2] = htonl(0x5a5aa5a5); + hostp->i6[3] = htonl(0xfedcba98); + } +#endif + return (0); + } + + if (!strcmp(name, "<thishost>")) + name = thishost; + + if (family == AF_INET) { + h = gethostbyname(name); + if (h != NULL) { + if ((h->h_addr != NULL) && + (h->h_length == sizeof(addr))) { + bcopy(h->h_addr, (char *)&addr, sizeof(addr)); + hostp->in4.s_addr = addr; + return (0); + } + } + + n = getnetbyname(name); + if (n != NULL) { + hostp->in4.s_addr = htonl(n->n_net & 0xffffffff); + return (0); + } + } +#ifdef USE_INET6 + if (family == AF_INET6) { + struct addrinfo hints, *res; + struct sockaddr_in6 *sin6; + + bzero((char *)&hints, sizeof(hints)); + hints.ai_family = PF_INET6; + + getaddrinfo(name, NULL, &hints, &res); + if (res != NULL) { + sin6 = (struct sockaddr_in6 *)res->ai_addr; + hostp->in6 = sin6->sin6_addr; + freeaddrinfo(res); + return (0); + } + } +#endif + return (-1); +} diff --git a/sbin/ipf/libipf/geticmptype.c b/sbin/ipf/libipf/geticmptype.c new file mode 100644 index 000000000000..1e406dd2ea67 --- /dev/null +++ b/sbin/ipf/libipf/geticmptype.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +int +geticmptype(int family, char *name) +{ + icmptype_t *i; + + for (i = icmptypelist; i->it_name != NULL; i++) { + if (!strcmp(name, i->it_name)) { + if (family == AF_INET) + return (i->it_v4); +#ifdef USE_INET6 + if (family == AF_INET6) + return (i->it_v6); +#endif + return (-1); + } + } + + return (-1); +} diff --git a/sbin/ipf/libipf/getifname.c b/sbin/ipf/libipf/getifname.c new file mode 100644 index 000000000000..970f2a6707bb --- /dev/null +++ b/sbin/ipf/libipf/getifname.c @@ -0,0 +1,53 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#include "kmem.h" + +/* +* Given a pointer to an interface in the kernel, return a pointer to a + * string which is the interface name. + */ +char * +getifname(struct ifnet *ptr) +{ +#if SOLARIS +# include <sys/mutex.h> +# include <sys/condvar.h> +# include "../pfil/qif.h" + char *ifname; + qif_t qif; + + if ((void *)ptr == (void *)-1) + return ("!"); + if (ptr == NULL) + return ("-"); + + if (kmemcpy((char *)&qif, (u_long)ptr, sizeof(qif)) == -1) + return ("X"); + ifname = strdup(qif.qf_name); + if ((ifname != NULL) && (*ifname == '\0')) { + free(ifname); + return ("!"); + } + return (ifname); +#else + struct ifnet netif; + + if ((void *)ptr == (void *)-1) + return ("!"); + if (ptr == NULL) + return ("-"); + + if (kmemcpy((char *)&netif, (u_long)ptr, sizeof(netif)) == -1) + return ("X"); + return (strdup(netif.if_xname)); +#endif +} diff --git a/sbin/ipf/libipf/getnattype.c b/sbin/ipf/libipf/getnattype.c new file mode 100644 index 000000000000..30bae7ce0216 --- /dev/null +++ b/sbin/ipf/libipf/getnattype.c @@ -0,0 +1,65 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ +#include "ipf.h" +#include "kmem.h" + + + +/* + * Get a nat filter type given its kernel address. + */ +char * +getnattype(nat_t *nat) +{ + static char unknownbuf[20]; + char *which; + + if (!nat) + return ("???"); + + switch (nat->nat_redir) + { + case NAT_MAP : + which = "MAP"; + break; + case NAT_MAPBLK : + which = "MAP-BLOCK"; + break; + case NAT_REDIRECT : + which = "RDR"; + break; + case NAT_MAP|NAT_REWRITE : + which = "RWR-MAP"; + break; + case NAT_REDIRECT|NAT_REWRITE : + which = "RWR-RDR"; + break; + case NAT_BIMAP : + which = "BIMAP"; + break; + case NAT_REDIRECT|NAT_DIVERTUDP : + which = "DIV-RDR"; + break; + case NAT_MAP|NAT_DIVERTUDP : + which = "DIV-MAP"; + break; + case NAT_REDIRECT|NAT_ENCAP : + which = "ENC-RDR"; + break; + case NAT_MAP|NAT_ENCAP : + which = "ENC-MAP"; + break; + default : + snprintf(unknownbuf, sizeof(unknownbuf), "unknown(%04x)", + nat->nat_redir & 0xffffffff); + which = unknownbuf; + break; + } + return (which); +} diff --git a/sbin/ipf/libipf/getport.c b/sbin/ipf/libipf/getport.c new file mode 100644 index 000000000000..8b659b2761b3 --- /dev/null +++ b/sbin/ipf/libipf/getport.c @@ -0,0 +1,87 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" +#include <ctype.h> + +int +getport(frentry_t *fr, char *name, u_short *port, char *proto) +{ + struct protoent *p; + struct servent *s; + u_short p1; + + if (fr == NULL || fr->fr_type != FR_T_IPF) { + s = getservbyname(name, proto); + if (s != NULL) { + *port = s->s_port; + return (0); + } + + if (ISDIGIT(*name)) { + int portval = atoi(name); + if (portval < 0 || portval > 65535) + return (-1); + *port = htons((u_short)portval); + return (0); + } + return (-1); + } + + /* + * Some people will use port names in rules without specifying + * either TCP or UDP because it is implied by the group head. + * If we don't know the protocol, then the best we can do here is + * to take either only the TCP or UDP mapping (if one or the other + * is missing) or make sure both of them agree. + */ + if (fr->fr_proto == 0) { + s = getservbyname(name, "tcp"); + if (s != NULL) + p1 = s->s_port; + else + p1 = 0; + s = getservbyname(name, "udp"); + if (s != NULL) { + if (p1 != s->s_port) + return (-1); + } + if ((p1 == 0) && (s == NULL)) + return (-1); + if (p1) + *port = p1; + else + *port = s->s_port; + return (0); + } + + if ((fr->fr_flx & FI_TCPUDP) != 0) { + /* + * If a rule is "tcp/udp" then check that both TCP and UDP + * mappings for this protocol name match ports. + */ + s = getservbyname(name, "tcp"); + if (s == NULL) + return (-1); + p1 = s->s_port; + s = getservbyname(name, "udp"); + if (s == NULL || s->s_port != p1) + return (-1); + *port = p1; + return (0); + } + + p = getprotobynumber(fr->fr_proto); + s = getservbyname(name, p ? p->p_name : NULL); + if (s != NULL) { + *port = s->s_port; + return (0); + } + return (-1); +} diff --git a/sbin/ipf/libipf/getportproto.c b/sbin/ipf/libipf/getportproto.c new file mode 100644 index 000000000000..637b000d8d51 --- /dev/null +++ b/sbin/ipf/libipf/getportproto.c @@ -0,0 +1,38 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> +#include "ipf.h" + +int +getportproto(char *name, int proto) +{ + struct servent *s; + struct protoent *p; + + if (ISDIGIT(*name)) { + int number; + char *s; + + for (s = name; *s != '\0'; s++) + if (!ISDIGIT(*s)) + return (-1); + + number = atoi(name); + if (number < 0 || number > 65535) + return (-1); + return (htons(number)); + } + + p = getprotobynumber(proto); + s = getservbyname(name, p ? p->p_name : NULL); + if (s != NULL) + return (s->s_port); + return (-1); +} diff --git a/sbin/ipf/libipf/getproto.c b/sbin/ipf/libipf/getproto.c new file mode 100644 index 000000000000..139bfd3ee41a --- /dev/null +++ b/sbin/ipf/libipf/getproto.c @@ -0,0 +1,34 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" +#include <ctype.h> + +int getproto(char *name); + +int +getproto(char *name) +{ + struct protoent *p; + char *s; + + for (s = name; *s != '\0'; s++) + if (!ISDIGIT(*s)) + break; + if (*s == '\0') + return (atoi(name)); + + if (!strcasecmp(name, "ip")) + return (0); + + p = getprotobyname(name); + if (p != NULL) + return (p->p_proto); + return (-1); +} diff --git a/sbin/ipf/libipf/getsumd.c b/sbin/ipf/libipf/getsumd.c new file mode 100644 index 000000000000..ede6f7ea134d --- /dev/null +++ b/sbin/ipf/libipf/getsumd.c @@ -0,0 +1,22 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +char * +getsumd(u_32_t sum) +{ + static char sumdbuf[17]; + + if (sum & NAT_HW_CKSUM) + snprintf(sumdbuf, sizeof(sumdbuf), "hw(%#0x)", sum & 0xffff); + else + snprintf(sumdbuf, sizeof(sumdbuf), "%#0x", sum); + return (sumdbuf); +} diff --git a/sbin/ipf/libipf/hostname.c b/sbin/ipf/libipf/hostname.c new file mode 100644 index 000000000000..1c3d3451b487 --- /dev/null +++ b/sbin/ipf/libipf/hostname.c @@ -0,0 +1,58 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +char * +hostname(int family, void *ip) +{ + static char hostbuf[MAXHOSTNAMELEN+1]; + struct hostent *hp; + struct in_addr ipa; + struct netent *np; + + memset(&ipa, 0, sizeof(ipa)); /* XXX gcc */ + + if (family == AF_INET) { + ipa.s_addr = *(u_32_t *)ip; + if (ipa.s_addr == htonl(0xfedcba98)) + return ("test.host.dots"); + } + + if ((opts & OPT_NORESOLVE) == 0) { + if (family == AF_INET) { + hp = gethostbyaddr(ip, 4, AF_INET); + if (hp != NULL && hp->h_name != NULL && + *hp->h_name != '\0') { + strncpy(hostbuf, hp->h_name, sizeof(hostbuf)); + hostbuf[sizeof(hostbuf) - 1] = '\0'; + return (hostbuf); + } + + np = getnetbyaddr(ipa.s_addr, AF_INET); + if (np != NULL && np->n_name != NULL && + *np->n_name != '\0') { + strncpy(hostbuf, np->n_name, sizeof(hostbuf)); + hostbuf[sizeof(hostbuf) - 1] = '\0'; + return (hostbuf); + } + } + } + + if (family == AF_INET) { + return (inet_ntoa(ipa)); + } +#ifdef USE_INET6 + (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); + hostbuf[MAXHOSTNAMELEN] = '\0'; + return (hostbuf); +#else + return ("IPv6"); +#endif +} diff --git a/sbin/ipf/libipf/icmpcode.c b/sbin/ipf/libipf/icmpcode.c new file mode 100644 index 000000000000..b7fc15451e08 --- /dev/null +++ b/sbin/ipf/libipf/icmpcode.c @@ -0,0 +1,23 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> + +#include "ipf.h" + +#ifndef MIN +# define MIN(a,b) ((a) > (b) ? (b) : (a)) +#endif + + +char *icmpcodes[MAX_ICMPCODE + 1] = { + "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail", + "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib", + "net-tos", "host-tos", "filter-prohib", "host-preced", "preced-cutoff", + NULL }; diff --git a/sbin/ipf/libipf/icmptypename.c b/sbin/ipf/libipf/icmptypename.c new file mode 100644 index 000000000000..08113853ffea --- /dev/null +++ b/sbin/ipf/libipf/icmptypename.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +char * +icmptypename(int family, int type) +{ + icmptype_t *i; + + if ((type < 0) || (type > 255)) + return (NULL); + + for (i = icmptypelist; i->it_name != NULL; i++) { + if ((family == AF_INET) && (i->it_v4 == type)) + return (i->it_name); +#ifdef USE_INET6 + if ((family == AF_INET6) && (i->it_v6 == type)) + return (i->it_name); +#endif + } + + return (NULL); +} diff --git a/sbin/ipf/libipf/icmptypes.c b/sbin/ipf/libipf/icmptypes.c new file mode 100644 index 000000000000..c1123ff5e04d --- /dev/null +++ b/sbin/ipf/libipf/icmptypes.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + +#ifndef USE_INET6 +# undef ICMP6_ECHO_REQUEST +# define ICMP6_ECHO_REQUEST 0 +# undef ICMP6_ECHO_REPLY +# define ICMP6_ECHO_REPLY 0 +# undef ICMP6_NI_QUERY +# define ICMP6_NI_QUERY 0 +# undef ICMP6_NI_REPLY +# define ICMP6_NI_REPLY 0 +# undef ICMP6_PARAM_PROB +# define ICMP6_PARAM_PROB 0 +# undef ND_ROUTER_ADVERT +# define ND_ROUTER_ADVERT 0 +# undef ND_ROUTER_SOLICIT +# define ND_ROUTER_SOLICIT 0 +# undef ICMP6_TIME_EXCEEDED +# define ICMP6_TIME_EXCEEDED 0 +# undef ICMP6_DST_UNREACH +# define ICMP6_DST_UNREACH 0 +# undef ICMP6_PACKET_TOO_BIG +# define ICMP6_PACKET_TOO_BIG 0 +# undef MLD_LISTENER_QUERY +# define MLD_LISTENER_QUERY 0 +# undef MLD_LISTENER_REPORT +# define MLD_LISTENER_REPORT 0 +# undef MLD_LISTENER_DONE +# define MLD_LISTENER_DONE 0 +# undef ICMP6_MEMBERSHIP_QUERY +# define ICMP6_MEMBERSHIP_QUERY 0 +# undef ICMP6_MEMBERSHIP_REPORT +# define ICMP6_MEMBERSHIP_REPORT 0 +# undef ICMP6_MEMBERSHIP_REDUCTION +# define ICMP6_MEMBERSHIP_REDUCTION 0 +# undef ND_NEIGHBOR_ADVERT +# define ND_NEIGHBOR_ADVERT 0 +# undef ND_NEIGHBOR_SOLICIT +# define ND_NEIGHBOR_SOLICIT 0 +# undef ICMP6_ROUTER_RENUMBERING +# define ICMP6_ROUTER_RENUMBERING 0 +# undef ICMP6_WRUREQUEST +# define ICMP6_WRUREQUEST 0 +# undef ICMP6_WRUREPLY +# define ICMP6_WRUREPLY 0 +# undef ICMP6_FQDN_QUERY +# define ICMP6_FQDN_QUERY 0 +# undef ICMP6_FQDN_REPLY +# define ICMP6_FQDN_REPLY 0 +#else +# if !defined(MLD_LISTENER_QUERY) +# define MLD_LISTENER_QUERY 130 +# endif +# if !defined(MLD_LISTENER_REPORT) +# define MLD_LISTENER_REPORT 131 +# endif +# if !defined(MLD_LISTENER_DONE) +# define MLD_LISTENER_DONE 132 +# endif +# if defined(MLD_LISTENER_REDUCTION) && !defined(MLD_LISTENER_DONE) +# define MLD_LISTENER_DONE MLD_LISTENER_REDUCTION +# endif +#endif + +icmptype_t icmptypelist[] = { + { "echo", ICMP_ECHO, ICMP6_ECHO_REQUEST }, + { "echorep", ICMP_ECHOREPLY, ICMP6_ECHO_REPLY }, + { "fqdnquery", -1, ICMP6_FQDN_QUERY }, + { "fqdnreply", -1, ICMP6_FQDN_REPLY }, + { "infoqry", -1, ICMP6_NI_QUERY }, + { "inforeq", ICMP_IREQ, ICMP6_NI_QUERY }, + { "inforep", ICMP_IREQREPLY, ICMP6_NI_REPLY }, + { "listendone", -1, MLD_LISTENER_DONE }, + { "listenqry", -1, MLD_LISTENER_QUERY }, + { "listenrep", -1, MLD_LISTENER_REPORT }, + { "maskrep", ICMP_MASKREPLY, -1 }, + { "maskreq", ICMP_MASKREQ, -1 }, + { "memberqry", -1, ICMP6_MEMBERSHIP_QUERY }, + { "memberred", -1, ICMP6_MEMBERSHIP_REDUCTION }, + { "memberreply",-1, ICMP6_MEMBERSHIP_REPORT }, + { "neighadvert", -1, ND_NEIGHBOR_ADVERT }, + { "neighborsol", -1, ND_NEIGHBOR_SOLICIT }, + { "neighborsolicit", -1, ND_NEIGHBOR_SOLICIT }, + { "paramprob", ICMP_PARAMPROB, ICMP6_PARAM_PROB }, + { "redir", ICMP_REDIRECT, ND_REDIRECT }, + { "renumber", -1, ICMP6_ROUTER_RENUMBERING }, + { "routerad", ICMP_ROUTERADVERT, ND_ROUTER_ADVERT }, + { "routeradvert",ICMP_ROUTERADVERT, ND_ROUTER_ADVERT }, + { "routersol", ICMP_ROUTERSOLICIT, ND_ROUTER_SOLICIT }, + { "routersolcit",ICMP_ROUTERSOLICIT, ND_ROUTER_SOLICIT }, + { "squench", ICMP_SOURCEQUENCH, -1 }, + { "timest", ICMP_TSTAMP, -1 }, + { "timestrep", ICMP_TSTAMPREPLY, -1 }, + { "timex", ICMP_TIMXCEED, ICMP6_TIME_EXCEEDED }, + { "toobig", -1, ICMP6_PACKET_TOO_BIG }, + { "unreach", ICMP_UNREACH, ICMP6_DST_UNREACH }, + { "whorep", -1, ICMP6_WRUREPLY }, + { "whoreq", -1, ICMP6_WRUREQUEST }, + { NULL, -1, -1 } +}; diff --git a/sbin/ipf/libipf/inet_addr.c b/sbin/ipf/libipf/inet_addr.c new file mode 100644 index 000000000000..d64b3da41361 --- /dev/null +++ b/sbin/ipf/libipf/inet_addr.c @@ -0,0 +1,196 @@ + +/* + * ++Copyright++ 1983, 1990, 1993 + * - + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * - + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + * - + * --Copyright-- + */ + + +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ctype.h> + +#ifndef __P +# define __P(x) x +#endif +int inet_aton(const char *, struct in_addr *); + +/* + * Because the ctype(3) posix definition, if used "safely" in code everywhere, + * would mean all normal code that walks through strings needed casts. Yuck. + */ +#define ISALNUM(x) isalnum((u_char)(x)) +#define ISALPHA(x) isalpha((u_char)(x)) +#define ISASCII(x) isascii((u_char)(x)) +#define ISDIGIT(x) isdigit((u_char)(x)) +#define ISPRINT(x) isprint((u_char)(x)) +#define ISSPACE(x) isspace((u_char)(x)) +#define ISUPPER(x) isupper((u_char)(x)) +#define ISXDIGIT(x) isxdigit((u_char)(x)) +#define ISLOWER(x) islower((u_char)(x)) + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. +* This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +inet_aton(register const char *cp, struct in_addr *addr) +{ + register u_long val; + register int base, n; + register char c; + u_int parts[4]; + register u_int *pp = parts; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!ISDIGIT(c)) + return (0); + val = 0; base = 10; + if (c == '0') { + c = *++cp; + if (c == 'x' || c == 'X') + base = 16, c = *++cp; + else + base = 8; + } + for (;;) { + if (ISASCII(c) && ISDIGIT(c)) { + val = (val * base) + (c - '0'); + c = *++cp; + } else if (base == 16 && ISASCII(c) && ISXDIGIT(c)) { + val = (val << 4) | + (c + 10 - (ISLOWER(c) ? 'a' : 'A')); + c = *++cp; + } else + break; + } + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp >= parts + 3) + return (0); + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!ISASCII(c) || !ISSPACE(c))) + return (0); + /* + * Concoct the address according to + * the number of parts specified. + */ + n = pp - parts + 1; + switch (n) { + + case 0: + return (0); /* initial nondigit */ + + case 1: /* a -- 32 bits */ + break; + + case 2: /* a.b -- 8.24 bits */ + if (val > 0xffffff) + return (0); + val |= parts[0] << 24; + break; + + case 3: /* a.b.c -- 8.8.16 bits */ + if (val > 0xffff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16); + break; + + case 4: /* a.b.c.d -- 8.8.8.8 bits */ + if (val > 0xff) + return (0); + val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8); + break; + } + if (addr) + addr->s_addr = htonl(val); + return (1); +} + +/* these are compatibility routines, not needed on recent BSD releases */ + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +#if 0 +inet_addr(const char *cp) +{ + struct in_addr val; + + if (inet_aton(cp, &val)) + return (val.s_addr); + return (0xffffffff); +} +#endif diff --git a/sbin/ipf/libipf/initparse.c b/sbin/ipf/libipf/initparse.c new file mode 100644 index 000000000000..2cb8906555dd --- /dev/null +++ b/sbin/ipf/libipf/initparse.c @@ -0,0 +1,19 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +char thishost[MAXHOSTNAMELEN]; + + +void initparse(void) +{ + gethostname(thishost, sizeof(thishost)); + thishost[sizeof(thishost) - 1] = '\0'; +} diff --git a/sbin/ipf/libipf/interror.c b/sbin/ipf/libipf/interror.c new file mode 100644 index 000000000000..a8dc3be2d5d1 --- /dev/null +++ b/sbin/ipf/libipf/interror.c @@ -0,0 +1,582 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: interror.c,v 1.9.2.12 2012/07/22 08:03:39 darren_r Exp $ + */ + +#include "ipf.h" +#include <fcntl.h> +#include <sys/ioctl.h> + +typedef struct { + int iee_number; + char *iee_text; +} ipf_error_entry_t; + +static ipf_error_entry_t *find_error(int); + +#define IPF_NUM_ERRORS sizeof(ipf_errors) / sizeof(ipf_error_entry_t) + +/* + * NO REUSE OF NUMBERS! + * + * IF YOU WANT TO ADD AN ERROR TO THIS TABLE, _ADD_ A NEW NUMBER. + * DO _NOT_ USE AN EMPTY NUMBER OR FILL IN A GAP. + */ +static ipf_error_entry_t ipf_errors[] = { + { 1, "auth table locked/full" }, + { 2, "" }, + { 3, "copyinptr received bad address" }, + { 4, "copyoutptr received bad address" }, + { 5, "" }, + { 6, "cannot load a rule with FR_T_BUILTIN flag set" }, + { 7, "internal rule without FR_T_BUILDINT flag set" }, + { 8, "no data provided with filter rule" }, + { 9, "invalid ioctl for rule" }, + { 10, "rule protocol is not 4 or 6" }, + { 11, "cannot find rule function" }, + { 12, "cannot find rule group" }, + { 13, "group in/out does not match rule in/out" }, + { 14, "rule without in/out does not belong to a group" }, + { 15, "cannot determine where to append rule" }, + { 16, "malloc for rule data failed" }, + { 17, "copyin for rule data failed" }, + { 18, "" }, + { 19, "zero data size for BPF rule" }, + { 20, "BPF validation failed" }, + { 21, "incorrect data size for IPF rule" }, + { 22, "'keep state' rule included 'with oow'" }, + { 23, "bad interface index with dynamic source address" }, + { 24, "bad interface index with dynamic dest. address" }, + { 25, "match array verif failed for filter rule" }, + { 26, "bad filter rule type" }, + { 27, "rule not found for zero'stats" }, + { 28, "copyout failed for zero'ing stats" }, + { 29, "rule not found for removing" }, + { 30, "cannot remove internal rule" }, + { 31, "rule in use" }, + { 32, "rule already exists" }, + { 33, "no memory for another rule" }, + { 34, "could not find function" }, + { 35, "copyout failed for resolving function name -> addr" }, + { 36, "copyout failed for resolving function addr -> name" }, + { 37, "function name/addr resolving search failed" }, + { 38, "group map cannot find it's hash table" }, + { 39, "group map hash-table in/out do not match rule" }, + { 40, "bcopyout failed for SIOCIPFINTERROR" }, + { 41, "" }, + { 42, "ipfilter not enabled for NAT ioctl" }, + { 43, "ipfilter not enabled for state ioctl" }, + { 44, "ipfilter not enabled for auth ioctl" }, + { 45, "ipfilter not enabled for sync ioctl" }, + { 46, "ipfilter not enabled for scan ioctl" }, + { 47, "ipfilter not enabled for lookup ioctl" }, + { 48, "unrecognised device minor number for ioctl" }, + { 49, "unrecognised object type for copying in ipfobj" }, + { 50, "mismatching object type for copying in ipfobj" }, + { 51, "object size too small for copying in ipfobj" }, + { 52, "object size mismatch for copying in ipfobj" }, + { 53, "compat object size too small for copying in ipfobj" }, + { 54, "compat object size mismatch for copying in ipfobj" }, + { 55, "error doing copyin of data for in ipfobj" }, + { 56, "unrecognised object type for size copy in ipfobj" }, + { 57, "object size too small for size copy in ipfobj" }, + { 58, "mismatching object type for size copy in ipfobj" }, + { 59, "object size mismatch for size copy in ipfobj" }, + { 60, "compat object size mismatch for size copy in ipfobj" }, + { 61, "error doing size copyin of data for in ipfobj" }, + { 62, "bad object type for size copy out ipfobj" }, + { 63, "mismatching object type for size copy out ipfobj" }, + { 64, "object size mismatch for size copy out ipfobj" }, + { 65, "compat object size wrong for size copy out ipfobj" }, + { 66, "error doing size copyout of data for out ipfobj" }, + { 67, "unrecognised object type for copying out ipfobj" }, + { 68, "mismatching object type for copying out ipfobj" }, + { 69, "object size too small for copying out ipfobj" }, + { 70, "object size mismatch for copying out ipfobj" }, + { 71, "compat object size too small for copying out ipfobj" }, + { 72, "compat object size mismatch for copying out ipfobj" }, + { 73, "error doing copyout of data for out ipfobj" }, + { 74, "attempt to add existing tunable name" }, + { 75, "cannot find tunable name to delete" }, + { 76, "internal data too big for next tunable" }, + { 77, "could not find tunable" }, + { 78, "tunable can only be changed when ipfilter disabled" }, + { 79, "new tunable value outside accepted range" }, + { 80, "ipftune called for unrecognised ioctl" }, + { 81, "" }, + { 82, "could not find token to delete" }, + { 83, "" }, + { 84, "attempt to get next rule when no more exist" }, + { 85, "value for iri_inout outside accepted range" }, + { 86, "value for iri_active outside accepted range" }, + { 87, "value for iri_nrules is 0" }, + { 88, "NULL pointer specified for where to copy rule to" }, + { 89, "copyout of rule failed" }, + { 90, "" }, + { 91, "could not get token for rule iteration" }, + { 92, "unrecognised generic iterator" }, + { 93, "could not find token for generic iterator" }, + { 94, "need write permissions to disable/enable ipfilter" }, + { 95, "error copying in enable/disable value" }, + { 96, "need write permissions to set ipf tunable" }, + { 97, "need write permissions to set ipf flags" }, + { 98, "error doing copyin of ipf flags" }, + { 99, "error doing copyout of ipf flags" }, + { 100, "need write permissions to add another rule" }, + { 101, "need write permissions to insert another rule" }, + { 102, "need write permissions to swap active rule set" }, + { 103, "error copying out current active rule set" }, + { 104, "need write permissions to zero ipf stats" }, + { 105, "need write permissions to flush ipf v4 rules" }, + { 106, "error copying out v4 flush results" }, + { 107, "error copying in v4 flush command" }, + { 108, "need write permissions to flush ipf v6 rules" }, + { 109, "error copying out v6 flush results" }, + { 110, "error copying in v6 flush command" }, + { 111, "error copying in new lock state for ipfilter" }, + { 112, "need write permissions to flush ipf logs" }, + { 113, "error copying out results of log flush" }, + { 114, "need write permissions to resync ipf" }, + { 115, "unrecognised ipf ioctl" }, + { 116, "error copying in match array" }, + { 117, "match array type is not IPFOBJ_IPFEXPR" }, + { 118, "bad size for match array" }, + { 119, "cannot allocate memory for match array" }, + { 120, "error copying in match array" }, + { 121, "error verifying contents of match array" }, + { 122, "need write permissions to set ipf lock status" }, + { 123, "error copying in data for function resolution" }, + { 124, "error copying in ipfobj structure" }, + { 125, "error copying in ipfobj structure" }, + { 126, "error copying in ipfobj structure" }, + { 127, "error copying in ipfobj structure" }, + { 128, "no memory for filter rule comment" }, + { 129, "error copying in filter rule comment" }, + { 130, "error copying out filter rule comment" }, + { 131, "no memory for new rule alloc buffer" }, + { 132, "cannot find source lookup pool" }, + { 133, "unknown source address type" }, + { 134, "cannot find destination lookup pool" }, + { 135, "unknown destination address type" }, + { 136, "icmp head group name index incorrect" }, + { 137, "group head name index incorrect" }, + { 138, "group name index incorrect" }, + { 139, "to interface name index incorrect" }, + { 140, "dup-to interface name index incorrect" }, + { 141, "reply-to interface name index incorrect" }, + { 142, "could not initialise call now function" }, + { 143, "could not initialise call function" }, + { 144, "could not find destination list" }, + { 145, "auth rules cannot have dup/to/fastroute" }, + { 146, "incorrect size for object to copy out" }, + { 147, "object type out of bounds for kernel copyout" }, + { 148, "object size too small for kernel copyout" }, + { 149, "object size validation failed for kernel copyout" }, + { 150, "error copying data out for kernel copyout" }, + { 151, "version mismatch for kernel copyout" }, +/* -------------------------------------------------------------------------- */ + { 10001, "could not find token for auth iterator" }, + { 10002, "write permissions require to add/remove auth rule" }, + { 10003, "need write permissions to set auth lock" }, + { 10004, "error copying out results of auth flush" }, + { 10005, "unknown auth ioctl" }, + { 10006, "can only append or remove preauth rules" }, + { 10007, "NULL pointers passed in for preauth remove" }, + { 10008, "preauth rule not found to remove" }, + { 10009, "could not malloc memory for preauth entry" }, + { 10010, "unrecognised preauth rule ioctl command" }, + { 10011, "iterator data supplied with NULL pointer" }, + { 10012, "unknown auth iterator type" }, + { 10013, "iterator error copying out auth data" }, + { 10014, "sleep waiting for auth packet interrupted" }, + { 10015, "bad index supplied in auth reply" }, + { 10016, "error injecting outbound packet back into kernel" }, + { 10017, "error injecting inbound packet back into kernel" }, + { 10018, "could not attempt to inject packet back into kernel" }, + { 10019, "packet id does not match" }, +/* -------------------------------------------------------------------------- */ + { 20001, "invalid frag token data pointer supplied" }, + { 20002, "error copying out frag token data" }, + { 20003, "can only copy one fragment state entry at a time" }, +/* -------------------------------------------------------------------------- */ + { 30001, "incorrect object size to get hash table stats" }, + { 30002, "could not malloc memory for new hash table" }, + { 30003, "error coping in hash table structure" }, + { 30004, "hash table already exists" }, + { 30005, "mismatch between new hash table and operation unit" }, + { 30006, "could not malloc memory for hash table base" }, + { 30007, "could not find hash table" }, + { 30008, "mismatch between hash table and operation unit" }, + { 30009, "could not find hash table for iterators next node" }, + { 30010, "unknown iterator tpe" }, + { 30011, "iterator error copying out hash table" }, + { 30012, "iterator error copying out hash table entry" }, + { 30013, "error copying out hash table statistics" }, + { 30014, "table node delete structure wrong size" }, + { 30015, "error copying in node to delete" }, + { 30016, "table to delete node from does not exist" }, + { 30017, "could not find table to remove node from" }, + { 30018, "table node add structure wrong size" }, + { 30019, "error copying in node to add" }, + { 30020, "could not find table to add node to" }, + { 30021, "node already exists in the table" }, + { 30022, "could not find node to delete in table" }, + { 30023, "uid mismatch on node to delete" }, + { 30024, "object size incorrect for hash table" }, + { 30025, "hash table size must be at least 1"}, + { 30026, "cannot allocate memory for hash table context" }, + { 30027, "hash table larger than maximum allowed" }, + { 30028, "hash table multiplication overflow" }, +/* -------------------------------------------------------------------------- */ + { 40001, "invalid minor device number for log read" }, + { 40002, "read size too small" }, + { 40003, "interrupted waiting for log data to read" }, + { 40004, "interrupted waiting for log data to read" }, + { 40005, "read size too large" }, + { 40006, "uiomove for read operation failed" }, +/* -------------------------------------------------------------------------- */ + { 50001, "unknown lookup ioctl" }, + { 50002, "error copying in object data for add node" }, + { 50003, "invalid unit for lookup add node" }, + { 50004, "incorrect size for adding a pool node" }, + { 50005, "error copying in pool node structure" }, + { 50006, "mismatch in pool node address/mask families" }, + { 50007, "could not find pool name" }, + { 50008, "node already exists in pool" }, + { 50009, "incorrect size for adding a hash node" }, + { 50010, "error copying in hash node structure" }, + { 50011, "could not find hash table name" }, + { 50012, "unrecognised object type for lookup add node" }, + { 50013, "invalid unit for lookup delete node" }, + { 50014, "incorrect size for deleting a pool node" }, + { 50015, "error copying in pool node structure" }, + { 50016, "could not find pool name" }, + { 50017, "could not find pool node" }, + { 50018, "incorrect size for removing a hash node" }, + { 50019, "error copying in hash node structure" }, + { 50020, "could not find hash table name" }, + { 50021, "unrecognised object type for lookup delete node" }, + { 50022, "error copying in add table data" }, + { 50023, "invalid unit for lookup add table" }, + { 50024, "pool name already exists" }, + { 50025, "hash table name already exists" }, + { 50026, "unrecognised object type for lookup add table" }, + { 50027, "error copying table data back out" }, + { 50028, "error copying in remove table data" }, + { 50029, "invalid unit for lookup remove table" }, + { 50030, "unrecognised object type for lookup remove table" }, + { 50031, "error copying in lookup stats structure" }, + { 50032, "invalid unit for lookup stats" }, + { 50033, "unrecognised object type for lookup stats" }, + { 50034, "error copying in flush lookup data" }, + { 50035, "invalid unit for lookup flush" }, + { 50036, "incorrect table type for lookup flush" }, + { 50037, "error copying out lookup flush results" }, + { 50038, "invalid unit for lookup iterator" }, + { 50039, "invalid unit for lookup iterator" }, + { 50040, "could not find token for lookup iterator" }, + { 50041, "unrecognised object type for lookup iterator" }, + { 50042, "error copying in lookup delete node operation" }, +/* -------------------------------------------------------------------------- */ + { 60001, "insufficient privilege for NAT write operation" }, + { 60002, "need write permissions to flush NAT logs" }, + { 60003, "need write permissions to turn NAT logging on/off" }, + { 60004, "error copying out current NAT log setting" }, + { 60005, "error copying out bytes waiting to be read in NAT \ +log" }, + { 60006, "need write permissions to add NAT rule" }, + { 60007, "NAT rule already exists" }, + { 60008, "could not allocate memory for NAT rule" }, + { 60009, "need write permissions to remove NAT rule" }, + { 60010, "NAT rule could not be found" }, + { 60011, "could not find NAT entry for redirect lookup" }, + { 60012, "need write permissions to flush NAT table" }, + { 60013, "error copying in NAT flush command" }, + { 60014, "need write permissions to do matching NAT flush" }, + { 60015, "need write permissions to set NAT lock" }, + { 60016, "need write permissions to add entry to NAT table" }, + { 60017, "NAT not locked for size retrieval" }, + { 60018, "NAT not locked for fetching NAT table entry" }, + { 60019, "error copying in NAT token data for deletion" }, + { 60020, "unknown NAT ioctl" }, + { 60021, "" }, + { 60022, "resolving proxy name in NAT rule failed" }, + { 60023, "only reply age specified in NAT rule" }, + { 60024, "error doing copyin to determine NAT entry size" }, + { 60025, "error copying out NAT size of 0" }, + { 60026, "NAT entry not found" }, + { 60027, "error doing copyout of NAT entry size" }, + { 60028, "invalid data size for getting NAT entry" }, + { 60029, "could not malloc temporary space for NAT entry" }, + { 60030, "no NAT table entries present" }, + { 60031, "NAT entry to get next from not found" }, + { 60032, "not enough space for proxy structure" }, + { 60033, "not enough space for private proxy data" }, + { 60034, "NAT entry size is too large" }, + { 60035, "could not malloc memory for NAT entry sratch space" }, + { 60036, "" }, + { 60037, "could not malloc memory for NAT entry" }, + { 60038, "could not malloc memory for NAT entry rule" }, + { 60039, "could not resolve NAT entry rule's proxy" }, + { 60040, "cannot add outbound duplicate NAT entry" }, + { 60041, "cannot add inbound duplicate NAT entry" }, + { 60042, "cannot add NAT entry that is neither IN nor OUT" }, + { 60043, "could not malloc memory for NAT proxy data" }, + { 60044, "proxy data size too big" }, + { 60045, "could not malloc proxy private data for NAT entry" }, + { 60046, "could not malloc memory for new NAT filter rule" }, + { 60047, "could not find existing filter rule for NAT entry" }, + { 60048, "insertion into NAT table failed" }, + { 60049, "iterator error copying out hostmap data" }, + { 60050, "iterator error copying out NAT rule data" }, + { 60051, "iterator error copying out NAT entry data" }, + { 60052, "iterator data supplied with NULL pointer" }, + { 60053, "unknown NAT iterator type" }, + { 60054, "unknown next address type" }, + { 60055, "iterator suppled with unknown type for get-next" }, + { 60056, "unknown lookup group for next address" }, + { 60057, "error copying out NAT log flush results" }, + { 60058, "bucket table type is incorrect" }, + { 60059, "error copying out NAT bucket table" }, + { 60060, "function not found for lookup" }, + { 60061, "address family not supported with SIOCSTPUT" }, + { 60062, "unknown timeout name" }, + { 60063, "cannot allocate new inbound NAT entry table" }, + { 60064, "cannot allocate new outbound NAT entry table" }, + { 60065, "cannot allocate new inbound NAT bucketlen table" }, + { 60066, "cannot allocate new outbound NAT bucketlen table" }, + { 60067, "cannot allocate new NAT rules table" }, + { 60068, "cannot allocate new NAT hostmap table" }, + { 60069, "new source lookup type is not dstlist" }, + { 60070, "cannot allocate NAT rule scratch space" }, + { 60071, "new destination lookup type is not dstlist" }, + { 60072, "function not found for lookup (ipv6)" }, + { 60073, "unknown lookup group for next address (ipv6)" }, + { 60074, "unknown next address type (ipv6)" }, + { 60075, "one object at a time must be copied" }, + { 60076, "NAT ioctl denied in jail without VNET" }, +/* -------------------------------------------------------------------------- */ + { 70001, "incorrect object size to get pool stats" }, + { 70002, "could not malloc memory for new pool node" }, + { 70003, "invalid address length for new pool node" }, + { 70004, "invalid mask length for new pool node" }, + { 70005, "error adding node to pool" }, + { 70006, "pool already exists" }, + { 70007, "could not malloc memory for new pool" }, + { 70008, "could not allocate radix tree for new pool" }, + { 70009, "could not find pool" }, + { 70010, "unknown pool name for iteration" }, + { 70011, "unknown pool iterator" }, + { 70012, "error copying out pool head" }, + { 70013, "error copying out pool node" }, + { 70014, "add node size incorrect" }, + { 70015, "error copying in pool node" }, + { 70016, "" }, + { 70017, "cannot find pool for node" }, + { 70018, "node entry already present in pool" }, + { 70019, "delete node size incorrect" }, + { 70020, "error copying in node to delete" }, + { 70021, "cannot find pool to delete node from" }, + { 70022, "cannot find node to delete in pool" }, + { 70023, "pool name already exists" }, + { 70024, "uid mismatch for node removal" }, + { 70025, "stats device unit is invalid" }, + { 70026, "error copying out statistics" }, + { 70027, "could not remove node from radix tree" }, + { 70028, "incorrect address length in pool node add" }, + { 70029, "incorrect mask length in pool node add" }, + { 70030, "incorrect address length in pool node remove" }, + { 70031, "incorrect mask length in pool node remove" }, + { 70032, "cannot allocate memory for pool context" }, + { 70033, "cannot allocate memory for radix tree context" }, + { 70034, "adding IPv6 node with incorrect address length" }, + { 70035, "IPv4 address not masked" }, + { 70036, "IPv6 address not masked" }, + { 70037, "removing IPv6 node with incorrect address length" }, +/* -------------------------------------------------------------------------- */ + { 80001, "could not find proxy" }, + { 80002, "proxy does not support control operations" }, + { 80003, "could not allocate data to hold proxy operation" }, + { 80004, "unknown proxy ioctl" }, + { 80005, "could not copyin proxy control structure" }, + { 80006, "DNS proxy could not find rule to delete" }, + { 80007, "DNS proxy found existing matching rule" }, + { 80008, "DNS proxy could not allocate memory for new rule" }, + { 80009, "DNS proxy unknown command request" }, +/* -------------------------------------------------------------------------- */ + { 90001, "could not malloc space for new scan structure" }, + { 90002, "scan tag already exists" }, + { 90003, "scan structure in use" }, + { 90004, "could not find matching scan tag for filter rule" }, + { 90005, "could not copyout scan statistics" }, +/* -------------------------------------------------------------------------- */ + { 100001, "cannot find matching state entry to remove" }, + { 100002, "error copying in v4 state flush command" }, + { 100003, "error copying out v4 state flush results" }, + { 100004, "error copying in v6 state flush command" }, + { 100005, "error copying out v6 state flush results" }, + { 100006, "" }, + { 100007, "" }, + { 100008, "need write permissions to flush state log" }, + { 100009, "error copyout results of flushing state log" }, + { 100010, "need write permissions to turn state logging on/off" }, + { 100011, "error copying in new state logging state" }, + { 100012, "error copying out current state logging state" }, + { 100013, "error copying out bytes waiting to be read in state \ +log" }, + { 100014, "need write permissions to set state lock" }, + { 100015, "need write permissions to add entry to state table" }, + { 100016, "state not locked for size retrieval" }, + { 100017, "error copying out hash table bucket lengths" }, + { 100018, "could not find token for state iterator" }, + { 100019, "error copying in state token data for deletion" }, + { 100020, "unknown state ioctl" }, + { 100021, "no state table entries present" }, + { 100022, "state entry to get next from not found" }, + { 100023, "could not malloc memory for state entry" }, + { 100024, "could not malloc memory for state entry rule" }, + { 100025, "could not copy back state entry to user space" }, + { 100026, "iterator data supplied with NULL pointer" }, + { 100027, "iterator supplied with 0 item count" }, + { 100028, "iterator type is incorrect" }, + { 100029, "invalid state token data pointer supplied" }, + { 100030, "error copying out next state entry" }, + { 100031, "unrecognised table request" }, + { 100032, "error copying out bucket length data" }, + { 100033, "could not find existing filter rule for state entry" }, + { 100034, "could not find timeout name" }, + { 100035, "could not allocate new state table" }, + { 100036, "could not allocate new state bucket length table" }, +/* -------------------------------------------------------------------------- */ + { 110001, "sync write header magic number is incorrect" }, + { 110002, "sync write header protocol is incorrect" }, + { 110003, "sync write header command is incorrect" }, + { 110004, "sync write header table number is incorrect" }, + { 110005, "data structure too small for sync write operation" }, + { 110006, "zero length data with sync write header" }, + { 110007, "insufficient data for sync write" }, + { 110008, "bad sync read size" }, + { 110009, "interrupted sync read (solaris)" }, + { 110010, "interrupted sync read (hpux)" }, + { 110011, "interrupted sync read (osf)" }, + { 110012, "interrupted sync read" }, + { 110013, "could not malloc memory for sync'd state" }, + { 110014, "could not malloc memory for sync-state list item" }, + { 110015, "sync update could not find state" }, + { 110016, "unrecognised sync state command" }, + { 110017, "could not malloc memory for new sync'd NAT entry" }, + { 110018, "could not malloc memory for sync-NAT list item" }, + { 110019, "sync update could not find NAT entry" }, + { 110020, "unrecognised sync NAT command" }, + { 110021, "ioctls are not handled with sync" }, +/* -------------------------------------------------------------------------- */ + { 120001, "null data pointer for iterator" }, + { 120002, "unit outside of acceptable range" }, + { 120003, "unknown iterator subtype" }, + { 120004, "cannot find dest. list for iteration" }, + { 120005, "error copying out destination iteration list" }, + { 120006, "error copying out destination iteration node" }, + { 120007, "wrong size for frdest_t structure" }, + { 120008, "cannot allocate memory for new destination node" }, + { 120009, "error copying in destination node to add" }, + { 120010, "could not find destination list to add node to" }, + { 120011, "error copying in destination node to remove" }, + { 120012, "could not find dest. list to remove node from" }, + { 120013, "destination list already exists" }, + { 120014, "could not allocate new destination table" }, + { 120015, "could not find destination list to remove" }, + { 120016, "destination list cannot be removed - it is busy" }, + { 120017, "error copying in names for destination" }, + { 120018, "destination name is too long/short" }, + { 120019, "unrecognised address family in destination" }, + { 120020, "" }, + { 120021, "error copying in new destination table" }, + { 120022, "cannot allocate memory for node table" }, + { 120023, "stats object size is incorrect for dest. lists" }, + { 120024, "stats device unit is invalid for dest. lists" }, + { 120025, "error copying out dest. list statistics" }, + { 120026, "cannot allocate memory for destination node" }, + { 120027, "error copying in destination node" }, + { 120028, "cannot allocate memory for destination context " }, +/* -------------------------------------------------------------------------- */ + { 130001, "ioctl denied by system security level" }, + { 130002, "ioctl operation on invalid minor device" }, + { 130003, "ioctl on device denied, ipfitler is disabled" }, + { 130004, "ioctl command not allowed when disabled" }, + { 130005, "ioctl denied due to insufficient authorisation" }, + { 130006, "cannot read while ipfilter is disabled" }, + { 130007, "read on minor device not supported" }, + { 130008, "cannot write while ipfilter is disabled" }, + { 130009, "write on minor device not supported" }, + { 130010, "poll on minor device is not supported" }, + { 130011, "error removing IPv4 filter hooks" }, + { 130012, "error removing IPv6 filter hooks" }, + { 130013, "attaching IPv4 hook failed" }, + { 130014, "attaching IPv6 hook failed" }, + { 130015, "ipf_init_all failed" }, + { 130016, "finding pfil head failed" }, + { 130017, "ipfilter is already initialised and running" }, + { 130018, "ioctl denied in jail without VNET" }, +}; + + +static ipf_error_entry_t * +find_error(int errnum) +{ + ipf_error_entry_t *ie; + + int l = -1, r = IPF_NUM_ERRORS + 1, step; + step = (r - l) / 2; + + while (step != 0) { + ie = ipf_errors + l + step; + if (ie->iee_number == errnum) + return (ie); + step = l + step; + if (ie->iee_number > errnum) + r = step; + else + l = step; + step = (r - l) / 2; + } + + return (NULL); +} + +char * +ipf_geterror(int fd, ioctlfunc_t *func) +{ + static char text[80]; + ipf_error_entry_t *ie; + int errnum; + + if ((*func)(fd, SIOCIPFINTERROR, &errnum) == 0) { + + ie = find_error(errnum); + if (ie != NULL) + return (ie->iee_text); + snprintf(text, sizeof(text), "unknown error %d", errnum); + } else { + snprintf(text, sizeof(text), "retrieving error number failed (%d)", errno); + } + return (text); +} + + +char * +ipf_strerror(int errnum) +{ + static char text[80]; + ipf_error_entry_t *ie; + + + ie = find_error(errnum); + if (ie != NULL) + return (ie->iee_text); + + snprintf(text, sizeof(text), "unknown error %d", errnum); + return (text); +} diff --git a/sbin/ipf/libipf/ionames.c b/sbin/ipf/libipf/ionames.c new file mode 100644 index 000000000000..9b2442f4e6e3 --- /dev/null +++ b/sbin/ipf/libipf/ionames.c @@ -0,0 +1,40 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +struct ipopt_names ionames[] ={ + { IPOPT_NOP, 0x000001, 1, "nop" }, /* RFC791 */ + { IPOPT_RR, 0x000002, 8, "rr" }, /* 1 route */ + { IPOPT_ZSU, 0x000004, 4, "zsu" }, /* size ?? */ + { IPOPT_MTUP, 0x000008, 4, "mtup" }, /* RFC1191 */ + { IPOPT_MTUR, 0x000010, 4, "mtur" }, /* RFC1191 */ + { IPOPT_ENCODE, 0x000020, 4, "encode" }, /* size ?? */ + { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */ + { IPOPT_TR, 0x000080, 4, "tr" }, /* RFC1393 */ + { IPOPT_SECURITY,0x000100, 12, "sec" }, /* RFC1108 */ + { IPOPT_SECURITY,0x000100, 12, "sec-class" }, /* RFC1108 */ + { IPOPT_LSRR, 0x000200, 8, "lsrr" }, /* 1 route */ + { IPOPT_E_SEC, 0x000400, 8, "e-sec" }, /* RFC1108 */ + { IPOPT_CIPSO, 0x000800, 8, "cipso" }, /* size ?? */ + { IPOPT_SATID, 0x001000, 4, "satid" }, /* RFC791 */ + { IPOPT_SSRR, 0x002000, 8, "ssrr" }, /* 1 route */ + { IPOPT_ADDEXT, 0x004000, 4, "addext" }, /* IPv7 ?? */ + { IPOPT_VISA, 0x008000, 4, "visa" }, /* size ?? */ + { IPOPT_IMITD, 0x010000, 4, "imitd" }, /* size ?? */ + { IPOPT_EIP, 0x020000, 4, "eip" }, /* RFC1385 */ + { IPOPT_FINN, 0x040000, 4, "finn" }, /* size ?? */ + { IPOPT_DPS, 0x080000, 4, "dps" }, /* size ?? */ + { IPOPT_SDB, 0x100000, 4, "sdb" }, /* size ?? */ + { IPOPT_NSAPA, 0x200000, 4, "nsapa" }, /* size ?? */ + { IPOPT_RTRALRT,0x400000, 4, "rtralrt" }, /* RFC2113 */ + { IPOPT_UMP, 0x800000, 4, "ump" }, /* size ?? */ + { IPOPT_AH, 0x1000000, 0, "ah" }, /* IPPROTO_AH */ + { 0, 0, 0, (char *)NULL } /* must be last */ +}; diff --git a/sbin/ipf/libipf/ipf_dotuning.c b/sbin/ipf/libipf/ipf_dotuning.c new file mode 100644 index 000000000000..74d5dd154aae --- /dev/null +++ b/sbin/ipf/libipf/ipf_dotuning.c @@ -0,0 +1,70 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" +#include "netinet/ipl.h" +#include <sys/ioctl.h> + +void ipf_dotuning(int fd, char *tuneargs, ioctlfunc_t iocfn) +{ + ipfobj_t obj; + ipftune_t tu; + char *s, *t; + + bzero((char *)&tu, sizeof(tu)); + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_size = sizeof(tu); + obj.ipfo_ptr = (void *)&tu; + obj.ipfo_type = IPFOBJ_TUNEABLE; + + for (s = strtok(tuneargs, ","); s != NULL; s = strtok(NULL, ",")) { + if (!strcmp(s, "list")) { + while (1) { + if ((*iocfn)(fd, SIOCIPFGETNEXT, &obj) == -1) { + ipf_perror_fd(fd, iocfn, + "ioctl(SIOCIPFGETNEXT)"); + break; + } + if (tu.ipft_cookie == NULL) + break; + + tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; + printtunable(&tu); + } + } else if ((t = strchr(s, '=')) != NULL) { + tu.ipft_cookie = NULL; + *t++ = '\0'; + strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); + if (sscanf(t, "%lu", &tu.ipft_vlong) == 1) { + if ((*iocfn)(fd, SIOCIPFSET, &obj) == -1) { + ipf_perror_fd(fd, iocfn, + "ioctl(SIOCIPFSET)"); + return; + } + } else { + fprintf(stderr, "invalid value '%s'\n", s); + return; + } + } else { + tu.ipft_cookie = NULL; + strncpy(tu.ipft_name, s, sizeof(tu.ipft_name)); + if ((*iocfn)(fd, SIOCIPFGET, &obj) == -1) { + ipf_perror_fd(fd, iocfn, "ioctl(SIOCIPFGET)"); + return; + } + if (tu.ipft_cookie == NULL) { + fprintf(stderr, "Null cookie for %s\n", s); + return; + } + + tu.ipft_name[sizeof(tu.ipft_name) - 1] = '\0'; + printtunable(&tu); + } + } +} diff --git a/sbin/ipf/libipf/ipf_perror.c b/sbin/ipf/libipf/ipf_perror.c new file mode 100644 index 000000000000..2c612afe2be3 --- /dev/null +++ b/sbin/ipf/libipf/ipf_perror.c @@ -0,0 +1,40 @@ +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" + +void +ipf_perror(int err, char *string) +{ + if (err == 0) + fprintf(stderr, "%s\n", string); + else + fprintf(stderr, "%s: %s\n", string, ipf_strerror(err)); +} + +int +ipf_perror_fd( int fd, ioctlfunc_t iocfunc, char *string) +{ + int save; + int realerr; + + save = errno; + if ((*iocfunc)(fd, SIOCIPFINTERROR, &realerr) == -1) + realerr = 0; + + errno = save; + fprintf(stderr, "%d:", realerr); + ipf_perror(realerr, string); + return (realerr ? realerr : save); + +} + +void +ipferror(int fd, char *msg) +{ + if (fd >= 0) { + ipf_perror_fd(fd, ioctl, msg); + } else { + fprintf(stderr, "0:"); + perror(msg); + } +} diff --git a/sbin/ipf/libipf/ipft_hx.c b/sbin/ipf/libipf/ipft_hx.c new file mode 100644 index 000000000000..98c0d1eb0114 --- /dev/null +++ b/sbin/ipf/libipf/ipft_hx.c @@ -0,0 +1,177 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <ctype.h> + +#include "ipf.h" +#include "ipt.h" + + +extern int opts; + +static int hex_open(char *); +static int hex_close(void); +static int hex_readip(mb_t *, char **, int *); +static char *readhex(char *, char *); + +struct ipread iphex = { hex_open, hex_close, hex_readip, 0 }; +static FILE *tfp = NULL; +static int tfd = -1; + +static int +hex_open(char *fname) +{ + if (tfp && tfd != -1) { + rewind(tfp); + return (tfd); + } + + if (!strcmp(fname, "-")) { + tfd = 0; + tfp = stdin; + } else { + tfd = open(fname, O_RDONLY); + if (tfd != -1) + tfp = fdopen(tfd, "r"); + } + return (tfd); +} + + +static int +hex_close(void) +{ + int cfd = tfd; + + tfd = -1; + return (close(cfd)); +} + + +static int +hex_readip(mb_t *mb, char **ifn, int *dir) +{ + register char *s, *t, *u; + char line[513]; + ip_t *ip; + char *buf; + + buf = (char *)mb->mb_buf; + /* + * interpret start of line as possibly "[ifname]" or + * "[in/out,ifname]". + */ + if (ifn) + *ifn = NULL; + if (dir) + *dir = 0; + ip = (ip_t *)buf; + while (fgets(line, sizeof(line)-1, tfp)) { + if ((s = strchr(line, '\n'))) { + if (s == line) { + mb->mb_len = (char *)ip - buf; + return (mb->mb_len); + } + *s = '\0'; + } + if ((s = strchr(line, '#'))) + *s = '\0'; + if (!*line) + continue; + if ((opts & OPT_DEBUG) != 0) { + printf("input: %s", line); + } + + if ((*line == '[') && (s = strchr(line, ']'))) { + t = line + 1; + if (s - t > 0) { + *s++ = '\0'; + if ((u = strchr(t, ',')) && (u < s)) { + u++; + if (ifn) + *ifn = strdup(u); + if (dir) { + if (*t == 'i') + *dir = 0; + else if (*t == 'o') + *dir = 1; + } + } else if (ifn) + *ifn = t; + } + + while (*s++ == '+') { + if (!strncasecmp(s, "mcast", 5)) { + mb->mb_flags |= M_MCAST; + s += 5; + } + if (!strncasecmp(s, "bcast", 5)) { + mb->mb_flags |= M_BCAST; + s += 5; + } + if (!strncasecmp(s, "mbcast", 6)) { + mb->mb_flags |= M_MBCAST; + s += 6; + } + } + while (ISSPACE(*s)) + s++; + } else + s = line; + t = (char *)ip; + ip = (ip_t *)readhex(s, (char *)ip); + if ((opts & OPT_DEBUG) != 0) { + if (opts & OPT_ASCII) { + int c = *t; + if (t < (char *)ip) + putchar('\t'); + while (t < (char *)ip) { + if (isprint(c) && isascii(c)) + putchar(c); + else + putchar('.'); + t++; + } + } + putchar('\n'); + fflush(stdout); + } + } + if (feof(tfp)) + return (0); + return (-1); +} + + +static char +*readhex(register char *src, register char *dst) +{ + int state = 0; + char c; + + while ((c = *src++)) { + if (ISSPACE(c)) { + if (state) { + dst++; + state = 0; + } + continue; + } else if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F')) { + c = ISDIGIT(c) ? (c - '0') : (TOUPPER(c) - 55); + if (state == 0) { + *dst = (c << 4); + state++; + } else { + *dst++ |= c; + state = 0; + } + } else + break; + } + return (dst); +} diff --git a/sbin/ipf/libipf/ipft_pc.c b/sbin/ipf/libipf/ipft_pc.c new file mode 100644 index 000000000000..ff4acd5d1753 --- /dev/null +++ b/sbin/ipf/libipf/ipft_pc.c @@ -0,0 +1,245 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" +#include "ipt.h" + + +struct llc { + int lc_type; + int lc_sz; /* LLC header length */ + int lc_to; /* LLC Type offset */ + int lc_tl; /* LLC Type length */ +}; + +/* + * While many of these maybe the same, some do have different header formats + * which make this useful. + */ + +static struct llc llcs[] = { + { 0, 0, 0, 0 }, /* DLT_NULL */ + { 1, 14, 12, 2 }, /* DLT_Ethernet */ + { 10, 0, 0, 0 }, /* DLT_FDDI */ + { 12, 0, 0, 0 }, /* DLT_RAW */ + { -1, -1, -1, -1 } +}; + +typedef struct { + u_int id; + u_short major; + u_short minor; + u_int timezone; + u_int sigfigs; + u_int snaplen; + u_int type; +} fileheader_t; + +typedef struct { + u_32_t seconds; + u_32_t microseconds; + u_32_t caplen; + u_32_t wirelen; +} packetheader_t; + +static int ipcap_open(char *); +static int ipcap_close(void); +static int ipcap_readip(mb_t *, char **, int *); +static int ipcap_read_rec(packetheader_t *); +static void iswap_hdr(fileheader_t *); + +static int pfd = -1, swapped = 0; +static struct llc *llcp = NULL; + +struct ipread pcap = { ipcap_open, ipcap_close, ipcap_readip, 0 }; + +#define SWAPLONG(y) \ + ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ + ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) + +static void +iswap_hdr(fileheader_t *p) +{ + p->major = SWAPSHORT(p->major); + p->minor = SWAPSHORT(p->minor); + p->timezone = SWAPLONG(p->timezone); + p->sigfigs = SWAPLONG(p->sigfigs); + p->snaplen = SWAPLONG(p->snaplen); + p->type = SWAPLONG(p->type); +} + +static int +ipcap_open(char *fname) +{ + fileheader_t ph; + int fd, i; + + if (pfd != -1) + return (pfd); + + if (!strcmp(fname, "-")) + fd = 0; + else if ((fd = open(fname, O_RDONLY)) == -1) + return (-1); + + if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) + return (-2); + + if (ph.id != 0xa1b2c3d4) { + if (SWAPLONG(ph.id) != 0xa1b2c3d4) { + (void) close(fd); + return (-2); + } + swapped = 1; + iswap_hdr(&ph); + } + + for (i = 0; llcs[i].lc_type != -1; i++) + if (llcs[i].lc_type == ph.type) { + llcp = llcs + i; + break; + } + + if (llcp == NULL) { + (void) close(fd); + return (-2); + } + + pfd = fd; + printf("opened pcap file %s:\n", fname); + printf("\tid: %08x version: %d.%d type: %d snap %d\n", + ph.id, ph.major, ph.minor, ph.type, ph.snaplen); + + return (fd); +} + + +static int +ipcap_close(void) +{ + return (close(pfd)); +} + + +/* + * read in the header (and validate) which should be the first record + * in a pcap file. + */ +static int +ipcap_read_rec(packetheader_t *rec) +{ + int n, p, i; + + n = sizeof(*rec); + + while (n > 0) { + i = read(pfd, (char *)rec, sizeof(*rec)); + if (i <= 0) + return (-2); + n -= i; + } + + if (swapped) { + rec->caplen = SWAPLONG(rec->caplen); + rec->wirelen = SWAPLONG(rec->wirelen); + rec->seconds = SWAPLONG(rec->seconds); + rec->microseconds = SWAPLONG(rec->microseconds); + } + p = rec->caplen; + n = MIN(p, rec->wirelen); + if (!n || n < 0) + return (-3); + + if (p < 0 || p > 65536) + return (-4); + return (p); +} + + +#ifdef notyet +/* + * read an entire pcap packet record. only the data part is copied into + * the available buffer, with the number of bytes copied returned. + */ +static int +ipcap_read(char *buf, int cnt) +{ + packetheader_t rec; + static char *bufp = NULL; + int i, n; + + if ((i = ipcap_read_rec(&rec)) <= 0) + return (i); + + if (!bufp) + bufp = malloc(i); + else + bufp = realloc(bufp, i); + + if (read(pfd, bufp, i) != i) + return (-2); + + n = MIN(i, cnt); + bcopy(bufp, buf, n); + return (n); +} +#endif + + +/* +* return only an IP packet read into buf + */ +static int +ipcap_readip(mb_t *mb, char **ifn, int *dir) +{ + static char *bufp = NULL; + packetheader_t rec; + struct llc *l; + char *s, ty[4]; + int i, j, n; + char *buf; + int cnt; + +#if 0 + ifn = ifn; /* gcc -Wextra */ + dir = dir; /* gcc -Wextra */ +#endif + buf = (char *)mb->mb_buf; + cnt = sizeof(mb->mb_buf); + l = llcp; + + /* do { */ + if ((i = ipcap_read_rec(&rec)) <= 0) + return (i); + + if (!bufp) + bufp = malloc(i); + else + bufp = realloc(bufp, i); + s = bufp; + + for (j = i, n = 0; j > 0; ) { + n = read(pfd, s, j); + if (n <= 0) + return (-2); + j -= n; + s += n; + } + s = bufp; + + i -= l->lc_sz; + s += l->lc_to; + bcopy(s, ty, l->lc_tl); + s += l->lc_tl; + /* } while (ty[0] != 0x8 && ty[1] != 0); */ + n = MIN(i, cnt); + bcopy(s, buf, n); + mb->mb_len = n; + return (n); +} diff --git a/sbin/ipf/libipf/ipft_tx.c b/sbin/ipf/libipf/ipft_tx.c new file mode 100644 index 000000000000..1e23f06be3fd --- /dev/null +++ b/sbin/ipf/libipf/ipft_tx.c @@ -0,0 +1,497 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> + +#include "ipf.h" +#include "ipt.h" + +extern int opts; + +static char *tx_proto = ""; + +static int text_open(char *), text_close(void); +static int text_readip(mb_t *, char **, int *); +static int parseline(char *, ip_t *, char **, int *); + +static char myflagset[] = "FSRPAUEWe"; +static uint16_t myflags[] = { TH_FIN, TH_SYN, TH_RST, TH_PUSH, + TH_ACK, TH_URG, TH_ECN, TH_CWR, TH_AE }; + +struct ipread iptext = { text_open, text_close, text_readip, R_DO_CKSUM }; +static FILE *tfp = NULL; +static int tfd = -1; + +static u_32_t tx_hostnum(char *, int *); +static u_short tx_portnum(char *); + +#ifdef USE_INET6 +int parseipv6(char **, ip6_t *, char **, int *); +#endif + +/* + * returns an ip address as a long var as a result of either a DNS lookup or + * straight inet_addr() call + */ +static u_32_t +tx_hostnum(char *host, int *resolved) +{ + i6addr_t ipa; + + *resolved = 0; + if (!strcasecmp("any", host)) + return (0L); + if (ISDIGIT(*host)) + return (inet_addr(host)); + + if (gethost(AF_INET, host, &ipa) == -1) { + *resolved = -1; + fprintf(stderr, "can't resolve hostname: %s\n", host); + return (0); + } + return (ipa.in4.s_addr); +} + + +/* + * find the port number given by the name, either from getservbyname() or + * straight atoi() + */ +static u_short +tx_portnum(char *name) +{ + struct servent *sp; + + if (ISDIGIT(*name)) + return (u_short)atoi(name); + sp = getservbyname(name, tx_proto); + if (sp) + return (ntohs(sp->s_port)); + (void) fprintf(stderr, "unknown service \"%s\".\n", name); + return (0); +} + + +static int +text_open(char *fname) +{ + if (tfp && tfd != -1) { + rewind(tfp); + return (tfd); + } + + if (!strcmp(fname, "-")) { + tfd = 0; + tfp = stdin; + } else { + tfd = open(fname, O_RDONLY); + if (tfd != -1) + tfp = fdopen(tfd, "r"); + } + return (tfd); +} + + +static int +text_close(void) +{ + int cfd = tfd; + + tfd = -1; + return (close(cfd)); +} + + +static int +text_readip(mb_t *mb, char **ifn, int *dir) +{ + register char *s; + char line[513]; + ip_t *ip; + char *buf; + + buf = (char *)mb->mb_buf; + + *ifn = NULL; + while (fgets(line, sizeof(line)-1, tfp)) { + if ((s = strchr(line, '\n'))) + *s = '\0'; + if ((s = strchr(line, '\r'))) + *s = '\0'; + if ((s = strchr(line, '#'))) + *s = '\0'; + if (!*line) + continue; + if ((opts & OPT_DEBUG) != 0) + printf("input: %s\n", line); + *ifn = NULL; + *dir = 0; + if (!parseline(line, (ip_t *)buf, ifn, dir)) { + ip = (ip_t *)buf; + if (IP_V(ip) == 6) { +#ifdef USE_INET6 + mb->mb_len = ntohs(((ip6_t *)ip)->ip6_plen) + + sizeof(ip6_t); +#else + mb->mb_len = 0; +#endif + } else { + mb->mb_len = ntohs(ip->ip_len); + } + return (mb->mb_len); + } + } + if (feof(tfp)) + return (0); + return (-1); +} + +static int +parseline(char *line, ip_t *ip, char **ifn, int *out) +{ + tcphdr_t th, *tcp = &th; + struct icmp icmp, *ic = &icmp; + char *cps[20], **cpp, c, ipopts[68]; + int i, r; + + if (*ifn) + free(*ifn); + bzero((char *)ip, MAX(sizeof(*tcp), sizeof(*ic)) + sizeof(*ip)); + bzero((char *)tcp, sizeof(*tcp)); + bzero((char *)ic, sizeof(*ic)); + bzero(ipopts, sizeof(ipopts)); + IP_HL_A(ip, sizeof(*ip) >> 2); + IP_V_A(ip, IPVERSION); + ip->ip_ttl = 63; + for (i = 0, cps[0] = strtok(line, " \b\t\r\n"); cps[i] && i < 19; ) + cps[++i] = strtok(NULL, " \b\t\r\n"); + + cpp = cps; + if (!*cpp) + return (1); + + c = **cpp; + if (!ISALPHA(c) || (TOLOWER(c) != 'o' && TOLOWER(c) != 'i')) { + fprintf(stderr, "bad direction \"%s\"\n", *cpp); + return (1); + } + +#ifdef USE_INET6 + if (!strcasecmp(*cpp, "out6") || !strcasecmp(*cpp, "in6")) { + return (parseipv6(cpp, (ip6_t *)ip, ifn, out)); + } +#endif + + *out = (TOLOWER(c) == 'o') ? 1 : 0; + cpp++; + if (!*cpp) + return (1); + + if (!strcasecmp(*cpp, "on")) { + cpp++; + if (!*cpp) + return (1); + *ifn = strdup(*cpp++); + if (!*cpp) + return (1); + } + + c = **cpp; + ip->ip_len = sizeof(ip_t); + if (!strcasecmp(*cpp, "tcp") || !strcasecmp(*cpp, "udp") || + !strcasecmp(*cpp, "icmp")) { + if (c == 't') { + ip->ip_p = IPPROTO_TCP; + ip->ip_len += sizeof(struct tcphdr); + tx_proto = "tcp"; + } else if (c == 'u') { + ip->ip_p = IPPROTO_UDP; + ip->ip_len += sizeof(struct udphdr); + tx_proto = "udp"; + } else { + ip->ip_p = IPPROTO_ICMP; + ip->ip_len += ICMPERR_IPICMPHLEN; + tx_proto = "icmp"; + } + cpp++; + } else if (ISDIGIT(**cpp) && !index(*cpp, '.')) { + ip->ip_p = atoi(*cpp); + cpp++; + } else + ip->ip_p = IPPROTO_IP; + + if (!*cpp) + return (1); + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no source port\n"); + return (1); + } + *last++ = '\0'; + tcp->th_sport = htons(tx_portnum(last)); + if (ip->ip_p == IPPROTO_TCP) { + tcp->th_win = htons(4096); + TCP_OFF_A(tcp, sizeof(*tcp) >> 2); + } + } + ip->ip_src.s_addr = tx_hostnum(*cpp, &r); + cpp++; + if (!*cpp) + return (1); + + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no destination port\n"); + return (1); + } + *last++ = '\0'; + tcp->th_dport = htons(tx_portnum(last)); + } + ip->ip_dst.s_addr = tx_hostnum(*cpp, &r); + cpp++; + if (ip->ip_p == IPPROTO_TCP) { + if (*cpp != NULL) { + char *s, *t; + + __tcp_set_flags(tcp, 0); + for (s = *cpp; *s; s++) + if ((t = strchr(myflagset, *s))) + __tcp_set_flags(tcp, __tcp_get_flags(tcp) | + myflags[t-myflagset]); + if (__tcp_get_flags(tcp)) + cpp++; + } + + if (__tcp_get_flags(tcp) & TH_URG) + tcp->th_urp = htons(1); + + if (*cpp && !strncasecmp(*cpp, "seq=", 4)) { + tcp->th_seq = htonl(atoi(*cpp + 4)); + cpp++; + } + + if (*cpp && !strncasecmp(*cpp, "ack=", 4)) { + tcp->th_ack = htonl(atoi(*cpp + 4)); + cpp++; + } + } else if (*cpp && ip->ip_p == IPPROTO_ICMP) { + char *t; + + t = strchr(*cpp, ','); + if (t != NULL) + *t = '\0'; + + ic->icmp_type = geticmptype(AF_INET, *cpp); + if (t != NULL) + ic->icmp_code = atoi(t + 1); + cpp++; + + if (ic->icmp_type == ICMP_ECHO || + ic->icmp_type == ICMP_ECHOREPLY) + ic->icmp_id = htons(getpid()); + if (t != NULL) + *t = ','; + } + + if (*cpp && !strcasecmp(*cpp, "opt")) { + u_long olen; + + cpp++; + olen = buildopts(*cpp, ipopts, (IP_HL(ip) - 5) << 2); + if (olen) { + bcopy(ipopts, (char *)(ip + 1), olen); + IP_HL_A(ip, IP_HL(ip) + (olen >> 2)); + ip->ip_len += olen; + } + } + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) + bcopy((char *)tcp, ((char *)ip) + (IP_HL(ip) << 2), + sizeof(*tcp)); + else if (ip->ip_p == IPPROTO_ICMP) + bcopy((char *)ic, ((char *)ip) + (IP_HL(ip) << 2), + sizeof(*ic)); + ip->ip_len = htons(ip->ip_len); + return (0); +} + + +#ifdef USE_INET6 +int +parseipv6(char **cpp, ip6_t *ip6, char **ifn, int *out) +{ + tcphdr_t th, *tcp = &th; + struct icmp6_hdr icmp, *ic6 = &icmp; + + bzero((char *)ip6, MAX(sizeof(*tcp), sizeof(*ic6)) + sizeof(*ip6)); + bzero((char *)tcp, sizeof(*tcp)); + bzero((char *)ic6, sizeof(*ic6)); + ip6->ip6_vfc = 0x60; + + *out = (**cpp == 'o') ? 1 : 0; + cpp++; + if (!*cpp) + return (1); + + if (!strcasecmp(*cpp, "on")) { + cpp++; + if (!*cpp) + return (1); + *ifn = strdup(*cpp++); + if (!*cpp) + return (1); + } + + if (!strcasecmp(*cpp, "tcp")) { + ip6->ip6_nxt = IPPROTO_TCP; + tx_proto = "tcp"; + cpp++; + } else if (!strcasecmp(*cpp, "udp")) { + ip6->ip6_nxt = IPPROTO_UDP; + tx_proto = "udp"; + cpp++; + } else if (!strcasecmp(*cpp, "icmpv6")) { + ip6->ip6_nxt = IPPROTO_ICMPV6; + tx_proto = "icmpv6"; + cpp++; + } else if (ISDIGIT(**cpp) && !index(*cpp, ':')) { + ip6->ip6_nxt = atoi(*cpp); + cpp++; + } else + ip6->ip6_nxt = IPPROTO_IPV6; + + if (!*cpp) + return (1); + + switch (ip6->ip6_nxt) + { + case IPPROTO_TCP : + ip6->ip6_plen = sizeof(struct tcphdr); + break; + case IPPROTO_UDP : + ip6->ip6_plen = sizeof(struct udphdr); + break; + case IPPROTO_ICMPV6 : + ip6->ip6_plen = ICMP6ERR_IPICMPHLEN; + break; + default : + break; + } + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no source port\n"); + return (1); + } + *last++ = '\0'; + tcp->th_sport = htons(tx_portnum(last)); + if (ip6->ip6_nxt == IPPROTO_TCP) { + tcp->th_win = htons(4096); + TCP_OFF_A(tcp, sizeof(*tcp) >> 2); + } + } + + if (inet_pton(AF_INET6, *cpp, &ip6->ip6_src) != 1) { + fprintf(stderr, "cannot parse source address '%s'\n", *cpp); + return (1); + } + + cpp++; + if (!*cpp) + return (1); + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + char *last; + + last = strchr(*cpp, ','); + if (!last) { + fprintf(stderr, "tcp/udp with no destination port\n"); + return (1); + } + *last++ = '\0'; + tcp->th_dport = htons(tx_portnum(last)); + } + + if (inet_pton(AF_INET6, *cpp, &ip6->ip6_dst) != 1) { + fprintf(stderr, "cannot parse destination address '%s'\n", + *cpp); + return (1); + } + + cpp++; + if (ip6->ip6_nxt == IPPROTO_TCP) { + if (*cpp != NULL) { + char *s, *t; + + __tcp_set_flags(tcp, 0); + for (s = *cpp; *s; s++) + if ((t = strchr(myflagset, *s))) + __tcp_set_flags(tcp, __tcp_get_flags(tcp) | + myflags[t-myflagset]); + if (__tcp_get_flags(tcp)) + cpp++; + } + + if (__tcp_get_flags(tcp) & TH_URG) + tcp->th_urp = htons(1); + + if (*cpp && !strncasecmp(*cpp, "seq=", 4)) { + tcp->th_seq = htonl(atoi(*cpp + 4)); + cpp++; + } + + if (*cpp && !strncasecmp(*cpp, "ack=", 4)) { + tcp->th_ack = htonl(atoi(*cpp + 4)); + cpp++; + } + } else if (*cpp && ip6->ip6_nxt == IPPROTO_ICMPV6) { + char *t; + + t = strchr(*cpp, ','); + if (t != NULL) + *t = '\0'; + + ic6->icmp6_type = geticmptype(AF_INET6, *cpp); + if (t != NULL) + ic6->icmp6_code = atoi(t + 1); + + if (ic6->icmp6_type == ICMP6_ECHO_REQUEST || + ic6->icmp6_type == ICMP6_ECHO_REPLY) + ic6->icmp6_id = htons(getpid()); + + if (t != NULL) + *t = ','; + } + + if (ip6->ip6_nxt == IPPROTO_TCP || ip6->ip6_nxt == IPPROTO_UDP) { + bcopy((char *)tcp, (char *)ip6 + sizeof(*ip6), + sizeof(*tcp)); + } else if (ip6->ip6_nxt == IPPROTO_ICMPV6) { + bcopy((char *)ic6, (char *)ip6 + sizeof(*ip6), + sizeof(*ic6)); + } + + /* + * Because a length of 0 == jumbo gram... + */ + if (ip6->ip6_plen == 0) { + ip6->ip6_plen++; + } + ip6->ip6_plen = htons(ip6->ip6_plen); + return (0); +} +#endif diff --git a/sbin/ipf/libipf/ipoptsec.c b/sbin/ipf/libipf/ipoptsec.c new file mode 100644 index 000000000000..fad2a564371e --- /dev/null +++ b/sbin/ipf/libipf/ipoptsec.c @@ -0,0 +1,60 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +struct ipopt_names secclass[] = { + { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" }, + { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" }, + { IPSO_CLASS_SECR, 0x04, 0, "secret" }, + { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" }, + { IPSO_CLASS_CONF, 0x10, 0, "confid" }, + { IPSO_CLASS_UNCL, 0x20, 0, "unclass" }, + { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" }, + { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" }, + { 0, 0, 0, NULL } /* must be last */ +}; + + +u_char +seclevel(char *slevel) +{ + struct ipopt_names *so; + + if (slevel == NULL || *slevel == '\0') + return (0); + + for (so = secclass; so->on_name; so++) + if (!strcasecmp(slevel, so->on_name)) + break; + + if (!so->on_name) { + fprintf(stderr, "no such security level: '%s'\n", slevel); + return (0); + } + return (u_char)so->on_value; +} + + +u_char +secbit(int class) +{ + struct ipopt_names *so; + + for (so = secclass; so->on_name; so++) + if (so->on_value == class) + break; + + if (!so->on_name) { + fprintf(stderr, "no such security class: %d.\n", class); + return (0); + } + return (u_char)so->on_bit; +} diff --git a/sbin/ipf/libipf/kmem.c b/sbin/ipf/libipf/kmem.c new file mode 100644 index 000000000000..6ebd0dee6b72 --- /dev/null +++ b/sbin/ipf/libipf/kmem.c @@ -0,0 +1,109 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ +/* + * kmemcpy() - copies n bytes from kernel memory into user buffer. + * returns 0 on success, -1 on error. + */ + +#include <stdio.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/file.h> +#include <kvm.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netinet/in_systm.h> +#include <netinet/ip.h> +#include <net/if.h> + +#include "kmem.h" + + + + +static kvm_t *kvm_f = NULL; + + +int +openkmem(char *kern, char *core) +{ + kvm_f = kvm_open(kern, core, NULL, O_RDONLY, NULL); + if (kvm_f == NULL) + { + perror("openkmem:open"); + return (-1); + } + return (kvm_f != NULL); +} + +int +kmemcpy(register char *buf, long pos, register int n) +{ + register int r; + + if (!n) + return (0); + + if (kvm_f == NULL) + if (openkmem(NULL, NULL) == -1) + return (-1); + + while ((r = kvm_read(kvm_f, pos, buf, n)) < n) + if (r <= 0) + { + fprintf(stderr, "pos=0x%lx ", (u_long)pos); + perror("kmemcpy:read"); + return (-1); + } + else + { + buf += r; + pos += r; + n -= r; + } + return (0); +} + +int +kstrncpy(register char *buf, long pos, register int n) +{ + register int r; + + if (!n) + return (0); + + if (kvm_f == NULL) + if (openkmem(NULL, NULL) == -1) + return (-1); + + while (n > 0) + { + r = kvm_read(kvm_f, pos, buf, 1); + if (r <= 0) + { + fprintf(stderr, "pos=0x%lx ", (u_long)pos); + perror("kmemcpy:read"); + return (-1); + } + else + { + if (*buf == '\0') + break; + buf++; + pos++; + n--; + } + } + return (0); +} diff --git a/sbin/ipf/libipf/kmem.h b/sbin/ipf/libipf/kmem.h new file mode 100644 index 000000000000..623d5760c614 --- /dev/null +++ b/sbin/ipf/libipf/kmem.h @@ -0,0 +1,29 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * $Id$ + */ + +#ifndef __KMEM_H__ +#define __KMEM_H__ + +#ifndef __P +# define __P(x) x +#endif +extern int openkmem(char *, char *); +extern int kmemcpy(char *, long, int); +extern int kstrncpy(char *, long, int); + +#if defined(__NetBSD__) +# include <paths.h> +#endif + +#ifdef _PATH_KMEM +# define KMEM _PATH_KMEM +#else +# define KMEM "/dev/kmem" +#endif + +#endif /* __KMEM_H__ */ diff --git a/sbin/ipf/libipf/kmemcpywrap.c b/sbin/ipf/libipf/kmemcpywrap.c new file mode 100644 index 000000000000..43f8833be72d --- /dev/null +++ b/sbin/ipf/libipf/kmemcpywrap.c @@ -0,0 +1,21 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" +#include "kmem.h" + +int +kmemcpywrap(void *from, void *to, size_t size) +{ + int ret; + + ret = kmemcpy((caddr_t)to, (u_long)from, size); + return (ret); +} + diff --git a/sbin/ipf/libipf/kvatoname.c b/sbin/ipf/libipf/kvatoname.c new file mode 100644 index 000000000000..1e53cd9c2cd5 --- /dev/null +++ b/sbin/ipf/libipf/kvatoname.c @@ -0,0 +1,37 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#include <fcntl.h> +#include <sys/ioctl.h> + +char * +kvatoname(ipfunc_t func, ioctlfunc_t iocfunc) +{ + static char funcname[40]; + ipfunc_resolve_t res; + int fd; + + res.ipfu_addr = func; + res.ipfu_name[0] = '\0'; + fd = -1; + + if ((opts & OPT_DONTOPEN) == 0) { + fd = open(IPL_NAME, O_RDONLY); + if (fd == -1) + return (NULL); + } + (void) (*iocfunc)(fd, SIOCFUNCL, &res); + if (fd >= 0) + close(fd); + strncpy(funcname, res.ipfu_name, sizeof(funcname)); + funcname[sizeof(funcname) - 1] = '\0'; + return (funcname); +} diff --git a/sbin/ipf/libipf/load_dstlist.c b/sbin/ipf/libipf/load_dstlist.c new file mode 100644 index 000000000000..4f5167cc40eb --- /dev/null +++ b/sbin/ipf/libipf/load_dstlist.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_dstlist.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_dstlist.h" + + +int +load_dstlist(ippool_dst_t *dst, ioctlfunc_t iocfunc, ipf_dstnode_t *nodes) +{ + iplookupop_t op; + ipf_dstnode_t *a; + ippool_dst_t dest; + + if (dst->ipld_name[0] == '\0') + return (-1); + + if (pool_open() == -1) + return (-1); + + op.iplo_unit = dst->ipld_unit; + op.iplo_type = IPLT_DSTLIST; + op.iplo_arg = 0; + strncpy(op.iplo_name, dst->ipld_name, sizeof(op.iplo_name)); + op.iplo_size = sizeof(dest); + op.iplo_struct = &dest; + bzero((char *)&dest, sizeof(dest)); + dest.ipld_unit = dst->ipld_unit; + dest.ipld_policy = dst->ipld_policy; + dest.ipld_flags = dst->ipld_flags; + strncpy(dest.ipld_name, dst->ipld_name, sizeof(dest.ipld_name)); + + if ((opts & OPT_REMOVE) == 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "add destination list table")); + } + } + + if ((opts & OPT_VERBOSE) != 0) { + dest.ipld_dests = dst->ipld_dests; + printdstlist(&dest, bcopywrap, dest.ipld_name, opts, nodes, NULL); + dest.ipld_dests = NULL; + } + + for (a = nodes; a != NULL; a = a->ipfd_next) + load_dstlistnode(dst->ipld_unit, dest.ipld_name, a, iocfunc); + + if ((opts & OPT_REMOVE) != 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "delete destination list table")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/load_dstlistnode.c b/sbin/ipf/libipf/load_dstlistnode.c new file mode 100644 index 000000000000..d2516eb64e2d --- /dev/null +++ b/sbin/ipf/libipf/load_dstlistnode.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_dstlistnode.c,v 1.1.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + + +int +load_dstlistnode(int role, char *name, ipf_dstnode_t *node, + ioctlfunc_t iocfunc) +{ + iplookupop_t op; + frdest_t *dst; + char *what; + int err; + + if (pool_open() == -1) + return (-1); + + dst = calloc(1, sizeof(*dst) + node->ipfd_dest.fd_name); + if (dst == NULL) + return (-1); + + op.iplo_unit = role; + op.iplo_type = IPLT_DSTLIST; + op.iplo_arg = 0; + op.iplo_struct = dst; + op.iplo_size = sizeof(*dst); + if (node->ipfd_dest.fd_name >= 0) + op.iplo_size += node->ipfd_dest.fd_name; + (void) strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + + dst->fd_addr = node->ipfd_dest.fd_addr; + dst->fd_type = node->ipfd_dest.fd_type; + dst->fd_name = node->ipfd_dest.fd_name; + if (node->ipfd_dest.fd_name >= 0) + bcopy(node->ipfd_names, (char *)dst + sizeof(*dst), + node->ipfd_dest.fd_name); + + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } + free(dst); + + if (err != 0) { + if ((opts & OPT_DONOTHING) == 0) { + char msg[80]; + + (void) snprintf(msg, sizeof(msg), "%s lookup node", what); + return (ipf_perror_fd(pool_fd(), iocfunc, msg)); + } + } + + return (0); +} diff --git a/sbin/ipf/libipf/load_file.c b/sbin/ipf/libipf/load_file.c new file mode 100644 index 000000000000..6ff05c1a61fd --- /dev/null +++ b/sbin/ipf/libipf/load_file.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_file.c,v 1.6.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +alist_t * +load_file(char *filename) +{ + alist_t *a, *rtop, *rbot; + char *s, line[1024], *t; + int linenum, not; + FILE *fp; + + fp = fopen(filename + 7, "r"); + if (fp == NULL) { + fprintf(stderr, "load_file cannot open '%s'\n", filename); + return (NULL); + } + + a = NULL; + rtop = NULL; + rbot = NULL; + linenum = 0; + + while (fgets(line, sizeof(line) - 1, fp)) { + line[sizeof(line) - 1] = '\0'; + linenum++; + /* + * Hunt for CR/LF. If no LF, stop processing. + */ + s = strchr(line, '\n'); + if (s == NULL) { + fprintf(stderr, "%d:%s: line too long\n", + linenum, filename); + fclose(fp); + alist_free(rtop); + return (NULL); + } + + /* + * Remove trailing spaces + */ + for (; ISSPACE(*s); s--) + *s = '\0'; + + s = strchr(line, '\r'); + if (s != NULL) + *s = '\0'; + for (t = line; ISSPACE(*t); t++) + ; + if (*t == '!') { + not = 1; + t++; + } else + not = 0; + + /* + * Remove comment markers + */ + s = strchr(t, '#'); + if (s != NULL) { + *s = '\0'; + if (s == t) + continue; + } + + /* + * Trim off tailing white spaces + */ + s = strlen(t) + t - 1; + while (ISSPACE(*s)) + *s-- = '\0'; + + a = alist_new(AF_UNSPEC, t); + if (a != NULL) { + a->al_not = not; + if (rbot != NULL) + rbot->al_next = a; + else + rtop = a; + rbot = a; + } else { + fprintf(stderr, "%s:%d unrecognised content :%s\n", + filename, linenum, t); + } + } + fclose(fp); + + return (rtop); +} diff --git a/sbin/ipf/libipf/load_hash.c b/sbin/ipf/libipf/load_hash.c new file mode 100644 index 000000000000..bfee0fc64642 --- /dev/null +++ b/sbin/ipf/libipf/load_hash.c @@ -0,0 +1,99 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_htable.h" + + +int +load_hash(iphtable_t *iphp, iphtent_t *list, ioctlfunc_t iocfunc) +{ + iplookupop_t op; + iphtable_t iph; + iphtent_t *a; + size_t size; + int n; + + if (pool_open() == -1) + return (-1); + + for (n = 0, a = list; a != NULL; a = a->ipe_next) + n++; + + bzero((char *)&iph, sizeof(iph)); + op.iplo_arg = 0; + op.iplo_type = IPLT_HASH; + op.iplo_unit = iphp->iph_unit; + strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name)); + if (*op.iplo_name == '\0') + op.iplo_arg = IPHASH_ANON; + op.iplo_size = sizeof(iph); + op.iplo_struct = &iph; + iph = *iphp; + if (n <= 0) + n = 1; + if (iphp->iph_size == 0) + size = n * 2 - 1; + else + size = iphp->iph_size; + if ((list == NULL) && (size == 1)) { + fprintf(stderr, + "WARNING: empty hash table %s, recommend setting %s\n", + iphp->iph_name, "size to match expected use"); + } + iph.iph_size = size; + iph.iph_table = NULL; + iph.iph_list = NULL; + iph.iph_ref = 0; + + if ((opts & OPT_REMOVE) == 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "add lookup hash table")); + } + } + + strncpy(iph.iph_name, op.iplo_name, sizeof(op.iplo_name)); + strncpy(iphp->iph_name, op.iplo_name, sizeof(op.iplo_name)); + + if (opts & OPT_VERBOSE) { + iph.iph_table = calloc(size, sizeof(*iph.iph_table)); + if (iph.iph_table == NULL) { + perror("calloc(size, sizeof(*iph.iph_table))"); + return (-1); + } + iph.iph_list = list; + printhash(&iph, bcopywrap, iph.iph_name, opts, NULL); + free(iph.iph_table); + + for (a = list; a != NULL; a = a->ipe_next) { + a->ipe_addr.in4_addr = htonl(a->ipe_addr.in4_addr); + a->ipe_mask.in4_addr = htonl(a->ipe_mask.in4_addr); + } + } + + if (opts & OPT_DEBUG) + printf("Hash %s:\n", iph.iph_name); + + for (a = list; a != NULL; a = a->ipe_next) + load_hashnode(iphp->iph_unit, iph.iph_name, a, 0, iocfunc); + + if ((opts & OPT_REMOVE) != 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup hash table")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/load_hashnode.c b/sbin/ipf/libipf/load_hashnode.c new file mode 100644 index 000000000000..12b11687710d --- /dev/null +++ b/sbin/ipf/libipf/load_hashnode.c @@ -0,0 +1,81 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_htable.h" + + +int +load_hashnode(int unit, char *name, iphtent_t *node, int ttl, + ioctlfunc_t iocfunc) +{ + iplookupop_t op; + iphtent_t ipe; + char *what; + int err; + + if (pool_open() == -1) + return (-1); + + op.iplo_type = IPLT_HASH; + op.iplo_unit = unit; + op.iplo_arg = 0; + op.iplo_size = sizeof(ipe); + op.iplo_struct = &ipe; + strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + + bzero((char *)&ipe, sizeof(ipe)); + ipe.ipe_family = node->ipe_family; + ipe.ipe_die = ttl; + bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr, + sizeof(ipe.ipe_addr)); + bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask, + sizeof(ipe.ipe_mask)); + bcopy((char *)&node->ipe_group, (char *)&ipe.ipe_group, + sizeof(ipe.ipe_group)); + + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } + + if (err != 0) + if (!(opts & OPT_DONOTHING)) { + char msg[255]; + char ipaddr[80], mask_msg[10], mask[8]; + + inet_ntop(ipe.ipe_family, + ipe.ipe_addr.vptr, ipaddr, + sizeof(ipaddr)); +#ifdef USE_INET6 + if (ipe.ipe_family == AF_INET) { +#endif + inet_ntop(ipe.ipe_family, + ipe.ipe_mask.vptr, mask, + sizeof(mask)); + mask_msg[0]='/'; + mask_msg[1]='\0'; + strlcat(mask_msg, mask, sizeof(mask_msg)); +#ifdef USE_INET6 + } else { + mask_msg[0]='\0'; + } +#endif + + snprintf(msg, sizeof(msg), "%s node from lookup hash table(%s) node(%s%s)", what, name, ipaddr, mask_msg); + return (ipf_perror_fd(pool_fd(), iocfunc, msg)); + } + return (0); +} diff --git a/sbin/ipf/libipf/load_http.c b/sbin/ipf/libipf/load_http.c new file mode 100644 index 000000000000..7ad0bfd733bf --- /dev/null +++ b/sbin/ipf/libipf/load_http.c @@ -0,0 +1,207 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_http.c,v 1.5.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + +/* + * Because the URL can be included twice into the buffer, once as the + * full path for the "GET" and once as the "Host:", the buffer it is + * put in needs to be larger than 512*2 to make room for the supporting + * text. Why not just use snprintf and truncate? The warning about the + * URL being too long tells you something is wrong and does not fetch + * any data - just truncating the URL (with snprintf, etc) and sending + * that to the server is allowing an unknown and unintentioned action + * to happen. + */ +#define MAX_URL_LEN 512 +#define LOAD_BUFSIZE (MAX_URL_LEN * 2 + 128) + +/* + * Format expected is one address per line, at the start of each line. + */ +alist_t * +load_http(char *url) +{ + int fd, len, left, port, endhdr, removed, linenum = 0; + char *s, *t, *u, buffer[LOAD_BUFSIZE], *myurl; + alist_t *a, *rtop, *rbot; + size_t avail; + int error; + + /* + * More than this would just be absurd. + */ + if (strlen(url) > MAX_URL_LEN) { + fprintf(stderr, "load_http has a URL > %d bytes?!\n", + MAX_URL_LEN); + return (NULL); + } + + fd = -1; + rtop = NULL; + rbot = NULL; + + avail = sizeof(buffer); + error = snprintf(buffer, avail, "GET %s HTTP/1.0\r\n", url); + + /* + * error is always less then avail due to the constraint on + * the url length above. + */ + avail -= error; + + myurl = strdup(url); + if (myurl == NULL) + goto done; + + s = myurl + 7; /* http:// */ + t = strchr(s, '/'); + if (t == NULL) { + fprintf(stderr, "load_http has a malformed URL '%s'\n", url); + free(myurl); + return (NULL); + } + *t++ = '\0'; + + /* + * 10 is the length of 'Host: \r\n\r\n' below. + */ + if (strlen(s) + strlen(buffer) + 10 > sizeof(buffer)) { + fprintf(stderr, "load_http has a malformed URL '%s'\n", url); + free(myurl); + return (NULL); + } + + u = strchr(s, '@'); + if (u != NULL) + s = u + 1; /* AUTH */ + + error = snprintf(buffer + strlen(buffer), avail, "Host: %s\r\n\r\n", s); + if (error >= avail) { + fprintf(stderr, "URL is too large: %s\n", url); + goto done; + } + + u = strchr(s, ':'); + if (u != NULL) { + *u++ = '\0'; + port = atoi(u); + if (port < 0 || port > 65535) + goto done; + } else { + port = 80; + } + + + fd = connecttcp(s, port); + if (fd == -1) + goto done; + + + len = strlen(buffer); + if (write(fd, buffer, len) != len) + goto done; + + s = buffer; + endhdr = 0; + left = sizeof(buffer) - 1; + + while ((len = read(fd, s, left)) > 0) { + s[len] = '\0'; + left -= len; + s += len; + + if (endhdr >= 0) { + if (endhdr == 0) { + t = strchr(buffer, ' '); + if (t == NULL) + continue; + t++; + if (*t != '2') + break; + } + + u = buffer; + while ((t = strchr(u, '\r')) != NULL) { + if (t == u) { + if (*(t + 1) == '\n') { + u = t + 2; + endhdr = -1; + break; + } else + t++; + } else if (*(t + 1) == '\n') { + endhdr++; + u = t + 2; + } else + u = t + 1; + } + if (endhdr >= 0) + continue; + removed = (u - buffer) + 1; + memmove(buffer, u, (sizeof(buffer) - left) - removed); + s -= removed; + left += removed; + } + + do { + t = strchr(buffer, '\n'); + if (t == NULL) + break; + + linenum++; + *t = '\0'; + + /* + * Remove comment and continue to the next line if + * the comment is at the start of the line. + */ + u = strchr(buffer, '#'); + if (u != NULL) { + *u = '\0'; + if (u == buffer) + continue; + } + + /* + * Trim off tailing white spaces, will include \r + */ + for (u = t - 1; (u >= buffer) && ISSPACE(*u); u--) + *u = '\0'; + + a = alist_new(AF_UNSPEC, buffer); + if (a != NULL) { + if (rbot != NULL) + rbot->al_next = a; + else + rtop = a; + rbot = a; + } else { + fprintf(stderr, + "%s:%d unrecognised content:%s\n", + url, linenum, buffer); + } + + t++; + removed = t - buffer; + memmove(buffer, t, sizeof(buffer) - left - removed); + s -= removed; + left += removed; + + } while (1); + } + +done: + if (myurl != NULL) + free(myurl); + if (fd != -1) + close(fd); + return (rtop); +} diff --git a/sbin/ipf/libipf/load_pool.c b/sbin/ipf/libipf/load_pool.c new file mode 100644 index 000000000000..0d90c81e81ff --- /dev/null +++ b/sbin/ipf/libipf/load_pool.c @@ -0,0 +1,69 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + + +int +load_pool(ip_pool_t *plp, ioctlfunc_t iocfunc) +{ + iplookupop_t op; + ip_pool_node_t *a; + ip_pool_t pool; + + if (pool_open() == -1) + return (-1); + + op.iplo_unit = plp->ipo_unit; + op.iplo_type = IPLT_POOL; + op.iplo_arg = 0; + strncpy(op.iplo_name, plp->ipo_name, sizeof(op.iplo_name)); + op.iplo_size = sizeof(pool); + op.iplo_struct = &pool; + bzero((char *)&pool, sizeof(pool)); + pool.ipo_unit = plp->ipo_unit; + strncpy(pool.ipo_name, plp->ipo_name, sizeof(pool.ipo_name)); + if (plp->ipo_name[0] == '\0') + op.iplo_arg |= IPOOL_ANON; + + if ((opts & OPT_REMOVE) == 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPADDTABLE, &op)) { + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "add lookup table")); + } + } + } + + if (op.iplo_arg & IPOOL_ANON) + strncpy(pool.ipo_name, op.iplo_name, sizeof(pool.ipo_name)); + + if ((opts & OPT_VERBOSE) != 0) { + pool.ipo_list = plp->ipo_list; + (void) printpool(&pool, bcopywrap, pool.ipo_name, opts, NULL); + pool.ipo_list = NULL; + } + + for (a = plp->ipo_list; a != NULL; a = a->ipn_next) + load_poolnode(plp->ipo_unit, pool.ipo_name, + a, 0, iocfunc); + + if ((opts & OPT_REMOVE) != 0) { + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup table")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/load_poolnode.c b/sbin/ipf/libipf/load_poolnode.c new file mode 100644 index 000000000000..880a6cd1c681 --- /dev/null +++ b/sbin/ipf/libipf/load_poolnode.c @@ -0,0 +1,84 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + + +int +load_poolnode(int role, char *name, ip_pool_node_t *node, int ttl, + ioctlfunc_t iocfunc) +{ + ip_pool_node_t pn; + iplookupop_t op; + char *what; + int err; + + if (pool_open() == -1) + return (-1); + + op.iplo_unit = role; + op.iplo_type = IPLT_POOL; + op.iplo_arg = 0; + op.iplo_struct = &pn; + op.iplo_size = sizeof(pn); + strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + + bzero((char *)&pn, sizeof(pn)); + bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr, + sizeof(pn.ipn_addr)); + bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask, + sizeof(pn.ipn_mask)); + pn.ipn_info = node->ipn_info; + pn.ipn_die = ttl; + strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); + + if ((opts & OPT_REMOVE) == 0) { + what = "add"; + err = pool_ioctl(iocfunc, SIOCLOOKUPADDNODE, &op); + } else { + what = "delete"; + err = pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op); + } + + if (err != 0) { + if ((opts & OPT_DONOTHING) == 0) { + char msg[255]; + char ipaddr[80], mask_msg[10], mask[8]; + + inet_ntop(pn.ipn_addr.adf_family, + pn.ipn_addr.adf_addr.vptr, ipaddr, + sizeof(ipaddr)); + +#ifdef USE_INET6 + if (pn.ipn_mask.adf_family == AF_INET) { +#endif + inet_ntop(pn.ipn_mask.adf_family, + pn.ipn_mask.adf_addr.vptr, mask, + sizeof(mask)); + mask_msg[0]='/'; + mask_msg[1]='\0'; + strlcat(mask_msg, mask, sizeof(mask_msg)); +#ifdef USE_INET6 + } else { + mask_msg[0]='\0'; + } +#endif + + snprintf(msg, sizeof(msg), "%s pool(%s) node(%s%s)", + what, name, ipaddr, mask_msg); + return (ipf_perror_fd(pool_fd(), iocfunc, msg)); + } + } + + return (0); +} diff --git a/sbin/ipf/libipf/load_url.c b/sbin/ipf/libipf/load_url.c new file mode 100644 index 000000000000..defca6026a95 --- /dev/null +++ b/sbin/ipf/libipf/load_url.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: load_url.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +alist_t * +load_url(char *url) +{ + alist_t *hosts = NULL; + + if (strncmp(url, "file://", 7) == 0) { + /* + * file:///etc/passwd + * ^------------s + */ + hosts = load_file(url); + + } else if (*url == '/' || *url == '.') { + hosts = load_file(url); + + } else if (strncmp(url, "http://", 7) == 0) { + hosts = load_http(url); + } + + return (hosts); +} diff --git a/sbin/ipf/libipf/mb_hexdump.c b/sbin/ipf/libipf/mb_hexdump.c new file mode 100644 index 000000000000..91351c3f815e --- /dev/null +++ b/sbin/ipf/libipf/mb_hexdump.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: mb_hexdump.c,v 1.1.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +void +mb_hexdump(mb_t *m, FILE *fp) +{ + u_char *s; + int len; + int i; + + for (; m != NULL; m = m->mb_next) { + len = m->mb_len; + for (s = (u_char *)m->mb_data, i = 0; i < len; i++) { + fprintf(fp, "%02x", *s++ & 0xff); + if (len - i > 1) { + i++; + fprintf(fp, "%02x", *s++ & 0xff); + } + fputc(' ', fp); + } + } + fputc('\n', fp); +} diff --git a/sbin/ipf/libipf/msgdsize.c b/sbin/ipf/libipf/msgdsize.c new file mode 100644 index 000000000000..3af1e4771e96 --- /dev/null +++ b/sbin/ipf/libipf/msgdsize.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: msgdsize.c,v 1.2.4.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +size_t msgdsize(mb_t *orig) +{ + size_t sz = 0; + mb_t *m; + + for (m = orig; m != NULL; m = m->mb_next) + sz += m->mb_len; + return (sz); +} diff --git a/sbin/ipf/libipf/mutex_emul.c b/sbin/ipf/libipf/mutex_emul.c new file mode 100644 index 000000000000..d7f34671d953 --- /dev/null +++ b/sbin/ipf/libipf/mutex_emul.c @@ -0,0 +1,119 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#define EMM_MAGIC 0x9d7adba3 + +static int mutex_debug = 0; +static FILE *mutex_file = NULL; +static int initcount = 0; + +void +eMmutex_enter(eMmutex_t *mtx, char *file, int line) +{ + if (mutex_debug & 2) + fprintf(mutex_file, "%s:%d:eMmutex_enter(%s)\n", file, line, + mtx->eMm_owner); + if (mtx->eMm_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMmutex_enter(%p): bad magic: %#x\n", + mtx->eMm_owner, mtx, mtx->eMm_magic); + abort(); + } + if (mtx->eMm_held != 0) { + fprintf(stderr, "%s:eMmutex_enter(%p): already locked: %d\n", + mtx->eMm_owner, mtx, mtx->eMm_held); + abort(); + } + mtx->eMm_held++; + mtx->eMm_heldin = file; + mtx->eMm_heldat = line; +} + + +void +eMmutex_exit(eMmutex_t *mtx, char *file, int line) +{ + if (mutex_debug & 2) + fprintf(mutex_file, "%s:%d:eMmutex_exit(%s)\n", file, line, + mtx->eMm_owner); + if (mtx->eMm_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMmutex_exit(%p): bad magic: %#x\n", + mtx->eMm_owner, mtx, mtx->eMm_magic); + abort(); + } + if (mtx->eMm_held != 1) { + fprintf(stderr, "%s:eMmutex_exit(%p): not locked: %d\n", + mtx->eMm_owner, mtx, mtx->eMm_held); + abort(); + } + mtx->eMm_held--; + mtx->eMm_heldin = NULL; + mtx->eMm_heldat = 0; +} + + +void +eMmutex_init(eMmutex_t *mtx, char *who, char *file, int line) +{ + if (mutex_file == NULL && mutex_debug) + mutex_file = fopen("ipf_mutex_log", "w"); + if (mutex_debug & 1) + fprintf(mutex_file, "%s:%d:eMmutex_init(%p,%s)\n", + file, line, mtx, who); + if (mtx->eMm_magic == EMM_MAGIC) { /* safe bet ? */ + fprintf(stderr, + "%s:eMmutex_init(%p): already initialised?: %#x\n", + mtx->eMm_owner, mtx, mtx->eMm_magic); + abort(); + } + mtx->eMm_magic = EMM_MAGIC; + mtx->eMm_held = 0; + if (who != NULL) + mtx->eMm_owner = strdup(who); + else + mtx->eMm_owner = NULL; + initcount++; +} + + +void +eMmutex_destroy(eMmutex_t *mtx, char *file, int line) +{ + if (mutex_debug & 1) + fprintf(mutex_file, + "%s:%d:eMmutex_destroy(%p,%s)\n", file, line, + mtx, mtx->eMm_owner); + if (mtx->eMm_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMmutex_destroy(%p): bad magic: %#x\n", + mtx->eMm_owner, mtx, mtx->eMm_magic); + abort(); + } + if (mtx->eMm_held != 0) { + fprintf(stderr, + "%s:eMmutex_enter(%p): still locked: %d\n", + mtx->eMm_owner, mtx, mtx->eMm_held); + abort(); + } + if (mtx->eMm_owner != NULL) + free(mtx->eMm_owner); + memset(mtx, 0xa5, sizeof(*mtx)); + initcount--; +} + + +void +ipf_mutex_clean(void) +{ + if (initcount != 0) { + if (mutex_file) + fprintf(mutex_file, "initcount %d\n", initcount); + abort(); + } +} diff --git a/sbin/ipf/libipf/nametokva.c b/sbin/ipf/libipf/nametokva.c new file mode 100644 index 000000000000..06635238165c --- /dev/null +++ b/sbin/ipf/libipf/nametokva.c @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#include <sys/ioctl.h> +#include <fcntl.h> + +ipfunc_t +nametokva(char *name, ioctlfunc_t iocfunc) +{ + ipfunc_resolve_t res; + int fd; + + strncpy(res.ipfu_name, name, sizeof(res.ipfu_name)); + res.ipfu_addr = NULL; + fd = -1; + + if ((opts & OPT_DONTOPEN) == 0) { + fd = open(IPL_NAME, O_RDONLY); + if (fd == -1) + return (NULL); + } + (void) (*iocfunc)(fd, SIOCFUNCL, &res); + if (fd >= 0) + close(fd); + if (res.ipfu_addr == NULL) + res.ipfu_addr = (ipfunc_t)-1; + return (res.ipfu_addr); +} diff --git a/sbin/ipf/libipf/nat_setgroupmap.c b/sbin/ipf/libipf/nat_setgroupmap.c new file mode 100644 index 000000000000..97a5211688c3 --- /dev/null +++ b/sbin/ipf/libipf/nat_setgroupmap.c @@ -0,0 +1,30 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + +void +nat_setgroupmap(ipnat_t *n) +{ + if (n->in_nsrcmsk == n->in_osrcmsk) + n->in_ippip = 1; + else if (n->in_flags & IPN_AUTOPORTMAP) { + n->in_ippip = ~ntohl(n->in_osrcmsk); + if (n->in_nsrcmsk != 0xffffffff) + n->in_ippip /= (~ntohl(n->in_nsrcmsk) + 1); + n->in_ippip++; + if (n->in_ippip == 0) + n->in_ippip = 1; + n->in_ppip = USABLE_PORTS / n->in_ippip; + } else { + n->in_space = USABLE_PORTS * ~ntohl(n->in_nsrcmsk); + n->in_snip = 0; + if (!(n->in_ppip = n->in_spmin)) + n->in_ppip = 1; + n->in_ippip = USABLE_PORTS / n->in_ppip; + } +} diff --git a/sbin/ipf/libipf/ntomask.c b/sbin/ipf/libipf/ntomask.c new file mode 100644 index 000000000000..3664d255254c --- /dev/null +++ b/sbin/ipf/libipf/ntomask.c @@ -0,0 +1,45 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +int +ntomask(int family, int nbits, u_32_t *ap) +{ + u_32_t mask; + + if (nbits < 0) + return (-1); + + switch (family) + { + case AF_INET : + if (nbits > 32 || use_inet6 == 1) + return (-1); + if (nbits == 0) { + mask = 0; + } else { + mask = 0xffffffff; + mask <<= (32 - nbits); + } + *ap = htonl(mask); + break; + + case 0 : + case AF_INET6 : + if ((nbits > 128) || (use_inet6 == -1)) + return (-1); + fill6bits(nbits, ap); + break; + + default : + return (-1); + } + return (0); +} diff --git a/sbin/ipf/libipf/optname.c b/sbin/ipf/libipf/optname.c new file mode 100644 index 000000000000..93bf276c7818 --- /dev/null +++ b/sbin/ipf/libipf/optname.c @@ -0,0 +1,62 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +u_32_t +optname(char ***cp, u_short *sp, int linenum) +{ + struct ipopt_names *io, *so; + u_long msk = 0; + u_short smsk = 0; + char *s; + int sec = 0; + + for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { + for (io = ionames; io->on_name; io++) + if (!strcasecmp(s, io->on_name)) { + msk |= io->on_bit; + break; + } + if (!io->on_name) { + fprintf(stderr, "%d: unknown IP option name %s\n", + linenum, s); + return (0); + } + if (!strcasecmp(s, "sec-class")) + sec = 1; + } + + if (sec && !*(*cp + 1)) { + fprintf(stderr, "%d: missing security level after sec-class\n", + linenum); + return (0); + } + + if (sec) { + (*cp)++; + for (s = strtok(**cp, ","); s; s = strtok(NULL, ",")) { + for (so = secclass; so->on_name; so++) + if (!strcasecmp(s, so->on_name)) { + smsk |= so->on_bit; + break; + } + if (!so->on_name) { + fprintf(stderr, + "%d: no such security level: %s\n", + linenum, s); + return (0); + } + } + if (smsk) + *sp = smsk; + } + return (msk); +} diff --git a/sbin/ipf/libipf/optprint.c b/sbin/ipf/libipf/optprint.c new file mode 100644 index 000000000000..a70ed28d611f --- /dev/null +++ b/sbin/ipf/libipf/optprint.c @@ -0,0 +1,81 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +void +optprint(u_short *sec, u_long optmsk, u_long optbits) +{ + u_short secmsk = sec[0], secbits = sec[1]; + struct ipopt_names *io, *so; + char *s; + + s = " opt "; + for (io = ionames; io->on_name; io++) + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) == (io->on_bit & optbits))) { + if ((io->on_value != IPOPT_SECURITY) || + (!secmsk && !secbits)) { + printf("%s%s", s, io->on_name); + /* + * Because the ionames table has this entry + * twice. + */ + if (io->on_value == IPOPT_SECURITY) + io++; + s = ","; + } + } + + + if (secmsk & secbits) { + printf("%ssec-class", s); + s = " "; + for (so = secclass; so->on_name; so++) + if ((secmsk & so->on_bit) && + ((so->on_bit & secmsk) == (so->on_bit & secbits))) { + printf("%s%s", s, so->on_name); + s = ","; + } + } + + if ((optmsk && (optmsk != optbits)) || + (secmsk && (secmsk != secbits))) { + s = " "; + printf(" not opt"); + if (optmsk != optbits) { + for (io = ionames; io->on_name; io++) + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) != + (io->on_bit & optbits))) { + if ((io->on_value != IPOPT_SECURITY) || + (!secmsk && !secbits)) { + printf("%s%s", s, io->on_name); + s = ","; + if (io->on_value == + IPOPT_SECURITY) + io++; + } else + io++; + } + } + + if (secmsk != secbits) { + printf("%ssec-class", s); + s = " "; + for (so = secclass; so->on_name; so++) + if ((so->on_bit & secmsk) && + ((so->on_bit & secmsk) != + (so->on_bit & secbits))) { + printf("%s%s", s, so->on_name); + s = ","; + } + } + } +} diff --git a/sbin/ipf/libipf/optprintv6.c b/sbin/ipf/libipf/optprintv6.c new file mode 100644 index 000000000000..e53a879fa439 --- /dev/null +++ b/sbin/ipf/libipf/optprintv6.c @@ -0,0 +1,45 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +#ifdef USE_INET6 + +void +optprintv6(u_short *sec, u_long optmsk, u_long optbits) +{ + u_short secmsk = sec[0], secbits = sec[1]; + struct ipopt_names *io; + char *s; + + s = " v6hdr "; + for (io = v6ionames; io->on_name; io++) + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) == (io->on_bit & optbits))) { + printf("%s%s", s, io->on_name); + s = ","; + } + + if ((optmsk && (optmsk != optbits)) || + (secmsk && (secmsk != secbits))) { + s = " "; + printf(" not v6hdrs"); + if (optmsk != optbits) { + for (io = v6ionames; io->on_name; io++) + if ((io->on_bit & optmsk) && + ((io->on_bit & optmsk) != + (io->on_bit & optbits))) { + printf("%s%s", s, io->on_name); + s = ","; + } + } + + } +} +#endif diff --git a/sbin/ipf/libipf/optvalue.c b/sbin/ipf/libipf/optvalue.c new file mode 100644 index 000000000000..44635b04a13a --- /dev/null +++ b/sbin/ipf/libipf/optvalue.c @@ -0,0 +1,33 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +u_32_t +getoptbyname(char *optname) +{ + struct ipopt_names *io; + + for (io = ionames; io->on_name; io++) + if (!strcasecmp(optname, io->on_name)) + return (io->on_bit); + return (-1); +} + + +u_32_t +getoptbyvalue(int optval) +{ + struct ipopt_names *io; + + for (io = ionames; io->on_name; io++) + if (io->on_value == optval) + return (io->on_bit); + return (-1); +} diff --git a/sbin/ipf/libipf/parsefields.c b/sbin/ipf/libipf/parsefields.c new file mode 100644 index 000000000000..c165dc2eea0d --- /dev/null +++ b/sbin/ipf/libipf/parsefields.c @@ -0,0 +1,51 @@ +#include "ipf.h" +#include <err.h> + +extern int nohdrfields; + +wordtab_t *parsefields(wordtab_t *table, char *arg) +{ + wordtab_t *f, *fields; + char *s, *t; + int num; + + fields = NULL; + num = 0; + + for (s = strtok(arg, ","); s != NULL; s = strtok(NULL, ",")) { + t = strchr(s, '='); + if (t != NULL) { + *t++ = '\0'; + if (*t == '\0') + nohdrfields = 1; + } + + f = findword(table, s); + if (f == NULL) { + fprintf(stderr, "Unknown field '%s'\n", s); + exit(1); + } + + num++; + if (fields == NULL) { + fields = malloc(2 * sizeof(*fields)); + } else { + fields = reallocarray(fields, num + 1, sizeof(*fields)); + if (fields == NULL) { + warnx("memory allocation error at %d in %s in %s", __LINE__, __FUNCTION__, __FILE__); + abort(); + } + } + + if (t == NULL) { + fields[num - 1].w_word = f->w_word; + } else { + fields[num - 1].w_word = t; + } + fields[num - 1].w_value = f->w_value; + fields[num].w_word = NULL; + fields[num].w_value = 0; + } + + return (fields); +} diff --git a/sbin/ipf/libipf/parseipfexpr.c b/sbin/ipf/libipf/parseipfexpr.c new file mode 100644 index 000000000000..be86456e143b --- /dev/null +++ b/sbin/ipf/libipf/parseipfexpr.c @@ -0,0 +1,277 @@ +#include "ipf.h" +#include <ctype.h> + + +typedef struct ipfopentry { + int ipoe_cmd; + int ipoe_nbasearg; + int ipoe_maxarg; + int ipoe_argsize; + char *ipoe_word; +} ipfopentry_t; + +static ipfopentry_t opwords[17] = { + { IPF_EXP_IP_ADDR, 2, 0, 1, "ip.addr" }, + { IPF_EXP_IP6_ADDR, 2, 0, 4, "ip6.addr" }, + { IPF_EXP_IP_PR, 1, 0, 1, "ip.p" }, + { IPF_EXP_IP_SRCADDR, 2, 0, 1, "ip.src" }, + { IPF_EXP_IP_DSTADDR, 2, 0, 1, "ip.dst" }, + { IPF_EXP_IP6_SRCADDR, 2, 0, 4, "ip6.src" }, + { IPF_EXP_IP6_DSTADDR, 2, 0, 4, "ip6.dst" }, + { IPF_EXP_TCP_PORT, 1, 0, 1, "tcp.port" }, + { IPF_EXP_TCP_DPORT, 1, 0, 1, "tcp.dport" }, + { IPF_EXP_TCP_SPORT, 1, 0, 1, "tcp.sport" }, + { IPF_EXP_TCP_FLAGS, 2, 0, 1, "tcp.flags" }, + { IPF_EXP_UDP_PORT, 1, 0, 1, "udp.port" }, + { IPF_EXP_UDP_DPORT, 1, 0, 1, "udp.dport" }, + { IPF_EXP_UDP_SPORT, 1, 0, 1, "udp.sport" }, + { IPF_EXP_TCP_STATE, 1, 0, 1, "tcp.state" }, + { IPF_EXP_IDLE_GT, 1, 1, 1, "idle-gt" }, + { -1, 0, 0, 0, NULL } +}; + + +int * +parseipfexpr(char *line, char **errorptr) +{ + int not, items, asize, *oplist, osize, i; + char *temp, *arg, *s, *t, *ops, *error; + ipfopentry_t *e; + ipfexp_t *ipfe; + + asize = 0; + error = NULL; + oplist = NULL; + + temp = strdup(line); + if (temp == NULL) { + error = "strdup failed"; + goto parseerror; + } + + /* + * Eliminate any white spaces to make parsing easier. + */ + for (s = temp; *s != '\0'; ) { + if (ISSPACE(*s)) + strcpy(s, s + 1); + else + s++; + } + + /* + * Parse the string. + * It should be sets of "ip.dst=1.2.3.4/32;" things. + * There must be a "=" or "!=" and it must end in ";". + */ + if (temp[strlen(temp) - 1] != ';') { + error = "last character not ';'"; + goto parseerror; + } + + /* + * Work through the list of complete operands present. + */ + for (ops = strtok(temp, ";"); ops != NULL; ops = strtok(NULL, ";")) { + arg = strchr(ops, '='); + if ((arg < ops + 2) || (arg == NULL)) { + error = "bad 'arg' value"; + goto parseerror; + } + + if (*(arg - 1) == '!') { + *(arg - 1) = '\0'; + not = 1; + } else { + not = 0; + } + *arg++ = '\0'; + + + for (e = opwords; e->ipoe_word; e++) { + if (strcmp(ops, e->ipoe_word) == 0) + break; + } + if (e->ipoe_word == NULL) { + asprintf(&error, "keyword (%.10s) not found", ops); + goto parseerror; + } + + /* + * Count the number of commas so we know how big to + * build the array + */ + for (s = arg, items = 1; *s != '\0'; s++) + if (*s == ',') + items++; + + if ((e->ipoe_maxarg != 0) && (items > e->ipoe_maxarg)) { + error = "too many items"; + goto parseerror; + } + + /* + * osize will mark the end of where we have filled up to + * and is thus where we start putting new data. + */ + osize = asize; + asize += 4 + (items * e->ipoe_nbasearg * e->ipoe_argsize); + if (oplist == NULL) + oplist = calloc(asize + 2, sizeof(int)); + else + oplist = reallocarray(oplist, asize + 2, sizeof(int)); + if (oplist == NULL) { + error = "oplist alloc failed"; + goto parseerror; + } + ipfe = (ipfexp_t *)(oplist + osize); + osize += 4; + ipfe->ipfe_cmd = e->ipoe_cmd; + ipfe->ipfe_not = not; + ipfe->ipfe_narg = items * e->ipoe_nbasearg; + ipfe->ipfe_size = items * e->ipoe_nbasearg * e->ipoe_argsize; + ipfe->ipfe_size += 4; + + for (s = arg; (*s != '\0') && (osize < asize); s = t) { + /* + * Look for the end of this arg or the ',' to say + * there is another following. + */ + for (t = s; (*t != '\0') && (*t != ','); t++) + ; + if (*t == ',') + *t++ = '\0'; + + if (!strcasecmp(ops, "ip.addr") || + !strcasecmp(ops, "ip.src") || + !strcasecmp(ops, "ip.dst")) { + i6addr_t mask, addr; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + if (genmask(AF_INET, delim, + &mask) == -1) { + error = "genmask failed"; + goto parseerror; + } + } else { + mask.in4.s_addr = 0xffffffff; + } + if (gethost(AF_INET, s, &addr) == -1) { + error = "gethost failed"; + goto parseerror; + } + + oplist[osize++] = addr.in4.s_addr; + oplist[osize++] = mask.in4.s_addr; + +#ifdef USE_INET6 + } else if (!strcasecmp(ops, "ip6.addr") || + !strcasecmp(ops, "ip6.src") || + !strcasecmp(ops, "ip6.dst")) { + i6addr_t mask, addr; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + if (genmask(AF_INET6, delim, + &mask) == -1) { + error = "genmask failed"; + goto parseerror; + } + } else { + mask.i6[0] = 0xffffffff; + mask.i6[1] = 0xffffffff; + mask.i6[2] = 0xffffffff; + mask.i6[3] = 0xffffffff; + } + if (gethost(AF_INET6, s, &addr) == -1) { + error = "gethost failed"; + goto parseerror; + } + + oplist[osize++] = addr.i6[0]; + oplist[osize++] = addr.i6[1]; + oplist[osize++] = addr.i6[2]; + oplist[osize++] = addr.i6[3]; + oplist[osize++] = mask.i6[0]; + oplist[osize++] = mask.i6[1]; + oplist[osize++] = mask.i6[2]; + oplist[osize++] = mask.i6[3]; +#endif + + } else if (!strcasecmp(ops, "ip.p")) { + int p; + + p = getproto(s); + if (p == -1) + goto parseerror; + oplist[osize++] = p; + + } else if (!strcasecmp(ops, "tcp.flags")) { + u_32_t mask, flags; + char *delim; + + delim = strchr(s, '/'); + if (delim != NULL) { + *delim++ = '\0'; + mask = tcpflags(delim); + } else { + mask = 0xff; + } + flags = tcpflags(s); + + oplist[osize++] = flags; + oplist[osize++] = mask; + + + } else if (!strcasecmp(ops, "tcp.port") || + !strcasecmp(ops, "tcp.sport") || + !strcasecmp(ops, "tcp.dport") || + !strcasecmp(ops, "udp.port") || + !strcasecmp(ops, "udp.sport") || + !strcasecmp(ops, "udp.dport")) { + char proto[4]; + u_short port; + + strncpy(proto, ops, 3); + proto[3] = '\0'; + if (getport(NULL, s, &port, proto) == -1) + goto parseerror; + oplist[osize++] = port; + + } else if (!strcasecmp(ops, "tcp.state")) { + oplist[osize++] = atoi(s); + + } else { + error = "unknown word"; + goto parseerror; + } + } + } + + free(temp); + + if (errorptr != NULL) + *errorptr = NULL; + + for (i = asize; i > 0; i--) + oplist[i] = oplist[i - 1]; + + oplist[0] = asize + 2; + oplist[asize + 1] = IPF_EXP_END; + + return (oplist); + +parseerror: + if (errorptr != NULL) + *errorptr = error; + if (oplist != NULL) + free(oplist); + if (temp != NULL) + free(temp); + return (NULL); +} diff --git a/sbin/ipf/libipf/parsewhoisline.c b/sbin/ipf/libipf/parsewhoisline.c new file mode 100644 index 000000000000..529372f91fe2 --- /dev/null +++ b/sbin/ipf/libipf/parsewhoisline.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: parsewhoisline.c,v 1.2.2.5 2012/07/22 08:04:24 darren_r Exp $ + */ +#include "ipf.h" + +/* +Microsoft Corp MICROSOFT19 (NET-198-136-97-0-1) 198.137.97.0 - 198.137.97.255 +Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47 + */ +int +parsewhoisline(char *line, addrfamily_t *addrp, addrfamily_t *maskp) +{ + struct in_addr a1, a2; + char *src = line; + char *s = NULL; + + if (line == NULL) + return (-1); + + while (*src != '\0') { + s = strchr(src, '('); + if (s == NULL) + break; + + if (strncmp(s, "(NET", 4)) { + src = s + 1; + } + break; + } + + if (s == NULL) + return (-1); + + memset(addrp, 0x00, sizeof(*maskp)); + memset(maskp, 0x00, sizeof(*maskp)); + + if (*(s + 4) == '6') { +#ifdef USE_INET6 + i6addr_t a61, a62; + + s = strchr(s, ')'); + if (s == NULL || *++s != ' ') + return (-1); + /* + * Parse the IPv6 + */ + if (inet_pton(AF_INET6, s, &a61.in6) != 1) + return (-1); + + s = strchr(s, ' '); + if (s == NULL || strncmp(s, " - ", 3)) + return (-1); + + s += 3; + if (inet_pton(AF_INET6, s, &a62) != 1) + return (-1); + + addrp->adf_addr = a61; + addrp->adf_family = AF_INET6; + addrp->adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in6_addr); + + maskp->adf_addr.i6[0] = ~(a62.i6[0] ^ a61.i6[0]); + maskp->adf_addr.i6[1] = ~(a62.i6[1] ^ a61.i6[1]); + maskp->adf_addr.i6[2] = ~(a62.i6[2] ^ a61.i6[2]); + maskp->adf_addr.i6[3] = ~(a62.i6[3] ^ a61.i6[3]); + + /* + * If the mask that's been generated isn't a consecutive mask + * then we can't add it into a pool. + */ + if (count6bits(maskp->adf_addr.i6) == -1) + return (-1); + + maskp->adf_family = AF_INET6; + maskp->adf_len = addrp->adf_len; + + if (IP6_MASKNEQ(&addrp->adf_addr.in6, &maskp->adf_addr.in6, + &addrp->adf_addr.in6)) { + return (-1); + } + return (0); +#else + return (-1); +#endif + } + + s = strchr(s, ')'); + if (s == NULL || *++s != ' ') + return (-1); + + s++; + + if (inet_aton(s, &a1) != 1) + return (-1); + + s = strchr(s, ' '); + if (s == NULL || strncmp(s, " - ", 3)) + return (-1); + + s += 3; + if (inet_aton(s, &a2) != 1) + return (-1); + + addrp->adf_addr.in4 = a1; + addrp->adf_family = AF_INET; + addrp->adf_len = offsetof(addrfamily_t, adf_addr) + + sizeof(struct in_addr); + maskp->adf_addr.in4.s_addr = ~(a2.s_addr ^ a1.s_addr); + + /* + * If the mask that's been generated isn't a consecutive mask then + * we can't add it into a pool. + */ + if (count4bits(maskp->adf_addr.in4.s_addr) == -1) + return (-1); + + maskp->adf_family = AF_INET; + maskp->adf_len = addrp->adf_len; + bzero((char *)maskp + maskp->adf_len, sizeof(*maskp) - maskp->adf_len); + if ((addrp->adf_addr.in4.s_addr & maskp->adf_addr.in4.s_addr) != + addrp->adf_addr.in4.s_addr) + return (-1); + return (0); +} diff --git a/sbin/ipf/libipf/poolio.c b/sbin/ipf/libipf/poolio.c new file mode 100644 index 000000000000..f12120fd5467 --- /dev/null +++ b/sbin/ipf/libipf/poolio.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: poolio.c,v 1.1.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + +static int poolfd = -1; + + +int +pool_open(void) +{ + + if ((opts & OPT_DONTOPEN) != 0) + return (0); + + if (poolfd == -1) + poolfd = open(IPLOOKUP_NAME, O_RDWR); + return (poolfd); +} + +int +pool_ioctl(ioctlfunc_t iocfunc, ioctlcmd_t cmd, void *ptr) +{ + return (*iocfunc)(poolfd, cmd, ptr); +} + + +void +pool_close(void) +{ + if (poolfd != -1) { + close(poolfd); + poolfd = -1; + } +} + +int +pool_fd(void) +{ + return (poolfd); +} diff --git a/sbin/ipf/libipf/portname.c b/sbin/ipf/libipf/portname.c new file mode 100644 index 000000000000..034c8255537d --- /dev/null +++ b/sbin/ipf/libipf/portname.c @@ -0,0 +1,42 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +char * +portname(int pr, int port) +{ + static char buf[32]; + struct protoent *p = NULL; + struct servent *sv = NULL; + struct servent *sv1 = NULL; + + if ((opts & OPT_NORESOLVE) == 0) { + if (pr == -1) { + if ((sv = getservbyport(htons(port), "tcp"))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + sv1 = getservbyport(htons(port), "udp"); + sv = strncasecmp(buf, sv->s_name, strlen(buf)) ? + NULL : sv1; + } + if (sv) + return (buf); + } else if ((pr != -2) && (p = getprotobynumber(pr))) { + if ((sv = getservbyport(htons(port), p->p_name))) { + strncpy(buf, sv->s_name, sizeof(buf)-1); + buf[sizeof(buf)-1] = '\0'; + return (buf); + } + } + } + + (void) snprintf(buf, sizeof(buf), "%d", port); + return (buf); +} diff --git a/sbin/ipf/libipf/prependmbt.c b/sbin/ipf/libipf/prependmbt.c new file mode 100644 index 000000000000..96b3454739b4 --- /dev/null +++ b/sbin/ipf/libipf/prependmbt.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: prependmbt.c,v 1.3.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + +int prependmbt( fr_info_t *fin, mb_t *m) +{ + m->mb_next = *fin->fin_mp; + *fin->fin_mp = m; + return (0); +} diff --git a/sbin/ipf/libipf/print_toif.c b/sbin/ipf/libipf/print_toif.c new file mode 100644 index 000000000000..2dcaec7394f9 --- /dev/null +++ b/sbin/ipf/libipf/print_toif.c @@ -0,0 +1,45 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +print_toif(int family, char *tag, char *base, frdest_t *fdp) +{ + switch (fdp->fd_type) + { + case FRD_NORMAL : + PRINTF("%s %s%s", tag, base + fdp->fd_name, + (fdp->fd_ptr || (long)fdp->fd_ptr == -1) ? "" : "(!)"); +#ifdef USE_INET6 + if (family == AF_INET6) { + if (IP6_NOTZERO(&fdp->fd_ip6)) { + char ipv6addr[80]; + + inet_ntop(AF_INET6, &fdp->fd_ip6, ipv6addr, + sizeof(fdp->fd_ip6)); + PRINTF(":%s", ipv6addr); + } + } else +#endif + if (fdp->fd_ip.s_addr) + PRINTF(":%s", inet_ntoa(fdp->fd_ip)); + putchar(' '); + break; + + case FRD_DSTLIST : + PRINTF("%s dstlist/%s ", tag, base + fdp->fd_name); + break; + + default : + PRINTF("%s <%d>", tag, fdp->fd_type); + break; + } +} diff --git a/sbin/ipf/libipf/printactiveaddr.c b/sbin/ipf/libipf/printactiveaddr.c new file mode 100644 index 000000000000..70deafa345e0 --- /dev/null +++ b/sbin/ipf/libipf/printactiveaddr.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" + + + + +void +printactiveaddress(int v, char *fmt, i6addr_t *addr, char *ifname) +{ + switch (v) + { + case 4 : + PRINTF(fmt, inet_ntoa(addr->in4)); + break; +#ifdef USE_INET6 + case 6 : + printaddr(AF_INET6, FRI_NORMAL, ifname, 0, + (u_32_t *)&addr->in6, NULL); + break; +#endif + default : + break; + } +} diff --git a/sbin/ipf/libipf/printactivenat.c b/sbin/ipf/libipf/printactivenat.c new file mode 100644 index 000000000000..ba792d3b2be0 --- /dev/null +++ b/sbin/ipf/libipf/printactivenat.c @@ -0,0 +1,159 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" + + + +static int proto_opened = 0; + +void +printactivenat(nat_t *nat, int opts, u_long ticks) +{ + struct protoent *pproto; + + if (proto_opened == 0) { + proto_opened = 1; + setprotoent(1); + } + + PRINTF("%s", getnattype(nat)); + + if (nat->nat_flags & SI_CLONE) + PRINTF(" CLONE"); + if (nat->nat_phnext[0] == NULL && nat->nat_phnext[1] == NULL) + PRINTF(" ORPHAN"); + + putchar(' '); + if (nat->nat_redir & NAT_REWRITE) { + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_osrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_osport)); + + putchar(' '); + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_odst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_odport)); + + PRINTF("<- -> "); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_nsrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_nsport)); + + putchar(' '); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_ndst6, + nat->nat_ifnames[0]); + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_ndport)); + + pproto = getprotobynumber(nat->nat_pr[0]); + PRINTF(" %s", pproto->p_name); + + } else if (nat->nat_dir == NAT_OUTBOUND) { + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_osrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_osport)); + + PRINTF(" <- -> "); + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_nsrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_nsport)); + + PRINTF(" ["); + printactiveaddress(nat->nat_v[0], "%s", &nat->nat_odst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %hu", ntohs(nat->nat_odport)); + PRINTF("]"); + + pproto = getprotobynumber(nat->nat_pr[1]); + PRINTF(" %s", pproto->p_name); + } else { + printactiveaddress(nat->nat_v[1], "%-15s", &nat->nat_ndst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_ndport)); + + PRINTF(" <- -> "); + printactiveaddress(nat->nat_v[0], "%-15s", &nat->nat_odst6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %-5hu", ntohs(nat->nat_odport)); + + PRINTF(" ["); + printactiveaddress(nat->nat_v[0], "%s", &nat->nat_osrc6, + nat->nat_ifnames[0]); + + if ((nat->nat_flags & IPN_TCPUDP) != 0) + PRINTF(" %hu", ntohs(nat->nat_osport)); + PRINTF("]"); + + pproto = getprotobynumber(nat->nat_pr[0]); + PRINTF(" %s", pproto->p_name); + } + + + if (opts & OPT_VERBOSE) { + PRINTF("\n\tttl %lu use %hu sumd %s/", + nat->nat_age - ticks, nat->nat_use, + getsumd(nat->nat_sumd[0])); + PRINTF("%s pr %u/%u hash %u/%u flags %x\n", + getsumd(nat->nat_sumd[1]), + nat->nat_pr[0], nat->nat_pr[1], + nat->nat_hv[0], nat->nat_hv[1], nat->nat_flags); + PRINTF("\tifp %s,%s ", FORMAT_IF(nat->nat_ifnames[0]), + FORMAT_IF(nat->nat_ifnames[1])); +#ifdef USE_QUAD_T + PRINTF("bytes %"PRIu64"/%"PRIu64" pkts %"PRIu64"/%"PRIu64"", + (unsigned long long)nat->nat_bytes[0], + (unsigned long long)nat->nat_bytes[1], + (unsigned long long)nat->nat_pkts[0], + (unsigned long long)nat->nat_pkts[1]); +#else + PRINTF("bytes %lu/%lu pkts %lu/%lu", nat->nat_bytes[0], + nat->nat_bytes[1], nat->nat_pkts[0], nat->nat_pkts[1]); +#endif + PRINTF(" ipsumd %x", nat->nat_ipsumd); + } + + if (opts & OPT_DEBUG) { + PRINTF("\n\tnat_next %p _pnext %p _hm %p\n", + nat->nat_next, nat->nat_pnext, nat->nat_hm); + PRINTF("\t_hnext %p/%p _phnext %p/%p\n", + nat->nat_hnext[0], nat->nat_hnext[1], + nat->nat_phnext[0], nat->nat_phnext[1]); + PRINTF("\t_data %p _me %p _state %p _aps %p\n", + nat->nat_data, nat->nat_me, nat->nat_state, + nat->nat_aps); + PRINTF("\tfr %p ptr %p ifps %p/%p sync %p\n", + nat->nat_fr, nat->nat_ptr, nat->nat_ifps[0], + nat->nat_ifps[1], nat->nat_sync); + PRINTF("\ttqe:pnext %p next %p ifq %p parent %p/%p\n", + nat->nat_tqe.tqe_pnext, nat->nat_tqe.tqe_next, + nat->nat_tqe.tqe_ifq, nat->nat_tqe.tqe_parent, nat); + PRINTF("\ttqe:die %d touched %d flags %x state %d/%d\n", + nat->nat_tqe.tqe_die, nat->nat_tqe.tqe_touched, + nat->nat_tqe.tqe_flags, nat->nat_tqe.tqe_state[0], + nat->nat_tqe.tqe_state[1]); + } + putchar('\n'); +} diff --git a/sbin/ipf/libipf/printaddr.c b/sbin/ipf/libipf/printaddr.c new file mode 100644 index 000000000000..461f62bcad55 --- /dev/null +++ b/sbin/ipf/libipf/printaddr.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +void +printaddr(int family, int type, char *base, int ifidx, u_32_t *addr, + u_32_t *mask) +{ + char *suffix; + + switch (type) + { + case FRI_BROADCAST : + suffix = "bcast"; + break; + + case FRI_DYNAMIC : + PRINTF("%s", base + ifidx); + printmask(family, mask); + suffix = NULL; + break; + + case FRI_NETWORK : + suffix = "net"; + break; + + case FRI_NETMASKED : + suffix = "netmasked"; + break; + + case FRI_PEERADDR : + suffix = "peer"; + break; + + case FRI_LOOKUP : + suffix = NULL; + printlookup(base, (i6addr_t *)addr, (i6addr_t *)mask); + break; + + case FRI_NONE : + case FRI_NORMAL : + printhostmask(family, addr, mask); + suffix = NULL; + break; + case FRI_RANGE : + printhost(family, addr); + putchar('-'); + printhost(family, mask); + suffix = NULL; + break; + case FRI_SPLIT : + printhost(family, addr); + putchar(','); + printhost(family, mask); + suffix = NULL; + break; + default : + PRINTF("<%d>", type); + printmask(family, mask); + suffix = NULL; + break; + } + + if (suffix != NULL) { + PRINTF("%s/%s", base + ifidx, suffix); + } +} diff --git a/sbin/ipf/libipf/printaps.c b/sbin/ipf/libipf/printaps.c new file mode 100644 index 000000000000..df27c48b72c8 --- /dev/null +++ b/sbin/ipf/libipf/printaps.c @@ -0,0 +1,107 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" +#include "kmem.h" + + + + +void +printaps(ap_session_t *aps, int opts, int proto) +{ + 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); +#ifdef USE_QUAD_T + PRINTF("\tbytes %"PRIu64" pkts %"PRIu64"", + (unsigned long long)ap.aps_bytes, + (unsigned long long)ap.aps_pkts); +#else + PRINTF("\tbytes %lu pkts %lu", ap.aps_bytes, ap.aps_pkts); +#endif + PRINTF(" data %s\n", ap.aps_data ? "YES" : "NO"); + if ((proto == 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)) || \ + defined(__FreeBSD__) + 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 %x (ack %x) len %d junk %d cmds %d\n", + ftp.ftp_side[0].ftps_seq[0], + ftp.ftp_side[0].ftps_seq[1], + 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 %x (ack %x) len %d junk %d cmds %d\n", + ftp.ftp_side[1].ftps_seq[0], + ftp.ftp_side[1].ftps_seq[1], + 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)"); + } +} diff --git a/sbin/ipf/libipf/printbuf.c b/sbin/ipf/libipf/printbuf.c new file mode 100644 index 000000000000..0fef3c5de854 --- /dev/null +++ b/sbin/ipf/libipf/printbuf.c @@ -0,0 +1,31 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> + +#include "ipf.h" + + +void +printbuf(char *buf, int len, int zend) +{ + char *s; + int c; + int i; + + for (s = buf, i = len; i; i--) { + c = *s++; + if (isprint(c)) + putchar(c); + else + PRINTF("\\%03o", c); + if ((c == '\0') && zend) + break; + } +} diff --git a/sbin/ipf/libipf/printdstl_live.c b/sbin/ipf/libipf/printdstl_live.c new file mode 100644 index 000000000000..72cb75a832c9 --- /dev/null +++ b/sbin/ipf/libipf/printdstl_live.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ipl.h" + + +/* + * Because the ipf_dstnode_t can vary in size because of the interface name, + * the size may be larger than just sizeof(). + */ +ippool_dst_t * +printdstl_live( ippool_dst_t *d, int fd, char *name, int opts, + wordtab_t *fields) +{ + ipf_dstnode_t *entry, *zero; + ipflookupiter_t iter; + int printed, last; + ipfobj_t obj; + + if ((name != NULL) && strncmp(name, d->ipld_name, FR_GROUPLEN)) + return (d->ipld_next); + + entry = calloc(1, sizeof(*entry) + 64); + if (entry == NULL) + return (d->ipld_next); + zero = calloc(1, sizeof(*zero) + 64); + if (zero == NULL) { + free(entry); + return (d->ipld_next); + } + + if (fields == NULL) + printdstlistdata(d, opts); + + if ((d->ipld_flags & IPHASH_DELETE) != 0) + PRINTF("# "); + + if (opts & OPT_SAVEOUT) + PRINTF("{\n"); + + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_ptr = &iter; + obj.ipfo_size = sizeof(iter); + + iter.ili_data = entry; + iter.ili_type = IPLT_DSTLIST; + iter.ili_otype = IPFLOOKUPITER_NODE; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_unit = d->ipld_unit; + strncpy(iter.ili_name, d->ipld_name, FR_GROUPLEN); + + last = 0; + printed = 0; + + while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { + if (entry->ipfd_next == NULL) + last = 1; + if (bcmp((char *)zero, (char *)entry, sizeof(*zero)) == 0) + break; + (void) printdstlistnode(entry, bcopywrap, opts, fields); + printed++; + } + + (void) ioctl(fd, SIOCIPFDELTOK, &iter.ili_key); + free(entry); + free(zero); + + if (printed == 0) + putchar(';'); + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + return (d->ipld_next); +} diff --git a/sbin/ipf/libipf/printdstlist.c b/sbin/ipf/libipf/printdstlist.c new file mode 100644 index 000000000000..497d7004c94c --- /dev/null +++ b/sbin/ipf/libipf/printdstlist.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ippool_dst_t * +printdstlist( ippool_dst_t *pp, copyfunc_t copyfunc, char *name, int opts, + ipf_dstnode_t *nodes, wordtab_t *fields) +{ + ipf_dstnode_t *node; + ippool_dst_t dst; + + if ((*copyfunc)(pp, &dst, sizeof(dst))) + return (NULL); + + if ((name != NULL) && strncmp(name, dst.ipld_name, FR_GROUPLEN)) + return (dst.ipld_next); + + if (fields == NULL) + printdstlistdata(&dst, opts); + + if ((dst.ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + if (nodes == NULL) { + putchar(';'); + } else { + for (node = nodes; node != NULL; ) { + ipf_dstnode_t *n; + + n = calloc(1, node->ipfd_size); + if (n == NULL) + break; + if ((*copyfunc)(node, n, node->ipfd_size)) { + free(n); + return (NULL); + } + + if (opts & OPT_SAVEOUT) + PRINTF("\t"); + node = printdstlistnode(n, bcopywrap, opts, fields); + + free(n); + } + } + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + + return (dst.ipld_next); +} diff --git a/sbin/ipf/libipf/printdstlistdata.c b/sbin/ipf/libipf/printdstlistdata.c new file mode 100644 index 000000000000..546bf35cabf6 --- /dev/null +++ b/sbin/ipf/libipf/printdstlistdata.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printdstlistdata( ippool_dst_t *pool, int opts) +{ + if ((opts & OPT_DEBUG) == 0 || opts & OPT_SAVEOUT) { + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("pool "); + } else { + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("Name: %s\tRole: ", pool->ipld_name); + } + + printunit(pool->ipld_unit); + + if ((opts & OPT_DEBUG) == 0 || opts & OPT_SAVEOUT) { + PRINTF("/dstlist (name %s;", pool->ipld_name); + if (pool->ipld_policy != IPLDP_NONE) { + PRINTF(" policy "); + printdstlistpolicy(pool->ipld_policy); + putchar(';'); + } + PRINTF(")\n"); + } else { + putchar(' '); + + PRINTF("\tReferences: %d\n", pool->ipld_ref); + if ((pool->ipld_flags & IPDST_DELETE) != 0) + PRINTF("# "); + PRINTF("Policy: \n"); + printdstlistpolicy(pool->ipld_policy); + PRINTF("\n\tNodes Starting at %p\n", pool->ipld_dests); + } +} diff --git a/sbin/ipf/libipf/printdstlistnode.c b/sbin/ipf/libipf/printdstlistnode.c new file mode 100644 index 000000000000..7f0d901dfbbd --- /dev/null +++ b/sbin/ipf/libipf/printdstlistnode.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ipf_dstnode_t * +printdstlistnode(ipf_dstnode_t *inp, copyfunc_t copyfunc, int opts, + wordtab_t *fields) +{ + ipf_dstnode_t node, *np; + int i; +#ifdef USE_INET6 + char buf[INET6_ADDRSTRLEN+1]; + const char *str; +#endif + + if ((*copyfunc)(inp, &node, sizeof(node))) + return (NULL); + + np = calloc(1, node.ipfd_size); + if (np == NULL) + return (node.ipfd_next); + if ((*copyfunc)(inp, np, node.ipfd_size)) + return (NULL); + + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(np, IPLT_DSTLIST, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) == 0) { + putchar(' '); + if (np->ipfd_dest.fd_name >= 0) + PRINTF("%s:", np->ipfd_names); + if (np->ipfd_dest.fd_addr.adf_family == AF_INET) { + printip(AF_INET, (u_32_t *)&np->ipfd_dest.fd_ip); + } else { +#ifdef USE_INET6 + str = inet_ntop(AF_INET6, &np->ipfd_dest.fd_ip6, + buf, sizeof(buf) - 1); + if (str != NULL) + PRINTF("%s", str); +#endif + } + putchar(';'); + } else { + PRINTF("Interface: [%s]/%d\n", np->ipfd_names, + np->ipfd_dest.fd_name); +#ifdef USE_INET6 + str = inet_ntop(np->ipfd_dest.fd_addr.adf_family, + &np->ipfd_dest.fd_ip6, buf, sizeof(buf) - 1); + if (str != NULL) { + PRINTF("\tAddress: %s\n", str); + } +#else + PRINTF("\tAddress: %s\n", inet_ntoa(np->ipfd_dest.fd_ip)); +#endif + PRINTF( +#ifdef USE_QUAD_T + "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", +#else + "\t\tStates %d\tRef %d\tName [%s]\tUid %d\n", +#endif + np->ipfd_states, np->ipfd_ref, + np->ipfd_names, np->ipfd_uid); + } + free(np); + return (node.ipfd_next); +} diff --git a/sbin/ipf/libipf/printdstlistpolicy.c b/sbin/ipf/libipf/printdstlistpolicy.c new file mode 100644 index 000000000000..96df1bc0bce1 --- /dev/null +++ b/sbin/ipf/libipf/printdstlistpolicy.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +void +printdstlistpolicy(ippool_policy_t policy) +{ + switch (policy) + { + case IPLDP_NONE : + PRINTF("none"); + break; + case IPLDP_ROUNDROBIN : + PRINTF("round-robin"); + break; + case IPLDP_CONNECTION : + PRINTF("weighting connection"); + break; + case IPLDP_RANDOM : + PRINTF("random"); + break; + default : + break; + } +} diff --git a/sbin/ipf/libipf/printfieldhdr.c b/sbin/ipf/libipf/printfieldhdr.c new file mode 100644 index 000000000000..ba14af40499c --- /dev/null +++ b/sbin/ipf/libipf/printfieldhdr.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printfieldhdr.c,v 1.5.2.3 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printfieldhdr(wordtab_t *words, wordtab_t *field) +{ + wordtab_t *w; + char *s, *t; + + if (field->w_value == -2) { + for (w = words; w->w_word != NULL; ) { + if (w->w_value > 0) { + printfieldhdr(words, w); + w++; + if (w->w_value > 0) + putchar('\t'); + } else { + w++; + } + } + return; + } + + for (w = words; w->w_word != NULL; w++) { + if (w->w_value == field->w_value) { + if (w->w_word == field->w_word) { + s = strdup(w->w_word); + } else { + s = NULL; + } + + if ((w->w_word != field->w_word) || (s == NULL)) { + PRINTF("%s", field->w_word); + } else { + for (t = s; *t != '\0'; t++) { + if (ISALPHA(*t) && ISLOWER(*t)) + *t = TOUPPER(*t); + } + PRINTF("%s", s); + free(s); + } + } + } +} diff --git a/sbin/ipf/libipf/printfr.c b/sbin/ipf/libipf/printfr.c new file mode 100644 index 000000000000..f507c8065c82 --- /dev/null +++ b/sbin/ipf/libipf/printfr.c @@ -0,0 +1,470 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +/* + * print the filter structure in a useful way + */ +void +printfr( struct frentry *fp, ioctlfunc_t iocfunc) +{ + struct protoent *p; + u_short sec[2]; + u_32_t type; + int pr, af; + char *s; + int hash; + + pr = -2; + type = fp->fr_type & ~FR_T_BUILTIN; + + if ((fp->fr_type & FR_T_BUILTIN) != 0) + PRINTF("# Builtin: "); + + if (fp->fr_collect != 0) + PRINTF("%u ", fp->fr_collect); + + if (fp->fr_type == FR_T_CALLFUNC) { + ; + } else if (fp->fr_func != NULL) { + PRINTF("call"); + if ((fp->fr_flags & FR_CALLNOW) != 0) + PRINTF(" now"); + s = kvatoname(fp->fr_func, iocfunc); + PRINTF(" %s/%u", s ? s : "?", fp->fr_arg); + } else if (FR_ISPASS(fp->fr_flags)) + PRINTF("pass"); + else if (FR_ISBLOCK(fp->fr_flags)) { + PRINTF("block"); + } else if ((fp->fr_flags & FR_LOGMASK) == FR_LOG) { + printlog(fp); + } else if (FR_ISACCOUNT(fp->fr_flags)) + PRINTF("count"); + else if (FR_ISAUTH(fp->fr_flags)) + PRINTF("auth"); + else if (FR_ISPREAUTH(fp->fr_flags)) + PRINTF("preauth"); + else if (FR_ISNOMATCH(fp->fr_flags)) + PRINTF("nomatch"); + else if (FR_ISDECAPS(fp->fr_flags)) + PRINTF("decapsulate"); + else if (FR_ISSKIP(fp->fr_flags)) + PRINTF("skip %u", fp->fr_arg); + else { + PRINTF("%x", fp->fr_flags); + } + if (fp->fr_flags & FR_RETICMP) { + if ((fp->fr_flags & FR_RETMASK) == FR_FAKEICMP) + PRINTF(" return-icmp-as-dest"); + else if ((fp->fr_flags & FR_RETMASK) == FR_RETICMP) + PRINTF(" return-icmp"); + if (fp->fr_icode) { + if (fp->fr_icode <= MAX_ICMPCODE) + PRINTF("(%s)", + icmpcodes[(int)fp->fr_icode]); + else + PRINTF("(%d)", fp->fr_icode); + } + } else if ((fp->fr_flags & FR_RETMASK) == FR_RETRST) + PRINTF(" return-rst"); + + if (fp->fr_flags & FR_OUTQUE) + PRINTF(" out "); + else if (fp->fr_flags & FR_INQUE) + PRINTF(" in "); + + if (((fp->fr_flags & FR_LOGB) == FR_LOGB) || + ((fp->fr_flags & FR_LOGP) == FR_LOGP)) { + printlog(fp); + putchar(' '); + } + + if (fp->fr_flags & FR_QUICK) + PRINTF("quick "); + + if (fp->fr_ifnames[0] != -1) { + printifname("on ", fp->fr_names + fp->fr_ifnames[0], + fp->fr_ifa); + if (fp->fr_ifnames[1] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[1], "*")) + printifname(",", fp->fr_names + fp->fr_ifnames[1], + fp->fr_ifas[1]); + putchar(' '); + } + + if (fp->fr_tif.fd_name != -1) + print_toif(fp->fr_family, "to", fp->fr_names, &fp->fr_tif); + if (fp->fr_dif.fd_name != -1) + print_toif(fp->fr_family, "dup-to", fp->fr_names, + &fp->fr_dif); + if (fp->fr_rif.fd_name != -1) + print_toif(fp->fr_family, "reply-to", fp->fr_names, + &fp->fr_rif); + if (fp->fr_flags & FR_FASTROUTE) + PRINTF("fastroute "); + + if ((fp->fr_ifnames[2] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[2], "*")) || + (fp->fr_ifnames[3] != -1 && + strcmp(fp->fr_names + fp->fr_ifnames[3], "*"))) { + if (fp->fr_flags & FR_OUTQUE) + PRINTF("in-via "); + else + PRINTF("out-via "); + + if (fp->fr_ifnames[2] != -1) { + printifname("", fp->fr_names + fp->fr_ifnames[2], + fp->fr_ifas[2]); + if (fp->fr_ifnames[3] != -1) { + printifname(",", + fp->fr_names + fp->fr_ifnames[3], + fp->fr_ifas[3]); + } + putchar(' '); + } + } + + if (fp->fr_family == AF_INET) { + PRINTF("inet "); + af = AF_INET; +#ifdef USE_INET6 + } else if (fp->fr_family == AF_INET6) { + PRINTF("inet6 "); + af = AF_INET6; +#endif + } else { + af = -1; + } + + if (type == FR_T_IPF) { + if (fp->fr_mip.fi_tos) + PRINTF("tos %#x ", fp->fr_tos); + if (fp->fr_mip.fi_ttl) + PRINTF("ttl %d ", fp->fr_ttl); + if (fp->fr_flx & FI_TCPUDP) { + PRINTF("proto tcp/udp "); + pr = -1; + } else if (fp->fr_mip.fi_p) { + pr = fp->fr_ip.fi_p; + p = getprotobynumber(pr); + PRINTF("proto "); + printproto(p, pr, NULL); + putchar(' '); + } + } + + switch (type) + { + case FR_T_NONE : + PRINTF("all"); + break; + + case FR_T_IPF : + PRINTF("from %s", fp->fr_flags & FR_NOTSRCIP ? "!" : ""); + printaddr(af, fp->fr_satype, fp->fr_names, fp->fr_ifnames[0], + &fp->fr_src.s_addr, &fp->fr_smsk.s_addr); + if (fp->fr_scmp) + printportcmp(pr, &fp->fr_tuc.ftu_src); + + PRINTF(" to %s", fp->fr_flags & FR_NOTDSTIP ? "!" : ""); + printaddr(af, fp->fr_datype, fp->fr_names, fp->fr_ifnames[0], + &fp->fr_dst.s_addr, &fp->fr_dmsk.s_addr); + if (fp->fr_dcmp) + printportcmp(pr, &fp->fr_tuc.ftu_dst); + + if (((fp->fr_proto == IPPROTO_ICMP) || + (fp->fr_proto == IPPROTO_ICMPV6)) && fp->fr_icmpm) { + int type = fp->fr_icmp, code; + char *name; + + type = ntohs(fp->fr_icmp); + code = type & 0xff; + type /= 256; + name = icmptypename(fp->fr_family, type); + if (name == NULL) + PRINTF(" icmp-type %d", type); + else + PRINTF(" icmp-type %s", name); + if (ntohs(fp->fr_icmpm) & 0xff) + PRINTF(" code %d", code); + } + if ((fp->fr_proto == IPPROTO_TCP) && + (fp->fr_tcpf || fp->fr_tcpfm)) { + PRINTF(" flags "); + printtcpflags(fp->fr_tcpf, fp->fr_tcpfm); + } + break; + + case FR_T_BPFOPC : + { + fakebpf_t *fb; + int i; + + PRINTF("bpf-v%d { \"", fp->fr_family); + i = fp->fr_dsize / sizeof(*fb); + + for (fb = fp->fr_data, s = ""; i; i--, fb++, s = " ") + PRINTF("%s%#x %#x %#x %#x", s, fb->fb_c, fb->fb_t, + fb->fb_f, fb->fb_k); + + PRINTF("\" }"); + break; + } + + case FR_T_COMPIPF : + break; + + case FR_T_CALLFUNC : + PRINTF("call function at %p", fp->fr_data); + break; + + case FR_T_IPFEXPR : + PRINTF("exp { \""); + printipfexpr(fp->fr_data); + PRINTF("\" } "); + break; + + default : + PRINTF("[unknown filter type %#x]", fp->fr_type); + break; + } + + if ((type == FR_T_IPF) && + ((fp->fr_flx & FI_WITH) || (fp->fr_mflx & FI_WITH) || + fp->fr_optbits || fp->fr_optmask || + fp->fr_secbits || fp->fr_secmask)) { + char *comma = " "; + + PRINTF(" with"); + if (fp->fr_optbits || fp->fr_optmask || + fp->fr_secbits || fp->fr_secmask) { + sec[0] = fp->fr_secmask; + sec[1] = fp->fr_secbits; + if (fp->fr_family == AF_INET) + optprint(sec, fp->fr_optmask, fp->fr_optbits); +#ifdef USE_INET6 + else + optprintv6(sec, fp->fr_optmask, + fp->fr_optbits); +#endif + } else if (fp->fr_mflx & FI_OPTIONS) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_OPTIONS)) + PRINTF("not "); + PRINTF("ipopts"); + comma = ","; + } + if (fp->fr_mflx & FI_SHORT) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_SHORT)) + PRINTF("not "); + PRINTF("short"); + comma = ","; + } + if (fp->fr_mflx & FI_FRAG) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_FRAG)) + PRINTF("not "); + PRINTF("frag"); + comma = ","; + } + if (fp->fr_mflx & FI_FRAGBODY) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_FRAGBODY)) + PRINTF("not "); + PRINTF("frag-body"); + comma = ","; + } + if (fp->fr_mflx & FI_NATED) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_NATED)) + PRINTF("not "); + PRINTF("nat"); + comma = ","; + } + if (fp->fr_mflx & FI_LOWTTL) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_LOWTTL)) + PRINTF("not "); + PRINTF("lowttl"); + comma = ","; + } + if (fp->fr_mflx & FI_BAD) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BAD)) + PRINTF("not "); + PRINTF("bad"); + comma = ","; + } + if (fp->fr_mflx & FI_BADSRC) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BADSRC)) + PRINTF("not "); + PRINTF("bad-src"); + comma = ","; + } + if (fp->fr_mflx & FI_BADNAT) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BADNAT)) + PRINTF("not "); + PRINTF("bad-nat"); + comma = ","; + } + if (fp->fr_mflx & FI_OOW) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_OOW)) + PRINTF("not "); + PRINTF("oow"); + comma = ","; + } + if (fp->fr_mflx & FI_MBCAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_MBCAST)) + PRINTF("not "); + PRINTF("mbcast"); + comma = ","; + } + if (fp->fr_mflx & FI_BROADCAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_BROADCAST)) + PRINTF("not "); + PRINTF("bcast"); + comma = ","; + } + if (fp->fr_mflx & FI_MULTICAST) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_MULTICAST)) + PRINTF("not "); + PRINTF("mcast"); + comma = ","; + } + if (fp->fr_mflx & FI_STATE) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_STATE)) + PRINTF("not "); + PRINTF("state"); + comma = ","; + } + if (fp->fr_mflx & FI_V6EXTHDR) { + fputs(comma, stdout); + if (!(fp->fr_flx & FI_V6EXTHDR)) + PRINTF("not "); + PRINTF("v6hdrs"); + comma = ","; + } + } + + if (fp->fr_flags & FR_KEEPSTATE) { + host_track_t *src = &fp->fr_srctrack; + PRINTF(" keep state"); + if ((fp->fr_flags & (FR_STSTRICT|FR_NEWISN| + FR_NOICMPERR|FR_STATESYNC)) || + (fp->fr_statemax != 0) || (fp->fr_age[0] != 0) || + (src->ht_max_nodes != 0)) { + char *comma = ""; + PRINTF(" ("); + if (fp->fr_statemax != 0) { + PRINTF("limit %u", fp->fr_statemax); + comma = ","; + } + if (src->ht_max_nodes != 0) { + PRINTF("%smax-nodes %d", comma, + src->ht_max_nodes); + if (src->ht_max_per_node) + PRINTF(", max-per-src %d/%d", + src->ht_max_per_node, + src->ht_netmask); + comma = ","; + } + if (fp->fr_flags & FR_STSTRICT) { + PRINTF("%sstrict", comma); + comma = ","; + } + if (fp->fr_flags & FR_STLOOSE) { + PRINTF("%sloose", comma); + comma = ","; + } + if (fp->fr_flags & FR_NEWISN) { + PRINTF("%snewisn", comma); + comma = ","; + } + if (fp->fr_flags & FR_NOICMPERR) { + PRINTF("%sno-icmp-err", comma); + comma = ","; + } + if (fp->fr_flags & FR_STATESYNC) { + PRINTF("%ssync", comma); + comma = ","; + } + if (fp->fr_age[0] || fp->fr_age[1]) + PRINTF("%sage %d/%d", comma, fp->fr_age[0], + fp->fr_age[1]); + PRINTF(")"); + } + } + if (fp->fr_flags & FR_KEEPFRAG) { + PRINTF(" keep frags"); + if (fp->fr_flags & (FR_FRSTRICT)) { + PRINTF(" ("); + if (fp->fr_flags & FR_FRSTRICT) + PRINTF("strict"); + PRINTF(")"); + + } + } + if (fp->fr_isc != (struct ipscan *)-1) { + if (fp->fr_isctag != -1) + PRINTF(" scan %s", fp->fr_isctag + fp->fr_names); + else + PRINTF(" scan *"); + } + if (fp->fr_grhead != -1) + PRINTF(" head %s", fp->fr_names + fp->fr_grhead); + if (fp->fr_group != -1) + PRINTF(" group %s", fp->fr_names + fp->fr_group); + if (fp->fr_logtag != FR_NOLOGTAG || *fp->fr_nattag.ipt_tag) { + char *s = ""; + + PRINTF(" set-tag("); + if (fp->fr_logtag != FR_NOLOGTAG) { + PRINTF("log=%u", fp->fr_logtag); + s = ", "; + } + if (*fp->fr_nattag.ipt_tag) { + PRINTF("%snat=%-.*s", s, IPFTAG_LEN, + fp->fr_nattag.ipt_tag); + } + PRINTF(")"); + } + + if (fp->fr_pps) + PRINTF(" pps %d", fp->fr_pps); + + if (fp->fr_comment != -1) + PRINTF(" comment \"%s\"", fp->fr_names + fp->fr_comment); + + hash = 0; + if ((fp->fr_flags & FR_KEEPSTATE) && (opts & OPT_VERBOSE)) { + PRINTF(" # count %d", fp->fr_statecnt); + if (fp->fr_die != 0) + PRINTF(" rule-ttl %u", fp->fr_die); + hash = 1; + } else if (fp->fr_die != 0) { + PRINTF(" # rule-ttl %u", fp->fr_die); + hash = 1; + } + if (opts & OPT_DEBUG) { + if (hash == 0) + putchar('#'); + PRINTF(" ref %d", fp->fr_ref); + } + (void)putchar('\n'); +} diff --git a/sbin/ipf/libipf/printfraginfo.c b/sbin/ipf/libipf/printfraginfo.c new file mode 100644 index 000000000000..4693e9335ffb --- /dev/null +++ b/sbin/ipf/libipf/printfraginfo.c @@ -0,0 +1,32 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" +#include "kmem.h" + + +void +printfraginfo(char *prefix, struct ipfr *ifr) +{ + int family; + + PRINTF("%s", prefix); + if (ifr->ipfr_v == 6) { + PRINTF("inet6"); + family = AF_INET6; + } else { + PRINTF("inet"); + family = AF_INET; + } + + PRINTF(" %s -> ", hostname(family, &ifr->ipfr_src)); + PRINTF("%s id %x ttl %lu pr %d pkts %u bytes %u seen0 %d ref %d\n", + hostname(family, &ifr->ipfr_dst), ifr->ipfr_id, + ifr->ipfr_ttl, ifr->ipfr_p, ifr->ipfr_pkts, ifr->ipfr_bytes, + ifr->ipfr_seen0, ifr->ipfr_ref); +} diff --git a/sbin/ipf/libipf/printhash.c b/sbin/ipf/libipf/printhash.c new file mode 100644 index 000000000000..f5ebb57a1c33 --- /dev/null +++ b/sbin/ipf/libipf/printhash.c @@ -0,0 +1,53 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +iphtable_t * +printhash( iphtable_t *hp, copyfunc_t copyfunc, char *name, int opts, + wordtab_t *fields) +{ + iphtent_t *ipep, **table; + iphtable_t iph; + int printed; + size_t sz; + + if ((*copyfunc)((char *)hp, (char *)&iph, sizeof(iph))) + return (NULL); + + if ((name != NULL) && strncmp(name, iph.iph_name, FR_GROUPLEN)) + return (iph.iph_next); + + if (fields == NULL) + printhashdata(hp, opts); + + if ((hp->iph_flags & IPHASH_DELETE) != 0) + PRINTF("# "); + + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + sz = iph.iph_size * sizeof(*table); + table = malloc(sz); + if ((*copyfunc)((char *)iph.iph_table, (char *)table, sz)) + return (NULL); + + for (printed = 0, ipep = iph.iph_list; ipep != NULL; ) { + ipep = printhashnode(&iph, ipep, copyfunc, opts, fields); + printed++; + } + if (printed == 0) + putchar(';'); + + free(table); + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + + return (iph.iph_next); +} diff --git a/sbin/ipf/libipf/printhash_live.c b/sbin/ipf/libipf/printhash_live.c new file mode 100644 index 000000000000..427daa18316b --- /dev/null +++ b/sbin/ipf/libipf/printhash_live.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ipl.h" + + +iphtable_t * +printhash_live(iphtable_t *hp, int fd, char *name, int opts, wordtab_t *fields) +{ + iphtent_t entry, zero; + ipflookupiter_t iter; + int last, printed; + ipfobj_t obj; + + if ((name != NULL) && strncmp(name, hp->iph_name, FR_GROUPLEN)) + return (hp->iph_next); + + if (fields == NULL) + printhashdata(hp, opts); + + if ((hp->iph_flags & IPHASH_DELETE) != 0) + PRINTF("# "); + + if (opts & OPT_SAVEOUT) + PRINTF("{\n"); + else if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_ptr = &iter; + obj.ipfo_size = sizeof(iter); + + iter.ili_data = &entry; + iter.ili_type = IPLT_HASH; + iter.ili_otype = IPFLOOKUPITER_NODE; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_unit = hp->iph_unit; + strncpy(iter.ili_name, hp->iph_name, FR_GROUPLEN); + + last = 0; + printed = 0; + bzero((char *)&zero, sizeof(zero)); + + while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { + if (entry.ipe_next == NULL) + last = 1; + if (bcmp(&zero, &entry, sizeof(zero)) == 0) + break; + if (opts & OPT_SAVEOUT) + PRINTF("\t"); + (void) printhashnode(hp, &entry, bcopywrap, opts, fields); + printed++; + } + if (last == 0) + ipferror(fd, "walking hash nodes"); + + if (printed == 0) + putchar(';'); + + if ((opts & OPT_DEBUG) == 0 || (opts & OPT_SAVEOUT)) + PRINTF(" };\n"); + + (void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key); + + return (hp->iph_next); +} diff --git a/sbin/ipf/libipf/printhashdata.c b/sbin/ipf/libipf/printhashdata.c new file mode 100644 index 000000000000..6fa62e67556d --- /dev/null +++ b/sbin/ipf/libipf/printhashdata.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printhashdata(iphtable_t *hp, int opts) +{ + + if (opts & OPT_SAVEOUT) { + if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE) + PRINTF("# "); + PRINTF("pool "); + } else if ((opts & OPT_DEBUG) == 0) { + if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON) + PRINTF("# 'anonymous' table refs %d\n", hp->iph_ref); + if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE) + PRINTF("# "); + switch (hp->iph_type & ~IPHASH_ANON) + { + case IPHASH_LOOKUP : + PRINTF("table"); + break; + case IPHASH_GROUPMAP : + PRINTF("group-map"); + if (hp->iph_flags & FR_INQUE) + PRINTF(" in"); + else if (hp->iph_flags & FR_OUTQUE) + PRINTF(" out"); + else + PRINTF(" ???"); + break; + default : + PRINTF("%#x", hp->iph_type); + break; + } + PRINTF(" role="); + } else { + if ((hp->iph_flags & IPHASH_DELETE) == IPHASH_DELETE) + PRINTF("# "); + PRINTF("Hash Table %s: %s", + ISDIGIT(*hp->iph_name) ? "Number" : "Name", + hp->iph_name); + if ((hp->iph_type & IPHASH_ANON) == IPHASH_ANON) + PRINTF("(anon)"); + putchar(' '); + PRINTF("Role: "); + } + + printunit(hp->iph_unit); + + if ((opts & OPT_SAVEOUT)) { + if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP) + PRINTF("/hash"); + PRINTF("(%s \"%s\"; size %lu;", + ISDIGIT(*hp->iph_name) ? "number" : "name", + hp->iph_name, (u_long)hp->iph_size); + if (hp->iph_seed != 0) + PRINTF(" seed %lu;", hp->iph_seed); + PRINTF(")\n", hp->iph_seed); + } else if ((opts & OPT_DEBUG) == 0) { + if ((hp->iph_type & ~IPHASH_ANON) == IPHASH_LOOKUP) + PRINTF(" type=hash"); + PRINTF(" %s=%s size=%lu", + ISDIGIT(*hp->iph_name) ? "number" : "name", + hp->iph_name, (u_long)hp->iph_size); + if (hp->iph_seed != 0) + PRINTF(" seed=%lu", hp->iph_seed); + putchar('\n'); + } else { + PRINTF(" Type: "); + switch (hp->iph_type & ~IPHASH_ANON) + { + case IPHASH_LOOKUP : + PRINTF("lookup"); + break; + case IPHASH_GROUPMAP : + PRINTF("groupmap Group. %s", hp->iph_name); + break; + default : + break; + } + + putchar('\n'); + PRINTF("\t\tSize: %lu\tSeed: %lu", + (u_long)hp->iph_size, hp->iph_seed); + PRINTF("\tRef. Count: %d\tMasks: %#x\n", hp->iph_ref, + hp->iph_maskset[0]); + } + + if ((opts & OPT_DEBUG) != 0) { + struct in_addr m; + int i; + + for (i = 0; i < 32; i++) { + if ((1 << i) & hp->iph_maskset[0]) { + ntomask(AF_INET, i, &m.s_addr); + PRINTF("\t\tMask: %s\n", inet_ntoa(m)); + } + } + } +} diff --git a/sbin/ipf/libipf/printhashnode.c b/sbin/ipf/libipf/printhashnode.c new file mode 100644 index 000000000000..b3c7140c84d3 --- /dev/null +++ b/sbin/ipf/libipf/printhashnode.c @@ -0,0 +1,93 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +iphtent_t * +printhashnode(iphtable_t *iph, iphtent_t *ipep, copyfunc_t copyfunc, int opts, + wordtab_t *fields) +{ + iphtent_t ipe; + u_int hv; + int i; + + if ((*copyfunc)(ipep, &ipe, sizeof(ipe))) + return (NULL); + + hv = IPE_V4_HASH_FN(ipe.ipe_addr.i6[0], ipe.ipe_mask.i6[0], + iph->iph_size); + + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(&ipe, IPLT_HASH, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) != 0) { +#ifdef USE_INET6 + if (ipe.ipe_family == AF_INET6) { + char buf[INET6_ADDRSTRLEN + 1]; + const char *str; + + buf[0] = '\0'; + str = inet_ntop(AF_INET6, &ipe.ipe_addr.in6, + buf, sizeof(buf) - 1); + if (str == NULL) + str = "???"; + PRINTF("\t%d\tAddress: %s", hv, str); + printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); + PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, + ipe.ipe_group); +#ifdef USE_QUAD_T + PRINTF("\tHits: %"PRIu64"\tBytes: %"PRIu64"\n", + ipe.ipe_hits, ipe.ipe_bytes); +#else + PRINTF("\tHits: %lu\tBytes: %lu\n", + ipe.ipe_hits, ipe.ipe_bytes); +#endif /* USE_QUAD_T */ + } else if (ipe.ipe_family == AF_INET) { +#else + if (ipe.ipe_family == AF_INET) { +#endif /* USE_INET6 */ + PRINTF("\t%d\tAddress: %s", hv, + inet_ntoa(ipe.ipe_addr.in4)); + printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); + PRINTF("\tRef. Count: %d\tGroup: %s\n", ipe.ipe_ref, + ipe.ipe_group); +#ifdef USE_QUAD_T + PRINTF("\tHits: %"PRIu64"\tBytes: %"PRIu64"\n", + ipe.ipe_hits, ipe.ipe_bytes); +#else + PRINTF("\tHits: %lu\tBytes: %lu\n", + ipe.ipe_hits, ipe.ipe_bytes); +#endif /* USE_QUAD_T */ + } else { + PRINTF("\tAddress: family: %d\n", + ipe.ipe_family); + } + } else { + putchar(' '); + printip(ipe.ipe_family, (u_32_t *)&ipe.ipe_addr.in4_addr); + printmask(ipe.ipe_family, (u_32_t *)&ipe.ipe_mask.in4_addr); + if (ipe.ipe_value != 0) { + switch (iph->iph_type & ~IPHASH_ANON) + { + case IPHASH_GROUPMAP : + if (strncmp(ipe.ipe_group, iph->iph_name, + FR_GROUPLEN)) + PRINTF(", group=%s", ipe.ipe_group); + break; + } + } + putchar(';'); + } + + ipep = ipe.ipe_next; + return (ipep); +} diff --git a/sbin/ipf/libipf/printhost.c b/sbin/ipf/libipf/printhost.c new file mode 100644 index 000000000000..e04882ffe614 --- /dev/null +++ b/sbin/ipf/libipf/printhost.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printhost.c,v 1.3.2.2 2012/07/22 08:04:24 darren_r Exp $ + */ + +#include "ipf.h" + + +void +printhost(int family, u_32_t *addr) +{ +#ifdef USE_INET6 + char ipbuf[64]; +#else + struct in_addr ipa; +#endif + + if ((family == -1) || !*addr) + PRINTF("any"); + else { +#ifdef USE_INET6 + void *ptr = addr; + + PRINTF("%s", inet_ntop(family, ptr, ipbuf, sizeof(ipbuf))); +#else + ipa.s_addr = *addr; + PRINTF("%s", inet_ntoa(ipa)); +#endif + } +} diff --git a/sbin/ipf/libipf/printhostmap.c b/sbin/ipf/libipf/printhostmap.c new file mode 100644 index 000000000000..bd8b71ceec16 --- /dev/null +++ b/sbin/ipf/libipf/printhostmap.c @@ -0,0 +1,28 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +void +printhostmap(hostmap_t *hmp, u_int hv) +{ + + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_osrcip6, NULL); + putchar(','); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_odstip6, NULL); + PRINTF(" -> "); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_nsrcip6, NULL); + putchar(','); + printactiveaddress(hmp->hm_v, "%s", &hmp->hm_ndstip6, NULL); + putchar(' '); + PRINTF("(use = %d", hmp->hm_ref); + if (opts & OPT_VERBOSE) + PRINTF(" hv = %u", hv); + printf(")\n"); +} diff --git a/sbin/ipf/libipf/printhostmask.c b/sbin/ipf/libipf/printhostmask.c new file mode 100644 index 000000000000..7f607dbedcfc --- /dev/null +++ b/sbin/ipf/libipf/printhostmask.c @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printhostmask( int family, u_32_t *addr, u_32_t *mask) +{ +#ifdef USE_INET6 + char ipbuf[64]; +#else + struct in_addr ipa; +#endif + + if ((family == -1) || ((!addr || !*addr) && (!mask || !*mask))) + PRINTF("any"); + else { +#ifdef USE_INET6 + void *ptr = addr; + + PRINTF("%s", inet_ntop(family, ptr, ipbuf, sizeof(ipbuf))); +#else + ipa.s_addr = *addr; + PRINTF("%s", inet_ntoa(ipa)); +#endif + if (mask != NULL) + printmask(family, mask); + } +} diff --git a/sbin/ipf/libipf/printifname.c b/sbin/ipf/libipf/printifname.c new file mode 100644 index 000000000000..4f19c30aef2a --- /dev/null +++ b/sbin/ipf/libipf/printifname.c @@ -0,0 +1,19 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printifname(char *format, char *name, void *ifp) +{ + PRINTF("%s%s", format, name); + if ((ifp == NULL) && strcmp(name, "-") && strcmp(name, "*")) + PRINTF("(!)"); +} diff --git a/sbin/ipf/libipf/printip.c b/sbin/ipf/libipf/printip.c new file mode 100644 index 000000000000..e4249541f946 --- /dev/null +++ b/sbin/ipf/libipf/printip.c @@ -0,0 +1,40 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printip(int family, u_32_t *addr) +{ + struct in_addr ipa; + + if (family == AF_INET) { + ipa.s_addr = *addr; + if (ntohl(ipa.s_addr) < 256) + PRINTF("%lu", (u_long)ntohl(ipa.s_addr)); + else + PRINTF("%s", inet_ntoa(ipa)); + } +#ifdef USE_INET6 + else if (family == AF_INET6) { + char buf[INET6_ADDRSTRLEN + 1]; + const char *str; + + buf[0] = '\0'; + str = inet_ntop(AF_INET6, addr, buf, sizeof(buf) - 1); + if (str != NULL) + PRINTF("%s", str); + else + PRINTF("???"); + } +#endif + else + PRINTF("?(%d)?", family); +} diff --git a/sbin/ipf/libipf/printipfexpr.c b/sbin/ipf/libipf/printipfexpr.c new file mode 100644 index 000000000000..535bee6f6b3e --- /dev/null +++ b/sbin/ipf/libipf/printipfexpr.c @@ -0,0 +1,194 @@ +#include "ipf.h" + +static void printport(int *); +static void printhosts(int *); +static void printsingle(int *); +#ifdef USE_INET6 +static void printhostsv6(int *); +#endif + +void +printipfexpr(int *array) +{ + int i, nelems, j, not; + ipfexp_t *ipfe; + + nelems = array[0]; + + for (i = 1; i < nelems; ) { + ipfe = (ipfexp_t *)(array + i); + if (ipfe->ipfe_cmd == IPF_EXP_END) + break; + + not = ipfe->ipfe_not; + + switch (ipfe->ipfe_cmd) + { + case IPF_EXP_IP_ADDR : + PRINTF("ip.addr %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_IP_PR : + PRINTF("ip.p %s= ", not ? "!" : ""); + printsingle(array + i); + break; + + case IPF_EXP_IP_SRCADDR : + PRINTF("ip.src %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_IP_DSTADDR : + PRINTF("ip.dst %s= ", not ? "!" : ""); + printhosts(array + i); + break; + + case IPF_EXP_TCP_PORT : + PRINTF("tcp.port %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_DPORT : + PRINTF("tcp.dport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_SPORT : + PRINTF("tcp.sport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_TCP_FLAGS : + PRINTF("tcp.flags %s= ", not ? "!" : ""); + + for (j = 0; j < ipfe->ipfe_narg; ) { + printtcpflags(array[i + 4], array[i + 5]); + j += 2; + if (j < array[4]) + putchar(','); + } + break; + + case IPF_EXP_UDP_PORT : + PRINTF("udp.port %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_UDP_DPORT : + PRINTF("udp.dport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_UDP_SPORT : + PRINTF("udp.sport %s= ", not ? "!" : ""); + printport(array + i); + break; + + case IPF_EXP_IDLE_GT : + PRINTF("idle-gt %s= ", not ? "!" : ""); + printsingle(array + i); + break; + + case IPF_EXP_TCP_STATE : + PRINTF("tcp-state %s= ", not ? "!" : ""); + printsingle(array + i); + break; + +#ifdef USE_INET6 + case IPF_EXP_IP6_ADDR : + PRINTF("ip6.addr %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; + + case IPF_EXP_IP6_SRCADDR : + PRINTF("ip6.src %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; + + case IPF_EXP_IP6_DSTADDR : + PRINTF("ip6.dst %s= ", not ? "!" : ""); + printhostsv6(array + i); + break; +#endif + + case IPF_EXP_END : + break; + + default : + PRINTF("#%#x,len=%d;", + ipfe->ipfe_cmd, ipfe->ipfe_narg); + } + + if (array[i] != IPF_EXP_END) + putchar(';'); + + i += ipfe->ipfe_size; + if (array[i] != IPF_EXP_END) + putchar(' '); + } +} + + +static void +printsingle(int *array) +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i; + + for (i = 0; i < ipfe->ipfe_narg; ) { + PRINTF("%d", array[i + 4]); + i++; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +static void +printport(int *array) +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i; + + for (i = 0; i < ipfe->ipfe_narg; ) { + PRINTF("%d", ntohs(array[i + 4])); + i++; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +static void +printhosts(int *array) +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i, j; + + for (i = 0, j = 0; i < ipfe->ipfe_narg; j++) { + printhostmask(AF_INET, (u_32_t *)ipfe->ipfe_arg0 + j * 2, + (u_32_t *)ipfe->ipfe_arg0 + j * 2 + 1); + i += 2; + if (i < ipfe->ipfe_narg) + putchar(','); + } +} + + +#ifdef USE_INET6 +static void +printhostsv6(int *array) +{ + ipfexp_t *ipfe = (ipfexp_t *)array; + int i, j; + + for (i = 4, j= 0; i < ipfe->ipfe_size; j++) { + printhostmask(AF_INET6, (u_32_t *)ipfe->ipfe_arg0 + j * 8, + (u_32_t *)ipfe->ipfe_arg0 + j * 8 + 4); + i += 8; + if (i < ipfe->ipfe_size) + putchar(','); + } +} +#endif diff --git a/sbin/ipf/libipf/printiphdr.c b/sbin/ipf/libipf/printiphdr.c new file mode 100644 index 000000000000..500b4dcb6ad4 --- /dev/null +++ b/sbin/ipf/libipf/printiphdr.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printiphdr.c,v 1.1 2009/03/01 12:48:32 darren_r Exp $ + */ + +#include "ipf.h" + + +void +printiphdr(ip_t *ip) +{ + PRINTF("ip(v=%d,hl=%d,len=%d,tos=%#x,off=%#x,sum=%#x,src=%#x,dst=%#x", + ip->ip_v, ip->ip_hl, ntohs(ip->ip_len), ip->ip_tos, + ntohs(ip->ip_off), ntohs(ip->ip_sum), ntohl(ip->ip_src.s_addr), + ntohl(ip->ip_dst.s_addr)); +} diff --git a/sbin/ipf/libipf/printlog.c b/sbin/ipf/libipf/printlog.c new file mode 100644 index 000000000000..c9faf40595c9 --- /dev/null +++ b/sbin/ipf/libipf/printlog.c @@ -0,0 +1,37 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#include <syslog.h> + + +void +printlog(frentry_t *fp) +{ + char *s, *u; + + PRINTF("log"); + if (fp->fr_flags & FR_LOGBODY) + PRINTF(" body"); + if (fp->fr_flags & FR_LOGFIRST) + PRINTF(" first"); + if (fp->fr_flags & FR_LOGORBLOCK) + PRINTF(" or-block"); + if (fp->fr_loglevel != 0xffff) { + PRINTF(" level "); + s = fac_toname(fp->fr_loglevel); + if (s == NULL || *s == '\0') + s = "!!!"; + u = pri_toname(fp->fr_loglevel); + if (u == NULL || *u == '\0') + u = "!!!"; + PRINTF("%s.%s", s, u); + } +} diff --git a/sbin/ipf/libipf/printlookup.c b/sbin/ipf/libipf/printlookup.c new file mode 100644 index 000000000000..c18faf61fbbb --- /dev/null +++ b/sbin/ipf/libipf/printlookup.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printlookup(char *base, i6addr_t *addr, i6addr_t *mask) +{ + char name[32]; + + switch (addr->iplookuptype) + { + case IPLT_POOL : + PRINTF("pool/"); + break; + case IPLT_HASH : + PRINTF("hash/"); + break; + case IPLT_DSTLIST : + PRINTF("dstlist/"); + break; + default : + PRINTF("lookup(%x)=", addr->iplookuptype); + break; + } + + if (addr->iplookupsubtype == 0) + PRINTF("%u", addr->iplookupnum); + else if (addr->iplookupsubtype == 1) { + strncpy(name, base + addr->iplookupname, sizeof(name)); + name[sizeof(name) - 1] = '\0'; + PRINTF("%s", name); + } +} diff --git a/sbin/ipf/libipf/printmask.c b/sbin/ipf/libipf/printmask.c new file mode 100644 index 000000000000..bdb28d8ee4a2 --- /dev/null +++ b/sbin/ipf/libipf/printmask.c @@ -0,0 +1,27 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printmask(int family, u_32_t *mask) +{ + struct in_addr ipa; + int ones; + + if (family == AF_INET6) { + PRINTF("/%d", count6bits(mask)); + } else if ((ones = count4bits(*mask)) == -1) { + ipa.s_addr = *mask; + PRINTF("/%s", inet_ntoa(ipa)); + } else { + PRINTF("/%d", ones); + } +} diff --git a/sbin/ipf/libipf/printnat.c b/sbin/ipf/libipf/printnat.c new file mode 100644 index 000000000000..0b032955c8d8 --- /dev/null +++ b/sbin/ipf/libipf/printnat.c @@ -0,0 +1,347 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" +#include "kmem.h" + + + + +/* + * Print out a NAT rule + */ +void +printnat(ipnat_t *np, int opts) +{ + struct protoent *pr; + char *base; + int family; + int proto; + + if (np->in_v[0] == 4) + family = AF_INET; +#ifdef USE_INET6 + else if (np->in_v[0] == 6) + family = AF_INET6; +#endif + else + family = AF_UNSPEC; + + if (np->in_flags & IPN_NO) + PRINTF("no "); + + switch (np->in_redir) + { + case NAT_REDIRECT|NAT_ENCAP : + PRINTF("encap in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_ENCAP : + PRINTF("encap out on"); + proto = np->in_pr[1]; + break; + case NAT_REDIRECT|NAT_DIVERTUDP : + PRINTF("divert in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_DIVERTUDP : + PRINTF("divert out on"); + proto = np->in_pr[1]; + break; + case NAT_REDIRECT|NAT_REWRITE : + PRINTF("rewrite in on"); + proto = np->in_pr[0]; + break; + case NAT_MAP|NAT_REWRITE : + PRINTF("rewrite out on"); + proto = np->in_pr[1]; + break; + case NAT_REDIRECT : + PRINTF("rdr"); + proto = np->in_pr[0]; + break; + case NAT_MAP : + PRINTF("map"); + proto = np->in_pr[1]; + break; + case NAT_MAPBLK : + PRINTF("map-block"); + proto = np->in_pr[1]; + break; + case NAT_BIMAP : + PRINTF("bimap"); + proto = np->in_pr[0]; + break; + default : + FPRINTF(stderr, "unknown value for in_redir: %#x\n", + np->in_redir); + proto = np->in_pr[0]; + break; + } + + pr = getprotobynumber(proto); + + base = np->in_names; + if (!strcmp(base + np->in_ifnames[0], "-")) + PRINTF(" \"%s\"", base + np->in_ifnames[0]); + else + PRINTF(" %s", base + np->in_ifnames[0]); + if ((np->in_ifnames[1] != -1) && + (strcmp(base + np->in_ifnames[0], base + np->in_ifnames[1]) != 0)) { + if (!strcmp(base + np->in_ifnames[1], "-")) + PRINTF(",\"%s\"", base + np->in_ifnames[1]); + else + PRINTF(",%s", base + np->in_ifnames[1]); + } + putchar(' '); + + if (family == AF_INET6) + PRINTF("inet6 "); + + if (np->in_redir & (NAT_REWRITE|NAT_ENCAP|NAT_DIVERTUDP)) { + if ((proto != 0) || (np->in_flags & IPN_TCPUDP)) { + PRINTF("proto "); + printproto(pr, proto, np); + putchar(' '); + } + } + + if (np->in_flags & IPN_FILTER) { + if (np->in_flags & IPN_NOTSRC) + PRINTF("! "); + PRINTF("from "); + printnataddr(np->in_v[0], np->in_names, &np->in_osrc, + np->in_ifnames[0]); + if (np->in_scmp) + printportcmp(proto, &np->in_tuc.ftu_src); + + if (np->in_flags & IPN_NOTDST) + PRINTF(" !"); + PRINTF(" to "); + printnataddr(np->in_v[0], np->in_names, &np->in_odst, + np->in_ifnames[0]); + if (np->in_dcmp) + printportcmp(proto, &np->in_tuc.ftu_dst); + } + + if (np->in_redir & (NAT_ENCAP|NAT_DIVERTUDP)) { + PRINTF(" -> src "); + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + if ((np->in_redir & NAT_DIVERTUDP) != 0) + PRINTF(",%u", np->in_spmin); + PRINTF(" dst "); + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); + if ((np->in_redir & NAT_DIVERTUDP) != 0) + PRINTF(",%u udp", np->in_dpmin); + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF(";\n"); + + } else if (np->in_redir & NAT_REWRITE) { + PRINTF(" -> src "); + if (np->in_nsrc.na_atype == FRI_LOOKUP && + np->in_nsrc.na_type == IPLT_DSTLIST) { + PRINTF("dstlist/"); + if (np->in_nsrc.na_subtype == 0) + PRINTF("%d", np->in_nsrc.na_num); + else + PRINTF("%s", base + np->in_nsrc.na_num); + } else { + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + } + if ((((np->in_flags & IPN_TCPUDP) != 0)) && + (np->in_spmin != 0)) { + if ((np->in_flags & IPN_FIXEDSPORT) != 0) { + PRINTF(",port = %u", np->in_spmin); + } else { + PRINTF(",%u", np->in_spmin); + if (np->in_spmax != np->in_spmin) + PRINTF("-%u", np->in_spmax); + } + } + PRINTF(" dst "); + if (np->in_ndst.na_atype == FRI_LOOKUP && + np->in_ndst.na_type == IPLT_DSTLIST) { + PRINTF("dstlist/"); + if (np->in_ndst.na_subtype == 0) + PRINTF("%d", np->in_nsrc.na_num); + else + PRINTF("%s", base + np->in_ndst.na_num); + } else { + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); + } + if ((((np->in_flags & IPN_TCPUDP) != 0)) && + (np->in_dpmin != 0)) { + if ((np->in_flags & IPN_FIXEDDPORT) != 0) { + PRINTF(",port = %u", np->in_dpmin); + } else { + PRINTF(",%u", np->in_dpmin); + if (np->in_dpmax != np->in_dpmin) + PRINTF("-%u", np->in_dpmax); + } + } + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF(";\n"); + + } else if (np->in_redir == NAT_REDIRECT) { + if (!(np->in_flags & IPN_FILTER)) { + printnataddr(np->in_v[0], np->in_names, &np->in_odst, + np->in_ifnames[0]); + if (np->in_flags & IPN_TCPUDP) { + PRINTF(" port %d", np->in_odport); + if (np->in_odport != np->in_dtop) + PRINTF("-%d", np->in_dtop); + } + } + if (np->in_flags & IPN_NO) { + putchar(' '); + printproto(pr, proto, np); + PRINTF(";\n"); + return; + } + PRINTF(" -> "); + printnataddr(np->in_v[1], np->in_names, &np->in_ndst, + np->in_ifnames[0]); + if (np->in_flags & IPN_TCPUDP) { + if ((np->in_flags & IPN_FIXEDDPORT) != 0) + PRINTF(" port = %d", np->in_dpmin); + else { + PRINTF(" port %d", np->in_dpmin); + if (np->in_dpmin != np->in_dpmax) + PRINTF("-%d", np->in_dpmax); + } + } + putchar(' '); + printproto(pr, proto, np); + if (np->in_flags & IPN_ROUNDR) + PRINTF(" round-robin"); + if (np->in_flags & IPN_FRAG) + PRINTF(" frag"); + if (np->in_age[0] != 0 || np->in_age[1] != 0) { + PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); + } + if (np->in_flags & IPN_STICKY) + PRINTF(" sticky"); + if (np->in_mssclamp != 0) + PRINTF(" mssclamp %d", np->in_mssclamp); + if (np->in_plabel != -1) + PRINTF(" proxy %s", np->in_names + np->in_plabel); + if (np->in_tag.ipt_tag[0] != '\0') + PRINTF(" tag %-.*s", IPFTAG_LEN, np->in_tag.ipt_tag); + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF("\n"); + if (opts & OPT_DEBUG) + PRINTF("\tpmax %u\n", np->in_dpmax); + + } else { + int protoprinted = 0; + + if (!(np->in_flags & IPN_FILTER)) { + printnataddr(np->in_v[0], np->in_names, &np->in_osrc, + np->in_ifnames[0]); + } + if (np->in_flags & IPN_NO) { + putchar(' '); + printproto(pr, proto, np); + PRINTF(";\n"); + return; + } + PRINTF(" -> "); + if (np->in_flags & IPN_SIPRANGE) { + PRINTF("range "); + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + } else { + printnataddr(np->in_v[1], np->in_names, &np->in_nsrc, + np->in_ifnames[0]); + } + if (np->in_plabel != -1) { + PRINTF(" proxy port "); + if (np->in_odport != 0) { + char *s; + + s = portname(proto, np->in_odport); + if (s != NULL) + fputs(s, stdout); + else + fputs("???", stdout); + } + PRINTF(" %s/", np->in_names + np->in_plabel); + printproto(pr, proto, NULL); + protoprinted = 1; + } else if (np->in_redir == NAT_MAPBLK) { + if ((np->in_spmin == 0) && + (np->in_flags & IPN_AUTOPORTMAP)) + PRINTF(" ports auto"); + else + PRINTF(" ports %d", np->in_spmin); + if (opts & OPT_DEBUG) + PRINTF("\n\tip modulous %d", np->in_spmax); + + } else if (np->in_spmin || np->in_spmax) { + if (np->in_flags & IPN_ICMPQUERY) { + PRINTF(" icmpidmap "); + } else { + PRINTF(" portmap "); + } + printproto(pr, proto, np); + protoprinted = 1; + if (np->in_flags & IPN_AUTOPORTMAP) { + PRINTF(" auto"); + if (opts & OPT_DEBUG) + PRINTF(" [%d:%d %d %d]", + np->in_spmin, np->in_spmax, + np->in_ippip, np->in_ppip); + } else { + PRINTF(" %d:%d", np->in_spmin, np->in_spmax); + } + if (np->in_flags & IPN_SEQUENTIAL) + PRINTF(" sequential"); + } + + if (np->in_flags & IPN_FRAG) + PRINTF(" frag"); + if (np->in_age[0] != 0 || np->in_age[1] != 0) { + PRINTF(" age %d/%d", np->in_age[0], np->in_age[1]); + } + if (np->in_mssclamp != 0) + PRINTF(" mssclamp %d", np->in_mssclamp); + if (np->in_tag.ipt_tag[0] != '\0') + PRINTF(" tag %s", np->in_tag.ipt_tag); + if (!protoprinted && (np->in_flags & IPN_TCPUDP || proto)) { + putchar(' '); + printproto(pr, proto, np); + } + if ((np->in_flags & IPN_PURGE) != 0) + PRINTF(" purge"); + PRINTF("\n"); + if (opts & OPT_DEBUG) { + PRINTF("\tnextip "); + printip(family, &np->in_snip); + PRINTF(" pnext %d\n", np->in_spnext); + } + } + + if (opts & OPT_DEBUG) { + PRINTF("\tspace %lu use %u hits %lu flags %#x proto %d/%d", + np->in_space, np->in_use, np->in_hits, + np->in_flags, np->in_pr[0], np->in_pr[1]); + PRINTF(" hv %u/%u\n", np->in_hv[0], np->in_hv[1]); + PRINTF("\tifp[0] %p ifp[1] %p apr %p\n", + np->in_ifps[0], np->in_ifps[1], np->in_apr); + PRINTF("\ttqehead %p/%p comment %p\n", + np->in_tqehead[0], np->in_tqehead[1], np->in_comment); + } +} diff --git a/sbin/ipf/libipf/printnataddr.c b/sbin/ipf/libipf/printnataddr.c new file mode 100644 index 000000000000..e6003f0b076b --- /dev/null +++ b/sbin/ipf/libipf/printnataddr.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com) + */ + +#include "ipf.h" +#include "kmem.h" + + + + +void +printnataddr( int v, char *base, nat_addr_t *addr, int ifidx) +{ + switch (v) + { + case 4 : + if (addr->na_atype == FRI_NORMAL && + addr->na_addr[0].in4.s_addr == 0) { + PRINTF("0/%d", count4bits(addr->na_addr[1].in4.s_addr)); + } else { + printaddr(AF_INET, addr->na_atype, base, ifidx, + (u_32_t *)&addr->na_addr[0].in4.s_addr, + (u_32_t *)&addr->na_addr[1].in4.s_addr); + } + break; +#ifdef USE_INET6 + case 6 : + printaddr(AF_INET6, addr->na_atype, base, ifidx, + (u_32_t *)&addr->na_addr[0].in6, + (u_32_t *)&addr->na_addr[1].in6); + break; +#endif + default : + printf("{v=%d}", v); + break; + } +} diff --git a/sbin/ipf/libipf/printnatfield.c b/sbin/ipf/libipf/printnatfield.c new file mode 100644 index 000000000000..7a4986ac8e72 --- /dev/null +++ b/sbin/ipf/libipf/printnatfield.c @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printnatfield.c,v 1.6.2.2 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t natfields[] = { + { "all", -2 }, + { "ifp0", 1 }, + { "ifp1", 2 }, + { "mtu0", 3 }, + { "mtu1", 4 }, + { "ifname0", 5 }, + { "ifname1", 6 }, + { "sumd0", 7 }, + { "sumd1", 8 }, + { "pkts0", 9 }, + { "pkts1", 10 }, + { "bytes0", 11 }, + { "bytes1", 12 }, + { "proto0", 13 }, + { "proto1", 14 }, + { "hash0", 15 }, + { "hash1", 16 }, + { "ref", 17 }, + { "rev", 18 }, + { "v0", 19 }, + { "redir", 20 }, + { "use", 21 }, + { "ipsumd", 22 }, + { "dir", 23 }, + { "olddstip", 24 }, + { "oldsrcip", 25 }, + { "newdstip", 26 }, + { "newsrcip", 27 }, + { "olddport", 28 }, + { "oldsport", 29 }, + { "newdport", 30 }, + { "newsport", 31 }, + { "age", 32 }, + { "v1", 33 }, + { NULL, 0 } +}; + + +void +printnatfield( nat_t *n, int fieldnum) +{ + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; natfields[i].w_word != NULL; i++) { + if (natfields[i].w_value > 0) { + printnatfield(n, i); + if (natfields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + PRINTF("%#lx", (u_long)n->nat_ifps[0]); + break; + + case 2: + PRINTF("%#lx", (u_long)n->nat_ifps[1]); + break; + + case 3: + PRINTF("%d", n->nat_mtu[0]); + break; + + case 4: + PRINTF("%d", n->nat_mtu[1]); + break; + + case 5: + PRINTF("%s", n->nat_ifnames[0]); + break; + + case 6: + PRINTF("%s", n->nat_ifnames[1]); + break; + + case 7: + PRINTF("%d", n->nat_sumd[0]); + break; + + case 8: + PRINTF("%d", n->nat_sumd[1]); + break; + + case 9: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_pkts[0]); +#else + PRINTF("%lu", n->nat_pkts[0]); +#endif + break; + + case 10: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_pkts[1]); +#else + PRINTF("%lu", n->nat_pkts[1]); +#endif + break; + + case 11: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_bytes[0]); +#else + PRINTF("%lu", n->nat_bytes[0]); +#endif + break; + + case 12: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", n->nat_bytes[1]); +#else + PRINTF("%lu", n->nat_bytes[1]); +#endif + break; + + case 13: + PRINTF("%d", n->nat_pr[0]); + break; + + case 14: + PRINTF("%d", n->nat_pr[1]); + break; + + case 15: + PRINTF("%u", n->nat_hv[0]); + break; + + case 16: + PRINTF("%u", n->nat_hv[1]); + break; + + case 17: + PRINTF("%d", n->nat_ref); + break; + + case 18: + PRINTF("%d", n->nat_rev); + break; + + case 19: + PRINTF("%d", n->nat_v[0]); + break; + + case 33: + PRINTF("%d", n->nat_v[0]); + break; + + case 20: + PRINTF("%d", n->nat_redir); + break; + + case 21: + PRINTF("%d", n->nat_use); + break; + + case 22: + PRINTF("%u", n->nat_ipsumd); + break; + + case 23: + PRINTF("%d", n->nat_dir); + break; + + case 24: + PRINTF("%s", hostname(n->nat_v[0], &n->nat_odstip)); + break; + + case 25: + PRINTF("%s", hostname(n->nat_v[0], &n->nat_osrcip)); + break; + + case 26: + PRINTF("%s", hostname(n->nat_v[1], &n->nat_ndstip)); + break; + + case 27: + PRINTF("%s", hostname(n->nat_v[1], &n->nat_nsrcip)); + break; + + case 28: + PRINTF("%hu", ntohs(n->nat_odport)); + break; + + case 29: + PRINTF("%hu", ntohs(n->nat_osport)); + break; + + case 30: + PRINTF("%hu", ntohs(n->nat_ndport)); + break; + + case 31: + PRINTF("%hu", ntohs(n->nat_nsport)); + break; + + case 32: + PRINTF("%u", n->nat_age); + break; + + default: + break; + } +} diff --git a/sbin/ipf/libipf/printnatside.c b/sbin/ipf/libipf/printnatside.c new file mode 100644 index 000000000000..9329623d03e5 --- /dev/null +++ b/sbin/ipf/libipf/printnatside.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printnatside.c,v 1.2.2.6 2012/07/22 08:04:24 darren_r Exp $ + */ +#include "ipf.h" + +void +printnatside(char *side, nat_stat_side_t *ns) +{ + PRINTF("%lu\tproxy create fail %s\n", ns->ns_appr_fail, side); + PRINTF("%lu\tproxy fail %s\n", ns->ns_ipf_proxy_fail, side); + PRINTF("%lu\tbad nat %s\n", ns->ns_badnat, side); + PRINTF("%lu\tbad nat new %s\n", ns->ns_badnatnew, side); + PRINTF("%lu\tbad next addr %s\n", ns->ns_badnextaddr, side); + PRINTF("%lu\tbucket max %s\n", ns->ns_bucket_max, side); + PRINTF("%lu\tclone nomem %s\n", ns->ns_clone_nomem, side); + PRINTF("%lu\tdecap bad %s\n", ns->ns_decap_bad, side); + PRINTF("%lu\tdecap fail %s\n", ns->ns_decap_fail, side); + PRINTF("%lu\tdecap pullup %s\n", ns->ns_decap_pullup, side); + PRINTF("%lu\tdivert dup %s\n", ns->ns_divert_dup, side); + PRINTF("%lu\tdivert exist %s\n", ns->ns_divert_exist, side); + PRINTF("%lu\tdrop %s\n", ns->ns_drop, side); + PRINTF("%lu\texhausted %s\n", ns->ns_exhausted, side); + PRINTF("%lu\ticmp address %s\n", ns->ns_icmp_address, side); + PRINTF("%lu\ticmp basic %s\n", ns->ns_icmp_basic, side); + PRINTF("%lu\tinuse %s\n", ns->ns_inuse, side); + PRINTF("%lu\ticmp mbuf wrong size %s\n", ns->ns_icmp_mbuf, side); + PRINTF("%lu\ticmp header unmatched %s\n", ns->ns_icmp_notfound, side); + PRINTF("%lu\ticmp rebuild failures %s\n", ns->ns_icmp_rebuild, side); + PRINTF("%lu\ticmp short %s\n", ns->ns_icmp_short, side); + PRINTF("%lu\ticmp packet size wrong %s\n", ns->ns_icmp_size, side); + PRINTF("%lu\tIFP address fetch failures %s\n", + ns->ns_ifpaddrfail, side); + PRINTF("%lu\tpackets untranslated %s\n", ns->ns_ignored, side); + PRINTF("%lu\tNAT insert failures %s\n", ns->ns_insert_fail, side); + PRINTF("%lu\tNAT lookup misses %s\n", ns->ns_lookup_miss, side); + PRINTF("%lu\tNAT lookup nowild %s\n", ns->ns_lookup_nowild, side); + PRINTF("%lu\tnew ifpaddr failed %s\n", ns->ns_new_ifpaddr, side); + PRINTF("%lu\tmemory requests failed %s\n", ns->ns_memfail, side); + PRINTF("%lu\ttable max reached %s\n", ns->ns_table_max, side); + PRINTF("%lu\tpackets translated %s\n", ns->ns_translated, side); + PRINTF("%lu\tfinalised failed %s\n", ns->ns_unfinalised, side); + PRINTF("%lu\tsearch wraps %s\n", ns->ns_wrap, side); + PRINTF("%lu\tnull translations %s\n", ns->ns_xlate_null, side); + PRINTF("%lu\ttranslation exists %s\n", ns->ns_xlate_exists, side); + PRINTF("%lu\tno memory %s\n", ns->ns_memfail, side); + + if (opts & OPT_VERBOSE) + PRINTF("%p table %s\n", ns->ns_table, side); +} diff --git a/sbin/ipf/libipf/printpacket.c b/sbin/ipf/libipf/printpacket.c new file mode 100644 index 000000000000..f8407c3a3102 --- /dev/null +++ b/sbin/ipf/libipf/printpacket.c @@ -0,0 +1,110 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#ifndef IP_OFFMASK +# define IP_OFFMASK 0x3fff +#endif + +void +printpacket(int dir, mb_t *m) +{ + u_short len, off; + tcphdr_t *tcp; + uint16_t tcpflags; + ip_t *ip; + + ip = MTOD(m, ip_t *); + + if (IP_V(ip) == 6) { +#ifdef USE_INET6 + len = ntohs(((ip6_t *)ip)->ip6_plen); +#else + len = ntohs(((u_short *)ip)[2]); +#endif + len += 40; + } else { + len = ntohs(ip->ip_len); + } + ASSERT(len == msgdsize(m)); + + if ((opts & OPT_HEX) == OPT_HEX) { + u_char *s; + int i; + + for (; m != NULL; m = m->mb_next) { + len = m->mb_len; + for (s = (u_char *)m->mb_data, i = 0; i < len; i++) { + PRINTF("%02x", *s++ & 0xff); + if (len - i > 1) { + i++; + PRINTF("%02x", *s++ & 0xff); + } + putchar(' '); + } + } + putchar('\n'); + putchar('\n'); + return; + } + + if (IP_V(ip) == 6) { + printpacket6(dir, m); + return; + } + + if (dir) + PRINTF("> "); + else + PRINTF("< "); + + PRINTF("%s ", IFNAME(m->mb_ifp)); + + off = ntohs(ip->ip_off); + tcp = (struct tcphdr *)((char *)ip + (IP_HL(ip) << 2)); + PRINTF("ip #%d %d(%d) %d", ntohs(ip->ip_id), ntohs(ip->ip_len), + IP_HL(ip) << 2, ip->ip_p); + if (off & IP_OFFMASK) + PRINTF(" @%d", off << 3); + PRINTF(" %s", inet_ntoa(ip->ip_src)); + if (!(off & IP_OFFMASK)) + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) + PRINTF(",%d", ntohs(tcp->th_sport)); + PRINTF(" > "); + PRINTF("%s", inet_ntoa(ip->ip_dst)); + if (!(off & IP_OFFMASK)) { + if (ip->ip_p == IPPROTO_TCP || ip->ip_p == IPPROTO_UDP) + PRINTF(",%d", ntohs(tcp->th_dport)); + if ((ip->ip_p == IPPROTO_TCP) && + ((tcpflags = __tcp_get_flags(tcp)) != 0)) { + putchar(' '); + if (tcpflags & TH_FIN) + putchar('F'); + if (tcpflags & TH_SYN) + putchar('S'); + if (tcpflags & TH_RST) + putchar('R'); + if (tcpflags & TH_PUSH) + putchar('P'); + if (tcpflags & TH_ACK) + putchar('A'); + if (tcpflags & TH_URG) + putchar('U'); + if (tcpflags & TH_ECN) + putchar('E'); + if (tcpflags & TH_CWR) + putchar('W'); + if (tcpflags & TH_AE) + putchar('e'); + } + } + + putchar('\n'); +} diff --git a/sbin/ipf/libipf/printpacket6.c b/sbin/ipf/libipf/printpacket6.c new file mode 100644 index 000000000000..c015eabdada5 --- /dev/null +++ b/sbin/ipf/libipf/printpacket6.c @@ -0,0 +1,57 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +/* + * This is meant to work without the IPv6 header files being present or + * the inet_ntop() library. + */ +void +printpacket6(int dir, mb_t *m) +{ + u_char *buf, p; + u_short plen, *addrs; + tcphdr_t *tcp; + u_32_t flow; + + buf = (u_char *)m->mb_data; + tcp = (tcphdr_t *)(buf + 40); + p = buf[6]; + flow = ntohl(*(u_32_t *)buf); + flow &= 0xfffff; + plen = ntohs(*((u_short *)buf +2)); + addrs = (u_short *)buf + 4; + + if (dir) + PRINTF("> "); + else + PRINTF("< "); + + PRINTF("%s ", IFNAME(m->mb_ifp)); + + PRINTF("ip6/%d %d %#x %d", buf[0] & 0xf, plen, flow, p); + PRINTF(" %x:%x:%x:%x:%x:%x:%x:%x", + ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), + ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), + ntohs(addrs[6]), ntohs(addrs[7])); + if (plen >= 4) + if (p == IPPROTO_TCP || p == IPPROTO_UDP) + (void)PRINTF(",%d", ntohs(tcp->th_sport)); + PRINTF(" >"); + addrs += 8; + PRINTF(" %x:%x:%x:%x:%x:%x:%x:%x", + ntohs(addrs[0]), ntohs(addrs[1]), ntohs(addrs[2]), + ntohs(addrs[3]), ntohs(addrs[4]), ntohs(addrs[5]), + ntohs(addrs[6]), ntohs(addrs[7])); + if (plen >= 4) + if (p == IPPROTO_TCP || p == IPPROTO_UDP) + PRINTF(",%d", ntohs(tcp->th_dport)); + putchar('\n'); +} diff --git a/sbin/ipf/libipf/printpool.c b/sbin/ipf/libipf/printpool.c new file mode 100644 index 000000000000..86f389c6cbaf --- /dev/null +++ b/sbin/ipf/libipf/printpool.c @@ -0,0 +1,60 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ip_pool_t * +printpool(ip_pool_t *pp, copyfunc_t copyfunc, char *name, int opts, + wordtab_t *fields) +{ + ip_pool_node_t *ipnp, *ipnpn, ipn, **pnext; + ip_pool_t ipp; + + if ((*copyfunc)(pp, &ipp, sizeof(ipp))) + return (NULL); + + if ((name != NULL) && strncmp(name, ipp.ipo_name, FR_GROUPLEN)) + return (ipp.ipo_next); + + printpooldata(&ipp, opts); + + if ((ipp.ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + ipnpn = ipp.ipo_list; + ipp.ipo_list = NULL; + pnext = &ipp.ipo_list; + while (ipnpn != NULL) { + ipnp = (ip_pool_node_t *)malloc(sizeof(*ipnp)); + (*copyfunc)(ipnpn, ipnp, sizeof(ipn)); + ipnpn = ipnp->ipn_next; + *pnext = ipnp; + pnext = &ipnp->ipn_next; + ipnp->ipn_next = NULL; + } + + if (ipp.ipo_list == NULL) { + putchar(';'); + } else { + for (ipnp = ipp.ipo_list; ipnp != NULL; ipnp = ipnpn) { + ipnpn = printpoolnode(ipnp, opts, fields); + free(ipnp); + + if ((opts & OPT_DEBUG) == 0) { + putchar(';'); + } + } + } + + if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + + return (ipp.ipo_next); +} diff --git a/sbin/ipf/libipf/printpool_live.c b/sbin/ipf/libipf/printpool_live.c new file mode 100644 index 000000000000..9bb19f2888b4 --- /dev/null +++ b/sbin/ipf/libipf/printpool_live.c @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ipl.h" + + +void +printpool_live(ip_pool_t *pool, int fd, char *name, int opts, + wordtab_t *fields) +{ + ip_pool_node_t entry; + ipflookupiter_t iter; + int printed, last; + ipfobj_t obj; + + if ((name != NULL) && strncmp(name, pool->ipo_name, FR_GROUPLEN)) + return; + + if (fields == NULL) + printpooldata(pool, opts); + + if ((pool->ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + if (opts & OPT_SAVEOUT) + PRINTF("{\n"); + else if ((opts & OPT_DEBUG) == 0) + PRINTF("\t{"); + + obj.ipfo_rev = IPFILTER_VERSION; + obj.ipfo_type = IPFOBJ_LOOKUPITER; + obj.ipfo_ptr = &iter; + obj.ipfo_size = sizeof(iter); + + iter.ili_data = &entry; + iter.ili_type = IPLT_POOL; + iter.ili_otype = IPFLOOKUPITER_NODE; + iter.ili_ival = IPFGENITER_LOOKUP; + iter.ili_unit = pool->ipo_unit; + strncpy(iter.ili_name, pool->ipo_name, FR_GROUPLEN); + + last = 0; + printed = 0; + + if (pool->ipo_list != NULL) { + while (!last && (ioctl(fd, SIOCLOOKUPITER, &obj) == 0)) { + if (entry.ipn_next == NULL) + last = 1; + if (opts & OPT_SAVEOUT) + PRINTF("\t"); + (void) printpoolnode(&entry, opts, fields); + if ((opts & OPT_DEBUG) == 0) + putchar(';'); + if (opts & OPT_SAVEOUT) + PRINTF("\n"); + printed++; + } + } + + if (printed == 0) + putchar(';'); + + if (opts & OPT_SAVEOUT) + PRINTF("};\n"); + else if ((opts & OPT_DEBUG) == 0) + PRINTF(" };\n"); + + (void) ioctl(fd,SIOCIPFDELTOK, &iter.ili_key); + + return; +} diff --git a/sbin/ipf/libipf/printpooldata.c b/sbin/ipf/libipf/printpooldata.c new file mode 100644 index 000000000000..b203522734be --- /dev/null +++ b/sbin/ipf/libipf/printpooldata.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include <ctype.h> + + +void +printpooldata(ip_pool_t *pool, int opts) +{ + + if (opts & OPT_SAVEOUT) { + if ((pool->ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + PRINTF("pool "); + } else if ((opts & OPT_DEBUG) == 0) { + if ((pool->ipo_flags & IPOOL_ANON) != 0) + PRINTF("# 'anonymous' tree %s\n", pool->ipo_name); + if ((pool->ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + PRINTF("table role="); + } else { + if ((pool->ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + PRINTF("%s: %s", + ISDIGIT(*pool->ipo_name) ? "Number" : "Name", + pool->ipo_name); + if ((pool->ipo_flags & IPOOL_ANON) == IPOOL_ANON) + PRINTF("(anon)"); + putchar(' '); + PRINTF("Role: "); + } + + printunit(pool->ipo_unit); + + if ((opts & OPT_SAVEOUT)) { + PRINTF("/tree (%s \"\%s\";)\n", + (!*pool->ipo_name || ISDIGIT(*pool->ipo_name)) ? \ + "number" : "name", pool->ipo_name); + } else if ((opts & OPT_DEBUG) == 0) { + PRINTF(" type=tree %s=%s\n", + (!*pool->ipo_name || ISDIGIT(*pool->ipo_name)) ? \ + "number" : "name", pool->ipo_name); + } else { + putchar(' '); + + PRINTF("\tReferences: %d\tHits: %lu\n", pool->ipo_ref, + pool->ipo_hits); + if ((pool->ipo_flags & IPOOL_DELETE) != 0) + PRINTF("# "); + PRINTF("\tNodes Starting at %p\n", pool->ipo_list); + } +} diff --git a/sbin/ipf/libipf/printpoolfield.c b/sbin/ipf/libipf/printpoolfield.c new file mode 100644 index 000000000000..2a461239ad91 --- /dev/null +++ b/sbin/ipf/libipf/printpoolfield.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printpoolfield.c,v 1.1.2.4 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t poolfields[] = { + { "all", -2 }, + { "address", 1 }, + { "mask", 2 }, + { "ifname", 3 }, + { "pkts", 4 }, + { "bytes", 5 }, + { "family", 6 }, + { NULL, 0 } +}; + + +void +printpoolfield(void *p, int ptype, int fieldnum) +{ + addrfamily_t *a; + char abuf[80]; + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; poolfields[i].w_word != NULL; i++) { + if (poolfields[i].w_value > 0) { + printpoolfield(p, ptype, i); + if (poolfields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + if (node->ipn_info) + PRINTF("!"); + a = &node->ipn_addr; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", inet_ntop(node->ipe_family, + &node->ipe_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + a = &node->ipfd_dest.fd_addr; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } + break; + + case 2: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + a = &node->ipn_mask; + PRINTF("%s", inet_ntop(a->adf_family, &a->adf_addr, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", inet_ntop(node->ipe_family, + &node->ipe_mask, + abuf, sizeof(abuf))); + } else if (ptype == IPLT_DSTLIST) { + PRINTF("%s", ""); + } + break; + + case 3: + if (ptype == IPLT_POOL) { + PRINTF("%s", ""); + } else if (ptype == IPLT_HASH) { + PRINTF("%s", ""); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + if (node->ipfd_dest.fd_name == -1) { + PRINTF("%s", ""); + } else { + PRINTF("%s", node->ipfd_names + + node->ipfd_dest.fd_name); + } + } + break; + + case 4: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipn_hits); +#else + PRINTF("%lu", node->ipn_hits); +#endif + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipe_hits); +#else + PRINTF("%lu", node->ipe_hits); +#endif + } else if (ptype == IPLT_DSTLIST) { + printf("0"); + } + break; + + case 5: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipn_bytes); +#else + PRINTF("%lu", node->ipn_bytes); +#endif + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", node->ipe_bytes); +#else + PRINTF("%lu", node->ipe_bytes); +#endif + } else if (ptype == IPLT_DSTLIST) { + printf("0"); + } + break; + + case 6: + if (ptype == IPLT_POOL) { + ip_pool_node_t *node = (ip_pool_node_t *)p; + + PRINTF("%s", familyname(node->ipn_addr.adf_family)); + } else if (ptype == IPLT_HASH) { + iphtent_t *node = (iphtent_t *)p; + + PRINTF("%s", familyname(node->ipe_family)); + } else if (ptype == IPLT_DSTLIST) { + ipf_dstnode_t *node = (ipf_dstnode_t *)p; + + a = &node->ipfd_dest.fd_addr; + PRINTF("%s", familyname(a->adf_family)); + } + break; + + default : + break; + } +} diff --git a/sbin/ipf/libipf/printpoolnode.c b/sbin/ipf/libipf/printpoolnode.c new file mode 100644 index 000000000000..8cec3fcae757 --- /dev/null +++ b/sbin/ipf/libipf/printpoolnode.c @@ -0,0 +1,67 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +ip_pool_node_t * +printpoolnode(ip_pool_node_t *np, int opts, wordtab_t *fields) +{ + int i; + + if (fields != NULL) { + for (i = 0; fields[i].w_value != 0; i++) { + printpoolfield(np, IPLT_POOL, i); + if (fields[i + 1].w_value != 0) + printf("\t"); + } + printf("\n"); + } else if ((opts & OPT_DEBUG) == 0) { + putchar(' '); + if (np->ipn_info == 1) + PRINTF("! "); + printip(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_addr.adf_addr.in4); + printmask(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_mask.adf_addr); + } else { +#ifdef USE_INET6 + if (np->ipn_addr.adf_family == AF_INET6) { + char buf[INET6_ADDRSTRLEN + 1]; + const char *str; + + buf[0] = '\0'; + str = inet_ntop(AF_INET6, &np->ipn_addr.adf_addr.in6, + buf, sizeof(buf) - 1); + if (str == NULL) + str = "???"; + PRINTF("\tAddress: %s%s", np->ipn_info ? "! " : "", + str); + } else if (np->ipn_addr.adf_family == AF_INET) { +#else + if (np->ipn_addr.adf_family == AF_INET) { +#endif + PRINTF("\tAddress: %s%s", np->ipn_info ? "! " : "", + inet_ntoa(np->ipn_addr.adf_addr.in4)); + } else { + PRINTF("\tAddress: family: %d\n", + np->ipn_addr.adf_family); + } + printmask(np->ipn_addr.adf_family, + (u_32_t *)&np->ipn_mask.adf_addr); +#ifdef USE_QUAD_T + PRINTF("\n\t\tHits %"PRIu64"\tBytes %"PRIu64"\tName %s\tRef %d\n", + np->ipn_hits, np->ipn_bytes, + np->ipn_name, np->ipn_ref); +#else + PRINTF("\n\t\tHits %lu\tBytes %lu\tName %s\tRef %d\n", + np->ipn_hits, np->ipn_bytes, + np->ipn_name, np->ipn_ref); +#endif + } + return (np->ipn_next); +} diff --git a/sbin/ipf/libipf/printportcmp.c b/sbin/ipf/libipf/printportcmp.c new file mode 100644 index 000000000000..2e3ee471e3e2 --- /dev/null +++ b/sbin/ipf/libipf/printportcmp.c @@ -0,0 +1,27 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +void +printportcmp(int pr, frpcmp_t *frp) +{ + static char *pcmp1[] = { "*", "=", "!=", "<", ">", "<=", ">=", + "<>", "><", ":" }; + + if (frp->frp_cmp == FR_INRANGE || frp->frp_cmp == FR_OUTRANGE) + PRINTF(" port %d %s %d", frp->frp_port, + pcmp1[frp->frp_cmp], frp->frp_top); + else if (frp->frp_cmp == FR_INCRANGE) + PRINTF(" port %d:%d", frp->frp_port, frp->frp_top); + else + PRINTF(" port %s %s", pcmp1[frp->frp_cmp], + portname(pr, frp->frp_port)); +} diff --git a/sbin/ipf/libipf/printproto.c b/sbin/ipf/libipf/printproto.c new file mode 100644 index 000000000000..3d4c881ff6d0 --- /dev/null +++ b/sbin/ipf/libipf/printproto.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + + + +void +printproto(struct protoent *pr, int p, ipnat_t *np) +{ + if (np != NULL) { + 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"); + else if (np->in_flags & IPN_ICMPQUERY) + PRINTF("icmp"); + else if (np->in_pr[0] == 0) + PRINTF("ip"); + else if (pr != NULL) + PRINTF("%s", pr->p_name); + else + PRINTF("%d", np->in_pr[0]); + } else { + if (pr != NULL) + PRINTF("%s", pr->p_name); + else + PRINTF("%d", p); + } +} diff --git a/sbin/ipf/libipf/printsbuf.c b/sbin/ipf/libipf/printsbuf.c new file mode 100644 index 000000000000..4d3de8468dee --- /dev/null +++ b/sbin/ipf/libipf/printsbuf.c @@ -0,0 +1,39 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#ifdef IPFILTER_SCAN + +#include <ctype.h> +#include <stdio.h> +#include "ipf.h" +#include "netinet/ip_scan.h" + +void +printsbuf(char *buf) +{ + u_char *s; + int i; + + for (s = (u_char *)buf, i = ISC_TLEN; i; i--, s++) { + if (ISPRINT(*s)) + putchar(*s); + else + PRINTF("\\%o", *s); + } +} +#else +void printsbuf(char *buf); + +void printsbuf(char *buf) +{ +#if 0 + buf = buf; /* gcc -Wextra */ +#endif +} +#endif diff --git a/sbin/ipf/libipf/printstate.c b/sbin/ipf/libipf/printstate.c new file mode 100644 index 000000000000..3b6f6c3b07d4 --- /dev/null +++ b/sbin/ipf/libipf/printstate.c @@ -0,0 +1,216 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" +#include "kmem.h" + + +ipstate_t * +printstate(ipstate_t *sp, int opts, u_long now) +{ + struct protoent *pr; + synclist_t ipsync; + + if ((opts & OPT_NORESOLVE) == 0) + pr = getprotobynumber(sp->is_p); + else + pr = NULL; + + PRINTF("%d:", sp->is_v); + if (pr != NULL) + PRINTF("%s", pr->p_name); + else + PRINTF("%d", sp->is_p); + + PRINTF(" src:%s", hostname(sp->is_family, &sp->is_src.in4)); + if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { + if (sp->is_flags & IS_WSPORT) + PRINTF(",*"); + else + PRINTF(",%d", ntohs(sp->is_sport)); + } + + PRINTF(" dst:%s", hostname(sp->is_family, &sp->is_dst.in4)); + if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) { + if (sp->is_flags & IS_WDPORT) + PRINTF(",*"); + else + PRINTF(",%d", ntohs(sp->is_dport)); + } + + if (sp->is_p == IPPROTO_TCP) { + PRINTF(" state:%d/%d", sp->is_state[0], sp->is_state[1]); + } + + PRINTF(" %ld", sp->is_die - now); + if (sp->is_phnext == NULL) + PRINTF(" ORPHAN"); + if (sp->is_flags & IS_CLONE) + PRINTF(" CLONE"); + putchar('\n'); + + if (sp->is_p == IPPROTO_TCP) { + PRINTF("\t%x:%x %hu<<%d:%hu<<%d\n", + sp->is_send, sp->is_dend, + sp->is_maxswin, sp->is_swinscale, + sp->is_maxdwin, sp->is_dwinscale); + if ((opts & OPT_VERBOSE) != 0) { + PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n", + sp->is_smsk[0], sp->is_smsk[1], sp->is_isc, + sp->is_s0[0], sp->is_s0[1]); + PRINTF("\tFWD: ISN inc %x sumd %x\n", + sp->is_isninc[0], sp->is_sumd[0]); + PRINTF("\tREV: ISN inc %x sumd %x\n", + sp->is_isninc[1], sp->is_sumd[1]); +#ifdef IPFILTER_SCAN + PRINTF("\tsbuf[0] ["); + printsbuf(sp->is_sbuf[0]); + PRINTF("] sbuf[1] ["); + printsbuf(sp->is_sbuf[1]); + PRINTF("]\n"); +#endif + } + } else if (sp->is_p == IPPROTO_GRE) { + PRINTF("\tcall %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]), + ntohs(sp->is_gre.gs_call[1])); + } else if (sp->is_p == IPPROTO_ICMP +#ifdef USE_INET6 + || sp->is_p == IPPROTO_ICMPV6 +#endif + ) { + PRINTF("\tid %hu seq %hu type %d\n", sp->is_icmp.ici_id, + sp->is_icmp.ici_seq, sp->is_icmp.ici_type); + } + +#ifdef USE_QUAD_T + PRINTF("\tFWD: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n\tREV: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n", + sp->is_pkts[0], sp->is_bytes[0], + sp->is_pkts[1], sp->is_bytes[1], + sp->is_pkts[2], sp->is_bytes[2], + sp->is_pkts[3], sp->is_bytes[3]); +#else + PRINTF("\tFWD: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n\tREV: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n", + sp->is_pkts[0], sp->is_bytes[0], + sp->is_pkts[1], sp->is_bytes[1], + sp->is_pkts[2], sp->is_bytes[2], + sp->is_pkts[3], sp->is_bytes[3]); +#endif + + PRINTF("\ttag %u pass %#x = ", sp->is_tag, sp->is_pass); + + /* + * Print out bits set in the result code for the state being + * kept as they would for a rule. + */ + if (FR_ISPASS(sp->is_pass)) { + PRINTF("pass"); + } else if (FR_ISBLOCK(sp->is_pass)) { + PRINTF("block"); + switch (sp->is_pass & FR_RETMASK) + { + case FR_RETICMP : + PRINTF(" return-icmp"); + break; + case FR_FAKEICMP : + PRINTF(" return-icmp-as-dest"); + break; + case FR_RETRST : + PRINTF(" return-rst"); + break; + default : + break; + } + } else if ((sp->is_pass & FR_LOGMASK) == FR_LOG) { + PRINTF("log"); + if (sp->is_pass & FR_LOGBODY) + PRINTF(" body"); + if (sp->is_pass & FR_LOGFIRST) + PRINTF(" first"); + } else if (FR_ISACCOUNT(sp->is_pass)) { + PRINTF("count"); + } else if (FR_ISPREAUTH(sp->is_pass)) { + PRINTF("preauth"); + } else if (FR_ISAUTH(sp->is_pass)) + PRINTF("auth"); + + if (sp->is_pass & FR_OUTQUE) + PRINTF(" out"); + else + PRINTF(" in"); + + if ((sp->is_pass & FR_LOG) != 0) { + PRINTF(" log"); + if (sp->is_pass & FR_LOGBODY) + PRINTF(" body"); + if (sp->is_pass & FR_LOGFIRST) + PRINTF(" first"); + if (sp->is_pass & FR_LOGORBLOCK) + PRINTF(" or-block"); + } + if (sp->is_pass & FR_QUICK) + PRINTF(" quick"); + if (sp->is_pass & FR_KEEPFRAG) + PRINTF(" keep frags"); + /* a given; no? */ + if (sp->is_pass & FR_KEEPSTATE) { + PRINTF(" keep state"); + if (sp->is_pass & (FR_STATESYNC|FR_STSTRICT|FR_STLOOSE)) { + PRINTF(" ("); + if (sp->is_pass & FR_STATESYNC) + PRINTF(" sync"); + if (sp->is_pass & FR_STSTRICT) + PRINTF(" strict"); + if (sp->is_pass & FR_STLOOSE) + PRINTF(" loose"); + PRINTF(" )"); + } + } + PRINTF("\n"); + + if ((opts & OPT_VERBOSE) != 0) { + PRINTF("\tref %d", sp->is_ref); + PRINTF(" pkt_flags & %x(%x) = %x\n", + sp->is_flags & 0xf, sp->is_flags, sp->is_flags >> 4); + PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0], + sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]); + PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n", + sp->is_secmsk, sp->is_sec, sp->is_authmsk, + sp->is_auth); + PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0], + sp->is_flx[0][1], sp->is_flx[1][0], sp->is_flx[1][1]); + } + PRINTF("\tinterfaces: in %s", FORMAT_IF(sp->is_ifname[0])); + if (opts & OPT_DEBUG) + PRINTF("/%p", sp->is_ifp[0]); + PRINTF(",%s", FORMAT_IF(sp->is_ifname[1])); + if (opts & OPT_DEBUG) + PRINTF("/%p", sp->is_ifp[1]); + PRINTF(" out %s", FORMAT_IF(sp->is_ifname[2])); + if (opts & OPT_DEBUG) + PRINTF("/%p", sp->is_ifp[2]); + PRINTF(",%s", FORMAT_IF(sp->is_ifname[3])); + if (opts & OPT_DEBUG) + PRINTF("/%p", sp->is_ifp[3]); + PRINTF("\n"); + + PRINTF("\tSync status: "); + if (sp->is_sync != NULL) { + if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync, + sizeof(ipsync))) { + PRINTF("status could not be retrieved\n"); + return (NULL); + } + + PRINTF("idx %d num %d v %d pr %d rev %d\n", + ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v, + ipsync.sl_p, ipsync.sl_rev); + } else { + PRINTF("not synchronized\n"); + } + + return (sp->is_next); +} diff --git a/sbin/ipf/libipf/printstatefields.c b/sbin/ipf/libipf/printstatefields.c new file mode 100644 index 000000000000..c928c637480b --- /dev/null +++ b/sbin/ipf/libipf/printstatefields.c @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: printstatefields.c,v 1.4.2.2 2012/01/26 05:44:26 darren_r Exp $ + */ + +#include "ipf.h" + +wordtab_t statefields[] = { + { "all", -2 }, + { "ifp0", 1 }, + { "ifp1", 2 }, + { "ifp2", 3 }, + { "ifp3", 4 }, + { "ifname0", 5 }, + { "ifname1", 6 }, + { "ifname2", 7 }, + { "ifname3", 8 }, + { "pkts0", 9 }, + { "pkts1", 10 }, + { "pkts2", 11 }, + { "pkts3", 12 }, + { "bytes0", 13 }, + { "bytes1", 14 }, + { "bytes2", 15 }, + { "bytes3", 16 }, + { "state0", 17 }, + { "state1", 18 }, + { "age0", 19 }, + { "age1", 20 }, + { "ref", 21 }, + { "isn0", 22 }, + { "isn1", 23 }, + { "sumd0", 24 }, + { "sumd1", 25 }, + { "src", 26 }, + { "dst", 27 }, + { "sport", 28 }, + { "dport", 29 }, + { "icmptype", 30 }, + { "-", 31 }, + { "pass", 32 }, + { "proto", 33 }, + { "version", 34 }, + { "hash", 35 }, + { "tag", 36 }, + { "flags", 37 }, + { "rulen", 38 }, + { "group", 39 }, + { "flx0", 40 }, + { "flx1", 41 }, + { "flx2", 42 }, + { "flx3", 43 }, + { "opt0", 44 }, + { "opt1", 45 }, + { "optmsk0", 46 }, + { "optmsk1", 47 }, + { "sec", 48 }, + { "secmsk", 49 }, + { "auth", 50 }, + { "authmsk", 51 }, + { "icmppkts0", 52 }, + { "icmppkts1", 53 }, + { "icmppkts2", 54 }, + { "icmppkts3", 55 }, + { NULL, 0 } +}; + + +void +printstatefield(ipstate_t *sp, int fieldnum) +{ + int i; + + switch (fieldnum) + { + case -2 : + for (i = 1; statefields[i].w_word != NULL; i++) { + if (statefields[i].w_value > 0) { + printstatefield(sp, i); + if (statefields[i + 1].w_value > 0) + putchar('\t'); + } + } + break; + + case 1: + PRINTF("%#lx", (u_long)sp->is_ifp[0]); + break; + + case 2: + PRINTF("%#lx", (u_long)sp->is_ifp[1]); + break; + + case 3: + PRINTF("%#lx", (u_long)sp->is_ifp[2]); + break; + + case 4: + PRINTF("%#lx", (u_long)sp->is_ifp[3]); + break; + + case 5: + PRINTF("%s", sp->is_ifname[0]); + break; + + case 6: + PRINTF("%s", sp->is_ifname[1]); + break; + + case 7: + PRINTF("%s", sp->is_ifname[2]); + break; + + case 8: + PRINTF("%s", sp->is_ifname[3]); + break; + + case 9: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[0]); +#else + PRINTF("%lu", sp->is_pkts[0]); +#endif + break; + + case 10: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[1]); +#else + PRINTF("%lu", sp->is_pkts[1]); +#endif + break; + + case 11: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[2]); +#else + PRINTF("%lu", sp->is_pkts[2]); +#endif + break; + + case 12: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_pkts[3]); +#else + PRINTF("%lu", sp->is_pkts[3]); +#endif + break; + + case 13: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[0]); +#else + PRINTF("%lu", sp->is_bytes[0]); +#endif + break; + + case 14: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[1]); +#else + PRINTF("%lu", sp->is_bytes[1]); +#endif + break; + + case 15: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[2]); +#else + PRINTF("%lu", sp->is_bytes[2]); +#endif + break; + + case 16: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_bytes[3]); +#else + PRINTF("%lu", sp->is_bytes[3]); +#endif + break; + + case 17: + PRINTF("%d", sp->is_state[0]); + break; + + case 18: + PRINTF("%d", sp->is_state[1]); + break; + + case 19: + PRINTF("%d", sp->is_frage[0]); + break; + + case 20: + PRINTF("%d", sp->is_frage[1]); + break; + + case 21: + PRINTF("%d", sp->is_ref); + break; + + case 22: + PRINTF("%d", sp->is_isninc[0]); + break; + + case 23: + PRINTF("%d", sp->is_isninc[1]); + break; + + case 24: + PRINTF("%hd", sp->is_sumd[0]); + break; + + case 25: + PRINTF("%hd", sp->is_sumd[1]); + break; + + case 26: + PRINTF("%s", hostname(sp->is_v, &sp->is_src.in4)); + break; + + case 27: + PRINTF("%s", hostname(sp->is_v, &sp->is_dst.in4)); + break; + + case 28: + PRINTF("%hu", ntohs(sp->is_sport)); + break; + + case 29: + PRINTF("%hu", ntohs(sp->is_dport)); + break; + + case 30: + PRINTF("%d", sp->is_type); + break; + + case 32: + PRINTF("%#x", sp->is_pass); + break; + + case 33: + PRINTF("%d", sp->is_p); + break; + + case 34: + PRINTF("%d", sp->is_v); + break; + + case 35: + PRINTF("%d", sp->is_hv); + break; + + case 36: + PRINTF("%d", sp->is_tag); + break; + + case 37: + PRINTF("%#x", sp->is_flags); + break; + + case 38: + PRINTF("%d", sp->is_rulen); + break; + + case 39: + PRINTF("%s", sp->is_group); + break; + + case 40: + PRINTF("%#x", sp->is_flx[0][0]); + break; + + case 41: + PRINTF("%#x", sp->is_flx[0][1]); + break; + + case 42: + PRINTF("%#x", sp->is_flx[1][0]); + break; + + case 43: + PRINTF("%#x", sp->is_flx[1][1]); + break; + + case 44: + PRINTF("%#x", sp->is_opt[0]); + break; + + case 45: + PRINTF("%#x", sp->is_opt[1]); + break; + + case 46: + PRINTF("%#x", sp->is_optmsk[0]); + break; + + case 47: + PRINTF("%#x", sp->is_optmsk[1]); + break; + + case 48: + PRINTF("%#x", sp->is_sec); + break; + + case 49: + PRINTF("%#x", sp->is_secmsk); + break; + + case 50: + PRINTF("%#x", sp->is_auth); + break; + + case 51: + PRINTF("%#x", sp->is_authmsk); + break; + + case 52: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[0]); +#else + PRINTF("%lu", sp->is_icmppkts[0]); +#endif + break; + + case 53: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[1]); +#else + PRINTF("%lu", sp->is_icmppkts[1]); +#endif + break; + + case 54: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[2]); +#else + PRINTF("%lu", sp->is_icmppkts[2]); +#endif + break; + + case 55: +#ifdef USE_QUAD_T + PRINTF("%"PRIu64"", sp->is_icmppkts[3]); +#else + PRINTF("%lu", sp->is_icmppkts[3]); +#endif + break; + + default: + break; + } +} diff --git a/sbin/ipf/libipf/printtcpflags.c b/sbin/ipf/libipf/printtcpflags.c new file mode 100644 index 000000000000..349e18be127e --- /dev/null +++ b/sbin/ipf/libipf/printtcpflags.c @@ -0,0 +1,29 @@ +#include "ipf.h" + + +void +printtcpflags(u_32_t tcpf, u_32_t tcpfm) +{ + uint16_t *t; + char *s; + + if (tcpf & ~TH_FLAGS) { + PRINTF("0x%x", tcpf); + } else { + for (s = flagset, t = flags; *s; s++, t++) { + if (tcpf & *t) + (void)putchar(*s); + } + } + + if (tcpfm) { + (void)putchar('/'); + if (tcpfm & ~TH_FLAGS) { + PRINTF("0x%x", tcpfm); + } else { + for (s = flagset, t = flags; *s; s++, t++) + if (tcpfm & *t) + (void)putchar(*s); + } + } +} diff --git a/sbin/ipf/libipf/printtqtable.c b/sbin/ipf/libipf/printtqtable.c new file mode 100644 index 000000000000..aff8724eff60 --- /dev/null +++ b/sbin/ipf/libipf/printtqtable.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" + + +void +printtqtable(ipftq_t *table) +{ + int i; + + PRINTF("TCP Entries per state\n"); + for (i = 0; i < IPF_TCP_NSTATES; i++) + PRINTF(" %5d", i); + PRINTF("\n"); + + for (i = 0; i < IPF_TCP_NSTATES; i++) + PRINTF(" %5d", table[i].ifq_ref - 1); + PRINTF("\n"); +} diff --git a/sbin/ipf/libipf/printtunable.c b/sbin/ipf/libipf/printtunable.c new file mode 100644 index 000000000000..8cd212a2b8b4 --- /dev/null +++ b/sbin/ipf/libipf/printtunable.c @@ -0,0 +1,28 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +void +printtunable(ipftune_t *tup) +{ + PRINTF("%s\tmin %lu\tmax %lu\tcurrent ", + tup->ipft_name, tup->ipft_min, tup->ipft_max); + if (tup->ipft_sz == sizeof(u_long)) + PRINTF("%lu\n", tup->ipft_vlong); + else if (tup->ipft_sz == sizeof(u_int)) + PRINTF("%u\n", tup->ipft_vint); + else if (tup->ipft_sz == sizeof(u_short)) + PRINTF("%hu\n", tup->ipft_vshort); + else if (tup->ipft_sz == sizeof(u_char)) + PRINTF("%u\n", (u_int)tup->ipft_vchar); + else { + PRINTF("sz = %d\n", tup->ipft_sz); + } +} diff --git a/sbin/ipf/libipf/printunit.c b/sbin/ipf/libipf/printunit.c new file mode 100644 index 000000000000..935faf0f303a --- /dev/null +++ b/sbin/ipf/libipf/printunit.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + */ + +#include "ipf.h" + + +void +printunit(int unit) +{ + + switch (unit) + { + case IPL_LOGIPF : + PRINTF("ipf"); + break; + case IPL_LOGNAT : + PRINTF("nat"); + break; + case IPL_LOGSTATE : + PRINTF("state"); + break; + case IPL_LOGAUTH : + PRINTF("auth"); + break; + case IPL_LOGSYNC : + PRINTF("sync"); + break; + case IPL_LOGSCAN : + PRINTF("scan"); + break; + case IPL_LOGLOOKUP : + PRINTF("lookup"); + break; + case IPL_LOGCOUNT : + PRINTF("count"); + break; + case IPL_LOGALL : + PRINTF("all"); + break; + default : + PRINTF("unknown(%d)", unit); + } +} diff --git a/sbin/ipf/libipf/remove_hash.c b/sbin/ipf/libipf/remove_hash.c new file mode 100644 index 000000000000..c6778e372224 --- /dev/null +++ b/sbin/ipf/libipf/remove_hash.c @@ -0,0 +1,47 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_htable.h" + + +int +remove_hash(iphtable_t *iphp, ioctlfunc_t iocfunc) +{ + iplookupop_t op; + iphtable_t iph; + + if (pool_open() == -1) + return (-1); + + op.iplo_type = IPLT_HASH; + op.iplo_unit = iphp->iph_unit; + strncpy(op.iplo_name, iphp->iph_name, sizeof(op.iplo_name)); + if (*op.iplo_name == '\0') + op.iplo_arg = IPHASH_ANON; + op.iplo_size = sizeof(iph); + op.iplo_struct = &iph; + + bzero((char *)&iph, sizeof(iph)); + iph.iph_unit = iphp->iph_unit; + iph.iph_type = iphp->iph_type; + strncpy(iph.iph_name, iphp->iph_name, sizeof(iph.iph_name)); + iph.iph_flags = iphp->iph_flags; + + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash table")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/remove_hashnode.c b/sbin/ipf/libipf/remove_hashnode.c new file mode 100644 index 000000000000..95fada0a81e5 --- /dev/null +++ b/sbin/ipf/libipf/remove_hashnode.c @@ -0,0 +1,51 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_htable.h" + + +int +remove_hashnode(int unit, char *name, iphtent_t *node, ioctlfunc_t iocfunc) +{ + iplookupop_t op; + iphtent_t ipe; + + if (pool_open() == -1) + return (-1); + + op.iplo_type = IPLT_HASH; + op.iplo_unit = unit; + op.iplo_size = sizeof(ipe); + op.iplo_struct = &ipe; + op.iplo_arg = 0; + strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + + bzero((char *)&ipe, sizeof(ipe)); + bcopy((char *)&node->ipe_addr, (char *)&ipe.ipe_addr, + sizeof(ipe.ipe_addr)); + bcopy((char *)&node->ipe_mask, (char *)&ipe.ipe_mask, + sizeof(ipe.ipe_mask)); + + if (opts & OPT_DEBUG) { + printf("\t%s - ", inet_ntoa(ipe.ipe_addr.in4)); + printf("%s\n", inet_ntoa(ipe.ipe_mask.in4)); + } + + if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { + if (!(opts & OPT_DONOTHING)) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup hash node")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/remove_pool.c b/sbin/ipf/libipf/remove_pool.c new file mode 100644 index 000000000000..21d01fdbc0a4 --- /dev/null +++ b/sbin/ipf/libipf/remove_pool.c @@ -0,0 +1,44 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_htable.h" + + +int +remove_pool(ip_pool_t *poolp, ioctlfunc_t iocfunc) +{ + iplookupop_t op; + ip_pool_t pool; + + if (pool_open() == -1) + return (-1); + + op.iplo_type = IPLT_POOL; + op.iplo_unit = poolp->ipo_unit; + strncpy(op.iplo_name, poolp->ipo_name, sizeof(op.iplo_name)); + op.iplo_size = sizeof(pool); + op.iplo_struct = &pool; + + bzero((char *)&pool, sizeof(pool)); + pool.ipo_unit = poolp->ipo_unit; + strncpy(pool.ipo_name, poolp->ipo_name, sizeof(pool.ipo_name)); + pool.ipo_flags = poolp->ipo_flags; + + if (pool_ioctl(iocfunc, SIOCLOOKUPDELTABLE, &op)) { + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "delete lookup pool")); + } + } + return (0); +} diff --git a/sbin/ipf/libipf/remove_poolnode.c b/sbin/ipf/libipf/remove_poolnode.c new file mode 100644 index 000000000000..2d8caa158604 --- /dev/null +++ b/sbin/ipf/libipf/remove_poolnode.c @@ -0,0 +1,50 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <fcntl.h> +#include <sys/ioctl.h> +#include "ipf.h" +#include "netinet/ip_lookup.h" +#include "netinet/ip_pool.h" + + +int +remove_poolnode(int unit, char *name, ip_pool_node_t *node, + ioctlfunc_t iocfunc) +{ + ip_pool_node_t pn; + iplookupop_t op; + + if (pool_open() == -1) + return (-1); + + op.iplo_unit = unit; + op.iplo_type = IPLT_POOL; + op.iplo_arg = 0; + strncpy(op.iplo_name, name, sizeof(op.iplo_name)); + op.iplo_struct = &pn; + op.iplo_size = sizeof(pn); + + bzero((char *)&pn, sizeof(pn)); + bcopy((char *)&node->ipn_addr, (char *)&pn.ipn_addr, + sizeof(pn.ipn_addr)); + bcopy((char *)&node->ipn_mask, (char *)&pn.ipn_mask, + sizeof(pn.ipn_mask)); + pn.ipn_info = node->ipn_info; + strncpy(pn.ipn_name, node->ipn_name, sizeof(pn.ipn_name)); + + if (pool_ioctl(iocfunc, SIOCLOOKUPDELNODE, &op)) { + if ((opts & OPT_DONOTHING) == 0) { + return (ipf_perror_fd(pool_fd(), iocfunc, + "remove lookup pool node")); + } + } + + return (0); +} diff --git a/sbin/ipf/libipf/resetlexer.c b/sbin/ipf/libipf/resetlexer.c new file mode 100644 index 000000000000..307ed657a46a --- /dev/null +++ b/sbin/ipf/libipf/resetlexer.c @@ -0,0 +1,24 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +long string_start = -1; +long string_end = -1; +char *string_val = NULL; +long pos = 0; + + +void resetlexer(void) +{ + string_start = -1; + string_end = -1; + string_val = NULL; + pos = 0; +} diff --git a/sbin/ipf/libipf/rwlock_emul.c b/sbin/ipf/libipf/rwlock_emul.c new file mode 100644 index 000000000000..ec8a61c5cff2 --- /dev/null +++ b/sbin/ipf/libipf/rwlock_emul.c @@ -0,0 +1,149 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + +#define EMM_MAGIC 0x97dd8b3a + +void eMrwlock_read_enter(eMrwlock_t *rw, char *file, int line) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_read_enter(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_read != 0 || rw->eMrw_write != 0) { + fprintf(stderr, + "%s:eMrwlock_read_enter(%p): already locked: %d/%d\n", + rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write); + abort(); + } + rw->eMrw_read++; + rw->eMrw_heldin = file; + rw->eMrw_heldat = line; +} + + +void eMrwlock_write_enter(eMrwlock_t *rw, char *file, int line) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_read != 0 || rw->eMrw_write != 0) { + fprintf(stderr, + "%s:eMrwlock_write_enter(%p): already locked: %d/%d\n", + rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write); + abort(); + } + rw->eMrw_write++; + rw->eMrw_heldin = file; + rw->eMrw_heldat = line; +} + + +void eMrwlock_try_upgrade(eMrwlock_t *rw, char *file, int line) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_read != 0 || rw->eMrw_write != 0) { + fprintf(stderr, + "%s:eMrwlock_try_upgrade(%p): already locked: %d/%d\n", + rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write); + abort(); + } + rw->eMrw_write++; + rw->eMrw_heldin = file; + rw->eMrw_heldat = line; +} + +void eMrwlock_downgrade(eMrwlock_t *rw, char *file, int line) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_write_enter(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_read != 0 || rw->eMrw_write != 1) { + fprintf(stderr, + "%s:eMrwlock_write_enter(%p): already locked: %d/%d\n", + rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write); + abort(); + } + rw->eMrw_write--; + rw->eMrw_read++; + rw->eMrw_heldin = file; + rw->eMrw_heldat = line; +} + + +void eMrwlock_exit(eMrwlock_t *rw) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_exit(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_read != 1 && rw->eMrw_write != 1) { + fprintf(stderr, "%s:eMrwlock_exit(%p): not locked: %d/%d\n", + rw->eMrw_owner, rw, rw->eMrw_read, rw->eMrw_write); + abort(); + } + if (rw->eMrw_read == 1) + rw->eMrw_read--; + else if (rw->eMrw_write == 1) + rw->eMrw_write--; + rw->eMrw_heldin = NULL; + rw->eMrw_heldat = 0; +} + + +static int initcount = 0; + +void eMrwlock_init(eMrwlock_t *rw, char *who) +{ + if (rw->eMrw_magic == EMM_MAGIC) { /* safe bet ? */ + fprintf(stderr, + "%s:eMrwlock_init(%p): already initialised?: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + rw->eMrw_magic = EMM_MAGIC; + rw->eMrw_read = 0; + rw->eMrw_write = 0; + if (who != NULL) + rw->eMrw_owner = strdup(who); + else + rw->eMrw_owner = NULL; + initcount++; +} + + +void eMrwlock_destroy(eMrwlock_t *rw) +{ + if (rw->eMrw_magic != EMM_MAGIC) { + fprintf(stderr, "%s:eMrwlock_destroy(%p): bad magic: %#x\n", + rw->eMrw_owner, rw, rw->eMrw_magic); + abort(); + } + if (rw->eMrw_owner != NULL) + free(rw->eMrw_owner); + memset(rw, 0xa5, sizeof(*rw)); + initcount--; +} + +void ipf_rwlock_clean(void) +{ + if (initcount != 0) + abort(); +} diff --git a/sbin/ipf/libipf/save_execute.c b/sbin/ipf/libipf/save_execute.c new file mode 100644 index 000000000000..dce5c2eeacda --- /dev/null +++ b/sbin/ipf/libipf/save_execute.c @@ -0,0 +1,76 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *execute_parse(char **); +static void execute_destroy(void *); +static int execute_send(void *, ipmon_msg_t *); +static void execute_print(void *); + +typedef struct execute_opts_s { + char *path; +} execute_opts_t; + +ipmon_saver_t executesaver = { + "execute", + execute_destroy, + NULL, /* dup */ + NULL, /* match */ + execute_parse, + execute_print, + execute_send +}; + + +static void * +execute_parse(char **strings) +{ + execute_opts_t *ctx; + + ctx = calloc(1, sizeof(*ctx)); + + if (ctx != NULL && strings[0] != NULL && strings[0][0] != '\0') { + ctx->path = strdup(strings[0]); + + } else { + free(ctx); + return (NULL); + } + + return (ctx); +} + + +static void +execute_print(void *ctx) +{ + execute_opts_t *exe = ctx; + + printf("%s", exe->path); +} + + +static void +execute_destroy(void *ctx) +{ + execute_opts_t *exe = ctx; + + if (exe != NULL) + free(exe->path); + free(exe); +} + + +static int +execute_send(void *ctx, ipmon_msg_t *msg) +{ + execute_opts_t *exe = ctx; + FILE *fp; + + fp = popen(exe->path, "w"); + if (fp != NULL) { + fwrite(msg->imm_msg, msg->imm_msglen, 1, fp); + pclose(fp); + } + return (0); +} + diff --git a/sbin/ipf/libipf/save_file.c b/sbin/ipf/libipf/save_file.c new file mode 100644 index 000000000000..1b39daa90974 --- /dev/null +++ b/sbin/ipf/libipf/save_file.c @@ -0,0 +1,123 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *file_parse(char **); +static void file_destroy(void *); +static int file_send(void *, ipmon_msg_t *); +static void file_print(void *); +static int file_match(void *, void *); +static void *file_dup(void *); + +typedef struct file_opts_s { + FILE *fp; + int raw; + char *path; + int ref; +} file_opts_t; + +ipmon_saver_t filesaver = { + "file", + file_destroy, + file_dup, + file_match, + file_parse, + file_print, + file_send +}; + + +static void * +file_parse(char **strings) +{ + file_opts_t *ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return (NULL); + + if (strings[0] != NULL && strings[0][0] != '\0') { + ctx->ref = 1; + if (!strncmp(strings[0], "raw://", 6)) { + ctx->raw = 1; + ctx->path = strdup(strings[0] + 6); + ctx->fp = fopen(ctx->path, "ab"); + } else if (!strncmp(strings[0], "file://", 7)) { + ctx->path = strdup(strings[0] + 7); + ctx->fp = fopen(ctx->path, "a"); + } else { + free(ctx); + ctx = NULL; + } + } else { + free(ctx); + ctx = NULL; + } + + return (ctx); +} + + +static int +file_match(void *ctx1, void *ctx2) +{ + file_opts_t *f1 = ctx1, *f2 = ctx2; + + if (f1->raw != f2->raw) + return (1); + if (strcmp(f1->path, f2->path)) + return (1); + return (0); +} + + +static void * +file_dup(void *ctx) +{ + file_opts_t *f = ctx; + + f->ref++; + return (f); +} + + +static void +file_print(void *ctx) +{ + file_opts_t *file = ctx; + + if (file->raw) + printf("raw://"); + else + printf("file://"); + printf("%s", file->path); +} + + +static void +file_destroy(void *ctx) +{ + file_opts_t *file = ctx; + + file->ref--; + if (file->ref > 0) + return; + + if (file->path != NULL) + free(file->path); + free(file); +} + + +static int +file_send(void *ctx, ipmon_msg_t *msg) +{ + file_opts_t *file = ctx; + + if (file->raw) { + fwrite(msg->imm_data, msg->imm_dsize, 1, file->fp); + } else { + fprintf(file->fp, "%s", msg->imm_msg); + } + return (0); +} + diff --git a/sbin/ipf/libipf/save_nothing.c b/sbin/ipf/libipf/save_nothing.c new file mode 100644 index 000000000000..7d8db5215e91 --- /dev/null +++ b/sbin/ipf/libipf/save_nothing.c @@ -0,0 +1,59 @@ +#include "ipf.h" +#include "ipmon.h" + +static void *nothing_parse(char **); +static void nothing_destroy(void *); +static int nothing_send(void *, ipmon_msg_t *); + +typedef struct nothing_opts_s { + FILE *fp; + int raw; + char *path; +} nothing_opts_t; + +ipmon_saver_t nothingsaver = { + "nothing", + nothing_destroy, + NULL, /* dup */ + NULL, /* match */ + nothing_parse, + NULL, /* print */ + nothing_send +}; + + +static void * +nothing_parse(char **strings) +{ + void *ctx; + +#if 0 + strings = strings; /* gcc -Wextra */ +#endif + + ctx = calloc(1, sizeof(void *)); + + return (ctx); +} + + +static void +nothing_destroy(void *ctx) +{ + free(ctx); +} + + +static int +nothing_send(void *ctx, ipmon_msg_t *msg) +{ +#if 0 + ctx = ctx; /* gcc -Wextra */ + msg = msg; /* gcc -Wextra */ +#endif + /* + * Do nothing + */ + return (0); +} + diff --git a/sbin/ipf/libipf/save_syslog.c b/sbin/ipf/libipf/save_syslog.c new file mode 100644 index 000000000000..71caa7bdaed2 --- /dev/null +++ b/sbin/ipf/libipf/save_syslog.c @@ -0,0 +1,133 @@ +#include "ipf.h" +#include "ipmon.h" +#include <syslog.h> + +static void *syslog_parse(char **); +static void syslog_destroy(void *); +static int syslog_send(void *, ipmon_msg_t *); +static void syslog_print(void *); + +typedef struct syslog_opts_s { + int facpri; + int fac; + int pri; +} syslog_opts_t; + +ipmon_saver_t syslogsaver = { + "syslog", + syslog_destroy, + NULL, /* dup */ + NULL, /* match */ + syslog_parse, + syslog_print, + syslog_send +}; + + +static void * +syslog_parse(char **strings) +{ + syslog_opts_t *ctx; + char *str; + char *s; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return (NULL); + + ctx->facpri = -1; + + if (strings[0] != NULL && strings[0][0] != '\0') { + str = strdup(*strings); + if (str != NULL && *str != '\0') { + int fac = -1, pri = -1; + + s = strchr(str, '.'); + if (s != NULL) + *s++ = '\0'; + + if (*str != '\0') { + fac = fac_findname(str); + if (fac == -1) { + free(str); + free(ctx); + return (NULL); + } + } + + if (s != NULL && *s != '\0') { + pri = pri_findname(s); + if (pri == -1) { + free(str); + free(ctx); + return (NULL); + } + } + free(str); + + ctx->fac = fac; + ctx->pri = pri; + if (pri == -1) + ctx->facpri = fac; + else if (fac == -1) + ctx->facpri = pri; + else + ctx->facpri = fac | pri; + } else { + if (str != NULL) + free(str); + free(ctx); + ctx = NULL; + } + } + + return (ctx); +} + + +static void +syslog_print(void *ctx) +{ + syslog_opts_t *sys = ctx; + + if (sys->facpri == -1) + return; + + if (sys->fac == -1) { + printf(".%s", pri_toname(sys->pri)); + } else if (sys->pri == -1) { + printf("%s.", fac_toname(sys->fac)); + } else { + printf("%s.%s", fac_toname(sys->facpri & LOG_FACMASK), + pri_toname(sys->facpri & LOG_PRIMASK)); + } +} + + +static void +syslog_destroy(void *ctx) +{ + free(ctx); +} + + +static int +syslog_send(void *ctx, ipmon_msg_t *msg) +{ + syslog_opts_t *sys = ctx; + int facpri; + + if (sys->facpri == -1) { + facpri = msg->imm_loglevel; + } else { + if (sys->pri == -1) { + facpri = sys->fac | (msg->imm_loglevel & LOG_PRIMASK); + } else if (sys->fac == -1) { + facpri = sys->pri | (msg->imm_loglevel & LOG_FACMASK); + } else { + facpri = sys->facpri; + } + } + syslog(facpri, "%s", msg->imm_msg); + return (0); +} diff --git a/sbin/ipf/libipf/save_v1trap.c b/sbin/ipf/libipf/save_v1trap.c new file mode 100644 index 000000000000..06aca1d54c12 --- /dev/null +++ b/sbin/ipf/libipf/save_v1trap.c @@ -0,0 +1,443 @@ +#include "ipf.h" +#include "netinet/ipl.h" +#include "ipmon.h" +#include <ctype.h> + +#define IPF_ENTERPRISE 9932 +/* + * Enterprise number OID: + * 1.3.6.1.4.1.9932 + */ +static u_char ipf_enterprise[] = { 6, 7, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c }; +static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; +static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; + +static int writeint(u_char *, int); +static int writelength(u_char *, u_int); +static int maketrap_v1(char *, u_char *, int, u_char *, int, u_32_t, + time_t); +static void snmpv1_destroy(void *); +static void *snmpv1_dup(void *); +static int snmpv1_match(void *, void *); +static void *snmpv1_parse(char **); +static void snmpv1_print(void *); +static int snmpv1_send(void *, ipmon_msg_t *); + +typedef struct snmpv1_opts_s { + char *community; + int fd; + int v6; + int ref; +#ifdef USE_INET6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_in sin; +} snmpv1_opts_t; + +ipmon_saver_t snmpv1saver = { + "snmpv1", + snmpv1_destroy, + snmpv1_dup, /* dup */ + snmpv1_match, /* match */ + snmpv1_parse, + snmpv1_print, + snmpv1_send +}; + + +static int +snmpv1_match(void *ctx1, void *ctx2) +{ + snmpv1_opts_t *s1 = ctx1, *s2 = ctx2; + + if (s1->v6 != s2->v6) + return (1); + + if (strcmp(s1->community, s2->community)) + return (1); + +#ifdef USE_INET6 + if (s1->v6 == 1) { + if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) + return (1); + } else +#endif + { + if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) + return (1); + } + + return (0); +} + + +static void * +snmpv1_dup(void *ctx) +{ + snmpv1_opts_t *s = ctx; + + s->ref++; + return (s); +} + + +static void +snmpv1_print(void *ctx) +{ + snmpv1_opts_t *snmpv1 = ctx; + + printf("%s ", snmpv1->community); +#ifdef USE_INET6 + if (snmpv1->v6 == 1) { + char buf[80]; + + printf("%s", inet_ntop(AF_INET6, &snmpv1->sin6.sin6_addr, buf, + sizeof(snmpv1->sin6.sin6_addr))); + } else +#endif + { + printf("%s", inet_ntoa(snmpv1->sin.sin_addr)); + } +} + + +static void * +snmpv1_parse(char **strings) +{ + snmpv1_opts_t *ctx; + int result; + char *str; + char *s; + + if (strings[0] == NULL || strings[0][0] == '\0') + return (NULL); + + if (strchr(*strings, ' ') == NULL) + return (NULL); + + str = strdup(*strings); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) + return (NULL); + + ctx->fd = -1; + + s = strchr(str, ' '); + *s++ = '\0'; + ctx->community = str; + + while (ISSPACE(*s)) + s++; + if (!*s) { + free(str); + free(ctx); + return (NULL); + } + +#ifdef USE_INET6 + if (strchr(s, ':') == NULL) { + result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv1_destroy(ctx); + return (NULL); + } + } + } + } else { + result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); + if (result == 1) { + ctx->v6 = 1; + ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin6.sin6_family = AF_INET6; + ctx->sin6.sin6_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin6, + sizeof(ctx->sin6)) != 0) { + snmpv1_destroy(ctx); + return (NULL); + } + } + } + } +#else + result = inet_aton(s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv1_destroy(ctx); + return (NULL); + } + } + } +#endif + + if (result != 1) { + free(str); + free(ctx); + return (NULL); + } + + ctx->ref = 1; + + return (ctx); +} + + +static void +snmpv1_destroy(void *ctx) +{ + snmpv1_opts_t *v1 = ctx; + + v1->ref--; + if (v1->ref > 0) + return; + + if (v1->community) + free(v1->community); + if (v1->fd >= 0) + close(v1->fd); + free(v1); +} + + +static int +snmpv1_send(void *ctx, ipmon_msg_t *msg) +{ + snmpv1_opts_t *v1 = ctx; + + return (sendtrap_v1_0(v1->fd, v1->community, + msg->imm_msg, msg->imm_msglen, msg->imm_when)); +} + +static char def_community[] = "public"; /* ublic */ + +static int +writelength(u_char *buffer, u_int value) +{ + u_int n = htonl(value); + int len; + + if (value < 128) { + *buffer = value; + return (1); + } + if (value > 0xffffff) + len = 4; + else if (value > 0xffff) + len = 3; + else if (value > 0xff) + len = 2; + else + len = 1; + + *buffer = 0x80 | len; + + bcopy((u_char *)&n + 4 - len, buffer + 1, len); + + return (len + 1); +} + + +static int +writeint(u_char *buffer, int value) +{ + u_char *s = buffer; + u_int n = value; + + if (value == 0) { + *buffer = 0; + return (1); + } + + if (n > 4194304) { + *s++ = 0x80 | (n / 4194304); + n -= 4194304 * (n / 4194304); + } + if (n > 32768) { + *s++ = 0x80 | (n / 32768); + n -= 32768 * (n / 327678); + } + if (n > 128) { + *s++ = 0x80 | (n / 128); + n -= (n / 128) * 128; + } + *s++ = (u_char)n; + + return (s - buffer); +} + + + +/* + * First style of traps is: + * 1.3.6.1.4.1.9932.1.1 + */ +static int +maketrap_v1(char *community, u_char *buffer, int bufsize, u_char *msg, + int msglen, u_32_t ipaddr, time_t when) +{ + u_char *s = buffer, *t, *pdulen, *varlen; + int basesize = 73; + u_short len; + int trapmsglen; + int pdulensz; + int varlensz; + int baselensz; + int n; + + if (community == NULL || *community == '\0') + community = def_community; + basesize += strlen(community) + msglen; + + if (basesize + 8 > bufsize) + return (0); + + memset(buffer, 0xff, bufsize); + *s++ = 0x30; /* Sequence */ + if (basesize - 1 >= 128) { + baselensz = 2; + basesize++; + } else { + baselensz = 1; + } + s += baselensz; + *s++ = 0x02; /* Integer32 */ + *s++ = 0x01; /* length 1 */ + *s++ = 0x00; /* version 1 */ + *s++ = 0x04; /* octet string */ + *s++ = strlen(community); /* length of "public" */ + bcopy(community, s, s[-1]); + s += s[-1]; + *s++ = 0xA4; /* PDU(4) */ + pdulen = s++; + if (basesize - (s - buffer) >= 128) { + pdulensz = 2; + basesize++; + s++; + } else { + pdulensz = 1; + } + + /* enterprise */ + bcopy(ipf_enterprise, s, sizeof(ipf_enterprise)); + s += sizeof(ipf_enterprise); + + /* Agent address */ + *s++ = 0x40; + *s++ = 0x4; + bcopy(&ipaddr, s, 4); + s += 4; + + /* Generic Trap code */ + *s++ = 0x2; + n = writeint(s + 1, 6); + if (n == 0) + return (0); + *s = n; + s += n + 1; + + /* Specific Trap code */ + *s++ = 0x2; + n = writeint(s + 1, 0); + if (n == 0) + return (0); + *s = n; + s += n + 1; + + /* Time stamp */ + *s++ = 0x43; /* TimeTicks */ + *s++ = 0x04; /* TimeTicks */ + s[0] = when >> 24; + s[1] = when >> 16; + s[2] = when >> 8; + s[3] = when & 0xff; + s += 4; + + /* + * The trap0 message is "ipfilter_version" followed by the message + */ + *s++ = 0x30; + varlen = s; + if (basesize - (s - buffer) >= 128) { + varlensz = 2; + basesize++; + } else { + varlensz = 1; + } + s += varlensz; + + *s++ = 0x30; + t = s + 1; + bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); + t += sizeof(ipf_trap0_1); + + *t++ = 0x2; /* Integer */ + n = writeint(t + 1, IPFILTER_VERSION); + *t = n; + t += n + 1; + + len = t - s - 1; + writelength(s, len); + + s = t; + *s++ = 0x30; + if (basesize - (s - buffer) >= 128) { + trapmsglen = 2; + basesize++; + } else { + trapmsglen = 1; + } + t = s + trapmsglen; + bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); + t += sizeof(ipf_trap0_2); + + *t++ = 0x4; /* Octet string */ + n = writelength(t, msglen); + t += n; + bcopy(msg, t, msglen); + t += msglen; + + len = t - s - trapmsglen; + writelength(s, len); + + len = t - varlen - varlensz; + writelength(varlen, len); /* pdu length */ + + len = t - pdulen - pdulensz; + writelength(pdulen, len); /* pdu length */ + + len = t - buffer - baselensz - 1; + writelength(buffer + 1, len); /* length of trap */ + + return (t - buffer); +} + + +int +sendtrap_v1_0(int fd, char *community, char *msg, int msglen, time_t when) +{ + + u_char buffer[1500]; + int n; + + n = maketrap_v1(community, buffer, sizeof(buffer), + (u_char *)msg, msglen, 0, when); + if (n > 0) { + return (send(fd, buffer, n, 0)); + } + + return (0); +} diff --git a/sbin/ipf/libipf/save_v2trap.c b/sbin/ipf/libipf/save_v2trap.c new file mode 100644 index 000000000000..2ad8d6806dbc --- /dev/null +++ b/sbin/ipf/libipf/save_v2trap.c @@ -0,0 +1,444 @@ +#include "ipf.h" +#include "netinet/ipl.h" +#include "ipmon.h" +#include <ctype.h> + +static u_char sysuptime[] = { 6, 8, 0x2b, 6, 1, 2, 1, 1, 3, 0 }; +/* + * Enterprise number OID: + * 1.3.6.1.4.1.9932 + */ +static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; +static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; + +static int writeint(u_char *, int); +static int writelength(u_char *, u_int); +static int maketrap_v2(char *, u_char *, int, u_char *, int); +static void snmpv2_destroy(void *); +static void *snmpv2_dup(void *); +static int snmpv2_match(void *, void *); +static void *snmpv2_parse(char **); +static void snmpv2_print(void *); +static int snmpv2_send(void *, ipmon_msg_t *); + + +int sendtrap_v2_0(int, char *, char *, int); + +static char def_community[] = "public"; /* ublic */ + +typedef struct snmpv2_opts_s { + char *community; + char *server; + int fd; + int v6; + int ref; +#ifdef USE_INET6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_in sin; +} snmpv2_opts_t; + +ipmon_saver_t snmpv2saver = { + "snmpv2", + snmpv2_destroy, + snmpv2_dup, /* dup */ + snmpv2_match, /* match */ + snmpv2_parse, + snmpv2_print, + snmpv2_send +}; + + +static int +snmpv2_match(void *ctx1, void *ctx2) +{ + snmpv2_opts_t *s1 = ctx1, *s2 = ctx2; + + if (s1->v6 != s2->v6) + return (1); + + if (strcmp(s1->community, s2->community)) + return (1); + +#ifdef USE_INET6 + if (s1->v6 == 1) { + if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) + return (1); + } else +#endif + { + if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) + return (1); + } + + return (0); +} + + +static void * +snmpv2_dup(void *ctx) +{ + snmpv2_opts_t *s = ctx; + + s->ref++; + return (s); +} + + +static void +snmpv2_print(void *ctx) +{ + snmpv2_opts_t *snmpv2 = ctx; + + printf("%s ", snmpv2->community); +#ifdef USE_INET6 + if (snmpv2->v6 == 1) { + char buf[80]; + + printf("%s", inet_ntop(AF_INET6, &snmpv2->sin6.sin6_addr, buf, + sizeof(snmpv2->sin6.sin6_addr))); + } else +#endif + { + printf("%s", inet_ntoa(snmpv2->sin.sin_addr)); + } +} + + +static void * +snmpv2_parse(char **strings) +{ + snmpv2_opts_t *ctx; + int result; + char *str; + char *s; + + if (strings[0] == NULL || strings[0][0] == '\0') + return (NULL); + if (strchr(*strings, ' ') == NULL) + return (NULL); + + str = strdup(*strings); + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + free(str); + return (NULL); + } + + ctx->fd = -1; + + s = strchr(str, ' '); + *s++ = '\0'; + ctx->community = str; + + while (ISSPACE(*s)) + s++; + if (!*s) { + free(str); + free(ctx); + return (NULL); + } + +#ifdef USE_INET6 + if (strchr(s, ':') == NULL) { + result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv2_destroy(ctx); + return (NULL); + } + } + } + } else { + result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); + if (result == 1) { + ctx->v6 = 1; + ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin6.sin6_family = AF_INET6; + ctx->sin6.sin6_port = htons(162); + if (connect(ctx->fd, + (struct sockaddr *)&ctx->sin6, + sizeof(ctx->sin6)) != 0) { + snmpv2_destroy(ctx); + return (NULL); + } + } + } + } +#else + result = inet_aton(s, &ctx->sin.sin_addr); + if (result == 1) { + ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); + if (ctx->fd >= 0) { + ctx->sin.sin_family = AF_INET; + ctx->sin.sin_port = htons(162); + if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, + sizeof(ctx->sin)) != 0) { + snmpv2_destroy(ctx); + return (NULL); + } + } + } +#endif + + if (result != 1) { + free(str); + free(ctx); + return (NULL); + } + + ctx->ref = 1; + + return (ctx); +} + + +static void +snmpv2_destroy(void *ctx) +{ + snmpv2_opts_t *v2 = ctx; + + v2->ref--; + if (v2->ref > 0) + return; + + if (v2->community) + free(v2->community); + if (v2->fd >= 0) + close(v2->fd); + free(v2); +} + + +static int +snmpv2_send(void *ctx, ipmon_msg_t *msg) +{ + snmpv2_opts_t *v2 = ctx; + + return (sendtrap_v2_0(v2->fd, v2->community, + msg->imm_msg, msg->imm_msglen)); +} +static int +writelength(u_char *buffer, u_int value) +{ + u_int n = htonl(value); + int len; + + if (value < 128) { + *buffer = value; + return (1); + } + if (value > 0xffffff) + len = 4; + else if (value > 0xffff) + len = 3; + else if (value > 0xff) + len = 2; + else + len = 1; + + *buffer = 0x80 | len; + + bcopy((u_char *)&n + 4 - len, buffer + 1, len); + + return (len + 1); +} + + +static int +writeint(u_char *buffer, int value) +{ + u_char *s = buffer; + u_int n = value; + + if (value == 0) { + *buffer = 0; + return (1); + } + + if (n > 4194304) { + *s++ = 0x80 | (n / 4194304); + n -= 4194304 * (n / 4194304); + } + if (n > 32768) { + *s++ = 0x80 | (n / 32768); + n -= 32768 * (n / 327678); + } + if (n > 128) { + *s++ = 0x80 | (n / 128); + n -= (n / 128) * 128; + } + *s++ = (u_char)n; + + return (s - buffer); +} + + + +/* + * First style of traps is: + * 1.3.6.1.4.1.9932.1.1 + */ +static int +maketrap_v2(char *community, u_char *buffer, int bufsize, u_char *msg, + int msglen) +{ + u_char *s = buffer, *t, *pdulen; + u_char *varlen; + int basesize = 77; + u_short len; + int trapmsglen; + int pdulensz; + int varlensz; + int baselensz; + int n; + + if (community == NULL || *community == '\0') + community = def_community; + basesize += strlen(community) + msglen; + + if (basesize + 8 > bufsize) + return (0); + + memset(buffer, 0xff, bufsize); + *s++ = 0x30; /* Sequence */ + + if (basesize - 1 >= 128) { + baselensz = 2; + basesize++; + } else { + baselensz = 1; + } + s += baselensz; + *s++ = 0x02; /* Integer32 */ + *s++ = 0x01; /* length 1 */ + *s++ = 0x01; /* version 2 */ + *s++ = 0x04; /* octet string */ + *s++ = strlen(community); /* length of "public" */ + bcopy(community, s, s[-1]); + s += s[-1]; + *s++ = 0xA7; /* PDU(7) */ + pdulen = s++; + if (basesize - (s - buffer) >= 128) { + pdulensz = 2; + basesize++; + s++; + } else { + pdulensz = 1; + } + /* request id */ + *s++ = 0x2; /* integer */ + *s++ = 0x4; /* len 4 */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + *s++ = 0x0; /* noError */ + + /* error status */ + *s++ = 0x2; /* integer */ + *s++ = 0x1; /* len 1 */ + *s++ = 0x0; /* noError */ + + /* error-index */ + *s++ = 0x2; /* integer */ + *s++ = 0x1; /* len 1 */ + *s++ = 0x0; /* noError */ + + *s++ = 0x30; /* sequence */ + varlen = s++; + if (basesize - (s - buffer) >= 128) { + varlensz = 2; + basesize++; + s++; + } else { + varlensz = 1; + } + + *s++ = 0x30; /* sequence */ + *s++ = sizeof(sysuptime) + 6; + + bcopy(sysuptime, s, sizeof(sysuptime)); + s += sizeof(sysuptime); + + *s++ = 0x43; /* Timestamp */ + *s++ = 0x04; /* TimeTicks */ + *s++ = 0x0; + *s++ = 0x0; + *s++ = 0x0; + *s++ = 0x0; + + *s++ = 0x30; + t = s + 1; + bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); + t += sizeof(ipf_trap0_1); + + *t++ = 0x2; /* Integer */ + n = writeint(t + 1, IPFILTER_VERSION); + *t = n; + t += n + 1; + + len = t - s - 1; + writelength(s, len); + + s = t; + *s++ = 0x30; + if (msglen < 128) { + if (msglen + 1 + 1 + sizeof(ipf_trap0_2) >= 128) + trapmsglen = 2; + else + trapmsglen = 1; + } else { + if (msglen + 2 + 1 + sizeof(ipf_trap0_2) >= 128) + trapmsglen = 2; + else + trapmsglen = 1; + } + t = s + trapmsglen; + bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); + t += sizeof(ipf_trap0_2); + + *t++ = 0x4; /* Octet string */ + n = writelength(t, msglen); + t += n; + bcopy(msg, t, msglen); + t += msglen; + + len = t - s - trapmsglen; + writelength(s, len); + + len = t - varlen - varlensz; + writelength(varlen, len); /* pdu length */ + + len = t - pdulen - pdulensz; + writelength(pdulen, len); /* pdu length */ + + len = t - buffer - baselensz - 1; + writelength(buffer + 1, len); /* length of trap */ + + return (t - buffer); +} + + +int +sendtrap_v2_0(int fd, char *community, char *msg, int msglen) +{ + + u_char buffer[1500]; + int n; + + n = maketrap_v2(community, buffer, sizeof(buffer), + (u_char *)msg, msglen); + if (n > 0) { + return (send(fd, buffer, n, 0)); + } + + return (0); +} diff --git a/sbin/ipf/libipf/tcp_flags.c b/sbin/ipf/libipf/tcp_flags.c new file mode 100644 index 000000000000..9247933ee85b --- /dev/null +++ b/sbin/ipf/libipf/tcp_flags.c @@ -0,0 +1,46 @@ + +/* + * Copyright (C) 2000-2004 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id: tcp_flags.c,v 1.8.2.1 2006/06/16 17:21:17 darrenr Exp $ + */ + +#include "ipf.h" + +extern char flagset[]; +extern uint16_t flags[]; + + +uint16_t tcp_flags(char *flgs, uint16_t *mask, int linenum) +{ + uint16_t tcpf = 0, tcpfm = 0; + char *s; + + s = strchr(flgs, '/'); + if (s) + *s++ = '\0'; + + if (*flgs == '0') { + tcpf = strtol(flgs, NULL, 0); + } else { + tcpf = tcpflags(flgs); + } + + if (s != NULL) { + if (*s == '0') + tcpfm = strtol(s, NULL, 0); + else + tcpfm = tcpflags(s); + } + + if (!tcpfm) { + if (tcpf == TH_SYN) + tcpfm = TH_FLAGS & ~(TH_ECN|TH_CWR); + else + tcpfm = TH_FLAGS & ~(TH_ECN); + } + *mask = tcpfm; + return (tcpf); +} diff --git a/sbin/ipf/libipf/tcpflags.c b/sbin/ipf/libipf/tcpflags.c new file mode 100644 index 000000000000..46b64e96deda --- /dev/null +++ b/sbin/ipf/libipf/tcpflags.c @@ -0,0 +1,46 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +/* + * ECN is a new addition to TCP - RFC 2481 + */ +#ifndef TH_ECN +# define TH_ECN 0x40 +#endif +#ifndef TH_CWR +# define TH_CWR 0x80 +#endif +#ifndef TH_AE +# define TH_AE 0x100 +#endif + +extern char flagset[]; +extern uint16_t flags[]; + + +uint16_t tcpflags(char *flgs) +{ + uint16_t tcpf = 0; + char *s, *t; + + for (s = flgs; *s; s++) { + if (*s == 'W') + tcpf |= TH_CWR; + else { + if (!(t = strchr(flagset, *s))) { + return (0); + } + tcpf |= flags[t - flagset]; + } + } + return (tcpf); +} diff --git a/sbin/ipf/libipf/tcpoptnames.c b/sbin/ipf/libipf/tcpoptnames.c new file mode 100644 index 000000000000..3044f939438d --- /dev/null +++ b/sbin/ipf/libipf/tcpoptnames.c @@ -0,0 +1,21 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include "ipf.h" + + +struct ipopt_names tcpoptnames[] ={ + { TCPOPT_NOP, 0x000001, 1, "nop" }, + { TCPOPT_MAXSEG, 0x000002, 4, "maxseg" }, + { TCPOPT_WINDOW, 0x000004, 3, "wscale" }, + { TCPOPT_SACK_PERMITTED, 0x000008, 2, "sackok" }, + { TCPOPT_SACK, 0x000010, 3, "sack" }, + { TCPOPT_TIMESTAMP, 0x000020, 10, "tstamp" }, + { 0, 0, 0, (char *)NULL } /* must be last */ +}; diff --git a/sbin/ipf/libipf/v6ionames.c b/sbin/ipf/libipf/v6ionames.c new file mode 100644 index 000000000000..485af14f7863 --- /dev/null +++ b/sbin/ipf/libipf/v6ionames.c @@ -0,0 +1,27 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + +#ifdef USE_INET6 + +struct ipopt_names v6ionames[] ={ + { IPPROTO_HOPOPTS, 0x000001, 0, "hopopts" }, + { IPPROTO_IPV6, 0x000002, 0, "ipv6" }, + { IPPROTO_ROUTING, 0x000004, 0, "routing" }, + { IPPROTO_FRAGMENT, 0x000008, 0, "frag" }, + { IPPROTO_ESP, 0x000010, 0, "esp" }, + { IPPROTO_AH, 0x000020, 0, "ah" }, + { IPPROTO_NONE, 0x000040, 0, "none" }, + { IPPROTO_DSTOPTS, 0x000080, 0, "dstopts" }, + { IPPROTO_MOBILITY, 0x000100, 0, "mobility" }, + { 0, 0, 0, (char *)NULL } +}; + +#endif diff --git a/sbin/ipf/libipf/v6optvalue.c b/sbin/ipf/libipf/v6optvalue.c new file mode 100644 index 000000000000..5d09ad1b584d --- /dev/null +++ b/sbin/ipf/libipf/v6optvalue.c @@ -0,0 +1,36 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ +#include "ipf.h" + + + +u_32_t getv6optbyname(char *optname) +{ +#ifdef USE_INET6 + struct ipopt_names *io; + + for (io = v6ionames; io->on_name; io++) + if (!strcasecmp(optname, io->on_name)) + return (io->on_bit); +#endif + return (-1); +} + + +u_32_t getv6optbyvalue(int optval) +{ +#ifdef USE_INET6 + struct ipopt_names *io; + + for (io = v6ionames; io->on_name; io++) + if (io->on_value == optval) + return (io->on_bit); +#endif + return (-1); +} diff --git a/sbin/ipf/libipf/var.c b/sbin/ipf/libipf/var.c new file mode 100644 index 000000000000..0ccc888b3246 --- /dev/null +++ b/sbin/ipf/libipf/var.c @@ -0,0 +1,171 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +#include <ctype.h> + +#include "ipf.h" + +typedef struct variable { + struct variable *v_next; + char *v_name; + char *v_value; +} variable_t; + +static variable_t *vtop = NULL; + +static variable_t *find_var(char *); +static char *expand_string(char *, int); + + +static variable_t *find_var(char *name) +{ + variable_t *v; + + for (v = vtop; v != NULL; v = v->v_next) + if (!strcmp(name, v->v_name)) + return (v); + return (NULL); +} + + +char *get_variable(char *string, char **after, int line) +{ + char c, *s, *t, *value; + variable_t *v; + + s = string; + + if (*s == '{') { + s++; + for (t = s; *t != '\0'; t++) + if (*t == '}') + break; + if (*t == '\0') { + fprintf(stderr, "%d: { without }\n", line); + return (NULL); + } + } else if (ISALPHA(*s)) { + for (t = s + 1; *t != '\0'; t++) + if (!ISALPHA(*t) && !ISDIGIT(*t) && (*t != '_')) + break; + } else { + fprintf(stderr, "%d: variables cannot start with '%c'\n", + line, *s); + return (NULL); + } + + if (after != NULL) + *after = t; + c = *t; + *t = '\0'; + v = find_var(s); + *t = c; + if (v == NULL) { + fprintf(stderr, "%d: unknown variable '%s'\n", line, s); + return (NULL); + } + + s = strdup(v->v_value); + value = expand_string(s, line); + if (value != s) + free(s); + return (value); +} + + +static char *expand_string(char *oldstring, int line) +{ + char c, *s, *p1, *p2, *p3, *newstring, *value; + int len; + + p3 = NULL; + newstring = oldstring; + + for (s = oldstring; *s != '\0'; s++) + if (*s == '$') { + *s = '\0'; + s++; + + switch (*s) + { + case '$' : + bcopy(s, s - 1, strlen(s)); + break; + default : + c = *s; + if (c == '\0') + return (newstring); + + value = get_variable(s, &p3, line); + if (value == NULL) + return (NULL); + + p2 = expand_string(value, line); + if (p2 == NULL) + return (NULL); + + len = strlen(newstring) + strlen(p2); + if (p3 != NULL) { + if (c == '{' && *p3 == '}') + p3++; + len += strlen(p3); + } + p1 = malloc(len + 1); + if (p1 == NULL) + return (NULL); + + *(s - 1) = '\0'; + strcpy(p1, newstring); + strcat(p1, p2); + if (p3 != NULL) + strcat(p1, p3); + + s = p1 + len - strlen(p3) - 1; + if (newstring != oldstring) + free(newstring); + newstring = p1; + break; + } + } + return (newstring); +} + + +void set_variable(char *name, char *value) +{ + variable_t *v; + int len; + + if (name == NULL || value == NULL || *name == '\0') + return; + + v = find_var(name); + if (v != NULL) { + free(v->v_value); + v->v_value = strdup(value); + return; + } + + len = strlen(value); + + if ((*value == '"' && value[len - 1] == '"') || + (*value == '\'' && value[len - 1] == '\'')) { + value[len - 1] = '\0'; + value++; + len -=2; + } + + v = (variable_t *)malloc(sizeof(*v)); + if (v == NULL) + return; + v->v_name = strdup(name); + v->v_value = strdup(value); + v->v_next = vtop; + vtop = v; +} diff --git a/sbin/ipf/libipf/verbose.c b/sbin/ipf/libipf/verbose.c new file mode 100644 index 000000000000..cfa22083ed02 --- /dev/null +++ b/sbin/ipf/libipf/verbose.c @@ -0,0 +1,38 @@ + +/* + * Copyright (C) 2012 by Darren Reed. + * + * See the IPFILTER.LICENCE file for details on licencing. + * + * $Id$ + */ + +# include <stdarg.h> +#include <stdio.h> + +#include "ipf.h" +#include "opts.h" + + +void verbose(int level, char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + + if (opts & OPT_VERBOSE) + vprintf(fmt, pvar); + va_end(pvar); +} + + +void ipfkverbose(char *fmt, ...) +{ + va_list pvar; + + va_start(pvar, fmt); + + if (opts & OPT_VERBOSE) + verbose(0x1fffffff, fmt, pvar); + va_end(pvar); +} diff --git a/sbin/ipf/libipf/vtof.c b/sbin/ipf/libipf/vtof.c new file mode 100644 index 000000000000..8e6c9e966d63 --- /dev/null +++ b/sbin/ipf/libipf/vtof.c @@ -0,0 +1,15 @@ +#include "ipf.h" + +int +vtof(int version) +{ +#ifdef USE_INET6 + if (version == 6) + return (AF_INET6); +#endif + if (version == 4) + return (AF_INET); + if (version == 0) + return (AF_UNSPEC); + return (-1); +} |
